@@ -179,15 +179,29 @@ angular.module('dndLists', [])
179
179
* - dnd-horizontal-list Optional boolean expresssion. When it evaluates to true, the positioning
180
180
* algorithm will use the left and right halfs of the list items instead of
181
181
* 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.
182
196
*
183
197
* CSS classes:
184
198
* - dndPlaceholder When an element is dragged over the list, a new placeholder child element
185
199
* will be added. This element is of type li and has the class
186
200
* dndPlaceholder set.
187
201
* - dndDragover Will be added to the list while an element is dragged over the list.
188
202
*/
189
- . directive ( 'dndList' , [ '$timeout' , 'dndDropEffectWorkaround' , 'dndDragTypeWorkaround' ,
190
- function ( $timeout , dndDropEffectWorkaround , dndDragTypeWorkaround ) {
203
+ . directive ( 'dndList' , [ '$parse' , '$ timeout', 'dndDropEffectWorkaround' , 'dndDragTypeWorkaround' ,
204
+ function ( $parse , $ timeout, dndDropEffectWorkaround , dndDragTypeWorkaround ) {
191
205
return function ( scope , element , attr ) {
192
206
// While an element is dragged over the list, this placeholder element is inserted
193
207
// at the location where the element would be inserted after dropping
@@ -252,6 +266,14 @@ angular.module('dndLists', [])
252
266
}
253
267
}
254
268
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
+
255
277
element . addClass ( "dndDragover" ) ;
256
278
event . preventDefault ( ) ;
257
279
event . stopPropagation ( ) ;
@@ -273,14 +295,20 @@ angular.module('dndLists', [])
273
295
var transferredObject = JSON . parse ( event . dataTransfer . getData ( "Text" )
274
296
|| event . dataTransfer . getData ( "text/plain" ) ) ;
275
297
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
+ }
278
307
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 ) ;
282
310
scope . $apply ( function ( ) {
283
- targetArray . splice ( placeholderIndex , 0 , transferredObject ) ;
311
+ targetArray . splice ( getPlaceholderIndex ( ) , 0 , transferredObject ) ;
284
312
} ) ;
285
313
286
314
// In Chrome on Windows the dropEffect will always be none...
@@ -337,6 +365,14 @@ angular.module('dndLists', [])
337
365
return mousePointer < targetPosition + targetSize / 2 ;
338
366
}
339
367
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
+
340
376
/**
341
377
* Checks various conditions that must be fulfilled for a drop to be allowed
342
378
*/
@@ -362,6 +398,18 @@ angular.module('dndLists', [])
362
398
return true ;
363
399
}
364
400
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
+
365
413
/**
366
414
* Check if the dataTransfer object contains a drag type that we can handle. In old versions
367
415
* of IE the types collection will not even be there, so we just assume a drop is possible.
0 commit comments