diff options
-rw-r--r-- | js/album.js | 486 | ||||
-rw-r--r-- | js/breadcrumb.js | 7 | ||||
-rw-r--r-- | js/eventsource.js | 5 | ||||
-rw-r--r-- | js/gallery.js | 4 | ||||
-rw-r--r-- | js/galleryalbum.js | 300 | ||||
-rw-r--r-- | js/gallerybutton.js | 10 | ||||
-rw-r--r-- | js/galleryfileaction.js | 4 | ||||
-rw-r--r-- | js/galleryimage.js | 115 | ||||
-rw-r--r-- | js/galleryrow.js | 92 | ||||
-rw-r--r-- | js/galleryview.js | 4 | ||||
-rw-r--r-- | js/thumbnail.js | 235 | ||||
-rw-r--r-- | templates/part.content.php | 4 | ||||
-rw-r--r-- | templates/public.php | 4 |
13 files changed, 654 insertions, 616 deletions
diff --git a/js/album.js b/js/album.js deleted file mode 100644 index 3b7f964b..00000000 --- a/js/album.js +++ /dev/null @@ -1,486 +0,0 @@ -/* global $, OC, Gallery, Thumbnails */ -/** - * Creates a new album object to store information about an album - * - * @param {string} path - * @param {Array<Album|GalleryImage>} subAlbums - * @param {Array<Album|GalleryImage>} images - * @param {string} name - * @constructor - */ -function Album (path, subAlbums, images, name) { - this.path = path; - this.subAlbums = subAlbums; - this.images = images; - this.viewedItems = 0; - this.name = name; - this.domDef = null; - this.preloadOffset = 0; -} - -/** - * Creates a row - * - * @param targetWidth - * @param requestId - * @constructor - */ -function Row (targetWidth, requestId) { - this.targetWidth = targetWidth; - this.items = []; - this.width = 8; // 4px margin to start with - this.requestId = requestId; -} - -/** - * Creates a new image object to store information about a media file - * - * @param src - * @param path - * @param fileId - * @param mimeType - * @param mTime modification time - * @param etag - * @constructor - */ -function GalleryImage (src, path, fileId, mimeType, mTime, etag) { - this.src = src; - this.path = path; - this.fileId = fileId; - this.mimeType = mimeType; - this.mTime = mTime; - this.etag = etag; - this.thumbnail = null; - this.domDef = null; - this.domHeigth = null; -} - -Album.prototype = { - _getThumbnail: function () { - if (this.images.length) { - return this.images[0].getThumbnail(true); - } - return this.subAlbums[0]._getThumbnail(); - }, - - /** - * Retrieves a thumbnail and adds it to the album representation - * - * Only attaches valid thumbnails to the album - * - * @param {GalleryImage} image - * @param {number} targetHeight Each row has a specific height - * @param {number} calcWidth Album width - * @param {object} a - * - * @returns {$.Deferred<Thumbnail>} - * @private - */ - _getOneImage: function (image, targetHeight, calcWidth, a) { - // img is a Thumbnail.image, true means square thumbnails - return image.getThumbnail(true).then(function (img) { - if (image.thumbnail.valid) { - var backgroundHeight, backgroundWidth; - img.alt = ''; - - backgroundHeight = (targetHeight / 2); - backgroundWidth = calcWidth - 2.01; - - // Adjust the size because of the margins around pictures - backgroundHeight -= 2; - - var croppedDiv = $('<div class="cropped">'); - croppedDiv.css("background-image", "url('" + img.src + "')"); - croppedDiv.css("height", backgroundHeight); - croppedDiv.css("width", backgroundWidth); - a.append(croppedDiv); - } - }); - }, - - /** - * Builds the album representation by placing 1 to 4 images on a grid - * - * @param {array<GalleryImage>} images - * @param {number} targetHeight Each row has a specific height - * @param {object} a - * - * @returns {$.Deferred<array>} - * @private - */ - _getFourImages: function (images, targetHeight, a) { - var calcWidth = targetHeight / 2; - var targetWidth; - var imagesCount = images.length; - var def = new $.Deferred(); - var validImages = []; - var fail = false; - var thumbsArray = []; - - for (var i = 0; i < imagesCount; i++) { - targetWidth = calcWidth; - if (imagesCount === 2 || (imagesCount === 3 && i === 0)) { - targetWidth = calcWidth * 2; - } - targetWidth = targetWidth.toFixed(3); - - thumbsArray.push(this._getOneImage(images[i], targetHeight, targetWidth, a)); - } - - var labelWidth = (targetHeight - 0.01); - a.find('.album-label').width(labelWidth); - - // This technique allows us to wait for all objects to be resolved before making a decision - $.when.apply($, thumbsArray).done(function () { - for (var i = 0; i < imagesCount; i++) { - // Collect all valid images, just in case - if (images[i].thumbnail.valid) { - validImages.push(images[i]); - } else { - fail = true; - } - } - - // At least one thumbnail could not be retrieved - if (fail) { - // Clean up the album - a.children().not('.album-label').remove(); - // Send back the list of images which have thumbnails - def.reject(validImages); - } - }); - - return def.promise(); - }, - - /** - * Fills the album representation with images we've received - * - * * Each album includes between 1 and 4 images - * * Each album is also a link to open that folder - * * An album has a natural size of 200x200 and is comprised of 4 thumbnails which have a - * natural size of 200x200 The whole thing gets resized to match the targetHeight - * - * @param targetHeight - * @param a - * @private - */ - _fillSubAlbum: function (targetHeight, a) { - var album = this; - - if (this.images.length > 1) { - this._getFourImages(this.images, targetHeight, a).fail(function (validImages) { - album.images = validImages; - album._fillSubAlbum(targetHeight, a); - }); - } else if (this.images.length === 1) { - this._getOneImage(this.images[0], 2 * targetHeight, targetHeight, a).fail(function () { - album.images = []; - album._showFolder(targetHeight, a); - }); - } else { - this._showFolder(targetHeight, a); - } - }, - - /** - * Shows a folder icon in the album since we couldn't get any proper thumbnail - * - * @param {number} targetHeight - * @param a - * @private - */ - _showFolder: function (targetHeight, a) { - var image = new GalleryImage('Generic folder', 'Generic folder', -1, 'image/png', - Gallery.token); - var thumb = Thumbnails.getStandardIcon(-1); - image.thumbnail = thumb; - this.images.push(image); - thumb.loadingDeferred.done(function (img) { - a.append(img); - img.height = (targetHeight - 2); - img.width = (targetHeight) - 2; - }); - }, - - /** - * Preloads the first $count thumbnails - * - * @param {number} count - * @private - */ - _preload: function (count) { - var items = this.subAlbums.concat(this.images); - var realCounter = 0; - var maxThumbs = 0; - var fileIds = []; - var squareFileIds = []; - for (var i = this.preloadOffset; i < this.preloadOffset + count && i < items.length; i++) { - if (items[i].subAlbums) { - maxThumbs = 4; - var imagesLength = items[i].images.length; - if (imagesLength > 0 && imagesLength < 4) { - maxThumbs = imagesLength; - } - var squareFileId = items[i].getThumbnailIds(maxThumbs); - squareFileIds = squareFileIds.concat(squareFileId); - realCounter = realCounter + maxThumbs; - } else { - var fileId = items[i].getThumbnailIds(); - fileIds = fileIds.concat(fileId); - realCounter++; - } - if (realCounter >= count) { - i++; - break; - } - } - - this.preloadOffset = i; - Thumbnails.loadBatch(fileIds, false); - Thumbnails.loadBatch(squareFileIds, true); - }, - - /** - * Creates the album, which will include between 1 and 4 images - * - * * Each album is also a link to open that folder - * * An album has a natural size of 200x200 and is comprised of 4 thumbnails which have a - * natural size of 200x200 The whole thing gets resized to match the targetHeight - * * Thumbnails are checked first in order to make sure that we have something to show - * - * @param {number} targetHeight Each row has a specific height - * - * @return {a} The album to be placed on the row - */ - getDom: function (targetHeight) { - var album = this; - - return this._getThumbnail().then(function () { - var a = $('<a/>').addClass('album').attr('href', '#' + encodeURIComponent(album.path)); - - a.append($('<span/>').addClass('album-label').text(album.name)); - - a.width(targetHeight); - a.height(targetHeight); - - album._fillSubAlbum(targetHeight, a); - - return a; - }); - }, - - /** - * Fills the row with albums and images - * - * @param {number} width - * @returns {$.Deferred<Row>} - */ - getNextRow: function (width) { - var numberOfThumbnailsToPreload = 6; - - /** - * Add images to the row until it's full - * - * @todo The number of images to preload should be a user setting - * - * @param {Album} album - * @param {Row} row - * @param {Array<Album|GalleryImage>} images - * - * @returns {$.Deferred<Row>} - */ - var addRowElements = function (album, row, images) { - if ((album.viewedItems + 5) > album.preloadOffset) { - album._preload(numberOfThumbnailsToPreload); - } - - var image = images[album.viewedItems]; - return row.addElement(image).then(function (more) { - album.viewedItems++; - if (more && album.viewedItems < images.length) { - return addRowElements(album, row, images); - } - return row; - }); - }; - var items = this.subAlbums.concat(this.images); - var row = new Row(width, this.requestId); - return addRowElements(this, row, items); - }, - - /** - * Returns IDs of thumbnails belonging to the album - * - * @param {number} count - * - * @return number[] - */ - getThumbnailIds: function (count) { - var ids = []; - var items = this.images.concat(this.subAlbums); - for (var i = 0; i < items.length && i < count; i++) { - ids = ids.concat(items[i].getThumbnailIds(count)); - } - - return ids; - } -}; - -Row.prototype = { - /** - * Calculates if the row is full - * - * @returns {boolean} - * @private - */ - _isFull: function () { - return this.width > this.targetWidth; - }, - - /** - * Adds sub-albums and images to the row until it's full - * - * @param {Album|GalleryImage} element - * - * @return {jQuery.Deferred<bool>} true if more images can be added to the row - */ - addElement: function (element) { - var row = this; - var fileNotFoundStatus = 404; - var def = new $.Deferred(); - - var appendDom = function (width) { - row.items.push(element); - row.width += width + 4; // add 4px for the margin - def.resolve(!row._isFull()); - }; - - // No need to use getThumbnailWidth() for albums, the width is always 200 - if (element instanceof Album) { - var width = 200; - appendDom(width); - } else { - element.getThumbnailWidth().then(function (width) { - if (element.thumbnail.status !== fileNotFoundStatus) { - appendDom(width); - } else { - def.resolve(true); - } - }, function () { - def.resolve(true); - }); - } - - return def.promise(); - }, - - getDom: function () { - var scaleRatio = (this.width > this.targetWidth) ? this.targetWidth / this.width : 1; - var targetHeight = 200 * scaleRatio; - targetHeight = targetHeight.toFixed(3); - var row = $('<div/>').addClass('row loading'); - /** - * @param row - * @param {GalleryImage[]} items - * @param i - * @returns {*} - */ - var addImageToDom = function (row, items, i) { - return items[i].getDom(targetHeight).then(function (itemDom) { - i++; - row.append(itemDom); - if (i < items.length) { - return addImageToDom(row, items, i); - } - return row; - }); - }; - return addImageToDom(row, this.items, 0); - } -}; - -GalleryImage.prototype = { - /** - * Returns the Thumbnail ID - * - * @returns {[number]} - */ - getThumbnailIds: function () { - return [this.fileId]; - }, - - /** - * Returns a reference to a loading Thumbnail.image - * - * @param {bool} square - * - * @returns {jQuery.Deferred<Thumbnail.image>} - */ - getThumbnail: function (square) { - if (this.thumbnail === null) { - this.thumbnail = Thumbnails.get(this.fileId, square); - } - return this.thumbnail.loadingDeferred; - }, - - /** - * Returns the width of a thumbnail - * - * Used to calculate the width of the row as we add more images to it - * - * @returns {number} - */ - getThumbnailWidth: function () { - - // img is a Thumbnail.image - return this.getThumbnail(false).then(function (img) { - if (img) { - return img.originalWidth; - } - return 0; - }); - }, - - /** - * Creates the a and img element in the DOM - * - * Each image is also a link to start the full screen slideshow - * - * @return {a} - */ - getDom: function (targetHeight) { - var image = this; - if (this.domDef === null || this.domHeigth !== targetHeight) { - this.domHeigth = targetHeight; - // img is a Thumbnail.image - this.domDef = this.getThumbnail(false).then(function (img) { - img.height = targetHeight; - img.width = targetHeight * img.ratio; - img.setAttribute('width', 'auto'); - img.alt = encodeURI(image.path); - var url = '#' + encodeURIComponent(image.path); - - if (!image.thumbnail.valid) { - url = Gallery.utility.getPreviewUrl(image.fileId, image.etag); - url = url + '&download'; - } - var a = $('<a/>').addClass('image').attr('href', url).attr('data-path', image.path); - - var imageLabel = $('<span/>').addClass('image-label'); - var imageTitle = $('<span/>').addClass('title').html( - OC.basename(image.path)); - imageLabel.append(imageTitle); - a.hover(function () { - imageLabel.slideToggle(OC.menuSpeed); - }, function () { - imageLabel.slideToggle(OC.menuSpeed); - }); - a.append(imageLabel); - a.append(img); - return a; - }); - } - return this.domDef; - } -}; diff --git a/js/breadcrumb.js b/js/breadcrumb.js index e0a754ab..3d6f67f7 100644 --- a/js/breadcrumb.js +++ b/js/breadcrumb.js @@ -1,5 +1,6 @@ -/* global $, OC, t, Gallery */ -(function () { +/* global Gallery */ +(function ($, OC, t, Gallery) { + "use strict"; /** * Breadcrumbs that represent the path to the current album * @@ -173,4 +174,4 @@ }; Gallery.Breadcrumb = Breadcrumb; -})(); +})(jQuery, OC, t, Gallery); diff --git a/js/eventsource.js b/js/eventsource.js index c70ea938..77a85b53 100644 --- a/js/eventsource.js +++ b/js/eventsource.js @@ -17,7 +17,8 @@ */ /* global EventSource, oc_requesttoken, Gallery */ -(function () { +(function (oc_requesttoken) { + "use strict"; /** * Create a new event source * @@ -102,4 +103,4 @@ }; Gallery.EventSource = CustomEventSource; -})(); +})(oc_requesttoken); diff --git a/js/gallery.js b/js/gallery.js index a2fceeda..ab749d47 100644 --- a/js/gallery.js +++ b/js/gallery.js @@ -1,5 +1,5 @@ /* global Album, GalleryImage */ -(function (OC, $, t) { +(function ($, OC, t) { "use strict"; var Gallery = { currentAlbum: null, @@ -487,4 +487,4 @@ } }; window.Gallery = Gallery; -}(OC, jQuery, t)); +})(jQuery, OC, t); diff --git a/js/galleryalbum.js b/js/galleryalbum.js new file mode 100644 index 00000000..6d31a7a1 --- /dev/null +++ b/js/galleryalbum.js @@ -0,0 +1,300 @@ +/* global Gallery, Thumbnails, GalleryImage, Row */ +(function ($, Gallery) { + "use strict"; + /** + * Creates a new album object to store information about an album + * + * @param {string} path + * @param {Array<Album|GalleryImage>} subAlbums + * @param {Array<Album|GalleryImage>} images + * @param {string} name + * @constructor + */ + var Album = function (path, subAlbums, images, name) { + this.path = path; + this.subAlbums = subAlbums; + this.images = images; + this.viewedItems = 0; + this.name = name; + this.domDef = null; + this.preloadOffset = 0; + }; + + Album.prototype = { + _getThumbnail: function () { + if (this.images.length) { + return this.images[0].getThumbnail(true); + } + return this.subAlbums[0]._getThumbnail(); + }, + + /** + * Retrieves a thumbnail and adds it to the album representation + * + * Only attaches valid thumbnails to the album + * + * @param {Image} image + * @param {number} targetHeight Each row has a specific height + * @param {number} calcWidth Album width + * @param {object} a + * + * @returns {$.Deferred<Thumbnail>} + * @private + */ + _getOneImage: function (image, targetHeight, calcWidth, a) { + // img is a Thumbnail.image, true means square thumbnails + return image.getThumbnail(true).then(function (img) { + if (image.thumbnail.valid) { + var backgroundHeight, backgroundWidth; + img.alt = ''; + + backgroundHeight = (targetHeight / 2); + backgroundWidth = calcWidth - 2.01; + + // Adjust the size because of the margins around pictures + backgroundHeight -= 2; + + var croppedDiv = $('<div class="cropped">'); + croppedDiv.css("background-image", "url('" + img.src + "')"); + croppedDiv.css("height", backgroundHeight); + croppedDiv.css("width", backgroundWidth); + a.append(croppedDiv); + } + }); + }, + + /** + * Builds the album representation by placing 1 to 4 images on a grid + * + * @param {array<GalleryImage>} images + * @param {number} targetHeight Each row has a specific height + * @param {object} a + * + * @returns {$.Deferred<array>} + * @private + */ + _getFourImages: function (images, targetHeight, a) { + var calcWidth = targetHeight / 2; + var targetWidth; + var imagesCount = images.length; + var def = new $.Deferred(); + var validImages = []; + var fail = false; + var thumbsArray = []; + + for (var i = 0; i < imagesCount; i++) { + targetWidth = calcWidth; + if (imagesCount === 2 || (imagesCount === 3 && i === 0)) { + targetWidth = calcWidth * 2; + } + targetWidth = targetWidth.toFixed(3); + + thumbsArray.push(this._getOneImage(images[i], targetHeight, targetWidth, a)); + } + + var labelWidth = (targetHeight - 0.01); + a.find('.album-label').width(labelWidth); + + // This technique allows us to wait for all objects to be resolved before making a + // decision + $.when.apply($, thumbsArray).done(function () { + for (var i = 0; i < imagesCount; i++) { + // Collect all valid images, just in case + if (images[i].thumbnail.valid) { + validImages.push(images[i]); + } else { + fail = true; + } + } + + // At least one thumbnail could not be retrieved + if (fail) { + // Clean up the album + a.children().not('.album-label').remove(); + // Send back the list of images which have thumbnails + def.reject(validImages); + } + }); + + return def.promise(); + }, + + /** + * Fills the album representation with images we've received + * + * * Each album includes between 1 and 4 images + * * Each album is also a link to open that folder + * * An album has a natural size of 200x200 and is comprised of 4 thumbnails which have a + * natural size of 200x200 The whole thing gets resized to match the targetHeight + * + * @param targetHeight + * @param a + * @private + */ + _fillSubAlbum: function (targetHeight, a) { + var album = this; + + if (this.images.length > 1) { + this._getFourImages(this.images, targetHeight, a).fail(function (validImages) { + album.images = validImages; + album._fillSubAlbum(targetHeight, a); + }); + } else if (this.images.length === 1) { + this._getOneImage(this.images[0], 2 * targetHeight, targetHeight, + a).fail(function () { + album.images = []; + album._showFolder(targetHeight, a); + }); + } else { + this._showFolder(targetHeight, a); + } + }, + + /** + * Shows a folder icon in the album since we couldn't get any proper thumbnail + * + * @param {number} targetHeight + * @param a + * @private + */ + _showFolder: function (targetHeight, a) { + var image = new GalleryImage('Generic folder', 'Generic folder', -1, 'image/png', + Gallery.token); + var thumb = Thumbnails.getStandardIcon(-1); + image.thumbnail = thumb; + this.images.push(image); + thumb.loadingDeferred.done(function (img) { + a.append(img); + img.height = (targetHeight - 2); + img.width = (targetHeight) - 2; + }); + }, + + /** + * Preloads the first $count thumbnails + * + * @param {number} count + * @private + */ + _preload: function (count) { + var items = this.subAlbums.concat(this.images); + var realCounter = 0; + var maxThumbs = 0; + var fileIds = []; + var squareFileIds = []; + for (var i = this.preloadOffset; i < this.preloadOffset + count && + i < items.length; i++) { + if (items[i].subAlbums) { + maxThumbs = 4; + var imagesLength = items[i].images.length; + if (imagesLength > 0 && imagesLength < 4) { + maxThumbs = imagesLength; + } + var squareFileId = items[i].getThumbnailIds(maxThumbs); + squareFileIds = squareFileIds.concat(squareFileId); + realCounter = realCounter + maxThumbs; + } else { + var fileId = items[i].getThumbnailIds(); + fileIds = fileIds.concat(fileId); + realCounter++; + } + if (realCounter >= count) { + i++; + break; + } + } + + this.preloadOffset = i; + Thumbnails.loadBatch(fileIds, false); + Thumbnails.loadBatch(squareFileIds, true); + }, + + /** + * Creates the album, which will include between 1 and 4 images + * + * * Each album is also a link to open that folder + * * An album has a natural size of 200x200 and is comprised of 4 thumbnails which have a + * natural size of 200x200 The whole thing gets resized to match the targetHeight + * * Thumbnails are checked first in order to make sure that we have something to show + * + * @param {number} targetHeight Each row has a specific height + * + * @return {a} The album to be placed on the row + */ + getDom: function (targetHeight) { + var album = this; + + return this._getThumbnail().then(function () { + var a = $('<a/>').addClass('album').attr('href', + '#' + encodeURIComponent(album.path)); + + a.append($('<span/>').addClass('album-label').text(album.name)); + + a.width(targetHeight); + a.height(targetHeight); + + album._fillSubAlbum(targetHeight, a); + + return a; + }); + }, + + /** + * Fills the row with albums and images + * + * @param {number} width + * @returns {$.Deferred<Gallery.Row>} + */ + getNextRow: function (width) { + var numberOfThumbnailsToPreload = 6; + + /** + * Add images to the row until it's full + * + * @todo The number of images to preload should be a user setting + * + * @param {Album} album + * @param {Row} row + * @param {Array<Album|GalleryImage>} images + * + * @returns {$.Deferred<Gallery.Row>} + */ + var addRowElements = function (album, row, images) { + if ((album.viewedItems + 5) > album.preloadOffset) { + album._preload(numberOfThumbnailsToPreload); + } + + var image = images[album.viewedItems]; + return row.addElement(image).then(function (more) { + album.viewedItems++; + if (more && album.viewedItems < images.length) { + return addRowElements(album, row, images); + } + return row; + }); + }; + var items = this.subAlbums.concat(this.images); + var row = new Gallery.Row(width, this.requestId); + return addRowElements(this, row, items); + }, + + /** + * Returns IDs of thumbnails belonging to the album + * + * @param {number} count + * + * @return number[] + */ + getThumbnailIds: function (count) { + var ids = []; + var items = this.images.concat(this.subAlbums); + for (var i = 0; i < items.length && i < count; i++) { + ids = ids.concat(items[i].getThumbnailIds(count)); + } + + return ids; + } + }; + + window.Album = Album; +})(jQuery, Gallery); diff --git a/js/gallerybutton.js b/js/gallerybutton.js index 3f23f7c8..1ac46650 100644 --- a/js/gallerybutton.js +++ b/js/gallerybutton.js @@ -5,6 +5,7 @@ GalleryButton.button = {}; GalleryButton.url = null; GalleryButton.onFileListUpdated = function () { + "use strict"; var fileList; if (GalleryButton.isPublic) { @@ -17,18 +18,21 @@ GalleryButton.onFileListUpdated = function () { }; GalleryButton.buildGalleryUrl = function (dir) { + "use strict"; var params = {}; var tokenPath = ''; - var token = ($('#sharingToken').val()) ? $('#sharingToken').val() : false; + var sharingTokenElement = $('#sharingToken'); + var token = (sharingTokenElement.val()) ? sharingTokenElement.val() : false; if (token) { params.token = token; tokenPath = 's/{token}'; } - GalleryButton.url = OC.generateUrl('apps/galleryplus/' + tokenPath, params) + '#' + encodeURIComponent(dir); + GalleryButton.url = + OC.generateUrl('apps/galleryplus/' + tokenPath, params) + '#' + encodeURIComponent(dir); }; $(document).ready(function () { - + "use strict"; if ($('#body-login').length > 0) { return true; //deactivate on login page } diff --git a/js/galleryfileaction.js b/js/galleryfileaction.js index 9fb5a3ad..3f562b98 100644 --- a/js/galleryfileaction.js +++ b/js/galleryfileaction.js @@ -1,5 +1,5 @@ /* global oc_requesttoken, FileList, SlideShow */ -(function (OC, OCA, $, oc_requesttoken) { +(function ($, OC, OCA, oc_requesttoken) { "use strict"; var galleryFileAction = { config: null, @@ -148,7 +148,7 @@ }; window.galleryFileAction = galleryFileAction; -}(OC, OCA, jQuery, oc_requesttoken)); +})(jQuery, OC, OCA, oc_requesttoken); $(document).ready(function () { "use strict"; diff --git a/js/galleryimage.js b/js/galleryimage.js new file mode 100644 index 00000000..2df86d9e --- /dev/null +++ b/js/galleryimage.js @@ -0,0 +1,115 @@ +/* global Gallery, Thumbnails */ +(function ($, Gallery) { + "use strict"; + /** + * Creates a new image object to store information about a media file + * + * @param src + * @param path + * @param fileId + * @param mimeType + * @param mTime modification time + * @param etag + * @constructor + */ + var GalleryImage = function (src, path, fileId, mimeType, mTime, etag) { + this.src = src; + this.path = path; + this.fileId = fileId; + this.mimeType = mimeType; + this.mTime = mTime; + this.etag = etag; + this.thumbnail = null; + this.domDef = null; + this.domHeigth = null; + }; + + GalleryImage.prototype = { + /** + * Returns the Thumbnail ID + * + * @returns {[number]} + */ + getThumbnailIds: function () { + return [this.fileId]; + }, + + /** + * Returns a reference to a loading Thumbnail.image + * + * @param {bool} square + * + * @returns {jQuery.Deferred<Thumbnail.image>} + */ + getThumbnail: function (square) { + if (this.thumbnail === null) { + this.thumbnail = Thumbnails.get(this.fileId, square); + } + return this.thumbnail.loadingDeferred; + }, + + /** + * Returns the width of a thumbnail + * + * Used to calculate the width of the row as we add more images to it + * + * @returns {number} + */ + getThumbnailWidth: function () { + + // img is a Thumbnail.image + return this.getThumbnail(false).then(function (img) { + if (img) { + return img.originalWidth; + } + return 0; + }); + }, + + /** + * Creates the a and img element in the DOM + * + * Each image is also a link to start the full screen slideshow + * + * @return {a} + */ + getDom: function (targetHeight) { + var image = this; + if (this.domDef === null || this.domHeigth !== targetHeight) { + this.domHeigth = targetHeight; + // img is a Thumbnail.image + this.domDef = this.getThumbnail(false).then(function (img) { + img.height = targetHeight; + img.width = targetHeight * img.ratio; + img.setAttribute('width', 'auto'); + img.alt = encodeURI(image.path); + var url = '#' + encodeURIComponent(image.path); + + if (!image.thumbnail.valid) { + url = Gallery.utility.getPreviewUrl(image.fileId, image.etag); + url = url + '&download'; + } + var a = $('<a/>').addClass('image').attr('href', url).attr('data-path', + image.path); + + var imageLabel = $('<span/>').addClass('image-label'); + var imageTitle = $('<span/>').addClass('title').html( + OC.basename(image.path)); + imageLabel.append(imageTitle); + a.hover(function () { + imageLabel.slideToggle(OC.menuSpeed); + }, function () { + imageLabel.slideToggle(OC.menuSpeed); + }); + a.append(imageLabel); + a.append(img); + return a; + }); + } + return this.domDef; + } + }; + + window.GalleryImage = GalleryImage; +})(jQuery, Gallery); + diff --git a/js/galleryrow.js b/js/galleryrow.js new file mode 100644 index 00000000..39251edc --- /dev/null +++ b/js/galleryrow.js @@ -0,0 +1,92 @@ +/* global Gallery, Album */ +(function ($, Gallery) { + "use strict"; + /** + * Creates a row + * + * @param targetWidth + * @param requestId + * @constructor + */ + var Row = function (targetWidth, requestId) { + this.targetWidth = targetWidth; + this.items = []; + this.width = 8; // 4px margin to start with + this.requestId = requestId; + }; + + Row.prototype = { + /** + * Calculates if the row is full + * + * @returns {boolean} + * @private + */ + _isFull: function () { + return this.width > this.targetWidth; + }, + + /** + * Adds sub-albums and images to the row until it's full + * + * @param {Album|GalleryImage} element + * + * @return {jQuery.Deferred<bool>} true if more images can be added to the row + */ + addElement: function (element) { + var row = this; + var fileNotFoundStatus = 404; + var def = new $.Deferred(); + + var appendDom = function (width) { + row.items.push(element); + row.width += width + 4; // add 4px for the margin + def.resolve(!row._isFull()); + }; + + // No need to use getThumbnailWidth() for albums, the width is always 200 + if (element instanceof Album) { + var width = 200; + appendDom(width); + } else { + element.getThumbnailWidth().then(function (width) { + if (element.thumbnail.status !== fileNotFoundStatus) { + appendDom(width); + } else { + def.resolve(true); + } + }, function () { + def.resolve(true); + }); + } + + return def.promise(); + }, + + getDom: function () { + var scaleRatio = (this.width > this.targetWidth) ? this.targetWidth / this.width : 1; + var targetHeight = 200 * scaleRatio; + targetHeight = targetHeight.toFixed(3); + var row = $('<div/>').addClass('row loading'); + /** + * @param row + * @param {Gallery.Image[]} items + * @param i + * @returns {*} + */ + var addImageToDom = function (row, items, i) { + return items[i].getDom(targetHeight).then(function (itemDom) { + i++; + row.append(itemDom); + if (i < items.length) { + return addImageToDom(row, items, i); + } + return row; + }); + }; + return addImageToDom(row, this.items, 0); + } + }; + + Gallery.Row = Row; +})(jQuery, Gallery); diff --git a/js/galleryview.js b/js/galleryview.js index eb616fc0..75b35b6c 100644 --- a/js/galleryview.js +++ b/js/galleryview.js @@ -1,5 +1,5 @@ /* global Gallery */ -(function (OC, t, $, _) { +(function ($, _, OC, t, Gallery) { "use strict"; /** * Builds and updates the Gallery view @@ -280,4 +280,4 @@ }; Gallery.View = View; -})(OC, t, jQuery, _); +})(jQuery, _, OC, t, Gallery); diff --git a/js/thumbnail.js b/js/thumbnail.js index 19b20491..a711a0a2 100644 --- a/js/thumbnail.js +++ b/js/thumbnail.js @@ -18,130 +18,137 @@ function Thumbnail (fileId, square) { this.status = 200; } -var Thumbnails = {}; -Thumbnails.map = {}; -Thumbnails.squareMap = {}; +(function ($, OC, Gallery) { + "use strict"; + var Thumbnails = { + map: {}, + squareMap: {}, -/** - * Retrieves the thumbnail linked to the given fileID - * - * @param {number} fileId - * @param {bool} square - * - * @returns {Thumbnail} - */ -Thumbnails.get = function (fileId, square) { - var map = {}; - if (square === true) { - map = Thumbnails.squareMap; - square = true; - } else { - map = Thumbnails.map; - square = false; - } - if (!map[fileId]) { - map[fileId] = new Thumbnail(fileId, square); - } - - return map[fileId]; -}; + /** + * Retrieves the thumbnail linked to the given fileID + * + * @param {number} fileId + * @param {bool} square + * + * @returns {Thumbnail} + */ + get: function (fileId, square) { + var map = {}; + if (square === true) { + map = Thumbnails.squareMap; + square = true; + } else { + map = Thumbnails.map; + square = false; + } + if (!map[fileId]) { + map[fileId] = new Thumbnail(fileId, square); + } -/** - * Returns an icon of a specific type - * - * -1 is for a folder - * -404 is for a broken file icon - * -500 is for a media type icon - * - * @param {number} type - * - * @returns {Thumbnail} - */ -Thumbnails.getStandardIcon = function (type) { - if (!Thumbnails.squareMap[type]) { - var icon = ''; - // true means square - var thumb = new Thumbnail(type, true); - thumb.image = new Image(); - thumb.image.onload = function () { - thumb.loadingDeferred.resolve(thumb.image); - }; + return map[fileId]; + }, - if (type === -1) { - icon = 'folder.svg'; - } - thumb.image.src = OC.imagePath(Gallery.appName, icon); + /** + * Returns an icon of a specific type + * + * -1 is for a folder + * -404 is for a broken file icon + * -500 is for a media type icon + * + * @param {number} type + * + * @returns {Thumbnail} + */ + getStandardIcon: function (type) { + if (!Thumbnails.squareMap[type]) { + var icon = ''; + // true means square + var thumb = new Thumbnail(type, true); + thumb.image = new Image(); + thumb.image.onload = function () { + thumb.loadingDeferred.resolve(thumb.image); + }; - Thumbnails.squareMap[type] = thumb; - } + if (type === -1) { + icon = 'folder.svg'; + } + thumb.image.src = OC.imagePath(Gallery.appName, icon); - return Thumbnails.squareMap[type]; -}; + Thumbnails.squareMap[type] = thumb; + } -/** - * Loads thumbnails in batch, using EventSource - * - * @param {array} ids - * @param {bool} square - * - * @returns {{}} - */ -Thumbnails.loadBatch = function (ids, square) { - var map = (square) ? Thumbnails.squareMap : Thumbnails.map; - // Purely here as a precaution - ids = ids.filter(function (id) { - return !map[id]; - }); - var batch = {}; - var i, idsLength = ids.length; - if (idsLength) { - for (i = 0; i < idsLength; i++) { - var thumb = new Thumbnail(ids[i], square); - thumb.image = new Image(); - map[ids[i]] = batch[ids[i]] = thumb; + return Thumbnails.squareMap[type]; + }, - } - var params = { - ids: ids.join(';'), - scale: window.devicePixelRatio, - square: (square) ? 1 : 0 - }; - var url = Gallery.utility.buildGalleryUrl('thumbnails', '', params); + /** + * Loads thumbnails in batch, using EventSource + * + * @param {Array} ids + * @param {bool} square + * + * @returns {{}} + */ + loadBatch: function (ids, square) { + var map = (square) ? Thumbnails.squareMap : Thumbnails.map; + // Purely here as a precaution + ids = ids.filter(function (id) { + return !map[id]; + }); + var batch = {}; + var i, idsLength = ids.length; + if (idsLength) { + for (i = 0; i < idsLength; i++) { + var thumb = new Thumbnail(ids[i], square); + thumb.image = new Image(); + map[ids[i]] = batch[ids[i]] = thumb; - var eventSource = new Gallery.EventSource(url); - eventSource.listen('preview', function (/**{path, status, mimetype, preview}*/ preview) { - var id = preview.fileid; - var thumb = batch[id]; - thumb.status = preview.status; - if (thumb.status === 404) { - thumb.valid = false; - thumb.loadingDeferred.resolve(null); - } else { - thumb.image.onload = function () { - // Fix for SVG files which can come in all sizes - if (square) { - thumb.image.width = 200; - thumb.image.height = 200; - } - thumb.image.ratio = thumb.image.width / thumb.image.height; - thumb.image.originalWidth = 200 * thumb.image.ratio; - thumb.loadingDeferred.resolve(thumb.image); - }; - thumb.image.onerror = function () { - thumb.valid = false; - thumb.loadingDeferred.resolve(null); + } + var params = { + ids: ids.join(';'), + scale: window.devicePixelRatio, + square: (square) ? 1 : 0 }; + var url = Gallery.utility.buildGalleryUrl('thumbnails', '', params); - if (thumb.status === 200) { - thumb.image.src = 'data:' + preview.mimetype + ';base64,' + preview.preview; - } else { - thumb.valid = false; - thumb.image.src = Gallery.config.mediaTypes[preview.mimetype]; + var eventSource = new Gallery.EventSource(url); + eventSource.listen('preview', + function (/**{path, status, mimetype, preview}*/ preview) { + var id = preview.fileid; + var thumb = batch[id]; + thumb.status = preview.status; + if (thumb.status === 404) { + thumb.valid = false; + thumb.loadingDeferred.resolve(null); + } else { + thumb.image.onload = function () { + // Fix for SVG files which can come in all sizes + if (square) { + thumb.image.width = 200; + thumb.image.height = 200; + } + thumb.image.ratio = thumb.image.width / thumb.image.height; + thumb.image.originalWidth = 200 * thumb.image.ratio; + thumb.loadingDeferred.resolve(thumb.image); + }; + thumb.image.onerror = function () { + thumb.valid = false; + thumb.loadingDeferred.resolve(null); + }; - } + if (thumb.status === 200) { + thumb.image.src = + 'data:' + preview.mimetype + ';base64,' + preview.preview; + } else { + thumb.valid = false; + thumb.image.src = Gallery.config.mediaTypes[preview.mimetype]; + } + } + }); } - }); - } - return batch; -}; + return batch; + } + }; + + window.Thumbnails = Thumbnails; +})(jQuery, OC, Gallery); diff --git a/templates/part.content.php b/templates/part.content.php index e9ab1926..fe13bb6e 100644 --- a/templates/part.content.php +++ b/templates/part.content.php @@ -15,7 +15,9 @@ script( 'galleryinfobox', 'galleryview', 'breadcrumb', - 'album', + 'galleryalbum', + 'galleryrow', + 'galleryimage', 'thumbnail', 'vendor/eventsource-polyfill/dist/eventsource.min', 'eventsource', diff --git a/templates/public.php b/templates/public.php index 15d0d769..a567f75a 100644 --- a/templates/public.php +++ b/templates/public.php @@ -15,7 +15,9 @@ script( 'galleryinfobox', 'galleryview', 'breadcrumb', - 'album', + 'galleryalbum', + 'galleryrow', + 'galleryimage', 'thumbnail', 'vendor/eventsource-polyfill/dist/eventsource.min', 'eventsource', |