Skip to content

Commit 01c645f

Browse files
Fixes marceljuenemann#11, marceljuenemann#12: Add dragover and drop callbacks
1 parent f2cf581 commit 01c645f

File tree

1 file changed

+56
-8
lines changed

1 file changed

+56
-8
lines changed

angular-drag-and-drop-lists.js

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -179,15 +179,29 @@ angular.module('dndLists', [])
179179
* - dnd-horizontal-list Optional boolean expresssion. When it evaluates to true, the positioning
180180
* algorithm will use the left and right halfs of the list items instead of
181181
* the upper and lower halfs.
182+
* - dnd-dragover Optional expression that is invoked when an element is dragged over the
183+
* list. If the expression is set, but does not return true, the element is
184+
* not allowed to be dropped. The following variables will be available:
185+
* - event: The original dragover event sent by the browser.
186+
* - index: The position in the list at which the element would be dropped.
187+
* - type: The dnd-type set on the dnd-draggable, or undefined if unset.
188+
* - dnd-drop Optional expression that is invoked when an element is dropped over the
189+
* list. If the expression is set, it must return the object that will be
190+
* inserted into the list. If it returns false, the drop will be aborted and
191+
* the drop event is propagated. The following variables will be available:
192+
* - event: The original dragover event sent by the browser.
193+
* - index: The position in the list at which the element would be dropped.
194+
* - item: The transferred object.
195+
* - type: The dnd-type set on the dnd-draggable, or undefined if unset.
182196
*
183197
* CSS classes:
184198
* - dndPlaceholder When an element is dragged over the list, a new placeholder child element
185199
* will be added. This element is of type li and has the class
186200
* dndPlaceholder set.
187201
* - dndDragover Will be added to the list while an element is dragged over the list.
188202
*/
189-
.directive('dndList', ['$timeout', 'dndDropEffectWorkaround', 'dndDragTypeWorkaround',
190-
function($timeout, dndDropEffectWorkaround, dndDragTypeWorkaround) {
203+
.directive('dndList', ['$parse', '$timeout', 'dndDropEffectWorkaround', 'dndDragTypeWorkaround',
204+
function($parse, $timeout, dndDropEffectWorkaround, dndDragTypeWorkaround) {
191205
return function(scope, element, attr) {
192206
// While an element is dragged over the list, this placeholder element is inserted
193207
// at the location where the element would be inserted after dropping
@@ -252,6 +266,14 @@ angular.module('dndLists', [])
252266
}
253267
}
254268

269+
// At this point we invoke the callback, which still can disallow the drop.
270+
// We can't do this earlier because we want to pass the index of the placeholder.
271+
if (attr.dndDragover && !invokeCallback(attr.dndDragover, event)) {
272+
placeholder.remove();
273+
element.removeClass("dndDragover");
274+
return true;
275+
}
276+
255277
element.addClass("dndDragover");
256278
event.preventDefault();
257279
event.stopPropagation();
@@ -273,14 +295,20 @@ angular.module('dndLists', [])
273295
var transferredObject = JSON.parse(event.dataTransfer.getData("Text")
274296
|| event.dataTransfer.getData("text/plain"));
275297

276-
// Retrieve the JSON array in which we are going to insert the transferred object
277-
var targetArray = scope.$eval(attr.dndList);
298+
// Invoke the callback, which can transform the transferredObject and even abort the drop.
299+
if (attr.dndDrop) {
300+
transferredObject = invokeCallback(attr.dndDrop, event, transferredObject);
301+
if (!transferredObject) {
302+
placeholder.remove();
303+
element.removeClass("dndDragover");
304+
return true;
305+
}
306+
}
278307

279-
// We use the position of the placeholder node to determine at which
280-
// position of the array we will insert the object
281-
var placeholderIndex = Array.prototype.indexOf.call(listNode.children, placeholderNode);
308+
// Retrieve the JSON array and insert the transferred object into it.
309+
var targetArray = scope.$eval(attr.dndList);
282310
scope.$apply(function() {
283-
targetArray.splice(placeholderIndex, 0, transferredObject);
311+
targetArray.splice(getPlaceholderIndex(), 0, transferredObject);
284312
});
285313

286314
// In Chrome on Windows the dropEffect will always be none...
@@ -337,6 +365,14 @@ angular.module('dndLists', [])
337365
return mousePointer < targetPosition + targetSize / 2;
338366
}
339367

368+
/**
369+
* We use the position of the placeholder node to determine at which position of the array the
370+
* object needs to be inserted
371+
*/
372+
function getPlaceholderIndex() {
373+
return Array.prototype.indexOf.call(listNode.children, placeholderNode);
374+
}
375+
340376
/**
341377
* Checks various conditions that must be fulfilled for a drop to be allowed
342378
*/
@@ -362,6 +398,18 @@ angular.module('dndLists', [])
362398
return true;
363399
}
364400

401+
/**
402+
* Invokes a callback with some interesting parameters and returns the callbacks return value.
403+
*/
404+
function invokeCallback(expression, event, item) {
405+
return $parse(expression)(scope, {
406+
event: event,
407+
index: getPlaceholderIndex(),
408+
item: item || undefined,
409+
type: dndDragTypeWorkaround.dragType
410+
});
411+
}
412+
365413
/**
366414
* Check if the dataTransfer object contains a drag type that we can handle. In old versions
367415
* of IE the types collection will not even be there, so we just assume a drop is possible.

0 commit comments

Comments
 (0)