jquery-mjs-nestedSortable-rails 1.3.5 → 2.0.0.alpha1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +57 -14
- data/lib/jquery/mjs/nestedSortable/rails/version.rb +1 -1
- data/vendor/assets/javascripts/jquery.mjs.nestedSortable.js +269 -86
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 30708b0dddfcc4c9c3f0f03ac0befee8d257bbe0
|
4
|
+
data.tar.gz: 9190fc9b9c90ca28c8296ae27b5356b928b524b5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c351d6d07e0c73e82157b7afba30ea22e7572154c038d0c4e7ca11d6c7b48cb5550f19725f403195e7db28e02720d925fb57634ed398f9f12f8f72727078fea
|
7
|
+
data.tar.gz: 6ffdac5aaff84066300c0ce0d08e6524d40c18a3d68cd38dd382f8fcd3c367cbade2bd4cd76afffd23f69e7e801dab9e10d4db980fd62aab82c586905e1928e3
|
data/README.md
CHANGED
@@ -5,6 +5,16 @@ Rails version of [mjs.nestedSortable](https://github.com/mjsarfatti/nestedSortab
|
|
5
5
|
*nestedSortable* is a jQuery plugin that extends jQuery Sortable UI functionalities to nested lists.
|
6
6
|
*Note:* **Version 2.0** *is published in branch '2.0alpha' and is ready for testing! At the moment it has only been tested in Firefox and Chrome, if you work with IE feel free to give it a shot and let me know if something goes wrong.*
|
7
7
|
|
8
|
+
## What's new in version 2.0
|
9
|
+
|
10
|
+
The biggest change is that your nested list can now behave as a tree with expand/collapse funcionality. Simply set `isTree` to **true** in the options and you are good to go! Check the [demo](http://mjsarfatti.com/sandbox/nestedSortable) out to see what can be done with nestedSortable and a little CSS. (Note that all **nestedSortable** does is to assign/remove classes on the fly)
|
11
|
+
Also:
|
12
|
+
- **isAllowed** function finally works as expected, see the docs below
|
13
|
+
- Fixed: a small bug in the **protectRoot** function
|
14
|
+
- Changed: no drop zone will appear at all if you try to nest an item under another one that has the *no-nesting* class.
|
15
|
+
- Added: **doNotClear** option to prevent the plugin from deleting empty lists
|
16
|
+
|
17
|
+
|
8
18
|
## Features
|
9
19
|
|
10
20
|
- Designed to work seamlessly with the [nested](http://articles.sitepoint.com/article/hierarchical-data-database "A Sitepoint tutorial on PHP, MYSQL and nested sets") [set](http://en.wikipedia.org/wiki/Nested_set_model "Wikipedia article on nested sets") model (have a look at the `toArray` method)
|
@@ -14,11 +24,13 @@ Rails version of [mjs.nestedSortable](https://github.com/mjsarfatti/nestedSortab
|
|
14
24
|
- It is possible to define elements that will not accept a new nested item/list and a maximum depth for nested items
|
15
25
|
- The root level can be protected
|
16
26
|
|
27
|
+
|
17
28
|
## Installation
|
18
29
|
|
19
30
|
Add this line to your application's Gemfile:
|
20
31
|
|
21
|
-
gem 'jquery-mjs-nestedSortable-rails'
|
32
|
+
gem 'jquery-mjs-nestedSortable-rails', '~> 2.0.0.pre.alpha.pre.1'
|
33
|
+
gem 'jquery-mjs-nestedSortable-rails', '~> 1.3.5'
|
22
34
|
|
23
35
|
And then execute:
|
24
36
|
|
@@ -68,27 +80,54 @@ Please note: every `<li>` must have either one or two direct children, the first
|
|
68
80
|
|
69
81
|
Also, the default list type is `<ol>`.
|
70
82
|
|
83
|
+
*This is the bare minimum to have a working nestedSortable. Check the [demo](http://mjsarfatti.com/sandbox/nestedSortable) out to see what can be accomplished with a little more.*
|
84
|
+
|
71
85
|
## Custom Options
|
72
86
|
|
73
87
|
<dl>
|
74
|
-
<dt>
|
75
|
-
<dd>
|
76
|
-
<dt>
|
77
|
-
<dd>
|
78
|
-
<dt>
|
79
|
-
<dd>
|
88
|
+
<dt>doNotClear (2.0)</dt>
|
89
|
+
<dd>Set this to true if you don't want empty lists to be removed. Default: <b>false</b></dd>
|
90
|
+
<dt>expandOnHover (2.0)</dt>
|
91
|
+
<dd>How long (in ms) to wait before expanding a collapsed node (useful only if <code>isTree: true</code>). Default: <b>700</b></dd>
|
92
|
+
<dt>isAllowed (function)</dt>
|
93
|
+
<dd>You can specify a custom function to verify if a drop location is allowed. Default: <b>function (placeholder, placeholderParent, currentItem) { return true; }</b></dd>
|
94
|
+
<dt>isTree (2.0)</dt>
|
95
|
+
<dd>Set this to true if you want to use the new tree functionality. Default: <b>false</b></dd>
|
80
96
|
<dt>listType</dt>
|
81
97
|
<dd>The list type used (ordered or unordered). Default: <b>ol</b></dd>
|
82
98
|
<dt>maxLevels</dt>
|
83
99
|
<dd>The maximum depth of nested items the list can accept. If set to '0' the levels are unlimited. Default: <b>0</b></dd>
|
84
100
|
<dt>protectRoot</dt>
|
85
|
-
<dd>
|
101
|
+
<dd>Whether to protect the root level (i.e. root items can be sorted but not nested, sub-items cannot become root items). Default: <b>false</b></dd>
|
86
102
|
<dt>rootID</dt>
|
87
103
|
<dd>The id given to the root element (set this to whatever suits your data structure). Default: <b>null</b></dd>
|
88
104
|
<dt>rtl</dt>
|
89
105
|
<dd>Set this to true if you have a right-to-left page. Default: <b>false</b></dd>
|
90
|
-
<dt>
|
91
|
-
<dd>
|
106
|
+
<dt>startCollapsed (2.0)</dt>
|
107
|
+
<dd>Set this to true if you want the plugin to collapse the tree on page load. Default: <b>false</b></dd>
|
108
|
+
<dt>tabSize</dt>
|
109
|
+
<dd>How far right or left (in pixels) the item has to travel in order to be nested or to be sent outside its current list. Default: <b>20</b></dd>
|
110
|
+
<dt>excludeRoot</dt>
|
111
|
+
<dd>Exlude the root item from the <code>toArray</code> output</dd>
|
112
|
+
</dl>
|
113
|
+
|
114
|
+
## Custom Classes (you will set them in the options as well)
|
115
|
+
|
116
|
+
<dl>
|
117
|
+
<dt>branchClass (2.0)</dt>
|
118
|
+
<dd>Given to all items that have children. Default: <b>mjs-nestedSortable-branch</b></dd>
|
119
|
+
<dt>collapsedClass (2.0)</dt>
|
120
|
+
<dd>Given to branches that are collapsed. It will be switched to <b>expandedClass</b> when hovering for more then <b>expandOnHover</b> ms. Default: <b>mjs-nestedSortable-collapsed</b></dd>
|
121
|
+
<dt>disableNestingClass</dt>
|
122
|
+
<dd>Given to items that will not accept children. Default: <b>mjs-nestedSortable-no-nesting</b></dd>
|
123
|
+
<dt>errorClass</dt>
|
124
|
+
<dd>Given to the placeholder in case of error. Default: <b>mjs-nestedSortable-error</b></dd>
|
125
|
+
<dt>expandedClass (2.0)</dt>
|
126
|
+
<dd>Given to branches that are expanded. Default: <b>mjs-nestedSortable-expanded</b></dd>
|
127
|
+
<dt>hoveringClass (2.0)</dt>
|
128
|
+
<dd>Given to collapsed branches when dragging an item over them. Default: <b>mjs-nestedSortable-hovering</b></dd>
|
129
|
+
<dt>leafClass (2.0)<dt>
|
130
|
+
<dd>Given to items that do not have children. Default: <b>mjs-nestedSortable-leaf</b></dd>
|
92
131
|
</dl>
|
93
132
|
|
94
133
|
## Custom Methods
|
@@ -132,18 +171,22 @@ Also, the default list type is `<ol>`.
|
|
132
171
|
|
133
172
|
## Requirements
|
134
173
|
|
135
|
-
jQuery 1.
|
136
|
-
jQuery UI Sortable 1.8+
|
174
|
+
jQuery UI Sortable 1.10+ (might work with 1.9, but not tested)
|
137
175
|
|
138
176
|
## Browser Compatibility
|
139
177
|
|
140
|
-
Tested with:
|
178
|
+
Tested with: Firefox, Chrome
|
179
|
+
**NOTE: This is still an alpha version, please test thoroughly in whichever version of IE you target**
|
141
180
|
|
142
181
|
## License
|
143
182
|
|
144
183
|
This work is licensed under the MIT License.
|
184
|
+
Which means you can do pretty much whatever you want with it.
|
185
|
+
|
186
|
+
Nonetheless if this plugin saved you money, saved you time or saved your life please take a moment to think about the work I've been doing for you and consider sharing a bit of your joy with me. Your donation, however small, will be greatly appreciated.
|
187
|
+
Thank you.
|
145
188
|
|
146
|
-
|
189
|
+
[Donate with PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=RSJEW3N9PRMYY&lc=IT&item_name=Manuele%20Sarfatti¤cy_code=EUR&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted)
|
147
190
|
|
148
191
|
## Contributing
|
149
192
|
|
@@ -1,52 +1,90 @@
|
|
1
1
|
/*
|
2
2
|
* jQuery UI Nested Sortable
|
3
|
-
* v
|
4
|
-
* http://mjsarfatti.com/
|
3
|
+
* v 2.0 / 29 oct 2012
|
4
|
+
* http://mjsarfatti.com/sandbox/nestedSortable
|
5
5
|
*
|
6
6
|
* Depends on:
|
7
|
-
* jquery.ui.sortable.js 1.
|
7
|
+
* jquery.ui.sortable.js 1.10+
|
8
8
|
*
|
9
|
-
* Copyright (c) 2010-
|
9
|
+
* Copyright (c) 2010-2013 Manuele J Sarfatti
|
10
10
|
* Licensed under the MIT License
|
11
11
|
* http://www.opensource.org/licenses/mit-license.php
|
12
12
|
*/
|
13
13
|
|
14
14
|
(function ($) {
|
15
15
|
|
16
|
+
function isOverAxis(x, reference, size) {
|
17
|
+
return ( x > reference ) && ( x < ( reference + size ) );
|
18
|
+
}
|
19
|
+
|
16
20
|
$.widget("mjs.nestedSortable", $.extend({}, $.ui.sortable.prototype, {
|
17
21
|
|
18
22
|
options: {
|
19
|
-
tabSize: 20,
|
20
|
-
disableNesting: 'mjs-nestedSortable-no-nesting',
|
21
|
-
errorClass: 'mjs-nestedSortable-error',
|
22
23
|
doNotClear: false,
|
24
|
+
expandOnHover: 700,
|
25
|
+
isAllowed: function (placeholder, placeholderParent, originalItem) {
|
26
|
+
return true;
|
27
|
+
},
|
28
|
+
isTree: false,
|
23
29
|
listType: 'ol',
|
24
30
|
maxLevels: 0,
|
25
31
|
protectRoot: false,
|
26
32
|
rootID: null,
|
27
33
|
rtl: false,
|
28
|
-
|
29
|
-
|
30
|
-
|
34
|
+
startCollapsed: false,
|
35
|
+
tabSize: 20,
|
36
|
+
|
37
|
+
branchClass: 'mjs-nestedSortable-branch',
|
38
|
+
collapsedClass: 'mjs-nestedSortable-collapsed',
|
39
|
+
disableNestingClass: 'mjs-nestedSortable-no-nesting',
|
40
|
+
errorClass: 'mjs-nestedSortable-error',
|
41
|
+
expandedClass: 'mjs-nestedSortable-expanded',
|
42
|
+
hoveringClass: 'mjs-nestedSortable-hovering',
|
43
|
+
leafClass: 'mjs-nestedSortable-leaf'
|
31
44
|
},
|
32
45
|
|
33
46
|
_create: function () {
|
34
|
-
this.element.data('sortable', this.element.data('nestedSortable'));
|
47
|
+
this.element.data('ui-sortable', this.element.data('mjs-nestedSortable'));
|
35
48
|
|
49
|
+
// mjs - prevent browser from freezing if the HTML is not correct
|
36
50
|
if (!this.element.is(this.options.listType))
|
37
|
-
throw new Error('nestedSortable: Please check the listType option is set to your actual list type');
|
51
|
+
throw new Error('nestedSortable: Please check that the listType option is set to your actual list type');
|
52
|
+
|
53
|
+
// mjs - force 'intersect' tolerance method if we have a tree with expanding/collapsing functionality
|
54
|
+
if (this.options.isTree && this.options.expandOnHover) {
|
55
|
+
this.options.tolerance = 'intersect';
|
56
|
+
}
|
38
57
|
|
39
|
-
|
58
|
+
$.ui.sortable.prototype._create.apply(this, arguments);
|
59
|
+
|
60
|
+
// mjs - prepare the tree by applying the right classes (the CSS is responsible for actual hide/show functionality)
|
61
|
+
if (this.options.isTree) {
|
62
|
+
var self = this;
|
63
|
+
$(this.items).each(function () {
|
64
|
+
var $li = this.item;
|
65
|
+
if ($li.children(self.options.listType).length) {
|
66
|
+
$li.addClass(self.options.branchClass);
|
67
|
+
// expand/collapse class only if they have children
|
68
|
+
if (self.options.startCollapsed) $li.addClass(self.options.collapsedClass);
|
69
|
+
else $li.addClass(self.options.expandedClass);
|
70
|
+
} else {
|
71
|
+
$li.addClass(self.options.leafClass);
|
72
|
+
}
|
73
|
+
})
|
74
|
+
}
|
40
75
|
},
|
41
76
|
|
42
|
-
|
77
|
+
_destroy: function () {
|
43
78
|
this.element
|
44
|
-
.removeData("nestedSortable")
|
45
|
-
.
|
46
|
-
return $.ui.sortable.prototype.
|
79
|
+
.removeData("mjs-nestedSortable")
|
80
|
+
.removeData("ui-sortable");
|
81
|
+
return $.ui.sortable.prototype._destroy.apply(this, arguments);
|
47
82
|
},
|
48
83
|
|
49
84
|
_mouseDrag: function (event) {
|
85
|
+
var i, item, itemElement, intersection,
|
86
|
+
o = this.options,
|
87
|
+
scrolled = false;
|
50
88
|
|
51
89
|
//Compute the helpers position
|
52
90
|
this.position = this._generatePosition(event);
|
@@ -56,34 +94,35 @@
|
|
56
94
|
this.lastPositionAbs = this.positionAbs;
|
57
95
|
}
|
58
96
|
|
59
|
-
var o = this.options;
|
60
|
-
|
61
97
|
//Do scrolling
|
62
98
|
if (this.options.scroll) {
|
63
|
-
var scrolled = false;
|
64
99
|
if (this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
|
65
100
|
|
66
|
-
if ((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
|
101
|
+
if ((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
|
67
102
|
this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
|
68
|
-
else if (event.pageY - this.overflowOffset.top < o.scrollSensitivity)
|
103
|
+
} else if (event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
|
69
104
|
this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
|
105
|
+
}
|
70
106
|
|
71
|
-
if ((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
|
107
|
+
if ((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
|
72
108
|
this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
|
73
|
-
else if (event.pageX - this.overflowOffset.left < o.scrollSensitivity)
|
109
|
+
} else if (event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
|
74
110
|
this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
|
111
|
+
}
|
75
112
|
|
76
113
|
} else {
|
77
114
|
|
78
|
-
if (event.pageY - $(document).scrollTop() < o.scrollSensitivity)
|
115
|
+
if (event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
|
79
116
|
scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
|
80
|
-
else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
|
117
|
+
} else if ($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
|
81
118
|
scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
|
119
|
+
}
|
82
120
|
|
83
|
-
if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
|
121
|
+
if (event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
|
84
122
|
scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
|
85
|
-
else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
|
123
|
+
} else if ($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
|
86
124
|
scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
|
125
|
+
}
|
87
126
|
|
88
127
|
}
|
89
128
|
|
@@ -94,34 +133,116 @@
|
|
94
133
|
//Regenerate the absolute position used for position checks
|
95
134
|
this.positionAbs = this._convertPositionTo("absolute");
|
96
135
|
|
97
|
-
//
|
136
|
+
// mjs - find the top offset before rearrangement,
|
98
137
|
var previousTopOffset = this.placeholder.offset().top;
|
99
138
|
|
100
139
|
//Set the helper position
|
101
|
-
if (!this.options.axis || this.options.axis
|
102
|
-
|
140
|
+
if (!this.options.axis || this.options.axis !== "y") {
|
141
|
+
this.helper[0].style.left = this.position.left + "px";
|
142
|
+
}
|
143
|
+
if (!this.options.axis || this.options.axis !== "x") {
|
144
|
+
this.helper[0].style.top = this.position.top + "px";
|
145
|
+
}
|
146
|
+
|
147
|
+
// mjs - check and reset hovering state at each cycle
|
148
|
+
this.hovering = this.hovering ? this.hovering : null;
|
149
|
+
this.mouseentered = this.mouseentered ? this.mouseentered : false;
|
150
|
+
|
151
|
+
// mjs - let's start caching some variables
|
152
|
+
var parentItem = (this.placeholder[0].parentNode.parentNode &&
|
153
|
+
$(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length)
|
154
|
+
? $(this.placeholder[0].parentNode.parentNode)
|
155
|
+
: null,
|
156
|
+
level = this._getLevel(this.placeholder),
|
157
|
+
childLevels = this._getChildLevels(this.helper);
|
158
|
+
|
159
|
+
var newList = document.createElement(o.listType);
|
103
160
|
|
104
161
|
//Rearrange
|
105
|
-
for (
|
162
|
+
for (i = this.items.length - 1; i >= 0; i--) {
|
106
163
|
|
107
164
|
//Cache variables and intersection, continue if no intersection
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
if (
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
165
|
+
item = this.items[i];
|
166
|
+
itemElement = item.item[0];
|
167
|
+
intersection = this._intersectsWithPointer(item);
|
168
|
+
if (!intersection) {
|
169
|
+
continue;
|
170
|
+
}
|
171
|
+
|
172
|
+
// Only put the placeholder inside the current Container, skip all
|
173
|
+
// items form other containers. This works because when moving
|
174
|
+
// an item from one container to another the
|
175
|
+
// currentContainer is switched before the placeholder is moved.
|
176
|
+
//
|
177
|
+
// Without this moving items in "sub-sortables" can cause the placeholder to jitter
|
178
|
+
// beetween the outer and inner container.
|
179
|
+
if (item.instance !== this.currentContainer) {
|
180
|
+
continue;
|
181
|
+
}
|
182
|
+
|
183
|
+
// cannot intersect with itself
|
184
|
+
// no useless actions that have been done before
|
185
|
+
// no action if the item moved is the parent of the item checked
|
186
|
+
if (itemElement !== this.currentItem[0] &&
|
187
|
+
this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement && !$.contains(this.placeholder[0], itemElement) &&
|
188
|
+
(this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
|
116
189
|
) {
|
117
190
|
|
118
|
-
|
191
|
+
// mjs - we are intersecting an element: trigger the mouseenter event and store this state
|
192
|
+
if (!this.mouseentered) {
|
193
|
+
$(itemElement).mouseenter();
|
194
|
+
this.mouseentered = true;
|
195
|
+
}
|
196
|
+
|
197
|
+
// mjs - if the element has children and they are hidden, show them after a delay (CSS responsible)
|
198
|
+
if (o.isTree && $(itemElement).hasClass(o.collapsedClass) && o.expandOnHover) {
|
199
|
+
if (!this.hovering) {
|
200
|
+
$(itemElement).addClass(o.hoveringClass);
|
201
|
+
var self = this;
|
202
|
+
this.hovering = window.setTimeout(function () {
|
203
|
+
$(itemElement).removeClass(o.collapsedClass).addClass(o.expandedClass);
|
204
|
+
self.refreshPositions();
|
205
|
+
self._trigger("expand", event, self._uiHash());
|
206
|
+
}, o.expandOnHover);
|
207
|
+
}
|
208
|
+
}
|
119
209
|
|
120
210
|
this.direction = intersection == 1 ? "down" : "up";
|
121
211
|
|
212
|
+
// mjs - rearrange the elements and reset timeouts and hovering state
|
122
213
|
if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
|
123
214
|
$(itemElement).mouseleave();
|
124
|
-
this.
|
215
|
+
this.mouseentered = false;
|
216
|
+
$(itemElement).removeClass(o.hoveringClass);
|
217
|
+
this.hovering && window.clearTimeout(this.hovering);
|
218
|
+
this.hovering = null;
|
219
|
+
|
220
|
+
// mjs - do not switch container if it's a root item and 'protectRoot' is true
|
221
|
+
// or if it's not a root item but we are trying to make it root
|
222
|
+
if (o.protectRoot
|
223
|
+
&& !(this.currentItem[0].parentNode == this.element[0] // it's a root item
|
224
|
+
&& itemElement.parentNode != this.element[0]) // it's intersecting a non-root item
|
225
|
+
) {
|
226
|
+
if (this.currentItem[0].parentNode != this.element[0]
|
227
|
+
&& itemElement.parentNode == this.element[0]
|
228
|
+
) {
|
229
|
+
|
230
|
+
if (!$(itemElement).children(o.listType).length) {
|
231
|
+
itemElement.appendChild(newList);
|
232
|
+
o.isTree && $(itemElement).removeClass(o.leafClass).addClass(o.branchClass + ' ' + o.expandedClass);
|
233
|
+
}
|
234
|
+
|
235
|
+
var a = this.direction === "down" ? $(itemElement).prev().children(o.listType) : $(itemElement).children(o.listType);
|
236
|
+
if (a[0] !== undefined) {
|
237
|
+
this._rearrange(event, null, a);
|
238
|
+
}
|
239
|
+
|
240
|
+
} else {
|
241
|
+
this._rearrange(event, item);
|
242
|
+
}
|
243
|
+
} else if (!o.protectRoot) {
|
244
|
+
this._rearrange(event, item);
|
245
|
+
}
|
125
246
|
} else {
|
126
247
|
break;
|
127
248
|
}
|
@@ -134,14 +255,7 @@
|
|
134
255
|
}
|
135
256
|
}
|
136
257
|
|
137
|
-
|
138
|
-
$(this.placeholder[0].parentNode.parentNode).closest('.ui-sortable').length)
|
139
|
-
? $(this.placeholder[0].parentNode.parentNode)
|
140
|
-
: null,
|
141
|
-
level = this._getLevel(this.placeholder),
|
142
|
-
childLevels = this._getChildLevels(this.helper);
|
143
|
-
|
144
|
-
// To find the previous sibling in the list, keep backtracking until we hit a valid list item.
|
258
|
+
// mjs - to find the previous sibling in the list, keep backtracking until we hit a valid list item.
|
145
259
|
var previousItem = this.placeholder[0].previousSibling ? $(this.placeholder[0].previousSibling) : null;
|
146
260
|
if (previousItem != null) {
|
147
261
|
while (previousItem[0].nodeName.toLowerCase() != 'li' || previousItem[0] == this.currentItem[0] || previousItem[0] == this.helper[0]) {
|
@@ -154,7 +268,7 @@
|
|
154
268
|
}
|
155
269
|
}
|
156
270
|
|
157
|
-
//
|
271
|
+
// mjs - to find the next sibling in the list, keep stepping forward until we hit a valid list item.
|
158
272
|
var nextItem = this.placeholder[0].nextSibling ? $(this.placeholder[0].nextSibling) : null;
|
159
273
|
if (nextItem != null) {
|
160
274
|
while (nextItem[0].nodeName.toLowerCase() != 'li' || nextItem[0] == this.currentItem[0] || nextItem[0] == this.helper[0]) {
|
@@ -167,34 +281,53 @@
|
|
167
281
|
}
|
168
282
|
}
|
169
283
|
|
170
|
-
var newList = document.createElement(o.listType);
|
171
|
-
|
172
284
|
this.beyondMaxLevels = 0;
|
173
285
|
|
174
|
-
//
|
175
|
-
if (parentItem != null
|
176
|
-
|
177
|
-
|
286
|
+
// mjs - if the item is moved to the left, send it one level up but only if it's at the bottom of the list
|
287
|
+
if (parentItem != null
|
288
|
+
&& nextItem == null
|
289
|
+
&& !(o.protectRoot && parentItem[0].parentNode == this.element[0])
|
290
|
+
&&
|
291
|
+
(o.rtl && (this.positionAbs.left + this.helper.outerWidth() > parentItem.offset().left + parentItem.outerWidth())
|
292
|
+
|| !o.rtl && (this.positionAbs.left < parentItem.offset().left))
|
293
|
+
) {
|
294
|
+
|
178
295
|
parentItem.after(this.placeholder[0]);
|
296
|
+
if (o.isTree && parentItem.children(o.listItem).children('li:visible:not(.ui-sortable-helper)').length < 1) {
|
297
|
+
parentItem.removeClass(this.options.branchClass + ' ' + this.options.expandedClass)
|
298
|
+
.addClass(this.options.leafClass);
|
299
|
+
}
|
179
300
|
this._clearEmpty(parentItem[0]);
|
180
301
|
this._trigger("change", event, this._uiHash());
|
181
302
|
}
|
182
|
-
//
|
183
|
-
else if (previousItem != null
|
184
|
-
|
185
|
-
|
303
|
+
// mjs - if the item is below a sibling and is moved to the right, make it a child of that sibling
|
304
|
+
else if (previousItem != null
|
305
|
+
&& !previousItem.hasClass(o.disableNestingClass)
|
306
|
+
&&
|
307
|
+
(previousItem.children(o.listType).length && previousItem.children(o.listType).is(':visible')
|
308
|
+
|| !previousItem.children(o.listType).length)
|
309
|
+
&& !(o.protectRoot && this.currentItem[0].parentNode == this.element[0])
|
310
|
+
&&
|
311
|
+
(o.rtl && (this.positionAbs.left + this.helper.outerWidth() < previousItem.offset().left + previousItem.outerWidth() - o.tabSize)
|
312
|
+
|| !o.rtl && (this.positionAbs.left > previousItem.offset().left + o.tabSize))
|
313
|
+
) {
|
314
|
+
|
186
315
|
this._isAllowed(previousItem, level, level + childLevels + 1);
|
316
|
+
|
187
317
|
if (!previousItem.children(o.listType).length) {
|
188
318
|
previousItem[0].appendChild(newList);
|
319
|
+
o.isTree && previousItem.removeClass(o.leafClass).addClass(o.branchClass + ' ' + o.expandedClass);
|
189
320
|
}
|
190
|
-
|
321
|
+
|
322
|
+
// mjs - if this item is being moved from the top, add it to the top of the list.
|
191
323
|
if (previousTopOffset && (previousTopOffset <= previousItem.offset().top)) {
|
192
324
|
previousItem.children(o.listType).prepend(this.placeholder);
|
193
325
|
}
|
194
|
-
//
|
326
|
+
// mjs - otherwise, add it to the bottom of the list.
|
195
327
|
else {
|
196
328
|
previousItem.children(o.listType)[0].appendChild(this.placeholder[0]);
|
197
329
|
}
|
330
|
+
|
198
331
|
this._trigger("change", event, this._uiHash());
|
199
332
|
}
|
200
333
|
else {
|
@@ -205,7 +338,9 @@
|
|
205
338
|
this._contactContainers(event);
|
206
339
|
|
207
340
|
//Interconnect with droppables
|
208
|
-
if ($.ui.ddmanager)
|
341
|
+
if ($.ui.ddmanager) {
|
342
|
+
$.ui.ddmanager.drag(this, event);
|
343
|
+
}
|
209
344
|
|
210
345
|
//Call callbacks
|
211
346
|
this._trigger('sort', event, this._uiHash());
|
@@ -217,7 +352,7 @@
|
|
217
352
|
|
218
353
|
_mouseStop: function (event, noPropagation) {
|
219
354
|
|
220
|
-
//
|
355
|
+
// mjs - if the item is in a position not allowed, send it back
|
221
356
|
if (this.beyondMaxLevels) {
|
222
357
|
|
223
358
|
this.placeholder.removeClass(this.options.errorClass);
|
@@ -232,14 +367,56 @@
|
|
232
367
|
|
233
368
|
}
|
234
369
|
|
235
|
-
|
370
|
+
|
371
|
+
// mjs - clear the hovering timeout, just to be sure
|
372
|
+
$('.' + this.options.hoveringClass).mouseleave().removeClass(this.options.hoveringClass);
|
373
|
+
this.mouseentered = false;
|
374
|
+
this.hovering && window.clearTimeout(this.hovering);
|
375
|
+
this.hovering = null;
|
376
|
+
|
377
|
+
$.ui.sortable.prototype._mouseStop.apply(this, arguments);
|
378
|
+
|
379
|
+
},
|
380
|
+
|
381
|
+
// mjs - this function is slightly modified to make it easier to hover over a collapsed element and have it expand
|
382
|
+
_intersectsWithSides: function (item) {
|
383
|
+
|
384
|
+
var half = this.options.isTree ? .8 : .5;
|
385
|
+
|
386
|
+
var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height * half), item.height),
|
387
|
+
isOverTopHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top - (item.height * half), item.height),
|
388
|
+
isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width / 2), item.width),
|
389
|
+
verticalDirection = this._getDragVerticalDirection(),
|
390
|
+
horizontalDirection = this._getDragHorizontalDirection();
|
391
|
+
|
392
|
+
if (this.floating && horizontalDirection) {
|
393
|
+
return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
|
394
|
+
} else {
|
395
|
+
return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && isOverTopHalf));
|
396
|
+
}
|
397
|
+
|
398
|
+
},
|
399
|
+
|
400
|
+
_contactContainers: function (event) {
|
401
|
+
|
402
|
+
if (this.options.protectRoot && this.currentItem[0].parentNode == this.element[0]) {
|
403
|
+
return;
|
404
|
+
}
|
405
|
+
|
406
|
+
$.ui.sortable.prototype._contactContainers.apply(this, arguments);
|
407
|
+
|
408
|
+
},
|
409
|
+
|
410
|
+
_clear: function (event, noPropagation) {
|
411
|
+
|
412
|
+
$.ui.sortable.prototype._clear.apply(this, arguments);
|
413
|
+
|
414
|
+
// mjs - clean last empty ul/ol
|
236
415
|
for (var i = this.items.length - 1; i >= 0; i--) {
|
237
416
|
var item = this.items[i].item[0];
|
238
417
|
this._clearEmpty(item);
|
239
418
|
}
|
240
419
|
|
241
|
-
$.ui.sortable.prototype._mouseStop.apply(this, arguments);
|
242
|
-
|
243
420
|
},
|
244
421
|
|
245
422
|
serialize: function (options) {
|
@@ -305,15 +482,18 @@
|
|
305
482
|
var o = $.extend({}, this.options, options),
|
306
483
|
sDepth = o.startDepthCount || 0,
|
307
484
|
ret = [],
|
308
|
-
left =
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
485
|
+
left = 1;
|
486
|
+
|
487
|
+
if (!o.excludeRoot) {
|
488
|
+
ret.push({
|
489
|
+
"item_id": o.rootID,
|
490
|
+
"parent_id": null,
|
491
|
+
"depth": sDepth,
|
492
|
+
"left": left,
|
493
|
+
"right": ($(o.items, this.element).length + 1) * 2
|
494
|
+
});
|
495
|
+
left++
|
496
|
+
}
|
317
497
|
|
318
498
|
$(this.element).children(o.items).each(function () {
|
319
499
|
left = _recursiveArray(this, sDepth + 1, left);
|
@@ -362,10 +542,17 @@
|
|
362
542
|
},
|
363
543
|
|
364
544
|
_clearEmpty: function (item) {
|
545
|
+
var o = this.options;
|
546
|
+
|
547
|
+
var emptyList = $(item).children(o.listType);
|
365
548
|
|
366
|
-
|
367
|
-
|
549
|
+
if (emptyList.length && !emptyList.children().length && !o.doNotClear) {
|
550
|
+
o.isTree && $(item).removeClass(o.branchClass + ' ' + o.expandedClass).addClass(o.leafClass);
|
368
551
|
emptyList.remove();
|
552
|
+
} else if (o.isTree && emptyList.length && emptyList.children().length && emptyList.is(':visible')) {
|
553
|
+
$(item).removeClass(o.leafClass).addClass(o.branchClass + ' ' + o.expandedClass);
|
554
|
+
} else if (o.isTree && emptyList.length && emptyList.children().length && !emptyList.is(':visible')) {
|
555
|
+
$(item).removeClass(o.leafClass).addClass(o.branchClass + ' ' + o.collapsedClass);
|
369
556
|
}
|
370
557
|
|
371
558
|
},
|
@@ -400,15 +587,11 @@
|
|
400
587
|
|
401
588
|
_isAllowed: function (parentItem, level, levels) {
|
402
589
|
var o = this.options,
|
403
|
-
isRoot = $(this.domPosition.parent).hasClass('ui-sortable') ? true : false,
|
404
590
|
maxLevels = this.placeholder.closest('.ui-sortable').nestedSortable('option', 'maxLevels'); // this takes into account the maxLevels set to the recipient list
|
405
591
|
|
406
|
-
//
|
407
|
-
//
|
408
|
-
|
409
|
-
if (!o.isAllowed(this.currentItem, parentItem) ||
|
410
|
-
parentItem && parentItem.hasClass(o.disableNesting) ||
|
411
|
-
o.protectRoot && (parentItem == null && !isRoot || isRoot && level > 1)) {
|
592
|
+
// mjs - is the root protected?
|
593
|
+
// mjs - are we nesting too deep?
|
594
|
+
if (!o.isAllowed(this.placeholder, parentItem, this.currentItem)) {
|
412
595
|
this.placeholder.addClass(o.errorClass);
|
413
596
|
if (maxLevels < levels && maxLevels != 0) {
|
414
597
|
this.beyondMaxLevels = levels - maxLevels;
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: jquery-mjs-nestedSortable-rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.alpha1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Sprauer
|
@@ -73,9 +73,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
73
73
|
version: '0'
|
74
74
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
75
75
|
requirements:
|
76
|
-
- - '
|
76
|
+
- - '>'
|
77
77
|
- !ruby/object:Gem::Version
|
78
|
-
version:
|
78
|
+
version: 1.3.1
|
79
79
|
requirements: []
|
80
80
|
rubyforge_project:
|
81
81
|
rubygems_version: 2.2.2
|