nestedsortabletree-rails 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +18 -0
- data/README.md +38 -0
- data/Rakefile +16 -0
- data/lib/nestedsortabletree-rails.rb +1 -0
- data/lib/nestedsortabletree/rails.rb +2 -0
- data/lib/nestedsortabletree/rails/engine.rb +6 -0
- data/lib/nestedsortabletree/rails/version.rb +5 -0
- data/vendor/assets/javascripts/jquery.ui.nestedSortableTree.coffee +540 -0
- metadata +116 -0
data/LICENSE
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (C) 2012 by Leif Ringstad
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
data/README.md
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
Rails 3.2 Integration for Jquery UI NestedSortableTree Plugin
|
2
|
+
=============================================================
|
3
|
+
|
4
|
+
The `nestedsortabletree-rails` gem integrates the [Jquery UI Nested Sortable Tree](http://leifcr.github.com/nestedSortableTree) plugin with the Rails 3.2 asset pipeline.
|
5
|
+
|
6
|
+
|
7
|
+
Instructions
|
8
|
+
------------
|
9
|
+
|
10
|
+
**1. Add `nestedsortabletree-rails` to your Gemfile**
|
11
|
+
|
12
|
+
gem 'nestedsortabletree-rails'
|
13
|
+
|
14
|
+
**2. Run `bundle install`.**
|
15
|
+
|
16
|
+
|
17
|
+
**3. Using**
|
18
|
+
|
19
|
+
Add to your application.js:
|
20
|
+
_JQuery_ and _JqueryUI_ is only needed if you haven't included them already
|
21
|
+
|
22
|
+
//= require jquery
|
23
|
+
//= require jquery_ui
|
24
|
+
//= require jquery.ui.nestedSortableTree
|
25
|
+
|
26
|
+
See http://leifcr.github.com/nestedSortableTree for usage.
|
27
|
+
|
28
|
+
Credits
|
29
|
+
-------
|
30
|
+
|
31
|
+
[Didier Laffourgue](https://github.com/did) for the [aloha-rails plugin](https://github.com/locomotivecms/aloha-rails) as a blueprint. See further credits in the readme on aloha-rails plugin.
|
32
|
+
|
33
|
+
Contact
|
34
|
+
-------
|
35
|
+
|
36
|
+
Feel free to contact me at @leifcr (twitter).
|
37
|
+
|
38
|
+
Copyright (c) 2012 Leif Ringstad
|
data/Rakefile
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rubygems/package_task'
|
4
|
+
|
5
|
+
$:.push File.expand_path('../lib', __FILE__)
|
6
|
+
require 'nestedsortabletree/rails/version'
|
7
|
+
|
8
|
+
gemspec = eval(File.read('nestedsortabletree-rails.gemspec'))
|
9
|
+
Gem::PackageTask.new(gemspec) do |pkg|
|
10
|
+
pkg.gem_spec = gemspec
|
11
|
+
end
|
12
|
+
|
13
|
+
desc 'build the gem and release it to rubygems.org'
|
14
|
+
task :release => :gem do
|
15
|
+
sh "gem push pkg/nestedsortabletree-rails-#{NestedSortableTree::Rails::VERSION}.gem"
|
16
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'nestedsortabletree/rails'
|
@@ -0,0 +1,540 @@
|
|
1
|
+
###
|
2
|
+
Nested Tree based with data and rational number support
|
3
|
+
based on jQuery sortable
|
4
|
+
Written in CoffeeScript, as the syntax is nice.
|
5
|
+
|
6
|
+
For debugging/ development it requires log4javascript
|
7
|
+
|
8
|
+
Derived from Manuele J Sarfattis work (https://github.com/mjsarfatti)
|
9
|
+
|
10
|
+
Still under MIT license.
|
11
|
+
|
12
|
+
Source can be found here:
|
13
|
+
|
14
|
+
https://github.com/leifcr/nestedSortableTree
|
15
|
+
|
16
|
+
Current version : v0.1.2
|
17
|
+
###
|
18
|
+
|
19
|
+
# Reference jQuery
|
20
|
+
$ = jQuery
|
21
|
+
|
22
|
+
# Extend ui.sortable
|
23
|
+
$.widget "ui.nestedSortableTree", $.ui.sortable,
|
24
|
+
options:
|
25
|
+
errorClass: "tree-error"
|
26
|
+
listType: "ol"
|
27
|
+
maxLevels: 0
|
28
|
+
nested_debug: false
|
29
|
+
tabSize: 20
|
30
|
+
rtl: false
|
31
|
+
use_rational_numbers: true
|
32
|
+
doNotClear: false
|
33
|
+
disableNesting: "no-nest"
|
34
|
+
protectRoot: false
|
35
|
+
rootID: null
|
36
|
+
isAllowed: (item, parent) ->
|
37
|
+
true
|
38
|
+
|
39
|
+
# TODO: verify that this will still be called even if overridden
|
40
|
+
start: (event, ui) ->
|
41
|
+
ui.item.data('startIndex', ui.item.index());
|
42
|
+
|
43
|
+
stop: (event, ui) ->
|
44
|
+
ui.item.data('stopIndex', ui.item.index());
|
45
|
+
|
46
|
+
# rootID: null
|
47
|
+
# FIX TODO: options = $.extend $ui.sortable::options, options
|
48
|
+
|
49
|
+
_create: ->
|
50
|
+
@element.data "sortable", @element.data("nestedSortableTree")
|
51
|
+
|
52
|
+
if (@options.nested_debug)
|
53
|
+
@nestedLogger = log4javascript.getLogger()
|
54
|
+
appender = new log4javascript.InPageAppender("logger")
|
55
|
+
appender.setWidth("100%")
|
56
|
+
appender.setHeight("100%")
|
57
|
+
appender.setThreshold(log4javascript.Level.ALL)
|
58
|
+
@nestedLogger.addAppender(appender)
|
59
|
+
|
60
|
+
@log("nestedSortableTree create", false)
|
61
|
+
#log("options: #{}")
|
62
|
+
if !@element.is(@options.listType)
|
63
|
+
throw new Error("nestedSortableTree: Wrong listtype... #{@element.get(0).tagname} is not #{options.listtype}");
|
64
|
+
|
65
|
+
$.ui.sortable::_create.apply this, arguments
|
66
|
+
|
67
|
+
destroy: ->
|
68
|
+
@log("nestedSortableTree destroy")
|
69
|
+
@element.removeData("nestedSortableTree").unbind ".nestedSortableTree"
|
70
|
+
$.ui.sortable::destroy.apply this, arguments
|
71
|
+
|
72
|
+
log: (msg, node_text = true) ->
|
73
|
+
#console.log msg if @options.nested_debug
|
74
|
+
if (@options.nested_debug)
|
75
|
+
if node_text
|
76
|
+
@nestedLogger.debug "#{@element_text_without_children(@currentItem)}: ", msg
|
77
|
+
else
|
78
|
+
@nestedLogger.debug msg
|
79
|
+
|
80
|
+
element_text_without_children: (node) ->
|
81
|
+
return "undefined" if typeof node == 'undefined'
|
82
|
+
return "" if !@options.nested_debug
|
83
|
+
return "null-object" if node == null
|
84
|
+
rettext = node.clone().find("li").remove().end().text().replace(/(\r\n|\n|\r)/gm,"");
|
85
|
+
rettext = rettext.replace(/(^\s*)|(\s*$)/gi,"");
|
86
|
+
rettext = rettext.replace(/[ ]{2,}/gi," ");
|
87
|
+
# text = text.replace(/\n /,"\n");
|
88
|
+
|
89
|
+
_mouseDrag: (event) ->
|
90
|
+
#Compute the helpers position
|
91
|
+
@position = @_generatePosition(event)
|
92
|
+
@positionAbs = @_convertPositionTo("absolute")
|
93
|
+
@lastPositionAbs = @positionAbs unless @lastPositionAbs
|
94
|
+
|
95
|
+
# call scrolling
|
96
|
+
@_internal_do_scrolling(event)
|
97
|
+
|
98
|
+
#Regenerate the absolute position used for position checks
|
99
|
+
@positionAbs = @_convertPositionTo("absolute")
|
100
|
+
|
101
|
+
# Find the top offset before rearrangement,
|
102
|
+
@previousTopOffset = @placeholder.offset().top
|
103
|
+
|
104
|
+
#Set the helper position
|
105
|
+
@helper[0].style.left = @position.left + "px" if not @options.axis or @options.axis isnt "y"
|
106
|
+
@helper[0].style.top = @position.top + "px" if not @options.axis or @options.axis isnt "x"
|
107
|
+
|
108
|
+
# rearrange
|
109
|
+
@_internal_rearrange(event)
|
110
|
+
|
111
|
+
#Post events to containers
|
112
|
+
@_contactContainers(event)
|
113
|
+
|
114
|
+
#Interconnect with droppables
|
115
|
+
$.ui.ddmanager.drag(this, event) if $.ui.ddmanager
|
116
|
+
|
117
|
+
#Call callbacks
|
118
|
+
@_trigger("sort", event, @_uiHash())
|
119
|
+
@lastPositionAbs = @positionAbs
|
120
|
+
false
|
121
|
+
|
122
|
+
_mouseStop: (event, noPropagation) ->
|
123
|
+
|
124
|
+
# If the item is in a position not allowed, send it back
|
125
|
+
if @beyondMaxLevels
|
126
|
+
@placeholder.removeClass @options.errorClass
|
127
|
+
if @domPosition.prev
|
128
|
+
$(@domPosition.prev).after @placeholder
|
129
|
+
else
|
130
|
+
$(@domPosition.parent).prepend @placeholder
|
131
|
+
@_trigger "revert", event, @_uiHash()
|
132
|
+
|
133
|
+
# Clean last empty ul/ol
|
134
|
+
|
135
|
+
while i >= 0
|
136
|
+
i = @items.length - 1
|
137
|
+
item = @items[i].item[0]
|
138
|
+
@_clearEmpty item
|
139
|
+
i--
|
140
|
+
|
141
|
+
$.ui.sortable::_mouseStop.apply this, arguments
|
142
|
+
# store previous ancestor keys
|
143
|
+
@previous_anc_keys = @_get_ancestor_keys(@currentItem[0])
|
144
|
+
false
|
145
|
+
|
146
|
+
_clear: (event) ->
|
147
|
+
retval = $.ui.sortable::_clear.apply this, arguments
|
148
|
+
@_update_nv_dv() if @options.use_rational_numbers
|
149
|
+
retval
|
150
|
+
|
151
|
+
_update_nv_dv: (event) ->
|
152
|
+
#
|
153
|
+
# @log "_update_nv_dv #{JSON.stringify @currentItem[0]}"
|
154
|
+
# @log "_update_nv_dv #{JSON.stringify $(@currentItem.data())}"
|
155
|
+
# get ancestor keys
|
156
|
+
|
157
|
+
new_anc_keys = @_get_ancestor_keys(@currentItem[0])
|
158
|
+
startIndex = @currentItem.data("startIndex")
|
159
|
+
stopIndex = @currentItem.data("stopIndex")
|
160
|
+
# @log "_update_nv_dv: new ancestor: #{JSON.stringify(new_anc_keys)}"
|
161
|
+
# @log "startidx: #{startIndex} stopidx: #{stopIndex}"
|
162
|
+
# if both ancestor keys and startIndex/stopIndex is equal. return...
|
163
|
+
if (@_compare_keys(@previous_anc_keys, new_anc_keys)) and (startIndex == stopIndex)
|
164
|
+
@log "_update_nv_dv: Same position. Item not moved"
|
165
|
+
return false
|
166
|
+
|
167
|
+
# calculate new nv/dv/snv/sdv
|
168
|
+
new_keys = @_create_keys_from_ancestor_keys( new_anc_keys, (stopIndex + 1) )
|
169
|
+
|
170
|
+
@log "_update_nv_dv: New keys #{JSON.stringify(new_keys)}"
|
171
|
+
|
172
|
+
# set new nv dv
|
173
|
+
@_set_nv_dv(@currentItem, new_keys, new_anc_keys)
|
174
|
+
true
|
175
|
+
|
176
|
+
_create_keys_from_ancestor_keys: (ancestor_keys, position) ->
|
177
|
+
@_create_key_array(
|
178
|
+
ancestor_keys["nv"] + (ancestor_keys["snv"] * (position)),
|
179
|
+
ancestor_keys["dv"] + (ancestor_keys["sdv"] * (position)),
|
180
|
+
ancestor_keys["nv"] + (ancestor_keys["snv"] * (position + 1)),
|
181
|
+
ancestor_keys["dv"] + (ancestor_keys["sdv"] * (position + 1))
|
182
|
+
)
|
183
|
+
|
184
|
+
_compare_keys: (keyset1, keyset2) ->
|
185
|
+
if keyset1["nv"] is keyset2["nv"] and
|
186
|
+
keyset1["dv"] is keyset2["dv"] and
|
187
|
+
keyset1["snv"] is keyset2["snv"] and
|
188
|
+
keyset1["sdv"] is keyset2["sdv"]
|
189
|
+
return true
|
190
|
+
return false
|
191
|
+
|
192
|
+
_check_if_correct_ancestor: (node) ->
|
193
|
+
@log "_check_if_correct_ancestor"
|
194
|
+
false
|
195
|
+
|
196
|
+
_check_if_conflicting_items: (keys) ->
|
197
|
+
@log "_check_if_conflicting_items"
|
198
|
+
# get parent node
|
199
|
+
# iterate over children to see if any has same nv/dv as we want to set
|
200
|
+
false
|
201
|
+
|
202
|
+
_get_conflicting_items: (node) ->
|
203
|
+
@log "_get_conflicting_items"
|
204
|
+
|
205
|
+
_get_ancestor_keys: (node) ->
|
206
|
+
parentItem = (if (node.parentNode.parentNode and $(node.parentNode.parentNode).closest(".ui-sortable").length) then $(node.parentNode.parentNode) else null)
|
207
|
+
parent_keys = @_create_key_array(0,1,1,0) if parentItem is null
|
208
|
+
parent_keys = @_create_key_array_from_data_attr(parentItem.data()) if parentItem isnt null
|
209
|
+
# @log "_get_ancestor_keys #{@element_text_without_children parentItem} - #{JSON.stringify parent_keys }"
|
210
|
+
parent_keys
|
211
|
+
|
212
|
+
_sibling_count: (node) ->
|
213
|
+
0
|
214
|
+
|
215
|
+
_position_from_nv_dv: (node) ->
|
216
|
+
0
|
217
|
+
|
218
|
+
_position_from_parent: (node) ->
|
219
|
+
# UNUSED #
|
220
|
+
# UNUSED #
|
221
|
+
|
222
|
+
#@log "_position_from_parent on #{@element_text_without_children(node)}"
|
223
|
+
|
224
|
+
# position = 0
|
225
|
+
# previousItem = (if node.previousSibling then $(node.previousSibling) else null)
|
226
|
+
# if previousItem isnt null
|
227
|
+
# @log "_position_from_parent previousItem: #{@element_text_without_children(previousItem)}"
|
228
|
+
# else
|
229
|
+
# @log "_position_from_parent previousItem: null"
|
230
|
+
# if previousItem?
|
231
|
+
# while previousItem isnt null
|
232
|
+
# position++ if (previousItem[0] isnt node) and (previousItem[0] isnt @helper[0])
|
233
|
+
# previousItem = (if previousItem[0].previousSibling then $(previousItem[0].previousSibling) else null)
|
234
|
+
# if previousItem isnt null
|
235
|
+
# @log "_position_from_parent previousItem: #{previousItem[0].id} #{@element_text_without_children(previousItem)}"
|
236
|
+
# else
|
237
|
+
# @log "_position_from_parent previousItem: null"
|
238
|
+
|
239
|
+
# parentItem = node.parentNode
|
240
|
+
# @log parentItem
|
241
|
+
|
242
|
+
|
243
|
+
# @log "_position_from_parent: #{position}"
|
244
|
+
# position = 1
|
245
|
+
|
246
|
+
|
247
|
+
_set_nv_dv: (node, keys, ancestor_keys, check_conflict = true) ->
|
248
|
+
node.attr("data-nv", keys["nv"])
|
249
|
+
node.attr("data-dv", keys["dv"])
|
250
|
+
node.attr("data-snv", keys["snv"])
|
251
|
+
node.attr("data-sdv", keys["sdv"])
|
252
|
+
@log "#{@element_text_without_children(node)}: _set_nv_dv #{JSON.stringify(keys)}", false
|
253
|
+
|
254
|
+
# if conflicting sibling see if conflict is above or below.
|
255
|
+
if (check_conflict)
|
256
|
+
items = $("li[data-nv=\"#{keys["nv"]}\"][data-dv=\"#{keys["dv"]}\"][id != \"#{node.attr("id")}\"]")
|
257
|
+
@log "Number of conflicting items: #{items.length}"
|
258
|
+
|
259
|
+
# TODO: implement support for multiple conflicts ?
|
260
|
+
# while i >= 0
|
261
|
+
# i = @items.length - 1
|
262
|
+
# item = @items[i].item[0]
|
263
|
+
# @_clearEmpty item
|
264
|
+
# i--
|
265
|
+
|
266
|
+
if items.length > 0
|
267
|
+
@log "Conflicting item #{@element_text_without_children($(items[0]))} Index: #{$(items[0]).index()}"
|
268
|
+
# there are conflicting items.
|
269
|
+
# if below, move to next position
|
270
|
+
@log "Node idx #{node.index()}"
|
271
|
+
conflict_node = $(items[0]);
|
272
|
+
new_keys = @_create_keys_from_ancestor_keys(ancestor_keys, conflict_node.index() + 1)
|
273
|
+
@log "Conflicting node New keys #{JSON.stringify(new_keys)}"
|
274
|
+
@_set_nv_dv(conflict_node, new_keys, ancestor_keys)
|
275
|
+
|
276
|
+
# See if there are any children
|
277
|
+
# process children since "node has moved!"
|
278
|
+
# should not check for conflicts on children, as conflicting items on same level will move their children as well
|
279
|
+
@_set_nv_dv_xl_child $(child), keys for child in node.children(@options.listType)
|
280
|
+
true
|
281
|
+
|
282
|
+
_set_nv_dv_xl_child: (node, parent_keys) ->
|
283
|
+
@_set_nv_dv_li_child $(child), parent_keys, i + 1 for child, i in node.children("li")
|
284
|
+
true
|
285
|
+
|
286
|
+
_set_nv_dv_li_child: (node, parent_keys, idx) ->
|
287
|
+
@log("#{@element_text_without_children($(node))}: Moving child item, idx: #{idx}", false)
|
288
|
+
new_keys = @_create_keys_from_ancestor_keys(parent_keys, idx)
|
289
|
+
@_set_nv_dv(node, new_keys, parent_keys, false)
|
290
|
+
@_set_nv_dv_xl_child $(child), new_keys for child in node.children(@options.listType)
|
291
|
+
true
|
292
|
+
|
293
|
+
_create_key_array: (nv, dv, snv, sdv) ->
|
294
|
+
key_array = # initally set root keys
|
295
|
+
nv: nv
|
296
|
+
dv: dv
|
297
|
+
snv: snv
|
298
|
+
sdv: sdv
|
299
|
+
|
300
|
+
_create_key_array_from_data_attr: (data_attr) ->
|
301
|
+
@_create_key_array(data_attr["nv"], data_attr["dv"], data_attr["snv"], data_attr["sdv"])
|
302
|
+
|
303
|
+
# customized rearrange
|
304
|
+
_internal_rearrange: (event)->
|
305
|
+
#Rearrange
|
306
|
+
# this is converted to coffee directly from jquery-ui sortables source
|
307
|
+
o = @options
|
308
|
+
i = @items.length
|
309
|
+
while i > 0
|
310
|
+
i--
|
311
|
+
# i for i in [@items.length..0] ->
|
312
|
+
#Cache variables and intersection, continue if no intersection
|
313
|
+
item = @items[i]
|
314
|
+
itemElement = item.item[0]
|
315
|
+
intersection = @_intersectsWithPointer(item)
|
316
|
+
continue unless intersection
|
317
|
+
|
318
|
+
if itemElement isnt @currentItem[0] and
|
319
|
+
@placeholder[if intersection is 1 then "next" else "prev"]()[0] isnt itemElement and
|
320
|
+
not $.contains(@placeholder[0], itemElement) and
|
321
|
+
((if o.type is "semi-dynamic" then not $.contains(@element[0], itemElement) else true))
|
322
|
+
$(itemElement).mouseenter()
|
323
|
+
@direction = (if intersection is 1 then "down" else "up")
|
324
|
+
if o.tolerance is "pointer" or @_intersectsWithSides(item)
|
325
|
+
$(itemElement).mouseleave();
|
326
|
+
@_rearrange event, item
|
327
|
+
else
|
328
|
+
break
|
329
|
+
# # Clear emtpy ul's/ol's
|
330
|
+
@_clearEmpty(itemElement);
|
331
|
+
@_trigger "change", event, @_uiHash()
|
332
|
+
break
|
333
|
+
#i--
|
334
|
+
|
335
|
+
# do nested rearrange stuff
|
336
|
+
|
337
|
+
# find parent item
|
338
|
+
parentItem = (if (@placeholder[0].parentNode.parentNode and $(@placeholder[0].parentNode.parentNode).closest(".ui-sortable").length) then $(@placeholder[0].parentNode.parentNode) else null)
|
339
|
+
level = @_getLevel(@placeholder)
|
340
|
+
childLevels = @_getChildLevels(@helper)
|
341
|
+
|
342
|
+
# To find the previous sibling in the list, keep backtracking until we hit a valid list item.
|
343
|
+
previousItem = (if @placeholder[0].previousSibling then $(@placeholder[0].previousSibling) else null)
|
344
|
+
if previousItem?
|
345
|
+
while previousItem[0].nodeName.toLowerCase() isnt "li" or previousItem[0] is @currentItem[0] or previousItem[0] is @helper[0]
|
346
|
+
if previousItem[0].previousSibling
|
347
|
+
previousItem = $(previousItem[0].previousSibling)
|
348
|
+
else
|
349
|
+
previousItem = null
|
350
|
+
break
|
351
|
+
|
352
|
+
# To find the next sibling in the list, keep stepping forward until we hit a valid list item.
|
353
|
+
nextItem = (if @placeholder[0].nextSibling then $(@placeholder[0].nextSibling) else null)
|
354
|
+
if nextItem?
|
355
|
+
while nextItem[0].nodeName.toLowerCase() isnt "li" or nextItem[0] is @currentItem[0] or nextItem[0] is @helper[0]
|
356
|
+
if nextItem[0].nextSibling
|
357
|
+
nextItem = $(nextItem[0].nextSibling)
|
358
|
+
else
|
359
|
+
nextItem = null
|
360
|
+
break
|
361
|
+
@beyondMaxLevels = 0
|
362
|
+
|
363
|
+
# If the item is moved to the left, send it to its parent's level unless there are siblings below it.
|
364
|
+
if parentItem? and not nextItem? and
|
365
|
+
(o.rtl and (@positionAbs.left + @helper.outerWidth() > parentItem.offset().left + parentItem.outerWidth()) or
|
366
|
+
not o.rtl and (@positionAbs.left < parentItem.offset().left))
|
367
|
+
parentItem.after @placeholder[0]
|
368
|
+
@_clearEmpty parentItem[0]
|
369
|
+
@_trigger "change", event, @_uiHash()
|
370
|
+
|
371
|
+
# If the item is below a sibling and is moved to the right, make it a child of that sibling.
|
372
|
+
else if previousItem? and (o.rtl and (@positionAbs.left + @helper.outerWidth() < previousItem.offset().left + previousItem.outerWidth() - o.tabSize) or not o.rtl and (@positionAbs.left > previousItem.offset().left + o.tabSize))
|
373
|
+
@_isAllowed previousItem, level, level + childLevels + 1
|
374
|
+
previousItem[0].appendChild document.createElement(o.listType) unless previousItem.children(o.listType).length
|
375
|
+
# If this item is being moved from the top, add it to the top of the list.
|
376
|
+
if @previousTopOffset and (@previousTopOffset <= previousItem.offset().top)
|
377
|
+
previousItem.children(o.listType).prepend @placeholder
|
378
|
+
|
379
|
+
# Otherwise, add it to the bottom of the list.
|
380
|
+
else
|
381
|
+
previousItem.children(o.listType)[0].appendChild @placeholder[0]
|
382
|
+
@_trigger "change", event, @_uiHash()
|
383
|
+
else
|
384
|
+
@_isAllowed parentItem, level, level + childLevels
|
385
|
+
|
386
|
+
true
|
387
|
+
|
388
|
+
# from jquery.ui.sortables copy/paste/converted
|
389
|
+
_internal_do_scrolling: (event)->
|
390
|
+
#Do scrolling
|
391
|
+
# this is part of mouse drag, but taken out to make source readable
|
392
|
+
if @options.scroll
|
393
|
+
o = @options
|
394
|
+
scrolled = false
|
395
|
+
if @scrollParent[0] isnt document and @scrollParent[0].tagName isnt "HTML"
|
396
|
+
if (@overflowOffset.top + @scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity
|
397
|
+
@scrollParent[0].scrollTop = scrolled = @scrollParent[0].scrollTop + o.scrollSpeed
|
398
|
+
else @scrollParent[0].scrollTop = scrolled = @scrollParent[0].scrollTop - o.scrollSpeed if event.pageY - @overflowOffset.top < o.scrollSensitivity
|
399
|
+
if (@overflowOffset.left + @scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity
|
400
|
+
@scrollParent[0].scrollLeft = scrolled = @scrollParent[0].scrollLeft + o.scrollSpeed
|
401
|
+
else @scrollParent[0].scrollLeft = scrolled = @scrollParent[0].scrollLeft - o.scrollSpeed if event.pageX - @overflowOffset.left < o.scrollSensitivity
|
402
|
+
else
|
403
|
+
if event.pageY - $(document).scrollTop() < o.scrollSensitivity
|
404
|
+
scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed)
|
405
|
+
else scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed) if $(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity
|
406
|
+
if event.pageX - $(document).scrollLeft() < o.scrollSensitivity
|
407
|
+
scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed)
|
408
|
+
else scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed) if $(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity
|
409
|
+
$.ui.ddmanager.prepareOffsets this, event if scrolled isnt false and $.ui.ddmanager and not o.dropBehaviour
|
410
|
+
true
|
411
|
+
|
412
|
+
_clearEmpty: (item) ->
|
413
|
+
emptyList = $(item).children(@options.listType)
|
414
|
+
emptyList.remove() if emptyList.length and not emptyList.children().length and not @options.doNotClear
|
415
|
+
|
416
|
+
_getLevel: (item) ->
|
417
|
+
level = 1
|
418
|
+
if @options.listType
|
419
|
+
list = item.closest(@options.listType)
|
420
|
+
until list.is(".ui-sortable")
|
421
|
+
level++
|
422
|
+
list = list.parent().closest(@options.listType)
|
423
|
+
level
|
424
|
+
|
425
|
+
_getChildLevels: (parent, depth) ->
|
426
|
+
self = this
|
427
|
+
o = @options
|
428
|
+
result = 0
|
429
|
+
depth = depth or 0
|
430
|
+
$(parent).children(o.listType).children(o.items).each (index, child) ->
|
431
|
+
result = Math.max(self._getChildLevels(child, depth + 1), result)
|
432
|
+
|
433
|
+
(if depth then result + 1 else result)
|
434
|
+
|
435
|
+
_isAllowed: (parentItem, level, levels) ->
|
436
|
+
o = @options
|
437
|
+
|
438
|
+
# NOTE: level isn't used. can probably be removed
|
439
|
+
|
440
|
+
# protectRoot and custom isAllowed is removed. dont' need it yet
|
441
|
+
# if not o.isAllowed(@placeholder, parentItem) or
|
442
|
+
# parentItem and parentItem.hasClass(o.disableNesting) or
|
443
|
+
# o.protectRoot and (not parentItem? and not isRoot or isRoot and level > 1)
|
444
|
+
|
445
|
+
#Are we trying to nest under a no-nest
|
446
|
+
# or are we nesting too deep?
|
447
|
+
if not parentItem? or not (parentItem.hasClass(o.disableNesting))
|
448
|
+
if o.maxLevels < levels and o.maxLevels isnt 0
|
449
|
+
@placeholder.addClass o.errorClass
|
450
|
+
@beyondMaxLevels = levels - o.maxLevels
|
451
|
+
else
|
452
|
+
@placeholder.removeClass o.errorClass
|
453
|
+
@beyondMaxLevels = 0
|
454
|
+
else
|
455
|
+
@placeholder.addClass o.errorClass
|
456
|
+
if o.maxLevels < levels and o.maxLevels isnt 0
|
457
|
+
@beyondMaxLevels = levels - o.maxLevels
|
458
|
+
else
|
459
|
+
@beyondMaxLevels = 1
|
460
|
+
|
461
|
+
serialize: (options) ->
|
462
|
+
o = $.extend({}, @options, options)
|
463
|
+
items = @_getItemsAsjQuery(o and o.connected)
|
464
|
+
str = []
|
465
|
+
_master_this = this;
|
466
|
+
$(items).each ->
|
467
|
+
res = ($(o.item or this).attr(o.attribute or "id") or "").match(o.expression or (/(.+)[-=_](.+)/))
|
468
|
+
pid = ($(o.item or this).parent(o.listType).parent(o.items).attr(o.attribute or "id") or "").match(o.expression or (/(.+)[-=_](.+)/))
|
469
|
+
# push the parent node
|
470
|
+
str.push ((o.key or res[1]) + "[" + ((if o.key and o.expression then res[1] else res[2])) + "][parent]") + "=" + ((if pid then ((if o.key and o.expression then pid[1] else pid[2])) else o.rootID)) if res
|
471
|
+
# push the nv
|
472
|
+
str.push ((o.key or res[1]) + "[" + ((if o.key and o.expression then res[1] else res[2])) + "][nv]") + "=" + $(o.item or this).attr("data-nv")
|
473
|
+
# push the dv
|
474
|
+
str.push ((o.key or res[1]) + "[" + ((if o.key and o.expression then res[1] else res[2])) + "][dv]") + "=" + $(o.item or this).attr("data-dv")
|
475
|
+
# push the snv
|
476
|
+
str.push ((o.key or res[1]) + "[" + ((if o.key and o.expression then res[1] else res[2])) + "][snv]") + "=" + $(o.item or this).attr("data-snv")
|
477
|
+
# push the sdv
|
478
|
+
str.push ((o.key or res[1]) + "[" + ((if o.key and o.expression then res[1] else res[2])) + "][sdv]") + "=" + $(o.item or this).attr("data-sdv")
|
479
|
+
|
480
|
+
str.push o.key + "=" if not str.length and o.key
|
481
|
+
str.join "&"
|
482
|
+
|
483
|
+
toArray: (options) ->
|
484
|
+
o = $.extend({}, @options, options)
|
485
|
+
@startDepth = o.startDepthCount or 0
|
486
|
+
@ret_arr = []
|
487
|
+
left = 2
|
488
|
+
@ret_arr.push
|
489
|
+
item_id: o.rootID
|
490
|
+
parent_id: "none"
|
491
|
+
depth: @startDepth
|
492
|
+
left: 1
|
493
|
+
right: ($(o.items, @element).length + 1) * 2
|
494
|
+
nv: 0
|
495
|
+
dv: 1
|
496
|
+
snv: 1
|
497
|
+
sdv: 0
|
498
|
+
|
499
|
+
_master_this = this
|
500
|
+
|
501
|
+
$(@element).children(o.items).each ->
|
502
|
+
left = _master_this._recursiveArray($(this), _master_this.startDepth + 1, o, _master_this, left)
|
503
|
+
@ret_arr = @ret_arr.sort((a, b) ->
|
504
|
+
a.left - b.left
|
505
|
+
)
|
506
|
+
@ret_arr
|
507
|
+
|
508
|
+
_recursiveArray: (item, depth, o, master, left) ->
|
509
|
+
right = left + 1
|
510
|
+
id = undefined
|
511
|
+
pid = undefined
|
512
|
+
if item.children(o.listType).children(o.items).length > 0
|
513
|
+
depth++
|
514
|
+
item.children(o.listType).children(o.items).each ->
|
515
|
+
right = master._recursiveArray($(this), depth, o, master, right)
|
516
|
+
|
517
|
+
depth--
|
518
|
+
id = (item.attr(o.attribute or "id")).match(o.expression or (/(.+)[-=_](.+)/))
|
519
|
+
if depth is @startDepth + 1
|
520
|
+
pid = o.rootID
|
521
|
+
else
|
522
|
+
parentItem = (item.parent(o.listType).parent(o.items).attr(o.attribute or "id")).match(o.expression or (/(.+)[-=_](.+)/))
|
523
|
+
pid = parentItem[2]
|
524
|
+
if id
|
525
|
+
@ret_arr.push
|
526
|
+
item_id: id[2]
|
527
|
+
parent_id: pid
|
528
|
+
depth: depth
|
529
|
+
left: left
|
530
|
+
right: right
|
531
|
+
nv: item.attr("data-nv")
|
532
|
+
dv: item.attr("data-dv")
|
533
|
+
snv: item.attr("data-snv")
|
534
|
+
sdv: item.attr("data-sdv")
|
535
|
+
|
536
|
+
left = right + 1
|
537
|
+
left
|
538
|
+
|
539
|
+
|
540
|
+
$.ui.nestedSortableTree.prototype.options = $.extend({}, $.ui.sortable.prototype.options, $.ui.nestedSortableTree.prototype.options);
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: nestedsortabletree-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Leif Ringstad
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-09-07 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: actionpack
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.2.8
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.2.8
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: jquery-rails
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ~>
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: 2.1.1
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ~>
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: 2.1.1
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: coffee-rails
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
49
|
+
none: false
|
50
|
+
requirements:
|
51
|
+
- - ~>
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 3.2.2
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: 3.2.2
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: rake
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
65
|
+
none: false
|
66
|
+
requirements:
|
67
|
+
- - '='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.9.2
|
70
|
+
type: :development
|
71
|
+
prerelease: false
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
73
|
+
none: false
|
74
|
+
requirements:
|
75
|
+
- - '='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.9.2
|
78
|
+
description: Integrates jquery UI Nested Sortable Tree plugin into rails apps.
|
79
|
+
email: leifcr@gmail.com
|
80
|
+
executables: []
|
81
|
+
extensions: []
|
82
|
+
extra_rdoc_files: []
|
83
|
+
files:
|
84
|
+
- README.md
|
85
|
+
- LICENSE
|
86
|
+
- Rakefile
|
87
|
+
- lib/nestedsortabletree/rails/engine.rb
|
88
|
+
- lib/nestedsortabletree/rails/version.rb
|
89
|
+
- lib/nestedsortabletree/rails.rb
|
90
|
+
- lib/nestedsortabletree-rails.rb
|
91
|
+
- vendor/assets/javascripts/jquery.ui.nestedSortableTree.coffee
|
92
|
+
homepage: https://github.com/leifcr/nestedsortabletree-rails
|
93
|
+
licenses: []
|
94
|
+
post_install_message:
|
95
|
+
rdoc_options: []
|
96
|
+
require_paths:
|
97
|
+
- lib
|
98
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
99
|
+
none: false
|
100
|
+
requirements:
|
101
|
+
- - ! '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
requirements: []
|
111
|
+
rubyforge_project:
|
112
|
+
rubygems_version: 1.8.24
|
113
|
+
signing_key:
|
114
|
+
specification_version: 3
|
115
|
+
summary: Rails 3.2 integration for Jquery UI Nested Sortable Tree plugin.
|
116
|
+
test_files: []
|