From 0355f66e964b5eca47e0e6489cc7f4c1ad93a756 Mon Sep 17 00:00:00 2001 From: Francis Lachapelle Date: Mon, 29 May 2017 15:19:03 -0400 Subject: [PATCH] (js) New ImageGallery ng service --- .../js/Mailer/sgImageGallery.service.js | 221 ++++++++++++++++++ 1 file changed, 221 insertions(+) create mode 100644 UI/WebServerResources/js/Mailer/sgImageGallery.service.js diff --git a/UI/WebServerResources/js/Mailer/sgImageGallery.service.js b/UI/WebServerResources/js/Mailer/sgImageGallery.service.js new file mode 100644 index 000000000..331d1fd44 --- /dev/null +++ b/UI/WebServerResources/js/Mailer/sgImageGallery.service.js @@ -0,0 +1,221 @@ +/* -*- Mode: javascript; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ + +(function() { + 'use strict'; + + /** + * @name ImageGallery + * @constructor + */ + function ImageGallery() { + this.show = false; + this.message = null; + this.elements = []; + } + + /** + * @memberof ImageGallery + * @desc The factory we'll use to register with Angular + * @returns an ImageGallery instance + */ + ImageGallery.$factory = ['$document', '$timeout', '$mdPanel', 'sgHotkeys', function($document, $timeout, $mdPanel, sgHotkeys) { + angular.extend(ImageGallery, { + $document: $document, + $timeout: $timeout, + $mdPanel: $mdPanel, + sgHotkeys: sgHotkeys + }); + + return new ImageGallery(); // return unique instance + }]; + + /** + * @function setMessage + * @memberof ImageGallery.prototype + * @desc Set current message object of gallery + */ + ImageGallery.prototype.setMessage = function(message) { + this.message = message; + }; + + /** + * @function registerImage + * @memberof ImageGallery.prototype + * @desc Add an image to the gallery. Called from sgZoomableImage directive. + */ + ImageGallery.prototype.registerImage = function(element) { + this.elements.push(element); + }; + + /** + * @function registerHotkeys + * @memberof ImageGallery.prototype + * @desc Allow keyboard navigation + */ + ImageGallery.prototype.registerHotkeys = function($ctrl) { + this.keys = [ + ImageGallery.sgHotkeys.createHotkey({ + key: 'left', + description: l('View previous item'), + callback: angular.bind($ctrl, $ctrl.previousImage) + }), + ImageGallery.sgHotkeys.createHotkey({ + key: 'right', + description: l('View next item'), + callback: angular.bind($ctrl, $ctrl.nextImage) + }) + ]; + _.forEach(this.keys, function(key) { + ImageGallery.sgHotkeys.registerHotkey(key); + }); + }; + + /** + * @function showGallery + * @memberof ImageGallery.prototype + * @desc Build and show the md-panel + */ + ImageGallery.prototype.showGallery = function($event, partIndex) { + var _this = this, + $mdPanel = ImageGallery.$mdPanel, + partSrc = angular.element(this.message.parts.content[partIndex].content).find('img')[0].src; + + var images = _.filter(this.message.attachmentAttrs, function(attrs) { + return attrs.mimetype.indexOf('image/') === 0; + }); + + var selectedIndex = _.findIndex(images, function(image) { + return image.url.indexOf(partSrc) >= 0; + }); + + // Add a class to the body in order to modify the panel backdrop opacity + angular.element(ImageGallery.$document[0].body).addClass('sg-image-gallery-backdrop'); + + // Fullscreen panel + var panelPosition = $mdPanel.newPanelPosition() + .absolute(); + + var panelAnimation = $mdPanel.newPanelAnimation() + .openFrom($event.target) + .duration(100) + .withAnimation($mdPanel.animation.FADE); + + var config = { + attachTo: angular.element(document.body), + locals: { + lastIndex: images.length -1, + images: images, + selectedIndex: selectedIndex, + selectedImage: images[selectedIndex] + }, + bindToController: true, + controller: PanelController, + controllerAs: '$panelCtrl', + position: panelPosition, + animation: panelAnimation, + targetEvent: $event, + fullscreen: true, + hasBackdrop: true, + template: [ + '', + '
', + '
', + ' ', + ' arrow_back', + ' ', + ' image', + ' ', + '
', + ' ', + ' file_download', + ' ', + '
', + '
', + ' ', + ' navigate_before', + ' ', + ' ', + ' ', + ' navigate_next', + ' ', + '
', + '
', + '
', + ' ', + '
', + '
', + '
' + ].join(''), + trapFocus: true, + clickOutsideToClose: true, + escapeToClose: true, + focusOnOpen: true, + onOpenComplete: function() { + _this.show = true; + _.forEach(ImageGallery.$document.find('sg-image-gallery')[0].getElementsByClassName('sg-image-thumbnail'), + function(imgContainer) { + var imgEl = imgContainer.children[0]; + angular.element(imgEl).one('load', function() { + if (imgEl.naturalWidth < imgEl.naturalHeight) + imgEl.classList.add('portrait'); + }); + // Display thumbnail + ImageGallery.$timeout(function() { + imgEl.classList.remove('sg-hide'); + }, 1000); + }); + }, + onDomRemoved: function() { + angular.element(ImageGallery.$document[0].body).removeClass('sg-image-gallery-backdrop'); + _this.show = false; + // Deregister hotkeys + _.forEach(_this.hotkeys, function(key) { + ImageGallery.sgHotkeys.deregisterHotkey(key); + }); + } + }; + + $mdPanel.open(config).then(function(mdPanelRef) { + _this.registerHotkeys(mdPanelRef.$ctrl); + }); + + PanelController.$inject = ['mdPanelRef']; + function PanelController(mdPanelRef) { + var $menuCtrl = this; + + mdPanelRef.$ctrl = this; + + this.close = function() { + mdPanelRef.close(); + }; + + this.selectImage = function(index) { + this.selectedIndex = index; + this.selectedImage = this.images[index]; + }; + + this.nextImage = function() { + if (this.selectedIndex != this.lastIndex) + this.selectImage(this.selectedIndex + 1); + }; + + this.previousImage = function() { + if (this.selectedIndex > 0) + this.selectImage(this.selectedIndex - 1); + }; + + } // PanelController + + }; + + /* Factory registration in Angular module */ + angular.module('SOGo.MailerUI') + .factory('ImageGallery', ImageGallery.$factory); + +})();