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 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,2 @@
1
+ require 'nestedsortabletree/rails/version'
2
+ require 'nestedsortabletree/rails/engine'
@@ -0,0 +1,6 @@
1
+ module Nestedsortabletree
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module Nestedsortabletree
2
+ module Rails
3
+ VERSION = '0.1.2'
4
+ end
5
+ end
@@ -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: []