Skip to content

Commit c86319e

Browse files
committed
Added andSelf option to Droppable to allow dragging and dropping a droppable onto itself.
Added highest option to Draggable to only drop on the droppable with the highest z-index.
1 parent b662fee commit c86319e

File tree

2 files changed

+89
-22
lines changed

2 files changed

+89
-22
lines changed

ui/jquery.ui.draggable.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ $.widget("ui.draggable", $.ui.mouse, {
4343
snapTolerance: 20,
4444
stack: false,
4545
zIndex: false,
46+
highest: false,
4647

4748
// callbacks
4849
drag: null,
@@ -168,6 +169,7 @@ $.widget("ui.draggable", $.ui.mouse, {
168169

169170
//Prepare the droppable offsets
170171
if ($.ui.ddmanager && !o.dropBehaviour) {
172+
$.ui.ddmanager.zStack[this.options.scope] = [];
171173
$.ui.ddmanager.prepareOffsets(this, event);
172174
}
173175

ui/jquery.ui.droppable.js

Lines changed: 87 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ $.widget("ui.droppable", {
3131
hoverClass: false,
3232
scope: "default",
3333
tolerance: "intersect",
34+
andSelf: false,
3435

3536
// callbacks
3637
activate: null,
@@ -105,52 +106,100 @@ $.widget("ui.droppable", {
105106
}
106107
},
107108

109+
_triggerOver: function(event, draggable) {
110+
if(this.options.hoverClass) {
111+
this.element.addClass(this.options.hoverClass);
112+
}
113+
this._trigger("over", event, this.ui(draggable));
114+
},
115+
116+
_triggerOut: function(event, draggable) {
117+
if(this.options.hoverClass) {
118+
this.element.removeClass(this.options.hoverClass);
119+
}
120+
this._trigger("out", event, this.ui(draggable));
121+
},
122+
108123
_over: function(event) {
109124

110125
var draggable = $.ui.ddmanager.current;
111-
112-
// Bail if draggable and droppable are same element
113-
if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
114-
return;
115-
}
126+
if (!draggable || ((draggable.currentItem || draggable.element)[0] == this.element[0] && !this.options.andSelf)) return; // Bail if draggable and droppable are same element
116127

117128
if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
118-
if(this.options.hoverClass) {
119-
this.element.addClass(this.options.hoverClass);
129+
if(!draggable.options.highest) {
130+
this._triggerOver(event, draggable);
131+
}
132+
else {
133+
var zStack = $.ui.ddmanager.zStack[draggable.options.scope];
134+
135+
if(zStack.indexOf(this) == -1) {
136+
var lastHighest = zStack[zStack.length - 1];
137+
138+
zStack.push(this);
139+
140+
zStack.sort(this._sortHighest);
141+
142+
var newHighest = zStack[zStack.length - 1];
143+
144+
if(lastHighest !== newHighest) {
145+
if(lastHighest != null) lastHighest._triggerOut(event, draggable);
146+
if(newHighest != null) newHighest._triggerOver(event, draggable);
147+
}
148+
}
120149
}
121-
this._trigger("over", event, this.ui(draggable));
122150
}
123151

124152
},
125153

126154
_out: function(event) {
127155

128156
var draggable = $.ui.ddmanager.current;
129-
130-
// Bail if draggable and droppable are same element
131-
if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
132-
return;
133-
}
157+
if (!draggable || ((draggable.currentItem || draggable.element)[0] == this.element[0] && !this.options.andSelf)) return; // Bail if draggable and droppable are same element
134158

135159
if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
136-
if(this.options.hoverClass) {
137-
this.element.removeClass(this.options.hoverClass);
160+
if(!draggable.options.highest) {
161+
this._triggerOut(event, draggable);
162+
}
163+
else {
164+
var zStack = $.ui.ddmanager.zStack[draggable.options.scope];
165+
166+
var lastHighest = zStack[zStack.length - 1];
167+
168+
zStack.splice(zStack.indexOf(this), 1);
169+
170+
zStack.sort(this._sortHighest);
171+
172+
var newHighest = zStack[zStack.length - 1];
173+
174+
if(lastHighest !== newHighest) {
175+
if(lastHighest != null) lastHighest._triggerOut(event, draggable);
176+
if(newHighest != null) newHighest._triggerOver(event, draggable);
177+
}
138178
}
139-
this._trigger("out", event, this.ui(draggable));
140179
}
141180

142181
},
143182

144183
_drop: function(event,custom) {
145184

146-
var draggable = custom || $.ui.ddmanager.current,
147-
childrenIntersection = false;
185+
var draggable = custom || $.ui.ddmanager.current;
148186

149-
// Bail if draggable and droppable are same element
150-
if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
151-
return false;
187+
if (!draggable || ((draggable.currentItem || draggable.element)[0] == this.element[0] && !this.options.andSelf)) return false; // Bail if draggable and droppable are same element
188+
189+
if(!draggable.options.highest) {
190+
return this._triggerDrop(event, draggable);
152191
}
192+
else {
193+
var zStack = $.ui.ddmanager.zStack[draggable.options.scope];
153194

195+
if(this == zStack[zStack.length - 1]) {
196+
return this._triggerDrop(event, draggable);
197+
}
198+
}
199+
},
200+
201+
_triggerDrop: function(event, draggable) {
202+
var childrenIntersection = false;
154203
this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() {
155204
var inst = $.data(this, "ui-droppable");
156205
if(
@@ -180,6 +229,21 @@ $.widget("ui.droppable", {
180229

181230
},
182231

232+
_sortHighest: function(a, b) {
233+
var zIndexA = parseInt(a.element.css("z-index"), 10);
234+
var zIndexB = parseInt(b.element.css("z-index"), 10);
235+
236+
if(zIndexA !== zIndexB) {
237+
return zIndexA - zIndexB;
238+
}
239+
240+
// If elements share a z-index, the element that is later in the DOM is on top.
241+
var indexA = a.element.index();
242+
var indexB = b.element.index();
243+
244+
return indexA - indexB;
245+
},
246+
183247
ui: function(c) {
184248
return {
185249
draggable: (c.currentItem || c.element),
@@ -237,6 +301,7 @@ $.ui.intersect = function(draggable, droppable, toleranceMode) {
237301
$.ui.ddmanager = {
238302
current: null,
239303
droppables: { "default": [] },
304+
zStack: { 'default': [] },
240305
prepareOffsets: function(t, event) {
241306

242307
var i, j,
@@ -253,7 +318,7 @@ $.ui.ddmanager = {
253318

254319
// Filter out elements in the current dragged item
255320
for (j=0; j < list.length; j++) {
256-
if(list[j] === m[i].element[0]) {
321+
if(list[j] === m[i].element[0] && !m[i].options.andSelf) {
257322
m[i].proportions.height = 0;
258323
continue droppablesLoop;
259324
}

0 commit comments

Comments
 (0)