nestedsortabletree-rails 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|