-
Notifications
You must be signed in to change notification settings - Fork 568
/
Copy pathangular-dragdrop.min.js
29 lines (28 loc) · 12.4 KB
/
angular-dragdrop.min.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
/**
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
/**
* Implementing Drag and Drop functionality in AngularJS is easier than ever.
* Demo: http://codef0rmer.github.com/angular-dragdrop/
*
* @version 1.0.13+
*
* (c) 2013 Amit Gharat a.k.a codef0rmer <[email protected]> - amitgharat.wordpress.com
*/
!function(window,angular,$,undefined){"use strict";var jqyoui=angular.module("ngDragDrop",[]).service("ngDragDropService",["$timeout","$parse","$q",function($timeout,$parse,$q){this.draggableScope=null,this.droppableScope=null,$("head").prepend('<style type="text/css">@charset "UTF-8";.angular-dragdrop-hide{display: none !important;}</style>'),this.callEventCallback=function(scope,callbackName,event,ui){if(callbackName){var objExtract=function(callbackName){var atStartBracket=-1!==callbackName.indexOf("(")?callbackName.indexOf("("):callbackName.length,atEndBracket=-1!==callbackName.lastIndexOf(")")?callbackName.lastIndexOf(")"):callbackName.length,args=callbackName.substring(atStartBracket+1,atEndBracket),constructor=-1!==callbackName.indexOf(".")?callbackName.substr(0,callbackName.indexOf(".")):null;return constructor=scope[constructor]&&"function"==typeof scope[constructor].constructor?constructor:null,{callback:callbackName.substring(constructor&&constructor.length+1||0,atStartBracket),args:$.map(args&&args.split(",")||[],function(item){return[$parse(item)(scope)]}),constructor:constructor}}(callbackName),callback=objExtract.callback,constructor=objExtract.constructor,args=[event,ui].concat(objExtract.args);return(scope[callback]||scope[constructor][callback]).apply(scope[callback]?scope:scope[constructor],args)}},this.invokeDrop=function($draggable,$droppable,event,ui){var dragModelValue,dropModelValue,temp,dragModel="",dropModel="",dragSettings={},dropSettings={},jqyoui_pos=null,dragItem={},dropItem={},$droppableDraggable=null,droppableScope=this.droppableScope,draggableScope=this.draggableScope,$helper=null,promises=[];dragModel=$draggable.ngattr("ng-model"),dropModel=$droppable.ngattr("ng-model"),dragModelValue=draggableScope.$eval(dragModel),dropModelValue=droppableScope.$eval(dropModel),$droppableDraggable=$droppable.find("[jqyoui-draggable]:last,[data-jqyoui-draggable]:last"),dropSettings=droppableScope.$eval($droppable.attr("jqyoui-droppable")||$droppable.attr("data-jqyoui-droppable"))||[],(dragSettings=draggableScope.$eval($draggable.attr("jqyoui-draggable")||$draggable.attr("data-jqyoui-draggable"))||[]).index=this.fixIndex(draggableScope,dragSettings,dragModelValue),dropSettings.index=this.fixIndex(droppableScope,dropSettings,dropModelValue),jqyoui_pos=angular.isArray(dragModelValue)?dragSettings.index:null,dragItem=angular.isArray(dragModelValue)?dragModelValue[jqyoui_pos]:dragModelValue,dragSettings.deepCopy&&(dragItem=angular.copy(dragItem)),dropItem=angular.isArray(dropModelValue)&&dropSettings&&void 0!==dropSettings.index?dropModelValue[dropSettings.index]:angular.isArray(dropModelValue)?{}:dropModelValue,dropSettings.deepCopy&&(dropItem=angular.copy(dropItem)),dragSettings.beforeDrop&&promises.push(this.callEventCallback(draggableScope,dragSettings.beforeDrop,event,ui)),$q.all(promises).then(angular.bind(this,function(){if(dragSettings.insertInline&&dragModel===dropModel){if(dragSettings.index>dropSettings.index){temp=dragModelValue[dragSettings.index];for(i=dragSettings.index;i>dropSettings.index;i--)dropModelValue[i]=angular.copy(dropModelValue[i-1]),dropModelValue[i-1]={},dropModelValue[i][dragSettings.direction]="left";dropModelValue[dropSettings.index]=temp}else{temp=dragModelValue[dragSettings.index];for(var i=dragSettings.index;i<dropSettings.index;i++)dropModelValue[i]=angular.copy(dropModelValue[i+1]),dropModelValue[i+1]={},dropModelValue[i][dragSettings.direction]="right";dropModelValue[dropSettings.index]=temp}this.callEventCallback(droppableScope,dropSettings.onDrop,event,ui)}else!0===dragSettings.animate?(($helper=$draggable.clone()).css({position:"absolute"}).css($draggable.offset()),$("body").append($helper),$draggable.addClass("angular-dragdrop-hide"),this.move($helper,$droppableDraggable.length>0?$droppableDraggable:$droppable,null,"fast",dropSettings,function(){$helper.remove()}),this.move($droppableDraggable.length>0&&!dropSettings.multiple?$droppableDraggable:[],$draggable.parent("[jqyoui-droppable],[data-jqyoui-droppable]"),jqyoui.startXY,"fast",dropSettings,angular.bind(this,function(){$timeout(angular.bind(this,function(){$draggable.css({position:"relative",left:"",top:""}).removeClass("angular-dragdrop-hide"),$droppableDraggable.css({position:"relative",left:"",top:"",display:"none"===$droppableDraggable.css("display")?"":$droppableDraggable.css("display")}),this.mutateDraggable(draggableScope,dropSettings,dragSettings,dragModel,dropModel,dropItem,$draggable),this.mutateDroppable(droppableScope,dropSettings,dragSettings,dropModel,dragItem,jqyoui_pos),this.callEventCallback(droppableScope,dropSettings.onDrop,event,ui)}))}))):$timeout(angular.bind(this,function(){this.mutateDraggable(draggableScope,dropSettings,dragSettings,dragModel,dropModel,dropItem,$draggable),this.mutateDroppable(droppableScope,dropSettings,dragSettings,dropModel,dragItem,jqyoui_pos),this.callEventCallback(droppableScope,dropSettings.onDrop,event,ui)}))})).finally(angular.bind(this,function(){this.restore($draggable)}))},this.move=function($fromEl,$toEl,toPos,duration,dropSettings,callback){if(0===$fromEl.length)return callback&&window.setTimeout(function(){callback()},300),!1;var zIndex=$fromEl.css("z-index"),fromPos=$fromEl[dropSettings.containment||"offset"](),displayProperty=$toEl.css("display"),hadNgHideCls=$toEl.hasClass("ng-hide"),hadDNDHideCls=$toEl.hasClass("angular-dragdrop-hide");null===toPos&&$toEl.length>0&&(void 0!==($toEl.attr("jqyoui-draggable")||$toEl.attr("data-jqyoui-draggable"))&&void 0!==$toEl.ngattr("ng-model")&&$toEl.is(":visible")&&dropSettings&&dropSettings.multiple?(toPos=$toEl[dropSettings.containment||"offset"](),!1===dropSettings.stack?toPos.left+=$toEl.outerWidth(!0):toPos.top+=$toEl.outerHeight(!0)):(hadNgHideCls&&$toEl.removeClass("ng-hide"),hadDNDHideCls&&$toEl.removeClass("angular-dragdrop-hide"),toPos=$toEl.css({visibility:"hidden",display:"block"})[dropSettings.containment||"offset"](),$toEl.css({visibility:"",display:displayProperty}))),$fromEl.css({position:"absolute","z-index":9999}).css(fromPos).animate(toPos,duration,function(){hadNgHideCls&&$toEl.addClass("ng-hide"),hadDNDHideCls&&$toEl.addClass("angular-dragdrop-hide"),$fromEl.css("z-index",zIndex),callback&&callback()})},this.mutateDroppable=function(scope,dropSettings,dragSettings,dropModel,dragItem,jqyoui_pos){var dropModelValue=scope.$eval(dropModel);scope.dndDragItem=dragItem,angular.isArray(dropModelValue)?(dropSettings&&dropSettings.index>=0?dropModelValue[dropSettings.index]=dragItem:dropModelValue.push(dragItem),dragSettings&&!0===dragSettings.placeholder&&(dropModelValue[dropModelValue.length-1].jqyoui_pos=jqyoui_pos)):($parse(dropModel+" = dndDragItem")(scope),dragSettings&&!0===dragSettings.placeholder&&(dropModelValue.jqyoui_pos=jqyoui_pos))},this.mutateDraggable=function(scope,dropSettings,dragSettings,dragModel,dropModel,dropItem,$draggable){var isEmpty=angular.equals(dropItem,{})||!dropItem,dragModelValue=scope.$eval(dragModel);scope.dndDropItem=dropItem,dragSettings&&dragSettings.placeholder?"keep"!=dragSettings.placeholder&&(angular.isArray(dragModelValue)&&void 0!==dragSettings.index?dragModelValue[dragSettings.index]=dropItem:$parse(dragModel+" = dndDropItem")(scope)):angular.isArray(dragModelValue)?isEmpty?dragSettings&&!0!==dragSettings.placeholder&&"keep"!==dragSettings.placeholder&&dragModelValue.splice(dragSettings.index,1):dragModelValue[dragSettings.index]=dropItem:($parse(dragModel+" = dndDropItem")(scope),scope.$parent&&$parse(dragModel+" = dndDropItem")(scope.$parent)),this.restore($draggable)},this.restore=function($draggable){$draggable.css({"z-index":"",left:"",top:""})},this.fixIndex=function(scope,settings,modelValue){if(settings.applyFilter&&angular.isArray(modelValue)&&modelValue.length>0){var lookup=scope[settings.applyFilter]()[settings.index],actualIndex=void 0;return modelValue.forEach(function(item,i){angular.equals(item,lookup)&&(actualIndex=i)}),actualIndex}return settings.index}}]).directive("jqyouiDraggable",["ngDragDropService",function(ngDragDropService){return{require:"?jqyouiDroppable",restrict:"A",link:function(scope,elem,attrs){var dragSettings,jqyouiOptions,zIndex,killWatcher,element=$(elem),updateDraggable=function(newValue,oldValue){newValue?(dragSettings=scope.$eval(element.attr("jqyoui-draggable")||element.attr("data-jqyoui-draggable"))||{},jqyouiOptions=scope.$eval(attrs.jqyouiOptions)||{},element.draggable({disabled:!1}).draggable(jqyouiOptions).draggable({start:function(event,ui){ngDragDropService.draggableScope=scope,zIndex=$(jqyouiOptions.helper?ui.helper:this).css("z-index"),$(jqyouiOptions.helper?ui.helper:this).css("z-index",9999),jqyoui.startXY=$(this)[dragSettings.containment||"offset"](),ngDragDropService.callEventCallback(scope,dragSettings.onStart,event,ui)},stop:function(event,ui){$(jqyouiOptions.helper?ui.helper:this).css("z-index",zIndex),ngDragDropService.callEventCallback(scope,dragSettings.onStop,event,ui)},drag:function(event,ui){ngDragDropService.callEventCallback(scope,dragSettings.onDrag,event,ui)}})):element.draggable({disabled:!0}),killWatcher&&angular.isDefined(newValue)&&(angular.equals(attrs.drag,"true")||angular.equals(attrs.drag,"false"))&&(killWatcher(),killWatcher=null)};killWatcher=scope.$watch(function(){return scope.$eval(attrs.drag)},updateDraggable),updateDraggable(),element.on("$destroy",function(){element.draggable({disabled:!0}).draggable("destroy")})}}}]).directive("jqyouiDroppable",["ngDragDropService","$q",function(ngDragDropService,$q){return{restrict:"A",priority:1,link:function(scope,elem,attrs){var dropSettings,jqyouiOptions,killWatcher,element=$(elem),updateDroppable=function(newValue,oldValue){newValue?(dropSettings=scope.$eval($(element).attr("jqyoui-droppable")||$(element).attr("data-jqyoui-droppable"))||{},jqyouiOptions=scope.$eval(attrs.jqyouiOptions)||{},element.droppable({disabled:!1}).droppable(jqyouiOptions).droppable({over:function(event,ui){ngDragDropService.callEventCallback(scope,dropSettings.onOver,event,ui)},out:function(event,ui){ngDragDropService.callEventCallback(scope,dropSettings.onOut,event,ui)},drop:function(event,ui){(dropSettings.beforeDrop?ngDragDropService.callEventCallback(scope,dropSettings.beforeDrop,event,ui):function(){var deferred=$q.defer();return deferred.resolve(),deferred.promise}()).then(angular.bind(this,function(){$(ui.draggable).ngattr("ng-model")&&attrs.ngModel?(ngDragDropService.droppableScope=scope,ngDragDropService.invokeDrop($(ui.draggable),$(this),event,ui)):ngDragDropService.callEventCallback(scope,dropSettings.onDrop,event,ui)}),function(){var originalPosition=ui.draggable.data("uiDraggable").originalPosition;originalPosition||(originalPosition={left:"",top:""}),ui.draggable.animate(originalPosition,jqyouiOptions.revertDuration||0)})}})):element.droppable({disabled:!0}),killWatcher&&angular.isDefined(newValue)&&(angular.equals(attrs.drop,"true")||angular.equals(attrs.drop,"false"))&&(killWatcher(),killWatcher=null)};killWatcher=scope.$watch(function(){return scope.$eval(attrs.drop)},updateDroppable),updateDroppable(),element.on("$destroy",function(){element.droppable({disabled:!0}).droppable("destroy")})}}}]);$.fn.ngattr=function(name,value){var element=this[0];return element.getAttribute(name)||element.getAttribute("data-"+name)}}(window,window.angular,window.jQuery);