ng-sortable
Version:
Angular Library for Drag and Drop, supports Sortable and Draggable.
197 lines (170 loc) • 6 kB
JavaScript
/*jshint undef: false, unused: false, indent: 2*/
/*global angular: false */
(function () {
'use strict';
var mainModule = angular.module('as.sortable');
/**
* Controller for Sortable.
* @param $scope - the sortable scope.
*/
mainModule.controller('as.sortable.sortableController', ['$scope', function ($scope) {
this.scope = $scope;
$scope.modelValue = null; // sortable list.
$scope.callbacks = null;
$scope.type = 'sortable';
$scope.options = {
longTouch: false
};
$scope.isDisabled = false;
/**
* Inserts the item in to the sortable list.
*
* @param index - the item index.
* @param itemData - the item model data.
*/
$scope.insertItem = function (index, itemData) {
if ($scope.options.allowDuplicates) {
$scope.modelValue.splice(index, 0, angular.copy(itemData));
} else {
$scope.modelValue.splice(index, 0, itemData);
}
};
/**
* Removes the item from the sortable list.
*
* @param index - index to be removed.
* @returns {*} - removed item.
*/
$scope.removeItem = function (index) {
var removedItem = null;
if (index > -1) {
removedItem = $scope.modelValue.splice(index, 1)[0];
}
return removedItem;
};
/**
* Checks whether the sortable list is empty.
*
* @returns {null|*|$scope.modelValue|boolean}
*/
$scope.isEmpty = function () {
return ($scope.modelValue && $scope.modelValue.length === 0);
};
/**
* Wrapper for the accept callback delegates to callback.
*
* @param sourceItemHandleScope - drag item handle scope.
* @param destScope - sortable target scope.
* @param destItemScope - sortable destination item scope.
* @returns {*|boolean} - true if drop is allowed for the drag item in drop target.
*/
$scope.accept = function (sourceItemHandleScope, destScope, destItemScope) {
return $scope.callbacks.accept(sourceItemHandleScope, destScope, destItemScope);
};
}]);
/**
* Sortable directive - defines callbacks.
* Parent directive for draggable and sortable items.
* Sets modelValue, callbacks, element in scope.
* sortOptions also includes a longTouch option which activates longTouch when set to true (default is false).
*/
mainModule.directive('asSortable',
function () {
return {
require: 'ngModel', // get a hold of NgModelController
restrict: 'A',
scope: true,
controller: 'as.sortable.sortableController',
link: function (scope, element, attrs, ngModelController) {
var ngModel, callbacks;
ngModel = ngModelController;
if (!ngModel) {
return; // do nothing if no ng-model
}
// Set the model value in to scope.
ngModel.$render = function () {
scope.modelValue = ngModel.$modelValue;
};
//set the element in scope to be accessed by its sub scope.
scope.element = element;
element.data('_scope',scope); // #144, work with angular debugInfoEnabled(false)
callbacks = {accept: null, orderChanged: null, itemMoved: null, dragStart: null, dragMove:null, dragCancel: null, dragEnd: null};
/**
* Invoked to decide whether to allow drop.
*
* @param sourceItemHandleScope - the drag item handle scope.
* @param destSortableScope - the drop target sortable scope.
* @param destItemScope - the drop target item scope.
* @returns {boolean} - true if allowed for drop.
*/
callbacks.accept = function (sourceItemHandleScope, destSortableScope, destItemScope) {
return true;
};
/**
* Invoked when order of a drag item is changed.
*
* @param event - the event object.
*/
callbacks.orderChanged = function (event) {
};
/**
* Invoked when the item is moved to other sortable.
*
* @param event - the event object.
*/
callbacks.itemMoved = function (event) {
};
/**
* Invoked when the drag started successfully.
*
* @param event - the event object.
*/
callbacks.dragStart = function (event) {
};
/**
* Invoked when the drag move.
*
* @param itemPosition - the item position.
* @param containment - the containment element.
* @param eventObj - the event object.
*/
callbacks.dragMove = angular.noop;
/**
* Invoked when the drag cancelled.
*
* @param event - the event object.
*/
callbacks.dragCancel = function (event) {
};
/**
* Invoked when the drag stopped.
*
* @param event - the event object.
*/
callbacks.dragEnd = function (event) {
};
//Set the sortOptions callbacks else set it to default.
scope.$watch(attrs.asSortable, function (newVal, oldVal) {
angular.forEach(newVal, function (value, key) {
if (callbacks[key]) {
if (typeof value === 'function') {
callbacks[key] = value;
}
} else {
scope.options[key] = value;
}
});
scope.callbacks = callbacks;
}, true);
// Set isDisabled if attr is set, if undefined isDisabled = false
if (angular.isDefined(attrs.isDisabled)) {
scope.$watch(attrs.isDisabled, function (newVal, oldVal) {
if (!angular.isUndefined(newVal)) {
scope.isDisabled = newVal;
}
}, true);
}
}
};
});
}());