UNPKG

ui-select

Version:
149 lines (118 loc) 4.5 kB
// Make multiple matches sortable uis.directive('uiSelectSort', ['$timeout', 'uiSelectConfig', 'uiSelectMinErr', function($timeout, uiSelectConfig, uiSelectMinErr) { return { require: ['^^uiSelect', '^ngModel'], link: function(scope, element, attrs, ctrls) { if (scope[attrs.uiSelectSort] === null) { throw uiSelectMinErr('sort', 'Expected a list to sort'); } var $select = ctrls[0]; var $ngModel = ctrls[1]; var options = angular.extend({ axis: 'horizontal' }, scope.$eval(attrs.uiSelectSortOptions)); var axis = options.axis; var draggingClassName = 'dragging'; var droppingClassName = 'dropping'; var droppingBeforeClassName = 'dropping-before'; var droppingAfterClassName = 'dropping-after'; scope.$watch(function(){ return $select.sortable; }, function(newValue){ if (newValue) { element.attr('draggable', true); } else { element.removeAttr('draggable'); } }); element.on('dragstart', function(event) { element.addClass(draggingClassName); (event.dataTransfer || event.originalEvent.dataTransfer).setData('text', scope.$index.toString()); }); element.on('dragend', function() { removeClass(draggingClassName); }); var move = function(from, to) { /*jshint validthis: true */ this.splice(to, 0, this.splice(from, 1)[0]); }; var removeClass = function(className) { angular.forEach($select.$element.querySelectorAll('.' + className), function(el){ angular.element(el).removeClass(className); }); }; var dragOverHandler = function(event) { event.preventDefault(); var offset = axis === 'vertical' ? event.offsetY || event.layerY || (event.originalEvent ? event.originalEvent.offsetY : 0) : event.offsetX || event.layerX || (event.originalEvent ? event.originalEvent.offsetX : 0); if (offset < (this[axis === 'vertical' ? 'offsetHeight' : 'offsetWidth'] / 2)) { removeClass(droppingAfterClassName); element.addClass(droppingBeforeClassName); } else { removeClass(droppingBeforeClassName); element.addClass(droppingAfterClassName); } }; var dropTimeout; var dropHandler = function(event) { event.preventDefault(); var droppedItemIndex = parseInt((event.dataTransfer || event.originalEvent.dataTransfer).getData('text'), 10); // prevent event firing multiple times in firefox $timeout.cancel(dropTimeout); dropTimeout = $timeout(function() { _dropHandler(droppedItemIndex); }, 20); }; var _dropHandler = function(droppedItemIndex) { var theList = scope.$eval(attrs.uiSelectSort); var itemToMove = theList[droppedItemIndex]; var newIndex = null; if (element.hasClass(droppingBeforeClassName)) { if (droppedItemIndex < scope.$index) { newIndex = scope.$index - 1; } else { newIndex = scope.$index; } } else { if (droppedItemIndex < scope.$index) { newIndex = scope.$index; } else { newIndex = scope.$index + 1; } } move.apply(theList, [droppedItemIndex, newIndex]); $ngModel.$setViewValue(Date.now()); scope.$apply(function() { scope.$emit('uiSelectSort:change', { array: theList, item: itemToMove, from: droppedItemIndex, to: newIndex }); }); removeClass(droppingClassName); removeClass(droppingBeforeClassName); removeClass(droppingAfterClassName); element.off('drop', dropHandler); }; element.on('dragenter', function() { if (element.hasClass(draggingClassName)) { return; } element.addClass(droppingClassName); element.on('dragover', dragOverHandler); element.on('drop', dropHandler); }); element.on('dragleave', function(event) { if (event.target != element) { return; } removeClass(droppingClassName); removeClass(droppingBeforeClassName); removeClass(droppingAfterClassName); element.off('dragover', dragOverHandler); element.off('drop', dropHandler); }); } }; }]);