Reorder Posts - Version 2.4.0

Version Description

  • Released 2016-08-14
  • Major CSS overhaul inspired by the Nested Pages plugin
  • The sorting is now mobile friendly
Download this release

Release Info

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

Code changes from version 2.3.0 to 2.4.0

class-reorder.php CHANGED
@@ -321,7 +321,7 @@ final class MN_Reorder {
321
  * @global string $pagenow Used internally by WordPress to designate what the current page is in the admin panel
322
  */
323
  public function print_styles() {
324
- wp_enqueue_style( 'reorderpages_style', REORDER_URL . '/css/admin.css', array(), '20151204' );
325
  }
326
 
327
  /**
@@ -333,8 +333,10 @@ final class MN_Reorder {
333
  * @global string $pagenow Used internally by WordPress to designate what the current page is in the admin panel
334
  */
335
  public function print_scripts() {
336
- wp_register_script( 'reorder_nested', REORDER_URL . '/scripts/jquery.mjs.nestedSortable.js', array( 'jquery-ui-sortable' ), '1.3.5', true );
337
- wp_enqueue_script( 'reorder_posts', REORDER_URL . '/scripts/sort.js', array( 'reorder_nested' ), '20151101', true );
 
 
338
  wp_localize_script( 'reorder_posts', 'reorder_posts', array(
339
  'action' => 'post_sort',
340
  'expand' => esc_js( __( 'Expand', 'metronet-reorder-posts' ) ),
@@ -506,11 +508,33 @@ final class MN_Reorder {
506
  //Output parent title
507
  if( $children->have_posts() ) {
508
  ?>
509
- <div><?php the_title(); ?><?php echo ( defined( 'REORDER_DEBUG' ) && REORDER_DEBUG == true ) ? ' - Menu Order:' . absint( $post->menu_order ) : ''; ?><a href='#' style="float: right"><?php esc_html_e( 'Expand', 'metronet-reorder-posts' ); ?></a></div>
 
 
 
 
 
 
 
510
  <?php
511
  } else {
512
  ?>
513
- <div><?php the_title(); ?><?php echo ( defined( 'REORDER_DEBUG' ) && REORDER_DEBUG == true ) ? ' - Menu Order:' . absint( $post->menu_order ) : ''; ?></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
514
  <?php
515
  }
516
 
321
  * @global string $pagenow Used internally by WordPress to designate what the current page is in the admin panel
322
  */
323
  public function print_styles() {
324
+ wp_enqueue_style( 'reorderpages_style', REORDER_URL . '/css/admin.css', array(), '20160813' );
325
  }
326
 
327
  /**
333
  * @global string $pagenow Used internally by WordPress to designate what the current page is in the admin panel
334
  */
335
  public function print_scripts() {
336
+ wp_enqueue_script( 'jquery-ui-touch-punch', REORDER_URL . '/scripts/jquery.ui.touch-punch.js', array( 'jquery-ui-sortable' ), '0.2.3', true );
337
+ wp_register_script( 'reorder_nested', REORDER_URL . '/scripts/jquery.mjs.nestedSortable.js', array( 'jquery-ui-touch-punch' ), '2.0.0', true );
338
+
339
+ wp_enqueue_script( 'reorder_posts', REORDER_URL . '/scripts/sort.js', array( 'reorder_nested' ), '20160813', true );
340
  wp_localize_script( 'reorder_posts', 'reorder_posts', array(
341
  'action' => 'post_sort',
342
  'expand' => esc_js( __( 'Expand', 'metronet-reorder-posts' ) ),
508
  //Output parent title
509
  if( $children->have_posts() ) {
510
  ?>
511
+ <div class="row">
512
+ <div class="expand row-action">
513
+ <span class="dashicons dashicons-arrow-right"></span>
514
+ </div><!-- .row-action -->
515
+ <div class="row-content">
516
+ <?php the_title(); ?><?php echo ( defined( 'REORDER_DEBUG' ) && REORDER_DEBUG == true ) ? ' - Menu Order:' . absint( $post->menu_order ) : ''; ?>
517
+ </div><!-- .row-content -->
518
+ </div><!-- .row -->
519
  <?php
520
  } else {
521
  ?>
522
+ <div class="row">
523
+ <?php
524
+ $is_hierarchical = true;
525
+ if( is_post_type_hierarchical( $post->post_type ) ) {
526
+ ?>
527
+ <div class="row-action">
528
+ </div><!-- .row-action -->
529
+ <?php
530
+ } else {
531
+ $is_hierarchical = false;
532
+ }
533
+ ?>
534
+ <div class="row-content <?php echo $is_hierarchical ? '' : 'non-hierarchical'; ?>">
535
+ <?php the_title(); ?><?php echo ( defined( 'REORDER_DEBUG' ) && REORDER_DEBUG == true ) ? ' - Menu Order:' . absint( $post->menu_order ) : ''; ?>
536
+ </div><!-- .row-content -->
537
+ </div><!-- .row -->
538
  <?php
539
  }
540
 
css/admin.css CHANGED
@@ -1,40 +1,67 @@
1
  #post-list {
2
  margin-top: 20px;
 
3
  }
4
  #post-list div {
5
- padding: 10px;
6
- width: 50%;
7
- font-weight: bold;
8
- background: #f0f0f0; /* for non-css3 browsers */
9
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#e7e7e7'); /* for IE 9 or older */
10
- background: -webkit-gradient(linear, left top, left bottom, from(#f7f7f7), to(#e7e7e7)); /* for WebKit */
11
- background: -webkit-linear-gradient(top, #f7f7f7, #e7e7e7); /* for newer versions of WebKit */
12
- background: -moz-linear-gradient(top, #f7f7f7, #e7e7e7); /* for Firefox 3.6+ */
13
- background: -o-linear-gradient(top, #f7f7f7, #e7e7e7); /* for Opera 11.1+ */
14
- background: -ms-linear-gradient(top, #f7f7f7, #e7e7e7); /* for IE 10+ */
15
- cursor: move;
16
- border: 1px solid #ddd;
17
- border-raidus: 5px;
18
- -moz-border-radius: 5px;
19
- -webkit-border-radius: 5px;
20
  }
21
  #post-list div:hover {
22
- background: #f0f0f0; /* for non-css3 browsers */
23
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#f7f7f7', endColorstr='#d8d8d8'); /* for IE 9 or older */
24
- background: -webkit-gradient(linear, left top, left bottom, from(#f7f7f7), to(#d8d8d8)); /* for WebKit */
25
- background: -webkit-linear-gradient(top, #f7f7f7, #d8d8d8); /* for newer versions of WebKit */
26
- background: -moz-linear-gradient(top, #f7f7f7, #d8d8d8); /* for Firefox 3.6+ */
27
- background: -o-linear-gradient(top, #f7f7f7, #d8d8d8); /* for Opera 11.1+ */
28
- background: -ms-linear-gradient(top, #f7f7f7, #d8d8d8); /* for IE 10+ */
 
 
 
 
29
  }
30
- #post-list ul {
31
- padding-left: 40px;
 
 
 
32
  }
33
  #post-list div img {
34
  vertical-align: middle;
35
  margin: 0 12px 0 0;
36
  border: 2px solid #ddd;
37
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  .ui-sortable-placeholder {
39
  border-radius: 0 !important;
40
  background: transparent !important;
@@ -48,4 +75,18 @@
48
  }
49
  #post-list .children {
50
  display: none;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  }
1
  #post-list {
2
  margin-top: 20px;
3
+ border: 1px solid #e5e5e5;
4
  }
5
  #post-list div {
6
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  }
8
  #post-list div:hover {
9
+
10
+ }
11
+ #post-list .non-hierarchical {
12
+ padding-left: 20px;
13
+ }
14
+ #post-list li {
15
+ background: #FFF;
16
+ margin-bottom: 0;
17
+ border-top: 1px solid #e1e1e1;
18
+ clear: both;
19
+ overflow: hidden;
20
  }
21
+ #post-list > li:first-child {
22
+ border-top: 0;
23
+ }
24
+ #post-list > li:last-child {
25
+ border-bottom: 1px solid #e1e1e1;
26
  }
27
  #post-list div img {
28
  vertical-align: middle;
29
  margin: 0 12px 0 0;
30
  border: 2px solid #ddd;
31
  }
32
+ .row-action {
33
+ float: left;
34
+ margin: 0px 10px 0 0;
35
+ width: 40px;
36
+ height: 40px;
37
+ background-color: #f0f0f0;
38
+ text-align: center;
39
+ }
40
+ .expand.row-action span,
41
+ .collapse.row-action span {
42
+ display: inline-block;
43
+ width: 26px;
44
+ height: 26px;
45
+ background: #FFF;
46
+ -webkit-border-radius: 50%;
47
+ border-radius: 50%;
48
+ border: 1px solid #e1e1e1;
49
+ font-size: 24px;
50
+ margin-top: 7px;
51
+ cursor: pointer;
52
+ }
53
+ .expand.row-action span:hover,
54
+ .collapse.row-action span:hover {
55
+ border-color: #c0c0c0;
56
+ }
57
+ .row-content {
58
+ padding: 10px 0;
59
+ font-weight: 700;
60
+ cursor: move;
61
+ }
62
+ .row-content:hover {
63
+ background: #FBFBFB;
64
+ }
65
  .ui-sortable-placeholder {
66
  border-radius: 0 !important;
67
  background: transparent !important;
75
  }
76
  #post-list .children {
77
  display: none;
78
+ }
79
+ .page-numbers {
80
+ display: inline-block;
81
+ padding: 5px 10px;
82
+ margin: 0 2px 0 0;
83
+ border: 1px solid #eee;
84
+ line-height: 1;
85
+ text-decoration: none;
86
+ border-radius: 2px;
87
+ font-weight: 600;
88
+ }
89
+ .page-numbers.current,
90
+ a.page-numbers:hover {
91
+ background: #e1e1e1;
92
  }
index.php CHANGED
@@ -3,7 +3,7 @@
3
  Plugin Name: Reorder Posts
4
  Plugin URI: https://wordpress.org/plugins/metronet-reorder-posts/
5
  Description: Easily reorder posts and pages in WordPress
6
- Version: 2.3.0
7
  Author: Ryan Hellyer, Ronald Huereca, Scott Basgaard
8
  Author URI: https://github.com/ronalfy/reorder-posts
9
  Text Domain: metronet-reorder-posts
3
  Plugin Name: Reorder Posts
4
  Plugin URI: https://wordpress.org/plugins/metronet-reorder-posts/
5
  Description: Easily reorder posts and pages in WordPress
6
+ Version: 2.4.0
7
  Author: Ryan Hellyer, Ronald Huereca, Scott Basgaard
8
  Author URI: https://github.com/ronalfy/reorder-posts
9
  Text Domain: metronet-reorder-posts
readme.txt CHANGED
@@ -3,9 +3,9 @@ Contributors: ryanhellyer, ronalfy, scottbasgaard
3
  Author URI: https://github.com/ronalfy/reorder-posts
4
  Plugin URL: https://wordpress.org/plugins/metronet-reorder-posts/
5
  Requires at Least: 3.7
6
- Tested up to: 4.6
7
  Tags: reorder, re-order, posts, wordpress, post-type, ajax, admin, hierarchical, menu_order, ordering
8
- Stable tag: 2.3.0
9
  License: GPLv3 or later
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
@@ -17,6 +17,8 @@ A simple and easy way to reorder your custom post-type posts in WordPress. Adds
17
 
18
  We consider Reorder Posts a <strong>developer tool</strong>. If you do not know what `menu_order` or custom queries are, then this plugin is likely not for you.
19
 
 
 
20
  <h3>Features</h3>
21
  <ul>
22
  <li>Adds "Reorder" sub-menu to all post types by default</li>
@@ -27,7 +29,11 @@ We consider Reorder Posts a <strong>developer tool</strong>. If you do not know
27
  <li>Advanced settings panel for overriding the menu order of custom post type queries</li>
28
  </ul>
29
 
30
-
 
 
 
 
31
 
32
  <h3>Spread the Word</h3>
33
  If you like this plugin, please help spread the word. Rate the plugin. Write about the plugin. Something :)
@@ -120,6 +126,10 @@ No, but there is an add-on for this plugin called <a href="https://wordpress.org
120
  2. Admin panel settings
121
 
122
  == Changelog ==
 
 
 
 
123
 
124
  = 2.3.0 =
125
  * Released 2016-08-12
@@ -221,29 +231,8 @@ No, but there is an add-on for this plugin called <a href="https://wordpress.org
221
 
222
  == Upgrade Notice ==
223
 
 
 
 
224
  = 2.3.0 =
225
  Added screen options to set the number of posts displayed
226
-
227
- = 2.2.2 =
228
- Fixing loading animation CSS issue
229
-
230
- = 2.2.1 =
231
- Fixing pagination issue.
232
-
233
- = 2.2.0 =
234
- Adding loading animation in better context
235
-
236
- = 2.1.5 =
237
- Fixing paging offset error in the backend.
238
-
239
- = 2.1.4 =
240
- Added cache-busting when re-ordering
241
-
242
- = 2.1.2 =
243
- Removed developer notice from Reorder pages
244
-
245
- = 2.1.1 =
246
- Fixed pagination issue. Improved Reorder save query performance significantly
247
-
248
- = 2.1.0 =
249
- Some capability fixes, pagination for post types with a lot of posts, improved query performance, and add-on capability.
3
  Author URI: https://github.com/ronalfy/reorder-posts
4
  Plugin URL: https://wordpress.org/plugins/metronet-reorder-posts/
5
  Requires at Least: 3.7
6
+ Tested up to: 4.9
7
  Tags: reorder, re-order, posts, wordpress, post-type, ajax, admin, hierarchical, menu_order, ordering
8
+ Stable tag: 2.4.0
9
  License: GPLv3 or later
10
  License URI: http://www.gnu.org/licenses/gpl-3.0.html
11
 
17
 
18
  We consider Reorder Posts a <strong>developer tool</strong>. If you do not know what `menu_order` or custom queries are, then this plugin is likely not for you.
19
 
20
+ [youtube https://www.youtube.com/watch?v=qDa6Q6mDPbo]
21
+
22
  <h3>Features</h3>
23
  <ul>
24
  <li>Adds "Reorder" sub-menu to all post types by default</li>
29
  <li>Advanced settings panel for overriding the menu order of custom post type queries</li>
30
  </ul>
31
 
32
+ <h3>Add-ons</h3>
33
+ <ul>
34
+ <li><a href="https://wordpress.org/plugins/reorder-by-term/">Reorder by Term</a></li>
35
+ <li><a href="https://wordpress.org/plugins/reorder-terms/">Reorder Terms</a></li>
36
+ </ul>
37
 
38
  <h3>Spread the Word</h3>
39
  If you like this plugin, please help spread the word. Rate the plugin. Write about the plugin. Something :)
126
  2. Admin panel settings
127
 
128
  == Changelog ==
129
+ = 2.4.0 =
130
+ * Released 2016-08-14
131
+ * Major CSS overhaul inspired by the Nested Pages plugin
132
+ * The sorting is now mobile friendly
133
 
134
  = 2.3.0 =
135
  * Released 2016-08-12
231
 
232
  == Upgrade Notice ==
233
 
234
+ = 2.4.0 =
235
+ Major CSS overhaul inspired by the Nested Pages plugin and the plugin is now mobile friendly.
236
+
237
  = 2.3.0 =
238
  Added screen options to set the number of posts displayed
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
scripts/jquery.mjs.nestedSortable.js CHANGED
@@ -1,49 +1,139 @@
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);
@@ -54,69 +144,257 @@
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
  }
@@ -129,17 +407,24 @@
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 {
@@ -149,70 +434,131 @@
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);
@@ -227,13 +573,87 @@
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
 
@@ -241,38 +661,42 @@
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
  });
@@ -280,9 +704,21 @@
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() {
@@ -299,78 +735,112 @@
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
  }
@@ -381,12 +851,12 @@
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;
@@ -394,23 +864,33 @@
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 {
@@ -422,5 +902,9 @@
422
 
423
  }));
424
 
425
- $.mjs.nestedSortable.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.mjs.nestedSortable.prototype.options);
426
- })(jQuery);
 
 
 
 
1
  /*
2
  * jQuery UI Nested Sortable
3
+ * v 2.0.0 / 2016-03-30 "Not April Fools"
4
+ * https://github.com/ilikenwf/nestedSortable
5
  *
6
  * Depends on:
7
+ * jquery.ui.sortable.js 1.10+
8
  *
9
+ * Copyright (c) 2010-2016 Manuele J Sarfatti and contributors
10
  * Licensed under the MIT License
11
  * http://www.opensource.org/licenses/mit-license.php
12
  */
13
+ (function( factory ) {
14
+ "use strict";
15
 
16
+ if ( typeof define === "function" && define.amd ) {
17
+
18
+ // AMD. Register as an anonymous module.
19
+ define([
20
+ "jquery",
21
+ "jquery-ui/sortable"
22
+ ], factory );
23
+ } else {
24
+
25
+ // Browser globals
26
+ factory( window.jQuery );
27
+ }
28
+ }(function($) {
29
+ "use strict";
30
+
31
+ function isOverAxis( x, reference, size ) {
32
+ return ( x > reference ) && ( x < ( reference + size ) );
33
+ }
34
 
35
  $.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, {
36
 
37
  options: {
38
+ disableParentChange: false,
39
+ doNotClear: false,
40
+ expandOnHover: 700,
41
+ isAllowed: function() { return true; },
42
+ isTree: false,
43
+ listType: "ol",
44
  maxLevels: 0,
45
  protectRoot: false,
46
  rootID: null,
47
  rtl: false,
48
+ startCollapsed: false,
49
+ tabSize: 20,
50
+
51
+ branchClass: "mjs-nestedSortable-branch",
52
+ collapsedClass: "mjs-nestedSortable-collapsed",
53
+ disableNestingClass: "mjs-nestedSortable-no-nesting",
54
+ errorClass: "mjs-nestedSortable-error",
55
+ expandedClass: "mjs-nestedSortable-expanded",
56
+ hoveringClass: "mjs-nestedSortable-hovering",
57
+ leafClass: "mjs-nestedSortable-leaf",
58
+ disabledClass: "mjs-nestedSortable-disabled"
59
  },
60
 
61
  _create: function() {
62
+ var self = this,
63
+ err;
64
 
65
+ this.element.data("ui-sortable", this.element.data("mjs-nestedSortable"));
 
66
 
67
+ // mjs - prevent browser from freezing if the HTML is not correct
68
+ if (!this.element.is(this.options.listType)) {
69
+ err = "nestedSortable: " +
70
+ "Please check that the listType option is set to your actual list type";
71
+
72
+ throw new Error(err);
73
+ }
74
+
75
+ // if we have a tree with expanding/collapsing functionality,
76
+ // force 'intersect' tolerance method
77
+ if (this.options.isTree && this.options.expandOnHover) {
78
+ this.options.tolerance = "intersect";
79
+ }
80
+
81
+ $.ui.sortable.prototype._create.apply(this, arguments);
82
+
83
+ // prepare the tree by applying the right classes
84
+ // (the CSS is responsible for actual hide/show functionality)
85
+ if (this.options.isTree) {
86
+ $(this.items).each(function() {
87
+ var $li = this.item,
88
+ hasCollapsedClass = $li.hasClass(self.options.collapsedClass),
89
+ hasExpandedClass = $li.hasClass(self.options.expandedClass);
90
+
91
+ if ($li.children(self.options.listType).length) {
92
+ $li.addClass(self.options.branchClass);
93
+ // expand/collapse class only if they have children
94
+
95
+ if ( !hasCollapsedClass && !hasExpandedClass ) {
96
+ if (self.options.startCollapsed) {
97
+ $li.addClass(self.options.collapsedClass);
98
+ } else {
99
+ $li.addClass(self.options.expandedClass);
100
+ }
101
+ }
102
+ } else {
103
+ $li.addClass(self.options.leafClass);
104
+ }
105
+ });
106
+ }
107
  },
108
 
109
+ _destroy: function() {
110
  this.element
111
+ .removeData("mjs-nestedSortable")
112
+ .removeData("ui-sortable");
113
+ return $.ui.sortable.prototype._destroy.apply(this, arguments);
114
  },
115
 
116
  _mouseDrag: function(event) {
117
+ var i,
118
+ item,
119
+ itemElement,
120
+ intersection,
121
+ self = this,
122
+ o = this.options,
123
+ scrolled = false,
124
+ $document = $(document),
125
+ previousTopOffset,
126
+ parentItem,
127
+ level,
128
+ childLevels,
129
+ itemAfter,
130
+ itemBefore,
131
+ newList,
132
+ method,
133
+ a,
134
+ previousItem,
135
+ nextItem,
136
+ helperIsNotSibling;
137
 
138
  //Compute the helpers position
139
  this.position = this._generatePosition(event);
144
  }
145
 
146
  //Do scrolling
147
+ if (this.options.scroll) {
148
+ if (this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
149
+
150
+ if (
151
+ (
152
+ this.overflowOffset.top +
153
+ this.scrollParent[0].offsetHeight
154
+ ) -
155
+ event.pageY <
156
+ o.scrollSensitivity
157
+ ) {
158
+ scrolled = this.scrollParent.scrollTop() + o.scrollSpeed;
159
+ this.scrollParent.scrollTop(scrolled);
160
+ } else if (
161
+ event.pageY -
162
+ this.overflowOffset.top <
163
+ o.scrollSensitivity
164
+ ) {
165
+ scrolled = this.scrollParent.scrollTop() - o.scrollSpeed;
166
+ this.scrollParent.scrollTop(scrolled);
167
+ }
168
 
169
+ if (
170
+ (
171
+ this.overflowOffset.left +
172
+ this.scrollParent[0].offsetWidth
173
+ ) -
174
+ event.pageX <
175
+ o.scrollSensitivity
176
+ ) {
177
+ scrolled = this.scrollParent.scrollLeft() + o.scrollSpeed;
178
+ this.scrollParent.scrollLeft(scrolled);
179
+ } else if (
180
+ event.pageX -
181
+ this.overflowOffset.left <
182
+ o.scrollSensitivity
183
+ ) {
184
+ scrolled = this.scrollParent.scrollLeft() - o.scrollSpeed;
185
+ this.scrollParent.scrollLeft(scrolled);
186
+ }
187
 
188
  } else {
189
 
190
+ if (
191
+ event.pageY -
192
+ $document.scrollTop() <
193
+ o.scrollSensitivity
194
+ ) {
195
+ scrolled = $document.scrollTop() - o.scrollSpeed;
196
+ $document.scrollTop(scrolled);
197
+ } else if (
198
+ $(window).height() -
199
+ (
200
+ event.pageY -
201
+ $document.scrollTop()
202
+ ) <
203
+ o.scrollSensitivity
204
+ ) {
205
+ scrolled = $document.scrollTop() + o.scrollSpeed;
206
+ $document.scrollTop(scrolled);
207
+ }
208
 
209
+ if (
210
+ event.pageX -
211
+ $document.scrollLeft() <
212
+ o.scrollSensitivity
213
+ ) {
214
+ scrolled = $document.scrollLeft() - o.scrollSpeed;
215
+ $document.scrollLeft(scrolled);
216
+ } else if (
217
+ $(window).width() -
218
+ (
219
+ event.pageX -
220
+ $document.scrollLeft()
221
+ ) <
222
+ o.scrollSensitivity
223
+ ) {
224
+ scrolled = $document.scrollLeft() + o.scrollSpeed;
225
+ $document.scrollLeft(scrolled);
226
+ }
227
 
228
  }
229
 
230
+ if (scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
231
  $.ui.ddmanager.prepareOffsets(this, event);
232
+ }
233
  }
234
 
235
  //Regenerate the absolute position used for position checks
236
  this.positionAbs = this._convertPositionTo("absolute");
237
 
238
+ // mjs - find the top offset before rearrangement,
239
+ previousTopOffset = this.placeholder.offset().top;
240
 
241
  //Set the helper position
242
+ if (!this.options.axis || this.options.axis !== "y") {
243
+ this.helper[0].style.left = this.position.left + "px";
244
+ }
245
+ if (!this.options.axis || this.options.axis !== "x") {
246
+ this.helper[0].style.top = (this.position.top) + "px";
247
+ }
248
+
249
+ // mjs - check and reset hovering state at each cycle
250
+ this.hovering = this.hovering ? this.hovering : null;
251
+ this.mouseentered = this.mouseentered ? this.mouseentered : false;
252
+
253
+ // mjs - let's start caching some variables
254
+ (function() {
255
+ var _parentItem = this.placeholder.parent().parent();
256
+ if (_parentItem && _parentItem.closest(".ui-sortable").length) {
257
+ parentItem = _parentItem;
258
+ }
259
+ }.call(this));
260
+
261
+ level = this._getLevel(this.placeholder);
262
+ childLevels = this._getChildLevels(this.helper);
263
+ newList = document.createElement(o.listType);
264
 
265
  //Rearrange
266
+ for (i = this.items.length - 1; i >= 0; i--) {
267
 
268
  //Cache variables and intersection, continue if no intersection
269
+ item = this.items[i];
270
+ itemElement = item.item[0];
271
+ intersection = this._intersectsWithPointer(item);
272
+ if (!intersection) {
273
+ continue;
274
+ }
275
+
276
+ // Only put the placeholder inside the current Container, skip all
277
+ // items form other containers. This works because when moving
278
+ // an item from one container to another the
279
+ // currentContainer is switched before the placeholder is moved.
280
+ //
281
+ // Without this moving items in "sub-sortables" can cause the placeholder to jitter
282
+ // beetween the outer and inner container.
283
+ if (item.instance !== this.currentContainer) {
284
+ continue;
285
+ }
286
+
287
+ // No action if intersected item is disabled
288
+ // and the element above or below in the direction we're going is also disabled
289
+ if (itemElement.className.indexOf(o.disabledClass) !== -1) {
290
+ // Note: intersection hardcoded direction values from
291
+ // jquery.ui.sortable.js:_intersectsWithPointer
292
+ if (intersection === 2) {
293
+ // Going down
294
+ itemAfter = this.items[i + 1];
295
+ if (itemAfter && itemAfter.item.hasClass(o.disabledClass)) {
296
+ continue;
297
+ }
298
+
299
+ } else if (intersection === 1) {
300
+ // Going up
301
+ itemBefore = this.items[i - 1];
302
+ if (itemBefore && itemBefore.item.hasClass(o.disabledClass)) {
303
+ continue;
304
+ }
305
+ }
306
+ }
307
+
308
+ method = intersection === 1 ? "next" : "prev";
309
+
310
+ // cannot intersect with itself
311
+ // no useless actions that have been done before
312
+ // no action if the item moved is the parent of the item checked
313
+ if (itemElement !== this.currentItem[0] &&
314
+ this.placeholder[method]()[0] !== itemElement &&
315
+ !$.contains(this.placeholder[0], itemElement) &&
316
+ (
317
+ this.options.type === "semi-dynamic" ?
318
+ !$.contains(this.element[0], itemElement) :
319
+ true
320
+ )
321
  ) {
322
 
323
+ // mjs - we are intersecting an element:
324
+ // trigger the mouseenter event and store this state
325
+ if (!this.mouseentered) {
326
+ $(itemElement).mouseenter();
327
+ this.mouseentered = true;
328
+ }
329
+
330
+ // mjs - if the element has children and they are hidden,
331
+ // show them after a delay (CSS responsible)
332
+ if (o.isTree && $(itemElement).hasClass(o.collapsedClass) && o.expandOnHover) {
333
+ if (!this.hovering) {
334
+ $(itemElement).addClass(o.hoveringClass);
335
+ this.hovering = window.setTimeout(function() {
336
+ $(itemElement)
337
+ .removeClass(o.collapsedClass)
338
+ .addClass(o.expandedClass);
339
+
340
+ self.refreshPositions();
341
+ self._trigger("expand", event, self._uiHash());
342
+ }, o.expandOnHover);
343
+ }
344
+ }
345
 
346
+ this.direction = intersection === 1 ? "down" : "up";
347
 
348
+ // mjs - rearrange the elements and reset timeouts and hovering state
349
+ if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
350
  $(itemElement).mouseleave();
351
+ this.mouseentered = false;
352
+ $(itemElement).removeClass(o.hoveringClass);
353
+ if (this.hovering) {
354
+ window.clearTimeout(this.hovering);
355
+ }
356
+ this.hovering = null;
357
+
358
+ // mjs - do not switch container if
359
+ // it's a root item and 'protectRoot' is true
360
+ // or if it's not a root item but we are trying to make it root
361
+ if (o.protectRoot &&
362
+ !(
363
+ this.currentItem[0].parentNode === this.element[0] &&
364
+ // it's a root item
365
+ itemElement.parentNode !== this.element[0]
366
+ // it's intersecting a non-root item
367
+ )
368
+ ) {
369
+ if (this.currentItem[0].parentNode !== this.element[0] &&
370
+ itemElement.parentNode === this.element[0]
371
+ ) {
372
+
373
+ if ( !$(itemElement).children(o.listType).length) {
374
+ itemElement.appendChild(newList);
375
+ if (o.isTree) {
376
+ $(itemElement)
377
+ .removeClass(o.leafClass)
378
+ .addClass(o.branchClass + " " + o.expandedClass);
379
+ }
380
+ }
381
+
382
+ if (this.direction === "down") {
383
+ a = $(itemElement).prev().children(o.listType);
384
+ } else {
385
+ a = $(itemElement).children(o.listType);
386
+ }
387
+
388
+ if (a[0] !== undefined) {
389
+ this._rearrange(event, null, a);
390
+ }
391
+
392
+ } else {
393
+ this._rearrange(event, item);
394
+ }
395
+ } else if (!o.protectRoot) {
396
+ this._rearrange(event, item);
397
+ }
398
  } else {
399
  break;
400
  }
407
  }
408
  }
409
 
410
+ // mjs - to find the previous sibling in the list,
411
+ // keep backtracking until we hit a valid list item.
412
+ (function() {
413
+ var _previousItem = this.placeholder.prev();
414
+ if (_previousItem.length) {
415
+ previousItem = _previousItem;
416
+ } else {
417
+ previousItem = null;
418
+ }
419
+ }.call(this));
420
 
 
 
421
  if (previousItem != null) {
422
+ while (
423
+ previousItem[0].nodeName.toLowerCase() !== "li" ||
424
+ previousItem[0].className.indexOf(o.disabledClass) !== -1 ||
425
+ previousItem[0] === this.currentItem[0] ||
426
+ previousItem[0] === this.helper[0]
427
+ ) {
428
  if (previousItem[0].previousSibling) {
429
  previousItem = $(previousItem[0].previousSibling);
430
  } else {
434
  }
435
  }
436
 
437
+ // mjs - to find the next sibling in the list,
438
+ // keep stepping forward until we hit a valid list item.
439
+ (function() {
440
+ var _nextItem = this.placeholder.next();
441
+ if (_nextItem.length) {
442
+ nextItem = _nextItem;
443
+ } else {
444
+ nextItem = null;
445
+ }
446
+ }.call(this));
447
+
448
+ if (nextItem != null) {
449
+ while (
450
+ nextItem[0].nodeName.toLowerCase() !== "li" ||
451
+ nextItem[0].className.indexOf(o.disabledClass) !== -1 ||
452
+ nextItem[0] === this.currentItem[0] ||
453
+ nextItem[0] === this.helper[0]
454
+ ) {
455
+ if (nextItem[0].nextSibling) {
456
+ nextItem = $(nextItem[0].nextSibling);
457
+ } else {
458
+ nextItem = null;
459
+ break;
460
+ }
461
+ }
462
+ }
463
 
464
  this.beyondMaxLevels = 0;
465
+
466
+ // mjs - if the item is moved to the left, send it one level up
467
+ // but only if it's at the bottom of the list
468
+ if (parentItem != null &&
469
+ nextItem == null &&
470
+ !(o.protectRoot && parentItem[0].parentNode == this.element[0]) &&
471
+ (
472
+ o.rtl &&
473
+ (
474
+ this.positionAbs.left +
475
+ this.helper.outerWidth() > parentItem.offset().left +
476
+ parentItem.outerWidth()
477
+ ) ||
478
+ !o.rtl && (this.positionAbs.left < parentItem.offset().left)
479
+ )
480
+ ) {
481
+
482
  parentItem.after(this.placeholder[0]);
483
+ helperIsNotSibling = !parentItem
484
+ .children(o.listItem)
485
+ .children("li:visible:not(.ui-sortable-helper)")
486
+ .length;
487
+ if (o.isTree && helperIsNotSibling) {
488
+ parentItem
489
+ .removeClass(this.options.branchClass + " " + this.options.expandedClass)
490
+ .addClass(this.options.leafClass);
491
+ }
492
+ if(typeof parentItem !== 'undefined')
493
+ this._clearEmpty(parentItem[0]);
494
  this._trigger("change", event, this._uiHash());
495
+ // mjs - if the item is below a sibling and is moved to the right,
496
+ // make it a child of that sibling
497
+ } else if (previousItem != null &&
498
+ !previousItem.hasClass(o.disableNestingClass) &&
499
+ (
500
+ previousItem.children(o.listType).length &&
501
+ previousItem.children(o.listType).is(":visible") ||
502
+ !previousItem.children(o.listType).length
503
+ ) &&
504
+ !(o.protectRoot && this.currentItem[0].parentNode === this.element[0]) &&
505
+ (
506
+ o.rtl &&
507
+ (
508
+ this.positionAbs.left +
509
+ this.helper.outerWidth() <
510
+ previousItem.offset().left +
511
+ previousItem.outerWidth() -
512
+ o.tabSize
513
+ ) ||
514
+ !o.rtl &&
515
+ (this.positionAbs.left > previousItem.offset().left + o.tabSize)
516
+ )
517
+ ) {
518
+
519
+ this._isAllowed(previousItem, level, level + childLevels + 1);
520
+
521
  if (!previousItem.children(o.listType).length) {
522
  previousItem[0].appendChild(newList);
523
+ if (o.isTree) {
524
+ previousItem
525
+ .removeClass(o.leafClass)
526
+ .addClass(o.branchClass + " " + o.expandedClass);
527
+ }
528
+ }
529
+
530
+ // mjs - if this item is being moved from the top, add it to the top of the list.
531
+ if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) {
532
+ previousItem.children(o.listType).prepend(this.placeholder);
533
+ } else {
534
+ // mjs - otherwise, add it to the bottom of the list.
535
+ previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
536
  }
537
+ if(typeof parentItem !== 'undefined')
538
+ this._clearEmpty(parentItem[0]);
 
 
 
 
 
 
539
  this._trigger("change", event, this._uiHash());
540
+ } else {
541
+ this._isAllowed(parentItem, level, level + childLevels);
 
542
  }
543
 
544
  //Post events to containers
545
  this._contactContainers(event);
546
 
547
  //Interconnect with droppables
548
+ if ($.ui.ddmanager) {
549
+ $.ui.ddmanager.drag(this, event);
550
+ }
551
 
552
  //Call callbacks
553
+ this._trigger("sort", event, this._uiHash());
554
 
555
  this.lastPositionAbs = this.positionAbs;
556
  return false;
557
 
558
  },
559
 
560
+ _mouseStop: function(event) {
561
+ // mjs - if the item is in a position not allowed, send it back
 
562
  if (this.beyondMaxLevels) {
563
 
564
  this.placeholder.removeClass(this.options.errorClass);
573
 
574
  }
575
 
576
+ // mjs - clear the hovering timeout, just to be sure
577
+ $("." + this.options.hoveringClass)
578
+ .mouseleave()
579
+ .removeClass(this.options.hoveringClass);
580
+
581
+ this.mouseentered = false;
582
+ if (this.hovering) {
583
+ window.clearTimeout(this.hovering);
584
  }
585
+ this.hovering = null;
586
 
587
+ this._relocate_event = event;
588
+ this._pid_current = $(this.domPosition.parent).parent().attr("id");
589
+ this._sort_current = this.domPosition.prev ? $(this.domPosition.prev).next().index() : 0;
590
+ $.ui.sortable.prototype._mouseStop.apply(this, arguments); //asybnchronous execution, @see _clear for the relocate event.
591
+ },
592
+
593
+ // mjs - this function is slightly modified
594
+ // to make it easier to hover over a collapsed element and have it expand
595
+ _intersectsWithSides: function(item) {
596
+
597
+ var half = this.options.isTree ? .8 : .5,
598
+ isOverBottomHalf = isOverAxis(
599
+ this.positionAbs.top + this.offset.click.top,
600
+ item.top + (item.height * half),
601
+ item.height
602
+ ),
603
+ isOverTopHalf = isOverAxis(
604
+ this.positionAbs.top + this.offset.click.top,
605
+ item.top - (item.height * half),
606
+ item.height
607
+ ),
608
+ isOverRightHalf = isOverAxis(
609
+ this.positionAbs.left + this.offset.click.left,
610
+ item.left + (item.width / 2),
611
+ item.width
612
+ ),
613
+ verticalDirection = this._getDragVerticalDirection(),
614
+ horizontalDirection = this._getDragHorizontalDirection();
615
+
616
+ if (this.floating && horizontalDirection) {
617
+ return (
618
+ (horizontalDirection === "right" && isOverRightHalf) ||
619
+ (horizontalDirection === "left" && !isOverRightHalf)
620
+ );
621
+ } else {
622
+ return verticalDirection && (
623
+ (verticalDirection === "down" && isOverBottomHalf) ||
624
+ (verticalDirection === "up" && isOverTopHalf)
625
+ );
626
+ }
627
+
628
+ },
629
+
630
+ _contactContainers: function() {
631
+
632
+ if (this.options.protectRoot && this.currentItem[0].parentNode === this.element[0] ) {
633
+ return;
634
+ }
635
+
636
+ $.ui.sortable.prototype._contactContainers.apply(this, arguments);
637
+
638
+ },
639
+
640
+ _clear: function() {
641
+ var i,
642
+ item;
643
+
644
+ $.ui.sortable.prototype._clear.apply(this, arguments);
645
+
646
+ //relocate event
647
+ if (!(this._pid_current === this._uiHash().item.parent().parent().attr("id") &&
648
+ this._sort_current === this._uiHash().item.index())) {
649
+ this._trigger("relocate", this._relocate_event, this._uiHash());
650
+ }
651
+
652
+ // mjs - clean last empty ul/ol
653
+ for (i = this.items.length - 1; i >= 0; i--) {
654
+ item = this.items[i].item[0];
655
+ this._clearEmpty(item);
656
+ }
657
 
658
  },
659
 
661
 
662
  var o = $.extend({}, this.options, options),
663
  items = this._getItemsAsjQuery(o && o.connected),
664
+ str = [];
665
 
666
  $(items).each(function() {
667
+ var res = ($(o.item || this).attr(o.attribute || "id") || "")
668
  .match(o.expression || (/(.+)[-=_](.+)/)),
669
+ pid = ($(o.item || this).parent(o.listType)
670
  .parent(o.items)
671
+ .attr(o.attribute || "id") || "")
672
  .match(o.expression || (/(.+)[-=_](.+)/));
673
 
674
  if (res) {
675
+ str.push(
676
+ (
677
+ (o.key || res[1]) +
678
+ "[" +
679
+ (o.key && o.expression ? res[1] : res[2]) + "]"
680
+ ) +
681
+ "=" +
682
+ (pid ? (o.key && o.expression ? pid[1] : pid[2]) : o.rootID));
683
  }
684
  });
685
 
686
+ if (!str.length && o.key) {
687
+ str.push(o.key + "=");
688
  }
689
 
690
+ return str.join("&");
691
 
692
  },
693
 
694
  toHierarchy: function(options) {
695
 
696
  var o = $.extend({}, this.options, options),
697
+ ret = [];
 
698
 
699
+ $(this.element).children(o.items).each(function() {
700
  var level = _recursiveItems(this);
701
  ret.push(level);
702
  });
704
  return ret;
705
 
706
  function _recursiveItems(item) {
707
+ var id = ($(item).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[-=_](.+)/)),
708
+ currentItem;
709
+
710
+ var data = $(item).data();
711
+ if (data.nestedSortableItem) {
712
+ delete data.nestedSortableItem; // Remove the nestedSortableItem object from the data
713
+ }
714
+
715
  if (id) {
716
+ currentItem = {
717
+ "id": id[2]
718
+ };
719
+
720
+ currentItem = $.extend({}, currentItem, data); // Combine the two objects
721
+
722
  if ($(item).children(o.listType).children(o.items).length > 0) {
723
  currentItem.children = [];
724
  $(item).children(o.listType).children(o.items).each(function() {
735
 
736
  var o = $.extend({}, this.options, options),
737
  sDepth = o.startDepthCount || 0,
738
+ ret = [],
739
+ left = 1;
740
+
741
+ if (!o.excludeRoot) {
742
+ ret.push({
743
+ "item_id": o.rootID,
744
+ "parent_id": null,
745
+ "depth": sDepth,
746
+ "left": left,
747
+ "right": ($(o.items, this.element).length + 1) * 2
748
+ });
749
+ left++;
750
+ }
751
 
752
+ $(this.element).children(o.items).each(function() {
753
+ left = _recursiveArray(this, sDepth, left);
754
  });
755
 
756
+ ret = ret.sort(function(a, b) { return (a.left - b.left); });
757
 
758
  return ret;
759
 
760
+ function _recursiveArray(item, depth, _left) {
761
 
762
+ var right = _left + 1,
763
+ id,
764
+ pid,
765
+ parentItem;
766
 
767
  if ($(item).children(o.listType).children(o.items).length > 0) {
768
+ depth++;
769
+ $(item).children(o.listType).children(o.items).each(function() {
770
  right = _recursiveArray($(this), depth, right);
771
  });
772
+ depth--;
773
  }
774
 
775
+ id = ($(item).attr(o.attribute || "id")).match(o.expression || (/(.+)[-=_](.+)/));
776
 
777
+ if (depth === sDepth) {
778
  pid = o.rootID;
779
  } else {
780
+ parentItem = ($(item).parent(o.listType)
781
+ .parent(o.items)
782
+ .attr(o.attribute || "id"))
783
+ .match(o.expression || (/(.+)[-=_](.+)/));
784
  pid = parentItem[2];
785
  }
786
 
787
  if (id) {
788
+ var name = $(item).data("name");
789
+ ret.push({
790
+ "id": id[2],
791
+ "parent_id": pid,
792
+ "depth": depth,
793
+ "left": _left,
794
+ "right": right,
795
+ "name":name
796
+ });
797
  }
798
 
799
+ _left = right + 1;
800
+ return _left;
801
  }
802
 
803
  },
804
 
805
+ _clearEmpty: function (item) {
806
+ function replaceClass(elem, search, replace, swap) {
807
+ if (swap) {
808
+ search = [replace, replace = search][0];
809
+ }
810
+
811
+ $(elem).removeClass(search).addClass(replace);
812
+ }
813
+
814
+ var o = this.options,
815
+ childrenList = $(item).children(o.listType),
816
+ hasChildren = childrenList.is(':not(:empty)');
817
+
818
+ var doNotClear =
819
+ o.doNotClear ||
820
+ hasChildren ||
821
+ o.protectRoot && $(item)[0] === this.element[0];
822
 
823
+ if (o.isTree) {
824
+ replaceClass(item, o.branchClass, o.leafClass, doNotClear);
825
+
826
+ if (doNotClear && hasChildren) {
827
+ replaceClass(item, o.collapsedClass, o.expandedClass);
828
+ }
829
  }
830
 
831
+ if (!doNotClear) {
832
+ childrenList.remove();
833
+ }
834
  },
835
 
836
  _getLevel: function(item) {
837
 
838
+ var level = 1,
839
+ list;
840
 
841
  if (this.options.listType) {
842
+ list = item.closest(this.options.listType);
843
+ while (list && list.length > 0 && !list.is(".ui-sortable")) {
 
844
  level++;
845
  list = list.parent().closest(this.options.listType);
846
  }
851
 
852
  _getChildLevels: function(parent, depth) {
853
  var self = this,
854
+ o = this.options,
855
+ result = 0;
856
  depth = depth || 0;
857
 
858
+ $(parent).children(o.listType).children(o.items).each(function(index, child) {
859
+ result = Math.max(self._getChildLevels(child, depth + 1), result);
860
  });
861
 
862
  return depth ? result + 1 : result;
864
 
865
  _isAllowed: function(parentItem, level, levels) {
866
  var o = this.options,
867
+ // this takes into account the maxLevels set to the recipient list
868
+ maxLevels = this
869
+ .placeholder
870
+ .closest(".ui-sortable")
871
+ .nestedSortable("option", "maxLevels"),
872
+
873
+ // Check if the parent has changed to prevent it, when o.disableParentChange is true
874
+ oldParent = this.currentItem.parent().parent(),
875
+ disabledByParentchange = o.disableParentChange && (
876
+ //From somewhere to somewhere else, except the root
877
+ typeof parentItem !== 'undefined' && !oldParent.is(parentItem) ||
878
+ typeof parentItem === 'undefined' && oldParent.is("li") //From somewhere to the root
879
+ );
880
+ // mjs - is the root protected?
881
+ // mjs - are we nesting too deep?
882
+ if (
883
+ disabledByParentchange ||
884
+ !o.isAllowed(this.placeholder, parentItem, this.currentItem)
885
+ ) {
886
+ this.placeholder.addClass(o.errorClass);
887
+ if (maxLevels < levels && maxLevels !== 0) {
888
+ this.beyondMaxLevels = levels - maxLevels;
889
+ } else {
890
+ this.beyondMaxLevels = 1;
891
+ }
892
  } else {
893
+ if (maxLevels < levels && maxLevels !== 0) {
894
  this.placeholder.addClass(o.errorClass);
895
  this.beyondMaxLevels = levels - maxLevels;
896
  } else {
902
 
903
  }));
904
 
905
+ $.mjs.nestedSortable.prototype.options = $.extend(
906
+ {},
907
+ $.ui.sortable.prototype.options,
908
+ $.mjs.nestedSortable.prototype.options
909
+ );
910
+ }));
scripts/jquery.ui.touch-punch.js ADDED
@@ -0,0 +1,180 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*!
2
+ * jQuery UI Touch Punch 0.2.3
3
+ *
4
+ * Copyright 2011–2014, Dave Furfero
5
+ * Dual licensed under the MIT or GPL Version 2 licenses.
6
+ *
7
+ * Depends:
8
+ * jquery.ui.widget.js
9
+ * jquery.ui.mouse.js
10
+ */
11
+ (function ($) {
12
+
13
+ // Detect touch support
14
+ $.support.touch = 'ontouchend' in document;
15
+
16
+ // Ignore browsers without touch support
17
+ if (!$.support.touch) {
18
+ return;
19
+ }
20
+
21
+ var mouseProto = $.ui.mouse.prototype,
22
+ _mouseInit = mouseProto._mouseInit,
23
+ _mouseDestroy = mouseProto._mouseDestroy,
24
+ touchHandled;
25
+
26
+ /**
27
+ * Simulate a mouse event based on a corresponding touch event
28
+ * @param {Object} event A touch event
29
+ * @param {String} simulatedType The corresponding mouse event
30
+ */
31
+ function simulateMouseEvent (event, simulatedType) {
32
+
33
+ // Ignore multi-touch events
34
+ if (event.originalEvent.touches.length > 1) {
35
+ return;
36
+ }
37
+
38
+ event.preventDefault();
39
+
40
+ var touch = event.originalEvent.changedTouches[0],
41
+ simulatedEvent = document.createEvent('MouseEvents');
42
+
43
+ // Initialize the simulated mouse event using the touch event's coordinates
44
+ simulatedEvent.initMouseEvent(
45
+ simulatedType, // type
46
+ true, // bubbles
47
+ true, // cancelable
48
+ window, // view
49
+ 1, // detail
50
+ touch.screenX, // screenX
51
+ touch.screenY, // screenY
52
+ touch.clientX, // clientX
53
+ touch.clientY, // clientY
54
+ false, // ctrlKey
55
+ false, // altKey
56
+ false, // shiftKey
57
+ false, // metaKey
58
+ 0, // button
59
+ null // relatedTarget
60
+ );
61
+
62
+ // Dispatch the simulated event to the target element
63
+ event.target.dispatchEvent(simulatedEvent);
64
+ }
65
+
66
+ /**
67
+ * Handle the jQuery UI widget's touchstart events
68
+ * @param {Object} event The widget element's touchstart event
69
+ */
70
+ mouseProto._touchStart = function (event) {
71
+
72
+ var self = this;
73
+
74
+ // Ignore the event if another widget is already being handled
75
+ if (touchHandled || !self._mouseCapture(event.originalEvent.changedTouches[0])) {
76
+ return;
77
+ }
78
+
79
+ // Set the flag to prevent other widgets from inheriting the touch event
80
+ touchHandled = true;
81
+
82
+ // Track movement to determine if interaction was a click
83
+ self._touchMoved = false;
84
+
85
+ // Simulate the mouseover event
86
+ simulateMouseEvent(event, 'mouseover');
87
+
88
+ // Simulate the mousemove event
89
+ simulateMouseEvent(event, 'mousemove');
90
+
91
+ // Simulate the mousedown event
92
+ simulateMouseEvent(event, 'mousedown');
93
+ };
94
+
95
+ /**
96
+ * Handle the jQuery UI widget's touchmove events
97
+ * @param {Object} event The document's touchmove event
98
+ */
99
+ mouseProto._touchMove = function (event) {
100
+
101
+ // Ignore event if not handled
102
+ if (!touchHandled) {
103
+ return;
104
+ }
105
+
106
+ // Interaction was not a click
107
+ this._touchMoved = true;
108
+
109
+ // Simulate the mousemove event
110
+ simulateMouseEvent(event, 'mousemove');
111
+ };
112
+
113
+ /**
114
+ * Handle the jQuery UI widget's touchend events
115
+ * @param {Object} event The document's touchend event
116
+ */
117
+ mouseProto._touchEnd = function (event) {
118
+
119
+ // Ignore event if not handled
120
+ if (!touchHandled) {
121
+ return;
122
+ }
123
+
124
+ // Simulate the mouseup event
125
+ simulateMouseEvent(event, 'mouseup');
126
+
127
+ // Simulate the mouseout event
128
+ simulateMouseEvent(event, 'mouseout');
129
+
130
+ // If the touch interaction did not move, it should trigger a click
131
+ if (!this._touchMoved) {
132
+
133
+ // Simulate the click event
134
+ simulateMouseEvent(event, 'click');
135
+ }
136
+
137
+ // Unset the flag to allow other widgets to inherit the touch event
138
+ touchHandled = false;
139
+ };
140
+
141
+ /**
142
+ * A duck punch of the $.ui.mouse _mouseInit method to support touch events.
143
+ * This method extends the widget with bound touch event handlers that
144
+ * translate touch events to mouse events and pass them to the widget's
145
+ * original mouse event handling methods.
146
+ */
147
+ mouseProto._mouseInit = function () {
148
+
149
+ var self = this;
150
+
151
+ // Delegate the touch handlers to the widget's element
152
+ self.element.bind({
153
+ touchstart: $.proxy(self, '_touchStart'),
154
+ touchmove: $.proxy(self, '_touchMove'),
155
+ touchend: $.proxy(self, '_touchEnd')
156
+ });
157
+
158
+ // Call the original $.ui.mouse init method
159
+ _mouseInit.call(self);
160
+ };
161
+
162
+ /**
163
+ * Remove the touch event handlers
164
+ */
165
+ mouseProto._mouseDestroy = function () {
166
+
167
+ var self = this;
168
+
169
+ // Delegate the touch handlers to the widget's element
170
+ self.element.unbind({
171
+ touchstart: $.proxy(self, '_touchStart'),
172
+ touchmove: $.proxy(self, '_touchMove'),
173
+ touchend: $.proxy(self, '_touchEnd')
174
+ });
175
+
176
+ // Call the original $.ui.mouse destroy method
177
+ _mouseDestroy.call(self);
178
+ };
179
+
180
+ })(jQuery);
scripts/sort.js CHANGED
@@ -15,13 +15,14 @@ jQuery(document).ready(function($) {
15
  items: 'li',
16
  maxLevels: max_levels,
17
  opacity: .6,
18
- placeholder: 'placeholder',
19
  revert: 250,
20
  tabSize: 25,
21
  tolerance: 'pointer',
22
  toleranceElement: '> div',
23
  listType: 'ul',
24
  update: function( event, ui ) {
 
25
  $loading_animation = jQuery( '#loading-animation' );
26
  var reorder_ajax_callback = function( response ) {
27
  response = jQuery.parseJSON( response );
@@ -38,7 +39,7 @@ jQuery(document).ready(function($) {
38
  }
39
  }
40
  };
41
- ui.item.find( 'div' ).append( $loading_animation );
42
 
43
  $loading_animation.show();
44
 
@@ -122,13 +123,30 @@ jQuery(document).ready(function($) {
122
  sort_start.next = ui.item.next( ':not(".placeholder")' );
123
  }
124
  });
125
- $( "#post-list a" ).toggle( function() {
126
- $( this ).html( reorder_posts.collapse );
127
- $( this ).parent().next( '.children' ).slideDown( "slow" );
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
128
  return false;
129
  }, function() {
130
- $( this ).html( reorder_posts.expand );
131
- $( this ).parent().next( '.children' ).slideUp( "slow" );
132
  return false;
133
  } );
134
  });
15
  items: 'li',
16
  maxLevels: max_levels,
17
  opacity: .6,
18
+ placeholder: 'ui-sortable-placeholder',
19
  revert: 250,
20
  tabSize: 25,
21
  tolerance: 'pointer',
22
  toleranceElement: '> div',
23
  listType: 'ul',
24
  update: function( event, ui ) {
25
+ reorder_row_nesting();
26
  $loading_animation = jQuery( '#loading-animation' );
27
  var reorder_ajax_callback = function( response ) {
28
  response = jQuery.parseJSON( response );
39
  }
40
  }
41
  };
42
+ ui.item.find( 'div.row-content:first' ).append( $loading_animation );
43
 
44
  $loading_animation.show();
45
 
123
  sort_start.next = ui.item.next( ':not(".placeholder")' );
124
  }
125
  });
126
+
127
+ function reorder_row_nesting() {
128
+ // Add Nesting capabilities
129
+ $( '.row-content' ).each( function() {
130
+ var parents_count = $( this ).parents( 'ul' ).length;
131
+ var padding = 30;
132
+ if ( parents_count > 1 ) {
133
+ var new_padding = parents_count * 20 + padding;
134
+ $( this ).css('padding-left', new_padding + 'px');
135
+ } else {
136
+ $( this ).css('padding-left', padding + 'px');
137
+ }
138
+ } );
139
+ }
140
+
141
+ reorder_row_nesting()
142
+
143
+ $( "#post-list .expand span" ).toggle( function() {
144
+ $( this ).removeClass( 'dashicons-arrow-right' ).addClass( 'dashicons-arrow-down' );
145
+ $( this ).parent().parent().next( '.children' ).fadeIn( "fast" );
146
  return false;
147
  }, function() {
148
+ $( this ).removeClass( 'dashicons-arrow-down' ).addClass( 'dashicons-arrow-right' );
149
+ $( this ).parent().parent().next( '.children' ).fadeOut( "fast" );
150
  return false;
151
  } );
152
  });