Skip to content

Commit 63b9dd9

Browse files
Jonas von AndrianJonas von Andrian
Jonas von Andrian
authored and
Jonas von Andrian
committed
added generic traverse method
properly implement destroy cleanup closes #42, #30
1 parent 71eeb5a commit 63b9dd9

File tree

2 files changed

+83
-62
lines changed

2 files changed

+83
-62
lines changed

TODO

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
1-
- [0/1] exampels
2-
- [ ] delay
3-
- [0/2] bugs
1+
- [0/3] bugs
42
- [ ] last Pointer is NaN in search valid target
53
- [ ] prevent infinite recursion
64
- [ ] bootstrap example jumps up on drop
75
- (only sometimes. preventDefault() does not work if called inside drop or on containing element. Look up where the on handler attaches itself)
86
- only firefox, chrome works
9-
- [0/5] consider
7+
- [0/6] consider
108
- [ ] better name for searchValidTarget
119
- [ ] shortcut on getNearest()
1210
- [ ] if items, break if distance is growing again
1311
- [ ] if containers, break if distance is 0
1412
- [ ] only calculate top/bottom if vertical and left/right if horizontal
1513
- [ ] support placeholder with height/width
1614
- [ ] calculate item/container dimensions relative to the container => Not all centers have to be recalculated
15+
- [ ] change subContainers handling, so that it becomes easier to remove them

source/js/jquery-sortable.js

+80-58
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@
123123
result.children = $children
124124
}
125125

126-
delete result.subContainer
127-
delete result[pluginName]
126+
delete result.subContainers
127+
delete result.sortable
128128

129129
return result
130130
},
@@ -139,13 +139,14 @@
139139
top: 0,
140140
bottom: 0,
141141
right:0
142-
}
142+
},
143143
eventNames = {
144144
start: "touchstart.sortable mousedown.sortable",
145145
drop: "touchend.sortable touchcancel.sortable mouseup.sortable",
146146
drag: "touchmove.sortable mousemove.sortable",
147147
scroll: "scroll.sortable"
148-
}
148+
},
149+
subContainerKey = "subContainers"
149150

150151
/*
151152
* a is Array [left, right, top, bottom]
@@ -209,7 +210,7 @@
209210
this.options = $.extend({}, groupDefaults, options)
210211
this.containers = []
211212

212-
if(!this.options.parentContainer){
213+
if(!this.options.rootGroup){
213214
this.scrollProxy = $.proxy(this.scroll, this)
214215
this.dragProxy = $.proxy(this.drag, this)
215216
this.dropProxy = $.proxy(this.drop, this)
@@ -221,34 +222,32 @@
221222
}
222223

223224
ContainerGroup.get = function (options) {
224-
if( !containerGroups[options.group]) {
225+
if(!containerGroups[options.group]) {
225226
if(options.group === undefined)
226227
options.group = groupCounter ++
228+
227229
containerGroups[options.group] = new ContainerGroup(options)
228230
}
231+
229232
return containerGroups[options.group]
230233
}
231234

232235
ContainerGroup.prototype = {
233236
dragInit: function (e, itemContainer) {
234237
this.$document = $(itemContainer.el[0].ownerDocument)
235238

236-
if(itemContainer.enabled()){
237-
// get item to drag
238-
this.item = $(e.target).closest(this.options.itemSelector)
239-
this.itemContainer = itemContainer
239+
// get item to drag
240+
this.item = $(e.target).closest(this.options.itemSelector)
241+
this.itemContainer = itemContainer
240242

241-
if(this.item.is(this.options.exclude) ||
242-
!this.options.onMousedown(this.item, groupDefaults.onMousedown, e)){
243-
return
244-
}
245-
246-
this.setPointer(e)
247-
this.toggleListeners('on')
248-
} else {
249-
this.toggleListeners('on', ['drop'])
243+
if(this.item.is(this.options.exclude) ||
244+
!this.options.onMousedown(this.item, groupDefaults.onMousedown, e)){
245+
return
250246
}
251247

248+
this.setPointer(e)
249+
this.toggleListeners('on')
250+
252251
this.setupDelayTimer()
253252
this.dragInitDone = true
254253
},
@@ -353,7 +352,7 @@
353352
var i = this.containers.length - 1,
354353
offsetParent = this.containers[i].getItemOffsetParent()
355354

356-
if(!this.options.parentContainer){
355+
if(!this.options.rootGroup){
357356
while(i--){
358357
if(offsetParent[0] != this.containers[i].getItemOffsetParent()[0]){
359358
// If every container has the same offset parent,
@@ -411,9 +410,9 @@
411410
this.clearDimensions()
412411
this.clearOffsetParent() // TODO is this needed?
413412
},
414-
toggleListeners: function (method, events) {
415-
var that = this
416-
events = events || ['drag','drop','scroll']
413+
toggleListeners: function (method) {
414+
var that = this,
415+
events = ['drag','drop','scroll']
417416

418417
$.each(events,function (i,event) {
419418
that.$document[method](eventNames[event], that[event + 'Proxy'])
@@ -424,15 +423,21 @@
424423
},
425424
// Recursively clear container and item dimensions
426425
clearDimensions: function () {
427-
this.containerDimensions = undefined
426+
this.traverse(function(object){
427+
object._clearDimensions()
428+
})
429+
},
430+
traverse: function(callback) {
431+
callback(this)
428432
var i = this.containers.length
429433
while(i--){
430-
this.containers[i].clearDimensions()
434+
this.containers[i].traverse(callback)
431435
}
432436
},
433-
destroy: function () {
434-
// TODO iterate over subgroups and destroy them
435-
// TODO remove all events
437+
_clearDimensions: function(){
438+
this.containerDimensions = undefined
439+
},
440+
_destroy: function () {
436441
containerGroups[this.options.group] = undefined
437442
}
438443
}
@@ -443,13 +448,12 @@
443448

444449
this.group = ContainerGroup.get(this.options)
445450
this.rootGroup = this.options.rootGroup || this.group
446-
this.parentContainer = this.options.parentContainer
447451
this.handle = this.rootGroup.options.handle || this.rootGroup.options.itemSelector
448452

449-
var itemPath = this.rootGroup.options.itemPath,
450-
target = itemPath ? this.el.find(itemPath) : this.el
453+
var itemPath = this.rootGroup.options.itemPath
454+
this.target = itemPath ? this.el.find(itemPath) : this.el
451455

452-
target.on(eventNames.start, this.handle, $.proxy(this.dragInit, this))
456+
this.target.on(eventNames.start, this.handle, $.proxy(this.dragInit, this))
453457

454458
if(this.options.drop)
455459
this.group.containers.push(this)
@@ -459,7 +463,8 @@
459463
dragInit: function (e) {
460464
var rootGroup = this.rootGroup
461465

462-
if( !rootGroup.dragInitDone &&
466+
if( !this.disabled &&
467+
!rootGroup.dragInitDone &&
463468
this.options.drag &&
464469
this.isValidDrag(e)) {
465470
rootGroup.dragInit(e, this)
@@ -479,10 +484,7 @@
479484
rootGroup.options.isValidTarget(rootGroup.item, this)
480485

481486
if(!i && validTarget){
482-
var itemPath = this.rootGroup.options.itemPath,
483-
target = itemPath ? this.el.find(itemPath) : this.el
484-
485-
rootGroup.movePlaceholder(this, target, "append")
487+
rootGroup.movePlaceholder(this, this.target, "append")
486488
return true
487489
} else
488490
while(i--){
@@ -555,26 +557,22 @@
555557
return this.options.nested && this.getContainerGroup(index)
556558
},
557559
getContainerGroup: function (index) {
558-
var childGroup = $.data(this.items[index], "subContainer")
560+
var childGroup = $.data(this.items[index], subContainerKey)
559561
if( childGroup === undefined){
560562
var childContainers = this.$getChildren(this.items[index], "container")
561563
childGroup = false
562564

563565
if(childContainers[0]){
564566
var options = $.extend({}, this.options, {
565-
parentContainer: this,
566567
rootGroup: this.rootGroup,
567568
group: groupCounter ++
568569
})
569570
childGroup = childContainers[pluginName](options).data(pluginName).group
570571
}
571-
$.data(this.items[index], "subContainer", childGroup)
572+
$.data(this.items[index], subContainerKey, childGroup)
572573
}
573574
return childGroup
574575
},
575-
enabled: function () {
576-
return !this.disabled && (!this.parentContainer || this.parentContainer.enabled())
577-
},
578576
$getChildren: function (parent, type) {
579577
var options = this.rootGroup.options,
580578
path = options[type + "Path"],
@@ -596,34 +594,58 @@
596594

597595
return this.rootGroup.options.serialize(parent, children, isContainer)
598596
},
599-
clearDimensions: function () {
597+
traverse: function(callback) {
598+
$.each(this.items || [], function(item){
599+
var group = $.data(this, subContainerKey)
600+
if(group)
601+
group.traverse(callback)
602+
});
603+
604+
callback(this)
605+
},
606+
_clearDimensions: function () {
600607
this.itemDimensions = undefined
601-
if(this.items && this.items[0]){
602-
var i = this.items.length
603-
while(i--){
604-
var group = $.data(this.items[i], "subContainer")
605-
if(group)
606-
group.clearDimensions()
607-
}
608-
}
608+
},
609+
_destroy: function() {
610+
var that = this;
611+
612+
this.target.off(eventNames.start, this.handle);
613+
this.el.removeData(pluginName)
614+
615+
if(this.options.drop)
616+
this.group.containers = $.grep(this.group.containers, function(val){
617+
return val != that
618+
})
619+
620+
$.each(this.items || [], function(){
621+
$.removeData(this, subContainerKey)
622+
})
609623
}
610624
}
611625

612626
var API = {
613-
enable: function (ignoreChildren) {
614-
this.disabled = false
627+
enable: function() {
628+
this.traverse(function(object){
629+
object.disabled = false
630+
})
615631
},
616-
disable: function (ignoreChildren) {
617-
this.disabled = true
632+
disable: function (){
633+
this.traverse(function(object){
634+
object.disabled = true
635+
})
618636
},
619637
serialize: function () {
620638
return this._serialize(this.el, true)
621639
},
622640
refresh: function() {
623-
this.clearDimensions()
641+
this.traverse(function(object){
642+
object._clearDimensions()
643+
})
624644
},
625645
destroy: function () {
626-
this.rootGroup.destroy()
646+
this.traverse(function(object){
647+
object._destroy();
648+
})
627649
}
628650
}
629651

0 commit comments

Comments
 (0)