diff options
-rw-r--r-- | css/slideshow.css | 5 | ||||
-rw-r--r-- | js/app.js | 3 | ||||
-rw-r--r-- | js/gallery.js | 23 | ||||
-rw-r--r-- | js/galleryfileaction.js | 257 | ||||
-rw-r--r-- | js/galleryview.js | 10 | ||||
-rw-r--r-- | js/slideshow.js | 625 | ||||
-rw-r--r-- | js/slideshowcontrols.js | 77 | ||||
-rw-r--r-- | js/slideshowzoomablepreview.js | 14 | ||||
-rw-r--r-- | templates/slideshow.php | 1 |
9 files changed, 557 insertions, 458 deletions
diff --git a/css/slideshow.css b/css/slideshow.css index 0e7af331..09c3762b 100644 --- a/css/slideshow.css +++ b/css/slideshow.css @@ -168,3 +168,8 @@ filter: alpha(opacity=90); opacity: .9; } + +#slideshow > .bigshotContainer { + width: 100%; + height: 100%; +} @@ -1,5 +1,6 @@ /* global OC, $, _, Gallery */ $(document).ready(function () { + "use strict"; Gallery.hideSearch(); Gallery.utility = new Gallery.Utility(); Gallery.view = new Gallery.View(); @@ -17,7 +18,6 @@ $(document).ready(function () { // Needed to centre the spinner in some browsers Gallery.resetContentHeight(); Gallery.showLoading(); - $.getJSON(Gallery.utility.buildGalleryUrl('config', '', {})) .then(function (config) { Gallery.config = new Gallery.Config(config); @@ -76,6 +76,7 @@ $(document).ready(function () { }); window.onhashchange = function () { + "use strict"; // The hash location is ALWAYS encoded var path = decodeURIComponent(window.location.href.split('#')[1] || ''); var albumPath = OC.dirname(path); diff --git a/js/gallery.js b/js/gallery.js index 99eba304..2fe6811d 100644 --- a/js/gallery.js +++ b/js/gallery.js @@ -1,4 +1,4 @@ -/* global OC, $, t, Album, GalleryImage, SlideShow, oc_requesttoken */ +/* global OC, $, t, Album, GalleryImage */ var Gallery = {}; Gallery.images = []; Gallery.currentAlbum = null; @@ -8,6 +8,7 @@ Gallery.imageMap = {}; Gallery.albumCache = {}; Gallery.appName = 'galleryplus'; Gallery.token = undefined; +Gallery.activeSlideShow = null; /** * Builds a map of the albums located in the current folder @@ -47,7 +48,7 @@ Gallery.refresh = function (path, albumPath) { if (Gallery.activeSlideShow) { Gallery.activeSlideShow.stop(); } - } else if (Gallery.imageMap[path] && !Gallery.activeSlideShow) { + } else if (Gallery.imageMap[path] && Gallery.activeSlideShow.active === false) { Gallery.view.startSlideshow(path, albumPath); } }; @@ -341,6 +342,7 @@ Gallery.resetContentHeight = function () { * @returns {boolean} */ Gallery.slideShow = function (images, startImage, autoPlay) { + "use strict"; if (startImage === undefined) { OC.Notification.showTemporary(t('gallery', 'Aborting preview. Could not find the file')); return false; @@ -371,21 +373,14 @@ Gallery.slideShow = function (images, startImage, autoPlay) { downloadUrl: downloadUrl }; }); - - var slideShow = new SlideShow($('#slideshow'), images); - slideShow.onStop = function () { - Gallery.activeSlideShow = null; + Gallery.activeSlideShow.setImages(images, autoPlay); + Gallery.activeSlideShow.onStop = function () { $('#content').show(); if (Gallery.currentAlbum !== '') { - location.hash = encodeURIComponent(Gallery.currentAlbum); + history.replaceState('', '', '#' + encodeURIComponent(Gallery.currentAlbum)); } else { - location.hash = '!'; + history.replaceState('', '', '#'); } }; - Gallery.activeSlideShow = slideShow; - - slideShow.init(autoPlay); - slideShow.show(start); + Gallery.activeSlideShow.show(start); }; - -Gallery.activeSlideShow = null; diff --git a/js/galleryfileaction.js b/js/galleryfileaction.js index 7ff9d3bf..53423cdd 100644 --- a/js/galleryfileaction.js +++ b/js/galleryfileaction.js @@ -1,130 +1,167 @@ -/* global OC ,OCA, $, oc_requesttoken, SlideShow */ -var galleryFileAction = { - config: null, - mediaTypes: {}, - - /** - * Builds a URL pointing to one of the app's controllers - * - * @param {string} endPoint - * @param {undefined|string} path - * @param params - * - * @returns {string} - */ - buildGalleryUrl: function (endPoint, path, params) { - var extension = ''; - var tokenElement = $('#sharingToken'); - var token = (tokenElement.val()) ? tokenElement.val() : false; - if (token) { - params.token = token; - extension = '.public'; - } - var query = OC.buildQueryString(params); - return OC.generateUrl('apps/galleryplus/' + endPoint + extension + path, null) + '?' + - query; - }, - - /** - * Registers a file action for each media type - * - * @param mediaTypes - */ - register: function (mediaTypes) { - //console.log("enabledPreviewProviders: ", mediaTypes); - if (mediaTypes) { - galleryFileAction.mediaTypes = mediaTypes; - } +/* global oc_requesttoken, FileList, SlideShow */ +(function (OC ,OCA, $, oc_requesttoken) { + "use strict"; + var galleryFileAction = { + config: null, + mediaTypes: {}, + scrollContainer: null, + slideShow: null, - // We only want to create slideshows for supported media types - for (var i = 0, keys = Object.keys(galleryFileAction.mediaTypes); i < keys.length; i++) { - // Each click handler gets the same function and images array and - // is responsible to load the slideshow - OCA.Files.fileActions.register(keys[i], 'View', OC.PERMISSION_READ, '', - galleryFileAction.onView); - OCA.Files.fileActions.setDefault(keys[i], 'View'); - } - }, - - /** - * Builds an array containing all the images we can show in the slideshow - * - * @param {string} filename - * @param context - */ - onView: function (filename, context) { - var imageUrl, downloadUrl; - var fileList = context.fileList; - var files = fileList.files; - var start = 0; - var images = []; - var dir = context.dir + '/'; - var width = Math.floor(screen.width * window.devicePixelRatio); - var height = Math.floor(screen.height * window.devicePixelRatio); - - /* Find value of longest edge. */ - var longEdge = Math.max(width, height); - - /* Find the next larger image size. */ - if (longEdge % 100 !== 0) { - longEdge = ( longEdge + 100 ) - ( longEdge % 100 ); - } + /** + * Builds a URL pointing to one of the app's controllers + * + * @param {string} endPoint + * @param {undefined|string} path + * @param params + * + * @returns {string} + */ + buildGalleryUrl: function (endPoint, path, params) { + var extension = ''; + var tokenElement = $('#sharingToken'); + var token = (tokenElement.val()) ? tokenElement.val() : false; + if (token) { + params.token = token; + extension = '.public'; + } + var query = OC.buildQueryString(params); + return OC.generateUrl('apps/galleryplus/' + endPoint + extension + path, null) + '?' + + query; + }, - for (var i = 0; i < files.length; i++) { - var file = files[i]; - // We only add images to the slideshow if we think we'll be able - // to generate previews for this media type - if (galleryFileAction.mediaTypes[file.mimetype]) { - /* jshint camelcase: false */ - var params = { - width: longEdge, - height: longEdge, - c: file.etag, - requesttoken: oc_requesttoken - }; - imageUrl = galleryFileAction.buildGalleryUrl('preview', '/' + file.id, params); - downloadUrl = imageUrl + '&download'; - - images.push({ - name: file.name, - path: dir + file.name, - fileId: file.id, - mimeType: file.mimetype, - url: imageUrl, - downloadUrl: downloadUrl - }); + /** + * Registers a file action for each media type + * + * @param mediaTypes + */ + register: function (mediaTypes) { + //console.log("enabledPreviewProviders: ", mediaTypes); + if (mediaTypes) { + galleryFileAction.mediaTypes = mediaTypes; } - } - for (i = 0; i < images.length; i++) { - //console.log("Images in the slideshow : ", images[i]); - if (images[i].name === filename) { - start = i; + + // We only want to create slideshows for supported media types + for (var i = 0, keys = Object.keys(galleryFileAction.mediaTypes); i < + keys.length; i++) { + // Each click handler gets the same function and images array and + // is responsible to load the slideshow + OCA.Files.fileActions.register(keys[i], 'View', OC.PERMISSION_READ, '', + galleryFileAction.onView); + OCA.Files.fileActions.setDefault(keys[i], 'View'); + } + }, + + /** + * Builds an array containing all the images we can show in the slideshow + * + * @param {string} filename + * @param context + */ + onView: function (filename, context) { + var imageUrl, downloadUrl; + var fileList = context.fileList; + var files = fileList.files; + var start = 0; + var images = []; + var dir = context.dir + '/'; + var width = Math.floor(screen.width * window.devicePixelRatio); + var height = Math.floor(screen.height * window.devicePixelRatio); + + /* Find value of longest edge. */ + var longEdge = Math.max(width, height); + + /* Find the next larger image size. */ + if (longEdge % 100 !== 0) { + longEdge = ( longEdge + 100 ) - ( longEdge % 100 ); + } + + for (var i = 0; i < files.length; i++) { + var file = files[i]; + // We only add images to the slideshow if we think we'll be able + // to generate previews for this media type + if (galleryFileAction.mediaTypes[file.mimetype]) { + /* jshint camelcase: false */ + var params = { + width: longEdge, + height: longEdge, + c: file.etag, + requesttoken: oc_requesttoken + }; + imageUrl = galleryFileAction.buildGalleryUrl('preview', '/' + file.id, params); + downloadUrl = imageUrl + '&download'; + + images.push({ + name: file.name, + path: dir + file.name, + fileId: file.id, + mimeType: file.mimetype, + url: imageUrl, + downloadUrl: downloadUrl + }); + } + } + for (i = 0; i < images.length; i++) { + //console.log("Images in the slideshow : ", images[i]); + if (images[i].name === filename) { + start = i; + } + } + + if ($.isEmptyObject(galleryFileAction.slideShow)) { + galleryFileAction.slideShow = new SlideShow($('#slideshow')); + galleryFileAction.slideShow.init(false, null); } + + galleryFileAction.slideShow.setImages(images); + + var scrollTop = galleryFileAction.scrollContainer.scrollTop(); + // This is only called when the slideshow is stopped + galleryFileAction.slideShow.onStop = function () { + // Adding to the history will add a new URL every time the slideshow is launched + /*history.pushState('', document.title, + window.location.pathname + window.location.search + '#');*/ + + FileList.$fileList.one('updated', function () { + galleryFileAction.scrollContainer.scrollTop(scrollTop); + }); + }; + + // This stores the fileslist in the history state + var stateData = { + dir: FileList.getCurrentDirectory() + }; + history.replaceState(stateData, document.title, window.location); + + // This creates a new entry in history for the slideshow. It will + // be updated as the user navigates from picture to picture + history.pushState(null, '', '#loading'); + + galleryFileAction.slideShow.show(start); } - var slideShow = new SlideShow($('#slideshow'), images); - slideShow.onStop = function () { - history.replaceState('', document.title, - window.location.pathname + window.location.search); - }; - slideShow.init(); - slideShow.show(start); - } + }; -}; + window.galleryFileAction = galleryFileAction; +}(OC ,OCA, jQuery, oc_requesttoken)); $(document).ready(function () { + "use strict"; // Deactivates fileaction on public preview page if ($('#imgframe').length > 0) { return true; } + window.galleryFileAction.scrollContainer = $('#app-content'); + if ($('#isPublic').val()) { + window.galleryFileAction.scrollContainer = $(window); + } + // We're also asking for a list of supported media types. // Media files are retrieved through the Files context - var url = galleryFileAction.buildGalleryUrl('config', '', {slideshow: 1}); + var url = window.galleryFileAction.buildGalleryUrl('config', '', {slideshow: 1}); $.getJSON(url).then(function (config) { if (!$.isEmptyObject(config.features)) { - galleryFileAction.config = config.features; + window.galleryFileAction.config = config.features; } - galleryFileAction.register(config.mediatypes); + window.galleryFileAction.register(config.mediatypes); }); }); diff --git a/js/galleryview.js b/js/galleryview.js index ca6f9d42..4af069e9 100644 --- a/js/galleryview.js +++ b/js/galleryview.js @@ -1,6 +1,6 @@ -/* global OC, t, $, _, Gallery */ -(function () { - +/* global Gallery, SlideShow */ +(function (OC, t, $, _) { + "use strict"; /** * Builds and updates the Gallery view * @@ -44,6 +44,8 @@ $('#sort-date-button').click(Gallery.sorter); $('#save #save-button').click(Gallery.showSaveForm); $('.save-form').submit(Gallery.saveForm); + Gallery.activeSlideShow = new SlideShow($('#slideshow')); + Gallery.activeSlideShow.init(false, null); } this.viewAlbum(albumPath); } @@ -272,4 +274,4 @@ }; Gallery.View = View; -})(); +})(OC, t, jQuery, _); diff --git a/js/slideshow.js b/js/slideshow.js index 48323b22..cfe11af0 100644 --- a/js/slideshow.js +++ b/js/slideshow.js @@ -1,322 +1,355 @@ -/* global jQuery, OC, OCA, $, t, Gallery */ -/** - * - * @param {jQuery} container - * @param {{name:string, url: string, path: string, fallBack: string}[]} images - * @param {int} interval - * @param {int} maxScale - * @constructor - */ -var SlideShow = function (container, images, interval, maxScale) { - this.container = container; - this.images = images; - this.maxScale = maxScale || 1; // This should come from the configuration -}; - -SlideShow.prototype = { - controls: null, - imageCache: {}, - currentImage: null, - errorLoadingImage: false, - onStop: null, - zoomablePreview: null, - +/* global $, OC, OCA, t, Gallery */ +(function ($, OC, OCA, t) { + "use strict"; /** - * Initialises the slideshow + * Slideshow featuring zooming * - * @param play + * @constructor */ - init: function (play) { - this._hideImage(); - this.zoomablePreview = new SlideShow.ZoomablePreview(this.container); - this.controls = - new SlideShow.Controls(this, this.container, this.zoomablePreview, this.images); - this.controls.init(play); - }, + var SlideShow = function () { + }; - /** - * Launches the slideshow - * - * @param index - * - * @returns {*} - */ - show: function (index) { - this.hideErrorNotification(); - this.container.show(); - this.container.css('background-position', 'center'); - $('html').css('overflow-y', 'hidden'); - this._hideImage(); - var currentImageId = index; - return this.loadImage(this.images[index]).then(function (img) { - this.container.css('background-position', '-10000px 0'); - this.container.find('.changeBackground').show(); - - // check if we moved along while we were loading - if (currentImageId === index) { - var image = this.images[index]; - this.errorLoadingImage = false; - this.currentImage = img; - this.currentImage.mimeType = image.mimeType; - this.container.append(img); - - var backgroundColour = '#fff'; - if (this.currentImage.mimeType === 'image/jpeg' || - this.currentImage.mimeType === 'image/x-dcraw') { - backgroundColour = '#000'; - } - img.setAttribute('alt', image.name); - $(img).css('position', 'absolute'); - $(img).css('background-color', backgroundColour); - var $border = 30 / window.devicePixelRatio; - $(img).css('outline', $border + 'px solid ' + backgroundColour); + SlideShow.prototype = { + container: null, + zoomablePreviewContainer: null, + controls: null, + imageCache: {}, + currentImage: null, + errorLoadingImage: false, + onStop: null, + zoomablePreview: null, + active: false, - this.zoomablePreview.startBigshot(img, this.currentImage); + /** + * Initialises the slideshow + * + * @param {bool} autoPlay + * @param {int} interval + */ + init: function (autoPlay, interval) { + this.container = $('#slideshow'); + this.zoomablePreviewContainer = this.container.find('.bigshotContainer'); + // FIXME: This should come from the configuration + /**@param {int} maxScale*/ + this.maxScale = 1; - this._setUrl(image.path); - this.controls.show(currentImageId); - } - }.bind(this), function () { - // Don't do anything if the user has moved along while we were loading as it would mess - // up the index - if (currentImageId === index) { - this.errorLoadingImage = true; - this.showErrorNotification(null); - this._setUrl(this.images[index].path); - this.images.splice(index, 1); - this.controls.updateControls(this.images, this.errorLoadingImage); + // Stop the slideshow when backing out. + var self = this; + if (history && history.pushState) { + $(window).bind('popstate.slideshow', function () { + if (self.active === true) { + self.active = false; + self.controls.stop(); + } + }); } - }.bind(this)); - }, + this.zoomablePreview = new SlideShow.ZoomablePreview(this.container); + this.controls = + new SlideShow.Controls(this, this.container, this.zoomablePreview, interval); + this.controls.init(); + }, - /** - * Loads the image to show in the slideshow and preloads the next one - * - * @param preview - * - * @returns {*} - */ - loadImage: function (preview) { - var url = preview.url; - var mimeType = preview.mimeType; + /** + * Refreshes the slideshow's data + * + * @param {{name:string, url: string, path: string, fallBack: string}[]} images + * @param autoPlay + */ + setImages: function (images, autoPlay) { + this._hideImage(); + this.images = images; + this.controls.update(images, autoPlay); + }, + + /** + * Launches the slideshow + * + * @param index + * + * @returns {*} + */ + show: function (index) { + this.hideErrorNotification(); + this.active = true; + this.container.show(); + this.container.css('background-position', 'center'); + $('html').css('overflow-y', 'hidden'); + this._hideImage(); + var currentImageId = index; + return this.loadImage(this.images[index]).then(function (img) { + this.container.css('background-position', '-10000px 0'); + this.container.find('.changeBackground').show(); + + // check if we moved along while we were loading + if (currentImageId === index) { + var image = this.images[index]; + this.errorLoadingImage = false; + this.currentImage = img; + this.currentImage.mimeType = image.mimeType; - if (!this.imageCache[url]) { - this.imageCache[url] = new jQuery.Deferred(); - var image = new Image(); + var backgroundColour = '#fff'; + if (this.currentImage.mimeType === 'image/jpeg' || + this.currentImage.mimeType === 'image/x-dcraw') { + backgroundColour = '#000'; + } + img.setAttribute('alt', image.name); + $(img).css('position', 'absolute'); + $(img).css('background-color', backgroundColour); + var $border = 30 / window.devicePixelRatio; + $(img).css('outline', $border + 'px solid ' + backgroundColour); - image.onload = function () { - if (this.imageCache[url]) { - this.imageCache[url].resolve(image); + this.zoomablePreview.startBigshot(img, this.currentImage); + + this._setUrl(image.path); + this.controls.show(currentImageId); } - }.bind(this); - image.onerror = function () { - if (this.imageCache[url]) { - this.imageCache[url].reject(url); + }.bind(this), function () { + // Don't do anything if the user has moved along while we were loading as it would + // mess up the index + if (currentImageId === index) { + this.errorLoadingImage = true; + this.showErrorNotification(null); + this._setUrl(this.images[index].path); + this.images.splice(index, 1); + this.controls.updateControls(this.images, this.errorLoadingImage); + } + }.bind(this)); + }, + + /** + * Loads the image to show in the slideshow and preloads the next one + * + * @param preview + * + * @returns {*} + */ + loadImage: function (preview) { + var url = preview.url; + var mimeType = preview.mimeType; + + if (!this.imageCache[url]) { + this.imageCache[url] = new $.Deferred(); + var image = new Image(); + + image.onload = function () { + if (this.imageCache[url]) { + this.imageCache[url].resolve(image); + } + }.bind(this); + image.onerror = function () { + if (this.imageCache[url]) { + this.imageCache[url].reject(url); + } + }.bind(this); + if (mimeType === 'image/svg+xml' && + !document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image", + "1.1")) { + image.src = this._getSVG(url); + } else { + image.src = url; } - }.bind(this); - if (mimeType === 'image/svg+xml' && - !document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#Image", - "1.1")) { - image.src = this._getSVG(url); - } else { - image.src = url; } - } - return this.imageCache[url]; - }, + return this.imageCache[url]; + }, - /** - * Stops the slideshow - */ - stop: function () { - $('html').css('overflow-y', 'scroll'); - if (this.onStop) { - this.onStop(); - } - }, + /** + * Stops the slideshow + */ + stop: function () { + $('html').css('overflow-y', 'scroll'); + this.active = false; + this.images = null; + this._hideImage(); + if (this.onStop) { + this.onStop(); + } + }, - /** - * Sends the current image as a download - * - * @param downloadUrl - * - * @returns {boolean} - */ - getImageDownload: function (downloadUrl) { - OC.redirect(downloadUrl); - return false; - }, + /** + * Sends the current image as a download + * + * @param downloadUrl + * + * @returns {boolean} + */ + getImageDownload: function (downloadUrl) { + OC.redirect(downloadUrl); + return false; + }, - /** - * Changes the colour of the background of the image - */ - toggleBackground: function () { - var toHex = function (x) { - return ("0" + parseInt(x).toString(16)).slice(-2); - }; - var container = this.container.children('img'); - var rgb = container.css('background-color').match(/\d+/g); - var hex = "#" + toHex(rgb[0]) + toHex(rgb[1]) + toHex(rgb[2]); - var $border = 30 / window.devicePixelRatio; - - // Grey #363636 - if (hex === "#000000") { - container.css('background-color', '#FFF'); - container.css('outline', $border + 'px solid #FFF'); - } else { - container.css('background-color', '#000'); - container.css('outline', $border + 'px solid #000'); - } - }, + /** + * Changes the colour of the background of the image + */ + toggleBackground: function () { + var toHex = function (x) { + return ("0" + parseInt(x).toString(16)).slice(-2); + }; + var container = this.zoomablePreviewContainer.children('img'); + var rgb = container.css('background-color').match(/\d+/g); + var hex = "#" + toHex(rgb[0]) + toHex(rgb[1]) + toHex(rgb[2]); + var $border = 30 / window.devicePixelRatio; - /** - * Shows an error notification - * - * @param {string} message - */ - showErrorNotification: function (message) { - if ($.isEmptyObject(message)) { - message = t('gallery', - '<strong>Error!</strong> Could not generate a preview of this file.<br>' + - 'Please go to the next slide while we remove this image from the slideshow'); - } - this.container.find('.notification').html(message); - this.container.find('.notification').show(); - this.container.find('.changeBackground').hide(); - }, + // Grey #363636 + if (hex === "#000000") { + container.css('background-color', '#FFF'); + container.css('outline', $border + 'px solid #FFF'); + } else { + container.css('background-color', '#000'); + container.css('outline', $border + 'px solid #000'); + } + }, - /** - * Hides the error notification - */ - hideErrorNotification: function () { - this.container.find('.notification').hide(); - this.container.find('.notification').html(''); - }, + /** + * Shows an error notification + * + * @param {string} message + */ + showErrorNotification: function (message) { + if ($.isEmptyObject(message)) { + message = t('gallery', + '<strong>Error!</strong> Could not generate a preview of this file.<br>' + + 'Please go to the next slide while we remove this image from the slideshow'); + } + this.container.find('.notification').html(message); + this.container.find('.notification').show(); + this.container.find('.changeBackground').hide(); + }, - /** - * Changes the browser Url, based on the current image - * - * @param {string} path - * @private - */ - _setUrl: function (path) { - if (history && history.replaceState) { - history.replaceState('', '', '#' + encodeURI(path)); - } - }, + /** + * Hides the error notification + */ + hideErrorNotification: function () { + this.container.find('.notification').hide(); + this.container.find('.notification').html(''); + }, - /** - * Hides the current image (before loading the next) - * @private - */ - _hideImage: function () { - this.container.children('img').remove(); - }, + /** + * Changes the browser Url, based on the current image + * + * @param {string} path + * @private + */ + _setUrl: function (path) { + if (history && history.replaceState) { + history.replaceState('', '', '#' + encodeURI(path)); + } + }, - /** - * Retrieves an SVG - * - * An SVG can't be simply attached to a src attribute like a bitmap image - * - * @param {string} source - * - * @returns {*} - * @private - */ - _getSVG: function (source) { - var svgPreview = null; - if (window.btoa) { - var xmlHttp = new XMLHttpRequest(); - xmlHttp.open("GET", source, false); - xmlHttp.send(null); - if (xmlHttp.status === 200) { - if (xmlHttp.responseXML) { - // Has to be base64 encoded for Firefox - svgPreview = "data:image/svg+xml;base64," + window.btoa(xmlHttp.responseText); - } else { - svgPreview = source; + /** + * Hides the current image (before loading the next) + * @private + */ + _hideImage: function () { + this.zoomablePreviewContainer.empty(); + }, + + /** + * Retrieves an SVG + * + * An SVG can't be simply attached to a src attribute like a bitmap image + * + * @param {string} source + * + * @returns {*} + * @private + */ + _getSVG: function (source) { + var svgPreview = null; + if (window.btoa) { + var xmlHttp = new XMLHttpRequest(); + xmlHttp.open("GET", source, false); + xmlHttp.send(null); + if (xmlHttp.status === 200) { + if (xmlHttp.responseXML) { + // Has to be base64 encoded for Firefox + svgPreview = + "data:image/svg+xml;base64," + window.btoa(xmlHttp.responseText); + } else { + svgPreview = source; + } } + } else { + var message = t('gallery', + "<strong>Error!</strong> Your browser can't show SVG files.<br>" + + "Please use a more modern alternative"); + this.showErrorNotification(message); + svgPreview = Gallery.config.mediaTypes['image/svg+xml']; } - } else { - var message = t('gallery', - "<strong>Error!</strong> Your browser can't show SVG files.<br>" + - "Please use a more modern alternative"); - this.showErrorNotification(message); - svgPreview = Gallery.config.mediaTypes['image/svg+xml']; - } - return svgPreview; - } -}; - -/** - * Retrieves the slideshow's template - * - * @returns {*} - * @private - */ -SlideShow.getSlideshowTemplate = function () { - var defer = $.Deferred(); - if (!this.$slideshowTemplate) { - var self = this; - var url = OC.generateUrl('apps/galleryplus/slideshow', null); - $.get(url, function (tmpl) { - var template = $(tmpl); - var tmplButton; - var tmplTrans; - var buttonsArray = [ - { - el: '.next', - trans: 'Next' - }, - { - el: '.play', - trans: 'Play' - }, - { - el: '.pause', - trans: 'Pause' - }, - { - el: '.previous', - trans: 'Previous' - }, - { - el: '.exit', - trans: 'Close' - }, - { - el: '.downloadImage', - trans: 'Download', - toolTip: true - }, - { - el: '.changeBackground', - trans: 'Toggle background', - toolTip: true - } - ]; - for (var i = 0; i < buttonsArray.length; i++) { - var button = buttonsArray[i]; - - tmplButton = template.find(button.el); - tmplTrans = t('gallery', button.trans); - tmplButton.val(tmplTrans); - if (button.toolTip) { - tmplButton.attr("title", tmplTrans); - } + return svgPreview; + }, + + /** + * Retrieves the slideshow's template + * + * @returns {*} + */ + getSlideshowTemplate: function () { + var defer = $.Deferred(); + if (!this.$slideshowTemplate) { + var self = this; + var url = OC.generateUrl('apps/galleryplus/slideshow', null); + $.get(url, function (tmpl) { + var template = $(tmpl); + var tmplButton; + var tmplTrans; + var buttonsArray = [ + { + el: '.next', + trans: 'Next' + }, + { + el: '.play', + trans: 'Play' + }, + { + el: '.pause', + trans: 'Pause' + }, + { + el: '.previous', + trans: 'Previous' + }, + { + el: '.exit', + trans: 'Close' + }, + { + el: '.downloadImage', + trans: 'Download', + toolTip: true + }, + { + el: '.changeBackground', + trans: 'Toggle background', + toolTip: true + } + ]; + for (var i = 0; i < buttonsArray.length; i++) { + var button = buttonsArray[i]; + + tmplButton = template.find(button.el); + tmplTrans = t('gallery', button.trans); + tmplButton.val(tmplTrans); + if (button.toolTip) { + tmplButton.attr("title", tmplTrans); + } + } + self.$slideshowTemplate = template; + defer.resolve(self.$slideshowTemplate); + }) + .fail(function () { + defer.reject(); + }); + } else { + defer.resolve(this.$slideshowTemplate); } - self.$slideshowTemplate = template; - defer.resolve(self.$slideshowTemplate); - }) - .fail(function () { - defer.reject(); - }); - } else { - defer.resolve(this.$slideshowTemplate); - } - return defer.promise(); -}; + return defer.promise(); + } + }; + + window.SlideShow = SlideShow; +})(jQuery, OC, OCA, t); $(document).ready(function () { // Deactivates slideshow on login page @@ -328,7 +361,9 @@ $(document).ready(function () { return true; } - $.when(SlideShow.getSlideshowTemplate()).then(function ($tmpl) { + var slideshow = new window.SlideShow(); + + $.when(slideshow.getSlideshowTemplate()).then(function ($tmpl) { $('body').append($tmpl); //move the slideshow outside the content so we can hide the content var inactiveCallback = function () { diff --git a/js/slideshowcontrols.js b/js/slideshowcontrols.js index 7c8e515b..f49b8d8f 100644 --- a/js/slideshowcontrols.js +++ b/js/slideshowcontrols.js @@ -1,20 +1,19 @@ -/* global $, SlideShow */ -(function () { +/* global SlideShow */ +(function ($, SlideShow) { + "use strict"; /** * Button and key controls for the slideshow * * @param {object} slideshow * @param {*} container * @param {object} zoomablePreview - * @param {array} images * @param {int} interval * @constructor */ - var Controls = function (slideshow, container, zoomablePreview, images, interval) { + var Controls = function (slideshow, container, zoomablePreview, interval) { this.slideshow = slideshow; this.container = container; this.zoomablePreview = zoomablePreview; - this.images = images; this.progressBar = container.find('.progress'); this.interval = interval || 5000; @@ -29,20 +28,8 @@ /** * Initialises the controls - * - * @param {bool} play */ - init: function (play) { - this.active = true; - // hide arrows and play/pause when only one pic - this.container.find('.next, .previous').toggle(this.images.length > 1); - if (this.images.length === 1) { - this.container.find('.play, .pause').hide(); - } - - // Hide the toggle background button until we have something to show - this.container.find('.changeBackground').hide(); - + init: function () { var makeCallBack = function (handler) { return function (evt) { if (!this.active) { @@ -56,6 +43,25 @@ this._buttonSetup(makeCallBack); this._specialButtonSetup(makeCallBack); this._keyCodeSetup(makeCallBack); + }, + + /** + * Updates the controls + * + * @param {{name:string, url: string, path: string, fallBack: string}[]} images + * @param {bool} play + */ + update: function (images, play) { + this.images = images; + this.active = true; + // hide arrows and play/pause when only one pic + this.container.find('.next, .previous').toggle(this.images.length > 1); + if (this.images.length === 1) { + this.container.find('.play, .pause').hide(); + } + + // Hide the toggle background button until we have something to show + this.container.find('.changeBackground').hide(); if (play) { this._play(); @@ -63,6 +69,7 @@ this._pause(); } }, + /** * Initialises local variables when the show starts * @@ -77,6 +84,18 @@ }, /** + * Stops the timed slideshow + */ + stop: function () { + this.slideshow.stop(); + this.zoomablePreview.stop(); + + this._clearTimeout(); + this.container.hide(); + this.active = false; + }, + + /** * Updates the private variables in case of problems loading an image * * @param {Array} images @@ -96,10 +115,9 @@ _buttonSetup: function (makeCallBack) { this.container.children('.next').click(makeCallBack(this._next)); this.container.children('.previous').click(makeCallBack(this._previous)); - this.container.children('.exit').click(makeCallBack(this._stop)); + this.container.children('.exit').click(makeCallBack(this._exit)); this.container.children('.pause').click(makeCallBack(this._pause)); this.container.children('.play').click(makeCallBack(this._play)); - //this.container.click(makeCallBack(this.next)); }, /** @@ -262,16 +280,17 @@ }, /** - * Stops the timed slideshow + * Exits the slideshow by going back in history * @private */ - _stop: function () { - this.slideshow.stop(); - this.zoomablePreview.stop(); - - this._clearTimeout(); - this.container.hide(); - this.active = false; + _exit: function () { + // We simulate a click on the back button in order to be consistent + if (history) { + window.history.back(); + } else{ + // For ancient browsers supported in core + this.stop(); + } }, /** @@ -322,4 +341,4 @@ }; SlideShow.Controls = Controls; -})(); +})(jQuery, SlideShow); diff --git a/js/slideshowzoomablepreview.js b/js/slideshowzoomablepreview.js index 1446a1f1..eb265cf9 100644 --- a/js/slideshowzoomablepreview.js +++ b/js/slideshowzoomablepreview.js @@ -1,6 +1,6 @@ -/* global $, SlideShow, bigshot*/ -(function () { - +/* global SlideShow, bigshot*/ +(function ($, SlideShow, bigshot) { + "use strict"; /** * Creates a zoomable preview * @@ -10,6 +10,8 @@ var ZoomablePreview = function (container) { this.container = container; this.element = this.container.get(0); + var bigshotContainer = container.find('.bigshotContainer'); + this.bigshotElement = bigshotContainer.get(0); this._detectFullscreen(); this._setupControls(); @@ -22,6 +24,8 @@ ZoomablePreview.prototype = { container: null, element: null, + bigshotContainer: null, + bigshotElement: null, zoomable: null, fullScreen: null, canFullScreen: false, @@ -52,7 +56,7 @@ this.currentImage.isSmallImage = true; } this.zoomable = new bigshot.SimpleImage(new bigshot.ImageParameters({ - container: this.element, + container: this.bigshotElement, maxZoom: maxZoom, minZoom: 0, touchUI: false, @@ -235,4 +239,4 @@ }; SlideShow.ZoomablePreview = ZoomablePreview; -})(); +})(jQuery, SlideShow, bigshot); diff --git a/templates/slideshow.php b/templates/slideshow.php index cb06d692..6e0bd715 100644 --- a/templates/slideshow.php +++ b/templates/slideshow.php @@ -9,4 +9,5 @@ <div class="progress icon-view-pause"/> <div class="notification"></div> + <div class="bigshotContainer"></div> </div> |