UNPKG

mobileoa-common-modules

Version:

移动办公平台前端公共功能模块

227 lines (189 loc) 5.85 kB
'use strict'; var angular = require('angular'), _ = require('jsUtil'); require('../modules'); function Point(x, y) { this.x = x; this.y = y; } Point.prototype = { move: function (deltaX, deltaY) { return new Point(this.x + deltaX, this.y + deltaY); }, relative: function (x, y) { return new Point(x - this.x, y - this.y); } }; function SinoModelListHitTests(items) { this.items = items; this.xNumber = 4; this.gapWidth = 0.3; this.gapHeight = 0.3; this.xItemWidth = document.body.clientWidth / 4; this.yItemHeight = 60; this.origin = new Point(0, 80); } SinoModelListHitTests.prototype = { setItems: function (items) { this.items = items; }, toIndex: function (x, y) { return y * this.xNumber + x; }, hitTestOnStartMoving: function (x, y) { var point = this.origin.relative(x, y); var xIndex = Math.floor(point.x / this.xItemWidth); var yIndex = Math.floor(point.y / this.yItemHeight); this.index = this.toIndex(xIndex, yIndex); this.point = new Point(xIndex * this.xItemWidth, yIndex * this.yItemHeight); return this.index; }, hitRegion: function (index, gap) { if (index - Math.floor(index) <= gap) { index = Math.floor(index); } else if (Math.ceil(index) - index <= gap) { index = Math.ceil(index); } else { index = -1; } return index; }, hitTestOnMoving: function (deltaX, deltaY) { var point = this.point.move(deltaX, deltaY), xIndex = point.x / this.xItemWidth, yIndex = point.y / this.yItemHeight, index = -1, originIndex = this.index, change = false; xIndex = this.hitRegion(xIndex, this.gapWidth); yIndex = this.hitRegion(yIndex, this.gapHeight); if (xIndex >= 0 && yIndex >= 0) { index = this.toIndex(xIndex, yIndex); if (index >= this.items.length) { return null; } change = index !== originIndex; this.index = index; return change? { from: originIndex, to: index } : null; } return null; } }; angular .module('infoDisplay.directives') .directive('sinoModelDrag', sinoModelDrag) .controller('sinoModelDragCtrl', sinoModelDragCtrl); /** @ngInject */ function sinoModelDrag() { return { restrict: 'AC', controller: 'sinoModelDragCtrl', require: 'sinoModelDrag' } } /** @ngInject */ function sinoModelDragCtrl($scope, $window, $timeout, $ionicGesture, $element, $attrs, $ionicScrollDelegate, Timer) { var self = this, floatElement, element, ionScroll = $ionicScrollDelegate.$getByHandle('sinoModelListScroll'), inDragging = false; self.listHitTests = new SinoModelListHitTests($scope.selectedItems); var dragStartGesture = $ionicGesture.on('dragstart', onDragStart, $element); var dragGesture = $ionicGesture.on('drag', onDrag, $element); var dragEndGesture = $ionicGesture.on('dragend', onDragEnd, $element); function getRelatedTouchPoint(touch) { if (ionScroll) { var scrollTop = ionScroll.getScrollPosition().top; return new Point(touch.pageX, touch.pageY + scrollTop); } else { return new Point(touch.pageX, touch.pageY); } } function onDragStart(event) { var touch = event.gesture.touches[0], point = getRelatedTouchPoint(touch); self.listHitTests.hitTestOnStartMoving(point.x, point.y); if (self.listHitTests.index >= $scope.selectedItems.length) { return false; } ionScroll && ionScroll.freezeScroll(true); event.preventDefault(); inDragging = true; element = $element[0].querySelector('.sino-model-button-bar:nth-child(' + (self.listHitTests.index + 1) + ')'); element = angular.element(element); floatElement = element.clone(); $element.append(floatElement); floatElement.css({ zIndex: '100', position: 'absolute', top: element[0].offsetTop + 'px', left: element[0].offsetLeft + 'px' }); element.addClass('dragging'); } function onDrag(event) { if (!inDragging) { return; } var deltaX = event.gesture.deltaX; var deltaY = event.gesture.deltaY; var index = self.listHitTests.hitTestOnMoving(deltaX, deltaY); floatElement.css({ transform: 'translate3d(' + deltaX + 'px,' + deltaY + 'px, 0)' }); if (index) { orderIndex(index.from, index.to); } } function onDragEnd() { ionScroll && ionScroll.freezeScroll(false); if (inDragging) { inDragging = false; floatElement.remove(); element.removeClass('dragging'); } } $scope.$on('$destroy', function () { $ionicGesture.off(dragStartGesture,'dragstart', onDragStart); $ionicGesture.off(dragGesture, 'drag', onDrag); $ionicGesture.off(dragEndGesture, 'dragend', onDragEnd); }); var orderChanges = [], updatingIndex = false, timerId; function updateIndex() { if (orderChanges && !updatingIndex) { updatingIndex = true; var changes = orderChanges, change; orderChanges = []; for (var i = 0, len = changes.length; i < len; i++) { change = changes[i]; exchangeIndex(change.from, change.to); } $scope.refreshItems($scope.selectedItems, $scope.notSelectedItems); updatingIndex = false; } } function exchangeIndex(from, to) { var items = $scope.selectedItems, fromItem = items[from], dataLength = items.length; if (from >= 0 && from < dataLength && to >= 0 && to < dataLength && fromItem) { items.splice(from, 1); items.splice(to, 0, fromItem); } } function updateIndexOnTimer() { timerId = Timer.interval(updateIndex, 16.67); $scope.$on('$destroy', function() { Timer.clear(timerId); }); } updateIndexOnTimer(); function orderIndex(from, to) { orderChanges.push({from: from, to: to}); } }