mirror of
https://github.com/inverse-inc/sogo.git
synced 2026-09-17 19:38:00 +00:00
Initial drag'n'drop support in Calendar module
TODO: - drag'n'drop in month's view; - drag to create an all-day event; - drag'n'drop to a calendar in the sidenav; - touchscreen gestures support.
This commit is contained in:
@@ -0,0 +1,181 @@
|
||||
/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
|
||||
(function() {
|
||||
/* jshint validthis: true */
|
||||
'use strict';
|
||||
|
||||
/*
|
||||
* sgCalendarScrollView - scrollable view that contains draggable elements
|
||||
* @memberof SOGo.SchedulerUI
|
||||
* @restrict attribute
|
||||
* @param {string} sgCalendarScrollView - the view type (multiday, multiday-allday, or monthly)
|
||||
*
|
||||
* @example:
|
||||
|
||||
<md-content sg-calendar-scroll-view="multiday">
|
||||
..
|
||||
</md-content>
|
||||
*/
|
||||
sgCalendarScrollView.$inject = ['$rootScope', '$window', '$document', '$q', '$timeout', '$mdGesture', 'Calendar', 'Component'];
|
||||
function sgCalendarScrollView($rootScope, $window, $document, $q, $timeout, $mdGesture, Calendar, Component) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: {
|
||||
type: '@sgCalendarScrollView'
|
||||
},
|
||||
controller: sgCalendarScrollViewController,
|
||||
link: function(scope, element, attrs, controller) {
|
||||
var view, scrollView, type, lastScroll, deregisterDragStart, deregisterDragStop;
|
||||
|
||||
scrollView = element[0];
|
||||
type = scope.type; // multiday, multiday-allday, monthly, unknown?
|
||||
lastScroll = 0;
|
||||
|
||||
// Listen to dragstart and dragend events
|
||||
deregisterDragStart = $rootScope.$on('calendar:dragstart', onDragStart);
|
||||
deregisterDragStop = $rootScope.$on('calendar:dragend', onDragEnd);
|
||||
|
||||
// Update the "view" object literal once the Angular template has been transformed
|
||||
$timeout(initView);
|
||||
|
||||
// Deregister listeners when destroying the view
|
||||
scope.$on('$destroy', function() {
|
||||
deregisterDragStart();
|
||||
deregisterDragStop();
|
||||
element.off('mouseover', updateFromPointerHandler);
|
||||
angular.element($window).off('resize', updateCoordinates);
|
||||
});
|
||||
|
||||
function initView() {
|
||||
var quarterHeight;
|
||||
|
||||
// Quarter height doesn't change if window is resize; compute it only once
|
||||
quarterHeight = getQuarterHeight();
|
||||
|
||||
view = {
|
||||
type: type,
|
||||
quarterHeight: quarterHeight,
|
||||
scrollStep: 6 * quarterHeight,
|
||||
maxX: getMaxColumns(),
|
||||
|
||||
// Expose a reference of the view element
|
||||
element: scrollView
|
||||
};
|
||||
|
||||
// Compute coordinates of view element; recompute it on window resize
|
||||
angular.element($window).on('resize', updateCoordinates);
|
||||
updateCoordinates();
|
||||
}
|
||||
|
||||
function getQuarterHeight() {
|
||||
var hour0, hour23, height;
|
||||
|
||||
hour0 = document.getElementById('hour0');
|
||||
hour23 = document.getElementById('hour23');
|
||||
height = ((hour23.offsetTop - hour0.offsetTop) / (23 * 4));
|
||||
|
||||
return height;
|
||||
}
|
||||
|
||||
function getDayWidth(viewLeft) {
|
||||
var width, offset, nodes, domRect;
|
||||
|
||||
width = 0;
|
||||
offset = 0;
|
||||
nodes = scrollView.getElementsByClassName('day0');
|
||||
|
||||
if (nodes.length > 0) {
|
||||
domRect = nodes[0].getBoundingClientRect();
|
||||
width = domRect.width;
|
||||
offset = domRect.left - viewLeft;
|
||||
}
|
||||
|
||||
return [width, offset];
|
||||
}
|
||||
|
||||
function getMaxColumns() {
|
||||
var max = 0;
|
||||
|
||||
//if (type == 'multiday') {
|
||||
max = scrollView.getElementsByClassName('day').length - 1;
|
||||
//}
|
||||
|
||||
return max;
|
||||
}
|
||||
|
||||
// View has been resized;
|
||||
// Compute the view's origins (x, y), a day's width (dayWidth) and the left margin (daysOffset).
|
||||
function updateCoordinates() {
|
||||
var domRect, dayWidth;
|
||||
|
||||
domRect = scrollView.getBoundingClientRect();
|
||||
dayWidth = getDayWidth(domRect.left);
|
||||
|
||||
angular.extend(view, {
|
||||
coordinates: {
|
||||
x: domRect.left,
|
||||
y: domRect.top
|
||||
},
|
||||
dayWidth: dayWidth[0],
|
||||
daysOffset: dayWidth[1]
|
||||
});
|
||||
}
|
||||
|
||||
function onDragStart() {
|
||||
element.on('mouseover', updateFromPointerHandler);
|
||||
updateFromPointerHandler();
|
||||
}
|
||||
|
||||
function onDragEnd() {
|
||||
element.off('mouseover', updateFromPointerHandler);
|
||||
Calendar.$view = null;
|
||||
}
|
||||
|
||||
// From SOGoScrollController.updateFromPointerHandler
|
||||
function updateFromPointerHandler() {
|
||||
var scrollStep, pointerHandler, pointerCoordinates, now, scrollY, minY, delta;
|
||||
|
||||
scrollStep = view.scrollStep;
|
||||
pointerHandler = Component.$ghost.pointerHandler;
|
||||
if (pointerHandler) {
|
||||
pointerCoordinates = pointerHandler.getContainerBasedCoordinates(view);
|
||||
|
||||
if (pointerCoordinates) {
|
||||
// Pointer is inside view; Adjust scrollbar if necessary
|
||||
Calendar.$view = view;
|
||||
now = new Date().getTime();
|
||||
if (!lastScroll || now > lastScroll + 100) {
|
||||
lastScroll = now;
|
||||
scrollY = pointerCoordinates.y - scrollStep;
|
||||
if (scrollY < 0) {
|
||||
minY = -scrollView.scrollTop;
|
||||
if (scrollY < minY)
|
||||
scrollY = minY;
|
||||
scrollView.scrollTop += scrollY;
|
||||
}
|
||||
else {
|
||||
scrollY = pointerCoordinates.y + scrollStep;
|
||||
delta = scrollY - scrollView.clientHeight;
|
||||
if (delta > 0) {
|
||||
scrollView.scrollTop += delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
sgCalendarScrollViewController.$inject = ['$scope'];
|
||||
function sgCalendarScrollViewController($scope) {
|
||||
// Expose the view type to the controller
|
||||
// See sgCalendarDayBlockGhost
|
||||
this.type = $scope.type;
|
||||
}
|
||||
|
||||
angular
|
||||
.module('SOGo.SchedulerUI')
|
||||
.directive('sgCalendarScrollView', sgCalendarScrollView);
|
||||
})();
|
||||
Reference in New Issue
Block a user