Reorder Posts - Version 1.0.4

Version Description

  • Added support for hierarchical post types
Download this release

Release Info

Developer ronalfy
Plugin Icon 128x128 Reorder Posts
Version 1.0.4
Comparing to
See all releases

Code changes from version 1.0.3 to 1.0.4

admin.css CHANGED
@@ -1,7 +1,7 @@
1
  #post-list {
2
  margin-top: 20px;
3
  }
4
- #post-list li {
5
  padding: 10px;
6
  width: 50%;
7
  font-weight: bold;
@@ -18,7 +18,10 @@
18
  -moz-border-radius: 10px;
19
  -webkit-border-radius: 10px;
20
  }
21
- #post-list li img {
 
 
 
22
  vertical-align: middle;
23
  margin: 0 12px 0 0;
24
  border: 2px solid #ddd;
1
  #post-list {
2
  margin-top: 20px;
3
  }
4
+ #post-list div {
5
  padding: 10px;
6
  width: 50%;
7
  font-weight: bold;
18
  -moz-border-radius: 10px;
19
  -webkit-border-radius: 10px;
20
  }
21
+ #post-list ul {
22
+ padding-left: 40px;
23
+ }
24
+ #post-list div img {
25
  vertical-align: middle;
26
  margin: 0 12px 0 0;
27
  border: 2px solid #ddd;
class-reorder.php CHANGED
@@ -114,7 +114,7 @@ class Reorder {
114
  $this->post_status = $post_status;
115
 
116
  // Add actions
117
- add_action( 'wp_ajax_post_sort', array( $this, 'save_post_order' ) );
118
  add_action( 'admin_print_styles', array( $this, 'print_styles' ) );
119
  add_action( 'admin_print_scripts', array( $this, 'print_scripts' ) );
120
  add_action( 'admin_menu', array( $this, 'enable_post_sort' ), 10, 'page' );
@@ -129,7 +129,7 @@ class Reorder {
129
  * @access public
130
  */
131
  public function create_nonce() {
132
- echo "<script>sortnonce = '" . wp_create_nonce( 'sortnonce' ) . "';</script>";
133
  }
134
 
135
  /**
@@ -140,28 +140,49 @@ class Reorder {
140
  * @access public
141
  * @global object $wpdb The primary global database object used internally by WordPress
142
  */
143
- public function save_post_order() {
144
  global $wpdb;
145
 
146
  // Verify nonce value, for security purposes
147
- wp_verify_nonce( json_encode( array( $_POST['nonce'] ) ), 'sortnonce' );
148
-
149
- // Split post output
150
- $order = explode( ',', $_POST['order'] );
151
-
152
- // Loop through blocks and stash in DB accordingly
153
- $counter = count( $order );
154
- foreach ( $order as $post_id ) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  $wpdb->update(
156
  $wpdb->posts,
157
- array( 'menu_order' => $counter ),
158
  array( 'ID' => $post_id )
159
  );
160
- $counter = $counter - 1;
161
- }
162
-
163
- die( 1 );
164
- }
165
 
166
  /**
167
  * Print styles to admin page
@@ -194,8 +215,8 @@ class Reorder {
194
 
195
  $pages = array( 'edit.php' );
196
  if ( in_array( $pagenow, $pages ) ) {
197
- wp_enqueue_script( 'jquery-ui-sortable' );
198
- wp_enqueue_script( 'levert_posts', REORDER_URL . '/scripts/sort.js' );
199
  }
200
  }
201
 
@@ -228,6 +249,74 @@ class Reorder {
228
  );
229
  }
230
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
231
 
232
  /**
233
  * HTML output
@@ -238,15 +327,6 @@ class Reorder {
238
  * @global string $post_type
239
  */
240
  public function sort_posts() {
241
- $posts = new WP_Query(
242
- array(
243
- 'post_type' => $this->post_type,
244
- 'posts_per_page' => -1,
245
- 'orderby' => 'menu_order',
246
- 'order' => $this->order,
247
- 'post_status' => $this->post_status,
248
- )
249
- );
250
  ?>
251
  <style type="text/css">
252
  #icon-reorder-posts {
@@ -261,18 +341,58 @@ class Reorder {
261
  </h2>
262
  <div id="reorder-error"></div>
263
  <?php echo $this->initial; ?>
264
- <ul id="post-list"><?php
265
-
266
- // Looping through all the posts
267
- while ( $posts->have_posts() ) {
268
- $posts->the_post();
269
- ?><li id="<?php the_id(); ?>"><?php the_title(); ?></li><?php
270
- }
271
- ?>
272
-
273
- </ul><?php
274
- echo $this->final; ?>
275
- </div><?php
276
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
 
278
  }
114
  $this->post_status = $post_status;
115
 
116
  // Add actions
117
+ add_action( 'wp_ajax_post_sort', array( $this, 'ajax_save_post_order' ) );
118
  add_action( 'admin_print_styles', array( $this, 'print_styles' ) );
119
  add_action( 'admin_print_scripts', array( $this, 'print_scripts' ) );
120
  add_action( 'admin_menu', array( $this, 'enable_post_sort' ), 10, 'page' );
129
  * @access public
130
  */
131
  public function create_nonce() {
132
+ echo "<script>var sortnonce = '" . wp_create_nonce( 'sortnonce' ) . "';</script>";
133
  }
134
 
135
  /**
140
  * @access public
141
  * @global object $wpdb The primary global database object used internally by WordPress
142
  */
143
+ public function ajax_save_post_order() {
144
  global $wpdb;
145
 
146
  // Verify nonce value, for security purposes
147
+ if ( !wp_verify_nonce( $_POST['nonce'], 'sortnonce' ) ) die( '' );
148
+
149
+ //Get JSON data
150
+ $post_data = json_decode( str_replace( "\\", '', $_POST[ 'data' ] ) );
151
+
152
+ //Iterate through post data
153
+ $this->update_posts( $post_data, 0 );
154
+
155
+ die( json_encode( array( 'success' => 'yo' ) ) );
156
+ } //end ajax_save_post_order
157
+
158
+ /**
159
+ * Saving the post order recursively
160
+ *
161
+ * @author Ronald Huereca <ronald@metronet.no>
162
+ * @since Reorder 1.0
163
+ * @access public
164
+ * @global object $wpdb The primary global database object used internally by WordPress
165
+ */
166
+ private function update_posts( $post_data, $parent_id ) {
167
+ global $wpdb;
168
+ $count = 0;
169
+
170
+ foreach( $post_data as $post_obj ) {
171
+ $post_id = absint( $post_obj->id );
172
+ $children = isset( $post_obj->children ) ? $post_obj->children : false;
173
+ if ( $children )
174
+ $this->update_posts( $children, $post_id );
175
+
176
+ //Update the posts
177
  $wpdb->update(
178
  $wpdb->posts,
179
+ array( 'menu_order' => $count, 'post_parent' => $parent_id ),
180
  array( 'ID' => $post_id )
181
  );
182
+ $count += 1;
183
+
184
+ } //end foreach $post_data
185
+ } //end update_posts
 
186
 
187
  /**
188
  * Print styles to admin page
215
 
216
  $pages = array( 'edit.php' );
217
  if ( in_array( $pagenow, $pages ) ) {
218
+ wp_register_script( 'reorder_nested', REORDER_URL . '/scripts/jquery.mjs.nestedSortable.js', array( 'jquery-ui-sortable' ), '1.3.5', true );
219
+ wp_enqueue_script( 'reorder_posts', REORDER_URL . '/scripts/sort.js', array( 'reorder_nested' ) );
220
  }
221
  }
222
 
249
  );
250
  }
251
  }
252
+
253
+ /**
254
+ * Post Row Output
255
+ *
256
+ * @author Ronald Huereca <ronald@metronet.no>
257
+ * @since Reorder 1.0.1
258
+ * @access private
259
+ * @param stdclass $post object to post
260
+ */
261
+ private function output_row( $the_post ) {
262
+ global $post;
263
+ $post = $the_post;
264
+ setup_postdata( $post );
265
+ ?>
266
+ <li id="list_<?php the_id(); ?>"><div><?php the_title(); ?></div></li>
267
+ <?php
268
+ } //end output_row
269
+
270
+ /**
271
+ * Post Row Output for Hierarchical posts
272
+ *
273
+ * @author Ronald Huereca <ronald@metronet.no>
274
+ * @since Reorder 1.0.1
275
+ * @access private
276
+ * @param stdclass $post object to post
277
+ * @param array $all_children - array of children
278
+ */
279
+ private function output_row_hierarchical( $the_post, $post_children, $all_children ) {
280
+ global $post;
281
+ $post = $the_post;
282
+ $post_id = $the_post->ID;
283
+
284
+ setup_postdata( $post );
285
+ ?>
286
+ <li id="list_<?php the_id(); ?>">
287
+ <div><?php the_title(); ?></div>
288
+ <ul class='children'>
289
+ <?php $this->output_row_children( $post_children, $all_children ); ?>
290
+ </ul>
291
+ </li>
292
+ <?php
293
+
294
+ ?>
295
+ <?php
296
+ } //end output_row_hierarchical
297
+
298
+ /**
299
+ * Output children posts
300
+ *
301
+ * @author Ronald Huereca <ronald@metronet.no>
302
+ * @since Reorder 1.0.1
303
+ * @access private
304
+ * @param stdclass $post object to post
305
+ * @param array $children_pages - array of children
306
+ */
307
+ private function output_row_children( $children_pages, $all_children ) {
308
+ foreach( $children_pages as $child ) {
309
+ $post_id = $child->ID;
310
+ if ( isset( $all_children[ $post_id ] ) && !empty( $all_children[ $post_id ] ) ) {
311
+ $this->output_row_hierarchical( $child, $all_children[ $post_id ], $all_children );
312
+ } else {
313
+ $this->output_row( $child );
314
+ }
315
+
316
+ } //end foreach $child
317
+ } //end output_row_children
318
+
319
+
320
 
321
  /**
322
  * HTML output
327
  * @global string $post_type
328
  */
329
  public function sort_posts() {
 
 
 
 
 
 
 
 
 
330
  ?>
331
  <style type="text/css">
332
  #icon-reorder-posts {
341
  </h2>
342
  <div id="reorder-error"></div>
343
  <?php echo $this->initial; ?>
344
+ <ul id="post-list">
345
+ <?php
346
+ if ( is_post_type_hierarchical( $this->post_type ) ) {
347
+ $pages = get_pages( array(
348
+ 'sort_column' => 'menu_order',
349
+ 'post_type' => $this->post_type,
350
+ ) );
351
+ //Get hiearchy of children/parents
352
+ $top_level_pages = array();
353
+ $children_pages = array();
354
+ foreach( $pages as $page ) {
355
+ if ( $page->post_parent == 0 ) {
356
+ //Parent page
357
+ $top_level_pages[] = $page;
358
+ } else {
359
+ $children_pages[ $page->post_parent ][] = $page;
360
+ }
361
+ } //end foreach
362
+
363
+ foreach( $top_level_pages as $page ) {
364
+ $page_id = $page->ID;
365
+ if ( isset( $children_pages[ $page_id ] ) && !empty( $children_pages[ $page_id ] ) ) {
366
+ //If page has children, output page and its children
367
+ $this->output_row_hierarchical( $page, $children_pages[ $page_id ], $children_pages );
368
+ } else {
369
+ $this->output_row( $page );
370
+ }
371
+ }
372
+ } else {
373
+ //Output non hierarchical posts
374
+ $post_query = new WP_Query(
375
+ array(
376
+ 'post_type' => $this->post_type,
377
+ 'posts_per_page' => -1,
378
+ 'orderby' => 'menu_order',
379
+ 'order' => $this->order,
380
+ 'post_status' => $this->post_status,
381
+ )
382
+ );
383
+ $posts = $post_query->get_posts();
384
+ if ( !$posts ) return;
385
+ foreach( $posts as $post ) {
386
+ $this->output_row( $post );
387
+ } //end foreach
388
+ }
389
+ ?>
390
+ </ul>
391
+ <?php
392
+ echo $this->final;
393
+ ?>
394
+ </div><!-- .wrap -->
395
+ <?php
396
+ } //end sort_posts
397
 
398
  }
index.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Metronet Reorder Posts
4
  Plugin URI: http://metronet.no/
5
  Description: Reorder posts
6
- Version: 1.0.3
7
  Author: Ryan Hellyer / Metronet
8
  Author URI: http://metronet.no/
9
 
@@ -49,8 +49,8 @@ require( 'class-reorder.php' );
49
  * @since 1.0
50
  * @author Ryan Hellyer <ryan@metronet.no>
51
  */
52
- define( 'REORDER_DIR', dirname( __FILE__ ) . '/' ); // Plugin folder DIR
53
- define( 'REORDER_URL', WP_PLUGIN_URL . '/' . basename( REORDER_DIR ) . '' ); // Plugin folder URL
54
 
55
  /**
56
  * Instantiate admin panel
@@ -64,15 +64,11 @@ function mn_reorder_posts_init() {
64
  $post_types = get_post_types( '','names' );
65
  foreach ( $post_types as $post_type ) {
66
 
67
- // Don't bother with hierarchical post types
68
- if ( is_post_type_hierarchical( $post_type ) )
69
- continue;
70
-
71
  // Instantiate new reordering
72
  new Reorder(
73
  array(
74
  'post_type' => $post_type,
75
- 'order' => 'DESC',
76
  'heading' => __( 'Metronet reorder posts', 'reorder' ),
77
  'final' => '',
78
  'initial' => '',
3
  Plugin Name: Metronet Reorder Posts
4
  Plugin URI: http://metronet.no/
5
  Description: Reorder posts
6
+ Version: 1.0.4
7
  Author: Ryan Hellyer / Metronet
8
  Author URI: http://metronet.no/
9
 
49
  * @since 1.0
50
  * @author Ryan Hellyer <ryan@metronet.no>
51
  */
52
+ define( 'REORDER_DIR', rtrim( plugin_dir_path(__FILE__), '/' ) ); // Plugin folder DIR
53
+ define( 'REORDER_URL', rtrim( plugin_dir_url(__FILE__), '/' ) ); // Plugin folder URL
54
 
55
  /**
56
  * Instantiate admin panel
64
  $post_types = get_post_types( '','names' );
65
  foreach ( $post_types as $post_type ) {
66
 
 
 
 
 
67
  // Instantiate new reordering
68
  new Reorder(
69
  array(
70
  'post_type' => $post_type,
71
+ 'order' => 'ASC',
72
  'heading' => __( 'Metronet reorder posts', 'reorder' ),
73
  'final' => '',
74
  'initial' => '',
readme.txt CHANGED
@@ -4,7 +4,7 @@ Author URI: http://metronet.no/
4
  Plugin URL: http://metronet.no/
5
  Requires at Least: 3.3
6
  Tags: reorder, posts, wordpress, post-type
7
- Stable tag: 1.0.3
8
 
9
  A simple and easy way to reorder your custom post-type posts in WordPress.
10
 
@@ -35,9 +35,9 @@ There isn't one. The changes are saved automatically .
35
 
36
  If you want to use the plugin on a single post type, then we recommend extracting the "Reorder" class from the plugin and using it directly. We have attempted to make the class as user-friendly and adaptable as possible.
37
 
38
- = Why doesn't it work with pages? =
39
 
40
- Because pages are hierarchical and that makes things a whole lot more complicated. If need this functionality in future, we may add it, but in the mean time the plugin only works with non-hierarchical post-types.
41
 
42
  = Does it work in older versions of WordPress? =
43
 
@@ -49,6 +49,9 @@ Probably, but we only support the latest version of WordPress.
49
 
50
  == Changelog ==
51
 
 
 
 
52
  = 1.0.3 =
53
  * Updated screenshot
54
  * Corrected function prefix
4
  Plugin URL: http://metronet.no/
5
  Requires at Least: 3.3
6
  Tags: reorder, posts, wordpress, post-type
7
+ Stable tag: 1.0.4
8
 
9
  A simple and easy way to reorder your custom post-type posts in WordPress.
10
 
35
 
36
  If you want to use the plugin on a single post type, then we recommend extracting the "Reorder" class from the plugin and using it directly. We have attempted to make the class as user-friendly and adaptable as possible.
37
 
38
+ = Does the plugin work with hierarchical post types? =
39
 
40
+ Yes, but be wary that the plugin now allows you to re-nest hierarchical items easily.
41
 
42
  = Does it work in older versions of WordPress? =
43
 
49
 
50
  == Changelog ==
51
 
52
+ = 1.0.4 =
53
+ * Added support for hierarchical post types
54
+
55
  = 1.0.3 =
56
  * Updated screenshot
57
  * Corrected function prefix
screenshot1.png ADDED
Binary file
scripts/jquery.mjs.nestedSortable.js ADDED
@@ -0,0 +1,426 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * jQuery UI Nested Sortable
3
+ * v 1.3.5 / 21 jun 2012
4
+ * http://mjsarfatti.com/code/nestedSortable
5
+ *
6
+ * Depends on:
7
+ * jquery.ui.sortable.js 1.8+
8
+ *
9
+ * Copyright (c) 2010-2012 Manuele J Sarfatti
10
+ * Licensed under the MIT License
11
+ * http://www.opensource.org/licenses/mit-license.php
12
+ */
13
+
14
+ (function($) {
15
+
16
+ $.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, {
17
+
18
+ options: {
19
+ tabSize: 20,
20
+ disableNesting: 'mjs-nestedSortable-no-nesting',
21
+ errorClass: 'mjs-nestedSortable-error',
22
+ listType: 'ol',
23
+ maxLevels: 0,
24
+ protectRoot: false,
25
+ rootID: null,
26
+ rtl: false,
27
+ isAllowed: function(item, parent) { return true; }
28
+ },
29
+
30
+ _create: function() {
31
+ this.element.data('sortable', this.element.data('nestedSortable'));
32
+
33
+ if (!this.element.is(this.options.listType))
34
+ throw new Error('nestedSortable: Please check the listType option is set to your actual list type');
35
+
36
+ return $.ui.sortable.prototype._create.apply(this, arguments);
37
+ },
38
+
39
+ destroy: function() {
40
+ this.element
41
+ .removeData("nestedSortable")
42
+ .unbind(".nestedSortable");
43
+ return $.ui.sortable.prototype.destroy.apply(this, arguments);
44
+ },
45
+
46
+ _mouseDrag: function(event) {
47
+
48
+ //Compute the helpers position
49
+ this.position = this._generatePosition(event);
50
+ this.positionAbs = this._convertPositionTo("absolute");
51
+
52
+ if (!this.lastPositionAbs) {
53
+ this.lastPositionAbs = this.positionAbs;
54
+ }
55
+
56
+ //Do scrolling
57
+ if(this.options.scroll) {
58
+ var o = this.options, scrolled = false;
59
+ if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
60
+
61
+ if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
62
+ this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
63
+ else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
64
+ this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
65
+
66
+ if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
67
+ this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
68
+ else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
69
+ this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
70
+
71
+ } else {
72
+
73
+ if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
74
+ scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
75
+ else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
76
+ scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
77
+
78
+ if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
79
+ scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
80
+ else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
81
+ scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
82
+
83
+ }
84
+
85
+ if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
86
+ $.ui.ddmanager.prepareOffsets(this, event);
87
+ }
88
+
89
+ //Regenerate the absolute position used for position checks
90
+ this.positionAbs = this._convertPositionTo("absolute");
91
+
92
+ // Find the top offset before rearrangement,
93
+ var previousTopOffset = this.placeholder.offset().top;
94
+
95
+ //Set the helper position
96
+ if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
97
+ if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
98
+
99
+ //Rearrange
100
+ for (var i = this.items.length - 1; i >= 0; i--) {
101
+
102
+ //Cache variables and intersection, continue if no intersection
103
+ var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
104
+ if (!intersection) continue;
105
+
106
+ if(itemElement != this.currentItem[0] //cannot intersect with itself
107
+ && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
108
+ && !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
109
+ && (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
110
+ //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
111
+ ) {
112
+
113
+ $(itemElement).mouseenter();
114
+
115
+ this.direction = intersection == 1 ? "down" : "up";
116
+
117
+ if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
118
+ $(itemElement).mouseleave();
119
+ this._rearrange(event, item);
120
+ } else {
121
+ break;
122
+ }
123
+
124
+ // Clear emtpy ul's/ol's
125
+ this._clearEmpty(itemElement);
126
+
127
+ this._trigger("change", event, this._uiHash());
128
+ break;
129
+ }
130
+ }
131
+
132
+ var parentItem = (this.placeholder[0].parentNode.parentNode &&
133
+ $(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length)
134
+ ? $(this.placeholder[0].parentNode.parentNode)
135
+ : null,
136
+ level = this._getLevel(this.placeholder),
137
+ childLevels = this._getChildLevels(this.helper);
138
+
139
+ // To find the previous sibling in the list, keep backtracking until we hit a valid list item.
140
+ var previousItem = this.placeholder[0].previousSibling ? $(this.placeholder[0].previousSibling) : null;
141
+ if (previousItem != null) {
142
+ while (previousItem[0].nodeName.toLowerCase() != 'li' || previousItem[0] == this.currentItem[0] || previousItem[0] == this.helper[0]) {
143
+ if (previousItem[0].previousSibling) {
144
+ previousItem = $(previousItem[0].previousSibling);
145
+ } else {
146
+ previousItem = null;
147
+ break;
148
+ }
149
+ }
150
+ }
151
+
152
+ // To find the next sibling in the list, keep stepping forward until we hit a valid list item.
153
+ var nextItem = this.placeholder[0].nextSibling ? $(this.placeholder[0].nextSibling) : null;
154
+ if (nextItem != null) {
155
+ while (nextItem[0].nodeName.toLowerCase() != 'li' || nextItem[0] == this.currentItem[0] || nextItem[0] == this.helper[0]) {
156
+ if (nextItem[0].nextSibling) {
157
+ nextItem = $(nextItem[0].nextSibling);
158
+ } else {
159
+ nextItem = null;
160
+ break;
161
+ }
162
+ }
163
+ }
164
+
165
+ var newList = document.createElement(o.listType);
166
+
167
+ this.beyondMaxLevels = 0;
168
+
169
+ // If the item is moved to the left, send it to its parent's level unless there are siblings below it.
170
+ if (parentItem != null && nextItem == null &&
171
+ (o.rtl && (this.positionAbs.left + this.helper.outerWidth() > parentItem.offset().left + parentItem.outerWidth()) ||
172
+ !o.rtl && (this.positionAbs.left < parentItem.offset().left))) {
173
+ parentItem.after(this.placeholder[0]);
174
+ this._clearEmpty(parentItem[0]);
175
+ this._trigger("change", event, this._uiHash());
176
+ }
177
+ // If the item is below a sibling and is moved to the right, make it a child of that sibling.
178
+ else if (previousItem != null &&
179
+ (o.rtl && (this.positionAbs.left + this.helper.outerWidth() < previousItem.offset().left + previousItem.outerWidth() - o.tabSize) ||
180
+ !o.rtl && (this.positionAbs.left > previousItem.offset().left + o.tabSize))) {
181
+ this._isAllowed(previousItem, level, level+childLevels+1);
182
+ if (!previousItem.children(o.listType).length) {
183
+ previousItem[0].appendChild(newList);
184
+ }
185
+ // If this item is being moved from the top, add it to the top of the list.
186
+ if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) {
187
+ previousItem.children(o.listType).prepend(this.placeholder);
188
+ }
189
+ // Otherwise, add it to the bottom of the list.
190
+ else {
191
+ previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
192
+ }
193
+ this._trigger("change", event, this._uiHash());
194
+ }
195
+ else {
196
+ this._isAllowed(parentItem, level, level+childLevels);
197
+ }
198
+
199
+ //Post events to containers
200
+ this._contactContainers(event);
201
+
202
+ //Interconnect with droppables
203
+ if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
204
+
205
+ //Call callbacks
206
+ this._trigger('sort', event, this._uiHash());
207
+
208
+ this.lastPositionAbs = this.positionAbs;
209
+ return false;
210
+
211
+ },
212
+
213
+ _mouseStop: function(event, noPropagation) {
214
+
215
+ // If the item is in a position not allowed, send it back
216
+ if (this.beyondMaxLevels) {
217
+
218
+ this.placeholder.removeClass(this.options.errorClass);
219
+
220
+ if (this.domPosition.prev) {
221
+ $(this.domPosition.prev).after(this.placeholder);
222
+ } else {
223
+ $(this.domPosition.parent).prepend(this.placeholder);
224
+ }
225
+
226
+ this._trigger("revert", event, this._uiHash());
227
+
228
+ }
229
+
230
+ // Clean last empty ul/ol
231
+ for (var i = this.items.length - 1; i >= 0; i--) {
232
+ var item = this.items[i].item[0];
233
+ this._clearEmpty(item);
234
+ }
235
+
236
+ $.ui.sortable.prototype._mouseStop.apply(this, arguments);
237
+
238
+ },
239
+
240
+ serialize: function(options) {
241
+
242
+ var o = $.extend({}, this.options, options),
243
+ items = this._getItemsAsjQuery(o && o.connected),
244
+ str = [];
245
+
246
+ $(items).each(function() {
247
+ var res = ($(o.item || this).attr(o.attribute || 'id') || '')
248
+ .match(o.expression || (/(.+)[-=_](.+)/)),
249
+ pid = ($(o.item || this).parent(o.listType)
250
+ .parent(o.items)
251
+ .attr(o.attribute || 'id') || '')
252
+ .match(o.expression || (/(.+)[-=_](.+)/));
253
+
254
+ if (res) {
255
+ str.push(((o.key || res[1]) + '[' + (o.key && o.expression ? res[1] : res[2]) + ']')
256
+ + '='
257
+ + (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID));
258
+ }
259
+ });
260
+
261
+ if(!str.length && o.key) {
262
+ str.push(o.key + '=');
263
+ }
264
+
265
+ return str.join('&');
266
+
267
+ },
268
+
269
+ toHierarchy: function(options) {
270
+
271
+ var o = $.extend({}, this.options, options),
272
+ sDepth = o.startDepthCount || 0,
273
+ ret = [];
274
+
275
+ $(this.element).children(o.items).each(function () {
276
+ var level = _recursiveItems(this);
277
+ ret.push(level);
278
+ });
279
+
280
+ return ret;
281
+
282
+ function _recursiveItems(item) {
283
+ var id = ($(item).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
284
+ if (id) {
285
+ var currentItem = {"id" : id[2]};
286
+ if ($(item).children(o.listType).children(o.items).length > 0) {
287
+ currentItem.children = [];
288
+ $(item).children(o.listType).children(o.items).each(function() {
289
+ var level = _recursiveItems(this);
290
+ currentItem.children.push(level);
291
+ });
292
+ }
293
+ return currentItem;
294
+ }
295
+ }
296
+ },
297
+
298
+ toArray: function(options) {
299
+
300
+ var o = $.extend({}, this.options, options),
301
+ sDepth = o.startDepthCount || 0,
302
+ ret = [],
303
+ left = 2;
304
+
305
+ ret.push({
306
+ "item_id": o.rootID,
307
+ "parent_id": 'none',
308
+ "depth": sDepth,
309
+ "left": '1',
310
+ "right": ($(o.items, this.element).length + 1) * 2
311
+ });
312
+
313
+ $(this.element).children(o.items).each(function () {
314
+ left = _recursiveArray(this, sDepth + 1, left);
315
+ });
316
+
317
+ ret = ret.sort(function(a,b){ return (a.left - b.left); });
318
+
319
+ return ret;
320
+
321
+ function _recursiveArray(item, depth, left) {
322
+
323
+ var right = left + 1,
324
+ id,
325
+ pid;
326
+
327
+ if ($(item).children(o.listType).children(o.items).length > 0) {
328
+ depth ++;
329
+ $(item).children(o.listType).children(o.items).each(function () {
330
+ right = _recursiveArray($(this), depth, right);
331
+ });
332
+ depth --;
333
+ }
334
+
335
+ id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));
336
+
337
+ if (depth === sDepth + 1) {
338
+ pid = o.rootID;
339
+ } else {
340
+ var parentItem = ($(item).parent(o.listType)
341
+ .parent(o.items)
342
+ .attr(o.attribute || 'id'))
343
+ .match(o.expression || (/(.+)[-=_](.+)/));
344
+ pid = parentItem[2];
345
+ }
346
+
347
+ if (id) {
348
+ ret.push({"item_id": id[2], "parent_id": pid, "depth": depth, "left": left, "right": right});
349
+ }
350
+
351
+ left = right + 1;
352
+ return left;
353
+ }
354
+
355
+ },
356
+
357
+ _clearEmpty: function(item) {
358
+
359
+ var emptyList = $(item).children(this.options.listType);
360
+ if (emptyList.length && !emptyList.children().length) {
361
+ emptyList.remove();
362
+ }
363
+
364
+ },
365
+
366
+ _getLevel: function(item) {
367
+
368
+ var level = 1;
369
+
370
+ if (this.options.listType) {
371
+ var list = item.closest(this.options.listType);
372
+ while (list && list.length > 0 &&
373
+ !list.is('.ui-sortable')) {
374
+ level++;
375
+ list = list.parent().closest(this.options.listType);
376
+ }
377
+ }
378
+
379
+ return level;
380
+ },
381
+
382
+ _getChildLevels: function(parent, depth) {
383
+ var self = this,
384
+ o = this.options,
385
+ result = 0;
386
+ depth = depth || 0;
387
+
388
+ $(parent).children(o.listType).children(o.items).each(function (index, child) {
389
+ result = Math.max(self._getChildLevels(child, depth + 1), result);
390
+ });
391
+
392
+ return depth ? result + 1 : result;
393
+ },
394
+
395
+ _isAllowed: function(parentItem, level, levels) {
396
+ var o = this.options,
397
+ isRoot = $(this.domPosition.parent).hasClass('ui-sortable') ? true : false,
398
+ maxLevels = this.placeholder.closest('.ui-sortable').nestedSortable('option', 'maxLevels'); // this takes into account the maxLevels set to the recipient list
399
+
400
+ // Is the root protected?
401
+ // Are we trying to nest under a no-nest?
402
+ // Are we nesting too deep?
403
+ if (!o.isAllowed(parentItem, this.placeholder) ||
404
+ parentItem && parentItem.hasClass(o.disableNesting) ||
405
+ o.protectRoot && (parentItem == null && !isRoot || isRoot && level > 1)) {
406
+ this.placeholder.addClass(o.errorClass);
407
+ if (maxLevels < levels && maxLevels != 0) {
408
+ this.beyondMaxLevels = levels - maxLevels;
409
+ } else {
410
+ this.beyondMaxLevels = 1;
411
+ }
412
+ } else {
413
+ if (maxLevels < levels && maxLevels != 0) {
414
+ this.placeholder.addClass(o.errorClass);
415
+ this.beyondMaxLevels = levels - maxLevels;
416
+ } else {
417
+ this.placeholder.removeClass(o.errorClass);
418
+ this.beyondMaxLevels = 0;
419
+ }
420
+ }
421
+ }
422
+
423
+ }));
424
+
425
+ $.mjs.nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.mjs.nestedSortable.prototype.options);
426
+ })(jQuery);
scripts/sort.js CHANGED
@@ -1,5 +1,32 @@
1
- jQuery(document).ready(function($) {
 
2
  var postList = $('#post-list');
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
  postList.sortable({
5
  update: function(event, ui) {
@@ -14,9 +41,11 @@ jQuery(document).ready(function($) {
14
  data:{
15
  action: 'post_sort', // Tell WordPress how to handle this ajax request
16
  order: postList.sortable('toArray').toString(), // Passes ID's of list items in 1,3,2 format
17
- nonce: sortnonce,
18
  },
19
  success: function(response) {
 
 
20
  $('#loading-animation').hide(); // Hide the loading animation
21
  $('#reorder-error').html('There was an error worked'); // Error message
22
  $('#reorder-error').html(response); // Error message
@@ -33,4 +62,5 @@ jQuery(document).ready(function($) {
33
  $.ajax(opts);
34
  }
35
  });
 
36
  });
1
+ jQuery(document).ready(function($) {
2
+ //Variable sortnonce is declared globally
3
  var postList = $('#post-list');
4
+
5
+ var blah = postList.nestedSortable( {
6
+ forcePlaceholderSize: true,
7
+ handle: 'div',
8
+ helper: 'clone',
9
+ items: 'li',
10
+ maxLevels: 6,
11
+ opacity: .6,
12
+ placeholder: 'placeholder',
13
+ revert: 250,
14
+ tabSize: 25,
15
+ tolerance: 'pointer',
16
+ toleranceElement: '> div',
17
+ listType: 'ul',
18
+ update: function( event, ui ) {
19
+ var order = $('ul#post-list').nestedSortable( 'toHierarchy',{ listType: 'ul'});
20
+ order = JSON.stringify( order , null, 2);
21
+ //console.log( order );
22
+ //return;
23
+ $.post( ajaxurl, { action: 'post_sort', nonce: sortnonce, data: order }, function( response ) {
24
+ }, 'json' );
25
+
26
+ }
27
+ });
28
+
29
+ /*
30
 
31
  postList.sortable({
32
  update: function(event, ui) {
41
  data:{
42
  action: 'post_sort', // Tell WordPress how to handle this ajax request
43
  order: postList.sortable('toArray').toString(), // Passes ID's of list items in 1,3,2 format
44
+ nonce: sortnonce,
45
  },
46
  success: function(response) {
47
+ console.log( response );
48
+ return;
49
  $('#loading-animation').hide(); // Hide the loading animation
50
  $('#reorder-error').html('There was an error worked'); // Error message
51
  $('#reorder-error').html(response); // Error message
62
  $.ajax(opts);
63
  }
64
  });
65
+ */
66
  });