diff --git a/ajax/libs/angular-ui-sortable/0.12.8/sortable.js b/ajax/libs/angular-ui-sortable/0.12.8/sortable.js new file mode 100644 index 000000000..94515125c --- /dev/null +++ b/ajax/libs/angular-ui-sortable/0.12.8/sortable.js @@ -0,0 +1,249 @@ +/* + jQuery UI Sortable plugin wrapper + + @param [ui-sortable] {object} Options to pass to $.fn.sortable() merged onto ui.config + */ +angular.module('ui.sortable', []) + .value('uiSortableConfig',{}) + .directive('uiSortable', [ + 'uiSortableConfig', '$timeout', '$log', + function(uiSortableConfig, $timeout, $log) { + return { + require: '?ngModel', + link: function(scope, element, attrs, ngModel) { + var savedNodes; + + function combineCallbacks(first,second){ + if(second && (typeof second === 'function')) { + return function(e, ui) { + first(e, ui); + second(e, ui); + }; + } + return first; + } + + function hasSortingHelper (element, ui) { + var helperOption = element.sortable('option','helper'); + return helperOption === 'clone' || (typeof helperOption === 'function' && ui.item.sortable.isCustomHelperUsed()); + } + + var opts = {}; + + var callbacks = { + receive: null, + remove:null, + start:null, + stop:null, + update:null + }; + + var wrappers = { + helper: null + }; + + angular.extend(opts, uiSortableConfig, scope.$eval(attrs.uiSortable)); + + if (!angular.element.fn || !angular.element.fn.jquery) { + $log.error('ui.sortable: jQuery should be included before AngularJS!'); + return; + } + + if (ngModel) { + + // When we add or remove elements, we need the sortable to 'refresh' + // so it can find the new/removed elements. + scope.$watch(attrs.ngModel+'.length', function() { + // Timeout to let ng-repeat modify the DOM + $timeout(function() { + // ensure that the jquery-ui-sortable widget instance + // is still bound to the directive's element + if (!!element.data('ui-sortable')) { + element.sortable('refresh'); + } + }); + }); + + callbacks.start = function(e, ui) { + // Save the starting position of dragged item + ui.item.sortable = { + index: ui.item.index(), + cancel: function () { + ui.item.sortable._isCanceled = true; + }, + isCanceled: function () { + return ui.item.sortable._isCanceled; + }, + isCustomHelperUsed: function () { + return !!ui.item.sortable._isCustomHelperUsed; + }, + _isCanceled: false, + _isCustomHelperUsed: ui.item.sortable._isCustomHelperUsed + }; + }; + + callbacks.activate = function(/*e, ui*/) { + // We need to make a copy of the current element's contents so + // we can restore it after sortable has messed it up. + // This is inside activate (instead of start) in order to save + // both lists when dragging between connected lists. + savedNodes = element.contents(); + + // If this list has a placeholder (the connected lists won't), + // don't inlcude it in saved nodes. + var placeholder = element.sortable('option','placeholder'); + + // placeholder.element will be a function if the placeholder, has + // been created (placeholder will be an object). If it hasn't + // been created, either placeholder will be false if no + // placeholder class was given or placeholder.element will be + // undefined if a class was given (placeholder will be a string) + if (placeholder && placeholder.element && typeof placeholder.element === 'function') { + var phElement = placeholder.element(); + // workaround for jquery ui 1.9.x, + // not returning jquery collection + phElement = angular.element(phElement); + + // exact match with the placeholder's class attribute to handle + // the case that multiple connected sortables exist and + // the placehoilder option equals the class of sortable items + var excludes = element.find('[class="' + phElement.attr('class') + '"]'); + + savedNodes = savedNodes.not(excludes); + } + }; + + callbacks.update = function(e, ui) { + // Save current drop position but only if this is not a second + // update that happens when moving between lists because then + // the value will be overwritten with the old value + if(!ui.item.sortable.received) { + ui.item.sortable.dropindex = ui.item.index(); + ui.item.sortable.droptarget = ui.item.parent(); + + // Cancel the sort (let ng-repeat do the sort for us) + // Don't cancel if this is the received list because it has + // already been canceled in the other list, and trying to cancel + // here will mess up the DOM. + element.sortable('cancel'); + } + + // Put the nodes back exactly the way they started (this is very + // important because ng-repeat uses comment elements to delineate + // the start and stop of repeat sections and sortable doesn't + // respect their order (even if we cancel, the order of the + // comments are still messed up). + if (hasSortingHelper(element, ui) && !ui.item.sortable.received) { + // restore all the savedNodes except .ui-sortable-helper element + // (which is placed last). That way it will be garbage collected. + savedNodes = savedNodes.not(savedNodes.last()); + } + savedNodes.appendTo(element); + + // If received is true (an item was dropped in from another list) + // then we add the new item to this list otherwise wait until the + // stop event where we will know if it was a sort or item was + // moved here from another list + if(ui.item.sortable.received && !ui.item.sortable.isCanceled()) { + scope.$apply(function () { + ngModel.$modelValue.splice(ui.item.sortable.dropindex, 0, + ui.item.sortable.moved); + }); + } + }; + + callbacks.stop = function(e, ui) { + // If the received flag hasn't be set on the item, this is a + // normal sort, if dropindex is set, the item was moved, so move + // the items in the list. + if(!ui.item.sortable.received && + ('dropindex' in ui.item.sortable) && + !ui.item.sortable.isCanceled()) { + + scope.$apply(function () { + ngModel.$modelValue.splice( + ui.item.sortable.dropindex, 0, + ngModel.$modelValue.splice(ui.item.sortable.index, 1)[0]); + }); + } else { + // if the item was not moved, then restore the elements + // so that the ngRepeat's comment are correct. + if ((!('dropindex' in ui.item.sortable) || ui.item.sortable.isCanceled()) && + !hasSortingHelper(element, ui)) { + savedNodes.appendTo(element); + } + } + }; + + callbacks.receive = function(e, ui) { + // An item was dropped here from another list, set a flag on the + // item. + ui.item.sortable.received = true; + }; + + callbacks.remove = function(e, ui) { + // Workaround for a problem observed in nested connected lists. + // There should be an 'update' event before 'remove' when moving + // elements. If the event did not fire, cancel sorting. + if (!('dropindex' in ui.item.sortable)) { + element.sortable('cancel'); + ui.item.sortable.cancel(); + } + + // Remove the item from this list's model and copy data into item, + // so the next list can retrive it + if (!ui.item.sortable.isCanceled()) { + scope.$apply(function () { + ui.item.sortable.moved = ngModel.$modelValue.splice( + ui.item.sortable.index, 1)[0]; + }); + } + }; + + wrappers.helper = function (inner) { + if (inner && typeof inner === 'function') { + return function (e, item) { + var innerResult = inner(e, item); + item.sortable._isCustomHelperUsed = item !== innerResult; + return innerResult; + }; + } + return inner; + }; + + scope.$watch(attrs.uiSortable, function(newVal /*, oldVal*/) { + // ensure that the jquery-ui-sortable widget instance + // is still bound to the directive's element + if (!!element.data('ui-sortable')) { + angular.forEach(newVal, function(value, key) { + if(callbacks[key]) { + if( key === 'stop' ){ + // call apply after stop + value = combineCallbacks( + value, function() { scope.$apply(); }); + } + // wrap the callback + value = combineCallbacks(callbacks[key], value); + } else if (wrappers[key]) { + value = wrappers[key](value); + } + + element.sortable('option', key, value); + }); + } + }, true); + + angular.forEach(callbacks, function(value, key) { + opts[key] = combineCallbacks(value, opts[key]); + }); + + } else { + $log.info('ui.sortable: ngModel not provided!', element); + } + + // Create sortable + element.sortable(opts); + } + }; + } + ]); \ No newline at end of file diff --git a/ajax/libs/angular-ui-sortable/0.12.8/sortable.min.js b/ajax/libs/angular-ui-sortable/0.12.8/sortable.min.js new file mode 100644 index 000000000..7abf28688 --- /dev/null +++ b/ajax/libs/angular-ui-sortable/0.12.8/sortable.min.js @@ -0,0 +1,6 @@ +/* + jQuery UI Sortable plugin wrapper + + @param [ui-sortable] {object} Options to pass to $.fn.sortable() merged onto ui.config + */ +angular.module("ui.sortable",[]).value("uiSortableConfig",{}).directive("uiSortable",["uiSortableConfig","$timeout","$log",function(e,t,n){return{require:"?ngModel",link:function(r,i,s,o){function a(e,t){if(t&&typeof t==="function"){return function(n,r){e(n,r);t(n,r)}}return e}function f(e,t){var n=e.sortable("option","helper");return n==="clone"||typeof n==="function"&&t.item.sortable.isCustomHelperUsed()}var u;var l={};var c={receive:null,remove:null,start:null,stop:null,update:null};var h={helper:null};angular.extend(l,e,r.$eval(s.uiSortable));if(!angular.element.fn||!angular.element.fn.jquery){n.error("ui.sortable: jQuery should be included before AngularJS!");return}if(o){r.$watch(s.ngModel+".length",function(){t(function(){if(!!i.data("ui-sortable")){i.sortable("refresh")}})});c.start=function(e,t){t.item.sortable={index:t.item.index(),cancel:function(){t.item.sortable._isCanceled=true},isCanceled:function(){return t.item.sortable._isCanceled},isCustomHelperUsed:function(){return!!t.item.sortable._isCustomHelperUsed},_isCanceled:false,_isCustomHelperUsed:t.item.sortable._isCustomHelperUsed}};c.activate=function(){u=i.contents();var e=i.sortable("option","placeholder");if(e&&e.element&&typeof e.element==="function"){var t=e.element();t=angular.element(t);var n=i.find('[class="'+t.attr("class")+'"]');u=u.not(n)}};c.update=function(e,t){if(!t.item.sortable.received){t.item.sortable.dropindex=t.item.index();t.item.sortable.droptarget=t.item.parent();i.sortable("cancel")}if(f(i,t)&&!t.item.sortable.received){u=u.not(u.last())}u.appendTo(i);if(t.item.sortable.received&&!t.item.sortable.isCanceled()){r.$apply(function(){o.$modelValue.splice(t.item.sortable.dropindex,0,t.item.sortable.moved)})}};c.stop=function(e,t){if(!t.item.sortable.received&&"dropindex"in t.item.sortable&&!t.item.sortable.isCanceled()){r.$apply(function(){o.$modelValue.splice(t.item.sortable.dropindex,0,o.$modelValue.splice(t.item.sortable.index,1)[0])})}else{if((!("dropindex"in t.item.sortable)||t.item.sortable.isCanceled())&&!f(i,t)){u.appendTo(i)}}};c.receive=function(e,t){t.item.sortable.received=true};c.remove=function(e,t){if(!("dropindex"in t.item.sortable)){i.sortable("cancel");t.item.sortable.cancel()}if(!t.item.sortable.isCanceled()){r.$apply(function(){t.item.sortable.moved=o.$modelValue.splice(t.item.sortable.index,1)[0]})}};h.helper=function(e){if(e&&typeof e==="function"){return function(t,n){var r=e(t,n);n.sortable._isCustomHelperUsed=n!==r;return r}}return e};r.$watch(s.uiSortable,function(e){if(!!i.data("ui-sortable")){angular.forEach(e,function(e,t){if(c[t]){if(t==="stop"){e=a(e,function(){r.$apply()})}e=a(c[t],e)}else if(h[t]){e=h[t](e)}i.sortable("option",t,e)})}},true);angular.forEach(c,function(e,t){l[t]=a(e,l[t])})}else{n.info("ui.sortable: ngModel not provided!",i)}i.sortable(l)}}}]) \ No newline at end of file diff --git a/ajax/libs/angular-ui-sortable/package.json b/ajax/libs/angular-ui-sortable/package.json new file mode 100644 index 000000000..804013ddf --- /dev/null +++ b/ajax/libs/angular-ui-sortable/package.json @@ -0,0 +1,43 @@ +{ + "name": "angular-ui-sortable", + "filename": "sortable.min.js", + "version": "0.12.8", + "description": "This directive allows you to jQueryUI Sortable.", + "author": "https://github.com/angular-ui/ui-sortable/graphs/contributors", + "license": "MIT", + "homepage": "http://angular-ui.github.com", + "main": "./src/sortable.js", + "dependencies": {}, + "devDependencies": { + "angular-ui-publisher": "1.2.x", + "grunt": "~0.4.x", + "grunt-contrib-connect": "0.5.x", + "grunt-contrib-jshint": "0.8.x", + "grunt-contrib-uglify": "0.2.x", + "grunt-contrib-watch": "0.5.x", + "grunt-conventional-changelog": "~1.0.0", + "grunt-karma": "0.6.x", + "grunt-ngmin": "0.0.x", + "grunt-surround": "0.1.x", + "karma": "0.10.x", + "karma-chrome-launcher": "0.1.x", + "karma-coffee-preprocessor": "0.1.x", + "karma-coverage": "~0.2.0", + "karma-coveralls": "~0.1.4", + "karma-firefox-launcher": "0.1.x", + "karma-html2js-preprocessor": "0.1.x", + "karma-jasmine": "0.1.x", + "karma-junit-reporter": "0.2.x", + "karma-phantomjs-launcher": "0.1.x", + "karma-requirejs": "0.2.x", + "karma-script-launcher": "0.1.x", + "load-grunt-tasks": "0.2.x", + "requirejs": "2.1.x", + "wiredep": "1.8.x" + }, + "scripts": {}, + "repository": { + "type": "git", + "url": "git://github.com/angular-ui/ui-sortable.git" + } +}