nestedsortabletree-rails 0.1.2

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