mobileoa-common-modules
Version:
移动办公平台前端公共功能模块
227 lines (189 loc) • 5.85 kB
JavaScript
'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});
}
}