effective_bootstrap 0.9.24 → 0.9.29

Sign up to get free protection for your applications and to get access to all the features.
Files changed (27) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/app/assets/images/icons/grip-lines.svg +1 -0
  4. data/app/assets/images/icons/reorder.svg +10 -0
  5. data/app/assets/javascripts/effective_article_editor/initialize.js.coffee +18 -0
  6. data/app/assets/javascripts/effective_article_editor/input.js +1 -0
  7. data/app/assets/javascripts/effective_bootstrap.js +1 -0
  8. data/app/assets/javascripts/effective_bootstrap/tabs.js +7 -0
  9. data/app/assets/javascripts/effective_has_many/initialize.js.coffee +10 -9
  10. data/app/assets/javascripts/effective_has_many/input.js +2 -1
  11. data/app/assets/javascripts/effective_has_many/sortable-jquery.js +76 -0
  12. data/app/assets/javascripts/effective_has_many/sortable.js +3722 -0
  13. data/app/assets/stylesheets/effective_article_editor/input.scss +1 -0
  14. data/app/assets/stylesheets/effective_article_editor/overrides.scss +1 -0
  15. data/app/assets/stylesheets/effective_bootstrap_article_editor.scss +1 -0
  16. data/app/assets/stylesheets/effective_has_many/input.scss +5 -30
  17. data/app/assets/stylesheets/effective_rich_text_area/extensions.scss +1 -13
  18. data/app/assets/stylesheets/effective_rich_text_area/rich_text_area.scss +0 -5
  19. data/app/models/effective/form_builder.rb +4 -0
  20. data/app/models/effective/form_inputs/article_editor.rb +77 -0
  21. data/app/models/effective/form_inputs/has_many.rb +30 -8
  22. data/config/effective_bootstrap.rb +0 -22
  23. data/lib/effective_bootstrap.rb +4 -23
  24. data/lib/effective_bootstrap/engine.rb +5 -1
  25. data/lib/effective_bootstrap/version.rb +1 -1
  26. metadata +29 -6
  27. data/app/assets/javascripts/effective_has_many/jquery.sortable.js +0 -696
@@ -1,696 +0,0 @@
1
- /* ===================================================
2
- * jquery-sortable.js v0.9.13
3
- * http://johnny.github.com/jquery-sortable/
4
- * ===================================================
5
- * Copyright (c) 2012 Jonas von Andrian
6
- * All rights reserved.
7
- *
8
- * Redistribution and use in source and binary forms, with or without
9
- * modification, are permitted provided that the following conditions are met:
10
- * * Redistributions of source code must retain the above copyright
11
- * notice, this list of conditions and the following disclaimer.
12
- * * Redistributions in binary form must reproduce the above copyright
13
- * notice, this list of conditions and the following disclaimer in the
14
- * documentation and/or other materials provided with the distribution.
15
- * * The name of the author may not be used to endorse or promote products
16
- * derived from this software without specific prior written permission.
17
- *
18
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
- * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
22
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
- * ========================================================== */
29
-
30
-
31
- !function ( $, window, pluginName, undefined){
32
- var containerDefaults = {
33
- // If true, items can be dragged from this container
34
- drag: true,
35
- // If true, items can be dropped onto this container
36
- drop: true,
37
- // Exclude items from being draggable, if the
38
- // selector matches the item
39
- exclude: "",
40
- // If true, search for nested containers within an item.If you nest containers,
41
- // either the original selector with which you call the plugin must only match the top containers,
42
- // or you need to specify a group (see the bootstrap nav example)
43
- nested: true,
44
- // If true, the items are assumed to be arranged vertically
45
- vertical: true
46
- }, // end container defaults
47
- groupDefaults = {
48
- // This is executed after the placeholder has been moved.
49
- // $closestItemOrContainer contains the closest item, the placeholder
50
- // has been put at or the closest empty Container, the placeholder has
51
- // been appended to.
52
- afterMove: function ($placeholder, container, $closestItemOrContainer) {
53
- },
54
- // The exact css path between the container and its items, e.g. "> tbody"
55
- containerPath: "",
56
- // The css selector of the containers
57
- containerSelector: "ol, ul",
58
- // Distance the mouse has to travel to start dragging
59
- distance: 0,
60
- // Time in milliseconds after mousedown until dragging should start.
61
- // This option can be used to prevent unwanted drags when clicking on an element.
62
- delay: 0,
63
- // The css selector of the drag handle
64
- handle: "",
65
- // The exact css path between the item and its subcontainers.
66
- // It should only match the immediate items of a container.
67
- // No item of a subcontainer should be matched. E.g. for ol>div>li the itemPath is "> div"
68
- itemPath: "",
69
- // The css selector of the items
70
- itemSelector: "li",
71
- // The class given to "body" while an item is being dragged
72
- bodyClass: "dragging",
73
- // The class giving to an item while being dragged
74
- draggedClass: "dragged",
75
- // Check if the dragged item may be inside the container.
76
- // Use with care, since the search for a valid container entails a depth first search
77
- // and may be quite expensive.
78
- isValidTarget: function ($item, container) {
79
- return true
80
- },
81
- // Executed before onDrop if placeholder is detached.
82
- // This happens if pullPlaceholder is set to false and the drop occurs outside a container.
83
- onCancel: function ($item, container, _super, event) {
84
- },
85
- // Executed at the beginning of a mouse move event.
86
- // The Placeholder has not been moved yet.
87
- onDrag: function ($item, position, _super, event) {
88
- $item.css(position)
89
- },
90
- // Called after the drag has been started,
91
- // that is the mouse button is being held down and
92
- // the mouse is moving.
93
- // The container is the closest initialized container.
94
- // Therefore it might not be the container, that actually contains the item.
95
- onDragStart: function ($item, container, _super, event) {
96
- $item.css({
97
- height: $item.outerHeight(),
98
- width: $item.outerWidth()
99
- })
100
- $item.addClass(container.group.options.draggedClass)
101
- $("body").addClass(container.group.options.bodyClass)
102
- },
103
- // Called when the mouse button is being released
104
- onDrop: function ($item, container, _super, event) {
105
- $item.removeClass(container.group.options.draggedClass).removeAttr("style")
106
- $("body").removeClass(container.group.options.bodyClass)
107
- // START MONKEY PATCH (for submitting form when heading positions are changed on touchscreen)
108
- $item.trigger('movimento:drop:complete', $item)
109
- // END MONKEY PATCH
110
- },
111
- // Called on mousedown. If falsy value is returned, the dragging will not start.
112
- // Ignore if element clicked is input, select or textarea
113
- onMousedown: function ($item, _super, event) {
114
- if (!event.target.nodeName.match(/^(input|select|textarea)$/i)) {
115
- event.preventDefault()
116
- return true
117
- }
118
- },
119
- // The class of the placeholder (must match placeholder option markup)
120
- placeholderClass: "placeholder",
121
- // Template for the placeholder. Can be any valid jQuery input
122
- // e.g. a string, a DOM element.
123
- // The placeholder must have the class "placeholder"
124
- placeholder: '<li class="placeholder"></li>',
125
- // If true, the position of the placeholder is calculated on every mousemove.
126
- // If false, it is only calculated when the mouse is above a container.
127
- pullPlaceholder: true,
128
- // Specifies serialization of the container group.
129
- // The pair $parent/$children is either container/items or item/subcontainers.
130
- serialize: function ($parent, $children, parentIsContainer) {
131
- var result = $.extend({}, $parent.data())
132
-
133
- if(parentIsContainer)
134
- return [$children]
135
- else if ($children[0]){
136
- result.children = $children
137
- }
138
-
139
- delete result.subContainers
140
- delete result.sortable
141
-
142
- return result
143
- },
144
- // Set tolerance while dragging. Positive values decrease sensitivity,
145
- // negative values increase it.
146
- tolerance: 0
147
- }, // end group defaults
148
- containerGroups = {},
149
- groupCounter = 0,
150
- emptyBox = {
151
- left: 0,
152
- top: 0,
153
- bottom: 0,
154
- right:0
155
- },
156
- eventNames = {
157
- start: "touchstart.sortable mousedown.sortable",
158
- drop: "touchend.sortable touchcancel.sortable mouseup.sortable",
159
- drag: "touchmove.sortable mousemove.sortable",
160
- scroll: "scroll.sortable"
161
- },
162
- subContainerKey = "subContainers"
163
-
164
- /*
165
- * a is Array [left, right, top, bottom]
166
- * b is array [left, top]
167
- */
168
- function d(a,b) {
169
- var x = Math.max(0, a[0] - b[0], b[0] - a[1]),
170
- y = Math.max(0, a[2] - b[1], b[1] - a[3])
171
- return x+y;
172
- }
173
-
174
- function setDimensions(array, dimensions, tolerance, useOffset) {
175
- var i = array.length,
176
- offsetMethod = useOffset ? "offset" : "position"
177
- tolerance = tolerance || 0
178
-
179
- while(i--){
180
- var el = array[i].el ? array[i].el : $(array[i]),
181
- // use fitting method
182
- pos = el[offsetMethod]()
183
- pos.left += parseInt(el.css('margin-left'), 10)
184
- pos.top += parseInt(el.css('margin-top'),10)
185
- dimensions[i] = [
186
- pos.left - tolerance,
187
- pos.left + el.outerWidth() + tolerance,
188
- pos.top - tolerance,
189
- pos.top + el.outerHeight() + tolerance
190
- ]
191
- }
192
- }
193
-
194
- function getRelativePosition(pointer, element) {
195
- var offset = element.offset()
196
- return {
197
- left: pointer.left - offset.left,
198
- top: pointer.top - offset.top
199
- }
200
- }
201
-
202
- function sortByDistanceDesc(dimensions, pointer, lastPointer) {
203
- pointer = [pointer.left, pointer.top]
204
- lastPointer = lastPointer && [lastPointer.left, lastPointer.top]
205
-
206
- var dim,
207
- i = dimensions.length,
208
- distances = []
209
-
210
- while(i--){
211
- dim = dimensions[i]
212
- distances[i] = [i,d(dim,pointer), lastPointer && d(dim, lastPointer)]
213
- }
214
- distances = distances.sort(function (a,b) {
215
- return b[1] - a[1] || b[2] - a[2] || b[0] - a[0]
216
- })
217
-
218
- // last entry is the closest
219
- return distances
220
- }
221
-
222
- function ContainerGroup(options) {
223
- this.options = $.extend({}, groupDefaults, options)
224
- this.containers = []
225
-
226
- if(!this.options.rootGroup){
227
- this.scrollProxy = $.proxy(this.scroll, this)
228
- this.dragProxy = $.proxy(this.drag, this)
229
- this.dropProxy = $.proxy(this.drop, this)
230
- this.placeholder = $(this.options.placeholder)
231
-
232
- if(!options.isValidTarget)
233
- this.options.isValidTarget = undefined
234
- }
235
- }
236
-
237
- ContainerGroup.get = function (options) {
238
- if(!containerGroups[options.group]) {
239
- if(options.group === undefined)
240
- options.group = groupCounter ++
241
-
242
- containerGroups[options.group] = new ContainerGroup(options)
243
- }
244
-
245
- return containerGroups[options.group]
246
- }
247
-
248
- ContainerGroup.prototype = {
249
- dragInit: function (e, itemContainer) {
250
- this.$document = $(itemContainer.el[0].ownerDocument)
251
-
252
- // get item to drag
253
- var closestItem = $(e.target).closest(this.options.itemSelector);
254
- // using the length of this item, prevents the plugin from being started if there is no handle being clicked on.
255
- // this may also be helpful in instantiating multidrag.
256
- if (closestItem.length) {
257
- this.item = closestItem;
258
- this.itemContainer = itemContainer;
259
- if (this.item.is(this.options.exclude) || !this.options.onMousedown(this.item, groupDefaults.onMousedown, e)) {
260
- return;
261
- }
262
- this.setPointer(e);
263
- this.toggleListeners('on');
264
- this.setupDelayTimer();
265
- this.dragInitDone = true;
266
- }
267
- },
268
- drag: function (e) {
269
- if(!this.dragging){
270
- if(!this.distanceMet(e) || !this.delayMet)
271
- return
272
-
273
- this.options.onDragStart(this.item, this.itemContainer, groupDefaults.onDragStart, e)
274
- this.item.before(this.placeholder)
275
- this.dragging = true
276
- }
277
-
278
- this.setPointer(e)
279
- // place item under the cursor
280
- this.options.onDrag(this.item,
281
- getRelativePosition(this.pointer, this.item.offsetParent()),
282
- groupDefaults.onDrag,
283
- e)
284
-
285
- var p = this.getPointer(e),
286
- box = this.sameResultBox,
287
- t = this.options.tolerance
288
-
289
- if(!box || box.top - t > p.top || box.bottom + t < p.top || box.left - t > p.left || box.right + t < p.left)
290
- if(!this.searchValidTarget()){
291
- this.placeholder.detach()
292
- this.lastAppendedItem = undefined
293
- }
294
- },
295
- drop: function (e) {
296
- this.toggleListeners('off')
297
-
298
- this.dragInitDone = false
299
-
300
- if(this.dragging){
301
- // processing Drop, check if placeholder is detached
302
- if(this.placeholder.closest("html")[0]){
303
- this.placeholder.before(this.item).detach()
304
- } else {
305
- this.options.onCancel(this.item, this.itemContainer, groupDefaults.onCancel, e)
306
- }
307
- this.options.onDrop(this.item, this.getContainer(this.item), groupDefaults.onDrop, e)
308
-
309
- // cleanup
310
- this.clearDimensions()
311
- this.clearOffsetParent()
312
- this.lastAppendedItem = this.sameResultBox = undefined
313
- this.dragging = false
314
- }
315
- },
316
- searchValidTarget: function (pointer, lastPointer) {
317
- if(!pointer){
318
- pointer = this.relativePointer || this.pointer
319
- lastPointer = this.lastRelativePointer || this.lastPointer
320
- }
321
-
322
- var distances = sortByDistanceDesc(this.getContainerDimensions(),
323
- pointer,
324
- lastPointer),
325
- i = distances.length
326
-
327
- while(i--){
328
- var index = distances[i][0],
329
- distance = distances[i][1]
330
-
331
- if(!distance || this.options.pullPlaceholder){
332
- var container = this.containers[index]
333
- if(!container.disabled){
334
- if(!this.$getOffsetParent()){
335
- var offsetParent = container.getItemOffsetParent()
336
- pointer = getRelativePosition(pointer, offsetParent)
337
- lastPointer = getRelativePosition(lastPointer, offsetParent)
338
- }
339
- if(container.searchValidTarget(pointer, lastPointer))
340
- return true
341
- }
342
- }
343
- }
344
- if(this.sameResultBox)
345
- this.sameResultBox = undefined
346
- },
347
- movePlaceholder: function (container, item, method, sameResultBox) {
348
- var lastAppendedItem = this.lastAppendedItem
349
- if(!sameResultBox && lastAppendedItem && lastAppendedItem[0] === item[0])
350
- return;
351
-
352
- item[method](this.placeholder)
353
- this.lastAppendedItem = item
354
- this.sameResultBox = sameResultBox
355
- this.options.afterMove(this.placeholder, container, item)
356
- },
357
- getContainerDimensions: function () {
358
- if(!this.containerDimensions)
359
- setDimensions(this.containers, this.containerDimensions = [], this.options.tolerance, !this.$getOffsetParent())
360
- return this.containerDimensions
361
- },
362
- getContainer: function (element) {
363
- return element.closest(this.options.containerSelector).data(pluginName)
364
- },
365
- $getOffsetParent: function () {
366
- if(this.offsetParent === undefined){
367
- var i = this.containers.length - 1,
368
- offsetParent = this.containers[i].getItemOffsetParent()
369
-
370
- if(!this.options.rootGroup){
371
- while(i--){
372
- if(offsetParent[0] != this.containers[i].getItemOffsetParent()[0]){
373
- // If every container has the same offset parent,
374
- // use position() which is relative to this parent,
375
- // otherwise use offset()
376
- // compare #setDimensions
377
- offsetParent = false
378
- break;
379
- }
380
- }
381
- }
382
-
383
- this.offsetParent = offsetParent
384
- }
385
- return this.offsetParent
386
- },
387
- setPointer: function (e) {
388
- var pointer = this.getPointer(e)
389
-
390
- if(this.$getOffsetParent()){
391
- var relativePointer = getRelativePosition(pointer, this.$getOffsetParent())
392
- this.lastRelativePointer = this.relativePointer
393
- this.relativePointer = relativePointer
394
- }
395
-
396
- this.lastPointer = this.pointer
397
- this.pointer = pointer
398
- },
399
- distanceMet: function (e) {
400
- var currentPointer = this.getPointer(e)
401
- return (Math.max(
402
- Math.abs(this.pointer.left - currentPointer.left),
403
- Math.abs(this.pointer.top - currentPointer.top)
404
- ) >= this.options.distance)
405
- },
406
- getPointer: function(e) {
407
- var o = e.originalEvent || e.originalEvent.touches && e.originalEvent.touches[0]
408
- return {
409
- left: e.pageX || o.pageX,
410
- top: e.pageY || o.pageY
411
- }
412
- },
413
- setupDelayTimer: function () {
414
- var that = this
415
- this.delayMet = !this.options.delay
416
-
417
- // init delay timer if needed
418
- if (!this.delayMet) {
419
- clearTimeout(this._mouseDelayTimer);
420
- this._mouseDelayTimer = setTimeout(function() {
421
- that.delayMet = true
422
- }, this.options.delay)
423
- }
424
- },
425
- scroll: function (e) {
426
- this.clearDimensions()
427
- this.clearOffsetParent() // TODO is this needed?
428
- },
429
- toggleListeners: function (method) {
430
- var that = this,
431
- events = ['drag','drop','scroll']
432
-
433
- $.each(events,function (i,event) {
434
- that.$document[method](eventNames[event], that[event + 'Proxy'])
435
- })
436
- },
437
- clearOffsetParent: function () {
438
- this.offsetParent = undefined
439
- },
440
- // Recursively clear container and item dimensions
441
- clearDimensions: function () {
442
- this.traverse(function(object){
443
- object._clearDimensions()
444
- })
445
- },
446
- traverse: function(callback) {
447
- callback(this)
448
- var i = this.containers.length
449
- while(i--){
450
- this.containers[i].traverse(callback)
451
- }
452
- },
453
- _clearDimensions: function(){
454
- this.containerDimensions = undefined
455
- },
456
- _destroy: function () {
457
- containerGroups[this.options.group] = undefined
458
- }
459
- }
460
-
461
- function Container(element, options) {
462
- this.el = element
463
- this.options = $.extend( {}, containerDefaults, options)
464
-
465
- this.group = ContainerGroup.get(this.options)
466
- this.rootGroup = this.options.rootGroup || this.group
467
- this.handle = this.rootGroup.options.handle || this.rootGroup.options.itemSelector
468
-
469
- var itemPath = this.rootGroup.options.itemPath
470
- this.target = itemPath ? this.el.find(itemPath) : this.el
471
-
472
- this.target.on(eventNames.start, this.handle, $.proxy(this.dragInit, this))
473
-
474
- if(this.options.drop)
475
- this.group.containers.push(this)
476
- }
477
-
478
- Container.prototype = {
479
- dragInit: function (e) {
480
- var rootGroup = this.rootGroup
481
-
482
- if( !this.disabled &&
483
- !rootGroup.dragInitDone &&
484
- this.options.drag &&
485
- this.isValidDrag(e)) {
486
- rootGroup.dragInit(e, this)
487
- }
488
- },
489
- isValidDrag: function(e) {
490
- return e.which == 1 ||
491
- e.type == "touchstart" && e.originalEvent.touches.length == 1
492
- },
493
- searchValidTarget: function (pointer, lastPointer) {
494
- var distances = sortByDistanceDesc(this.getItemDimensions(),
495
- pointer,
496
- lastPointer),
497
- i = distances.length,
498
- rootGroup = this.rootGroup,
499
- validTarget = !rootGroup.options.isValidTarget ||
500
- rootGroup.options.isValidTarget(rootGroup.item, this)
501
-
502
- if(!i && validTarget){
503
- rootGroup.movePlaceholder(this, this.target, "append")
504
- return true
505
- } else
506
- while(i--){
507
- var index = distances[i][0],
508
- distance = distances[i][1]
509
- if(!distance && this.hasChildGroup(index)){
510
- var found = this.getContainerGroup(index).searchValidTarget(pointer, lastPointer)
511
- if(found)
512
- return true
513
- }
514
- else if(validTarget){
515
- this.movePlaceholder(index, pointer)
516
- return true
517
- }
518
- }
519
- },
520
- movePlaceholder: function (index, pointer) {
521
- var item = $(this.items[index]),
522
- dim = this.itemDimensions[index],
523
- method = "after",
524
- width = item.outerWidth(),
525
- height = item.outerHeight(),
526
- offset = item.offset(),
527
- sameResultBox = {
528
- left: offset.left,
529
- right: offset.left + width,
530
- top: offset.top,
531
- bottom: offset.top + height
532
- }
533
- if(this.options.vertical){
534
- var yCenter = (dim[2] + dim[3]) / 2,
535
- inUpperHalf = pointer.top <= yCenter
536
- if(inUpperHalf){
537
- method = "before"
538
- sameResultBox.bottom -= height / 2
539
- } else
540
- sameResultBox.top += height / 2
541
- } else {
542
- var xCenter = (dim[0] + dim[1]) / 2,
543
- inLeftHalf = pointer.left <= xCenter
544
- if(inLeftHalf){
545
- method = "before"
546
- sameResultBox.right -= width / 2
547
- } else
548
- sameResultBox.left += width / 2
549
- }
550
- if(this.hasChildGroup(index))
551
- sameResultBox = emptyBox
552
- this.rootGroup.movePlaceholder(this, item, method, sameResultBox)
553
- },
554
- getItemDimensions: function () {
555
- if(!this.itemDimensions){
556
- this.items = this.$getChildren(this.el, "item").filter(
557
- ":not(." + this.group.options.placeholderClass + ", ." + this.group.options.draggedClass + ")"
558
- ).get()
559
- setDimensions(this.items, this.itemDimensions = [], this.options.tolerance)
560
- }
561
- return this.itemDimensions
562
- },
563
- getItemOffsetParent: function () {
564
- var offsetParent,
565
- el = this.el
566
- // Since el might be empty we have to check el itself and
567
- // can not do something like el.children().first().offsetParent()
568
- if(el.css("position") === "relative" || el.css("position") === "absolute" || el.css("position") === "fixed")
569
- offsetParent = el
570
- else
571
- offsetParent = el.offsetParent()
572
- return offsetParent
573
- },
574
- hasChildGroup: function (index) {
575
- return this.options.nested && this.getContainerGroup(index)
576
- },
577
- getContainerGroup: function (index) {
578
- var childGroup = $.data(this.items[index], subContainerKey)
579
- if( childGroup === undefined){
580
- var childContainers = this.$getChildren(this.items[index], "container")
581
- childGroup = false
582
-
583
- if(childContainers[0]){
584
- var options = $.extend({}, this.options, {
585
- rootGroup: this.rootGroup,
586
- group: groupCounter ++
587
- })
588
- childGroup = childContainers[pluginName](options).data(pluginName).group
589
- }
590
- $.data(this.items[index], subContainerKey, childGroup)
591
- }
592
- return childGroup
593
- },
594
- $getChildren: function (parent, type) {
595
- var options = this.rootGroup.options,
596
- path = options[type + "Path"],
597
- selector = options[type + "Selector"]
598
-
599
- parent = $(parent)
600
- if(path)
601
- parent = parent.find(path)
602
-
603
- return parent.children(selector)
604
- },
605
- _serialize: function (parent, isContainer) {
606
- var that = this,
607
- childType = isContainer ? "item" : "container",
608
-
609
- children = this.$getChildren(parent, childType).not(this.options.exclude).map(function () {
610
- return that._serialize($(this), !isContainer)
611
- }).get()
612
-
613
- return this.rootGroup.options.serialize(parent, children, isContainer)
614
- },
615
- traverse: function(callback) {
616
- $.each(this.items || [], function(item){
617
- var group = $.data(this, subContainerKey)
618
- if(group)
619
- group.traverse(callback)
620
- });
621
-
622
- callback(this)
623
- },
624
- _clearDimensions: function () {
625
- this.itemDimensions = undefined
626
- },
627
- _destroy: function() {
628
- var that = this;
629
-
630
- this.target.off(eventNames.start, this.handle);
631
- this.el.removeData(pluginName)
632
-
633
- if(this.options.drop)
634
- this.group.containers = $.grep(this.group.containers, function(val){
635
- return val != that
636
- })
637
-
638
- $.each(this.items || [], function(){
639
- $.removeData(this, subContainerKey)
640
- })
641
- }
642
- }
643
-
644
- var API = {
645
- enable: function() {
646
- this.traverse(function(object){
647
- object.disabled = false
648
- })
649
- },
650
- disable: function (){
651
- this.traverse(function(object){
652
- object.disabled = true
653
- })
654
- },
655
- serialize: function () {
656
- return this._serialize(this.el, true)
657
- },
658
- refresh: function() {
659
- this.traverse(function(object){
660
- object._clearDimensions()
661
- })
662
- },
663
- destroy: function () {
664
- this.traverse(function(object){
665
- object._destroy();
666
- })
667
- }
668
- }
669
-
670
- $.extend(Container.prototype, API)
671
-
672
- /**
673
- * jQuery API
674
- *
675
- * Parameters are
676
- * either options on init
677
- * or a method name followed by arguments to pass to the method
678
- */
679
- $.fn[pluginName] = function(methodOrOptions) {
680
- var args = Array.prototype.slice.call(arguments, 1)
681
-
682
- return this.map(function(){
683
- var $t = $(this),
684
- object = $t.data(pluginName)
685
-
686
- if(object && API[methodOrOptions])
687
- return API[methodOrOptions].apply(object, args) || this
688
- else if(!object && (methodOrOptions === undefined ||
689
- typeof methodOrOptions === "object"))
690
- $t.data(pluginName, new Container($t, methodOrOptions))
691
-
692
- return this
693
- });
694
- };
695
-
696
- }(jQuery, window, 'sortable');