nextcloud-gallery/js/breadcrumb.js

286 lines
6.7 KiB
JavaScript

/**
* Nextcloud - Gallery
*
*
* This file is licensed under the Affero General Public License version 3 or
* later. See the COPYING file.
*
* @author Olivier Paroz <galleryapps@oparoz.com>
*
* @copyright Olivier Paroz 2017
*/
/* global Handlebars, Gallery */
(function ($, OC, t, Gallery) {
"use strict";
/**
* Breadcrumbs that represent the path to the current album
*
* @constructor
*/
var Breadcrumb = function () {
this.breadcrumbsElement = $('#breadcrumbs');
};
Breadcrumb.prototype = {
breadcrumbs: [],
breadcrumbsElement: null,
ellipsis: null,
albumPath: null,
availableWidth: 0,
onClick: null,
droppableOptions: {
accept: "#gallery > .row > a",
activeClass: 'breadcrumbs-droppable',
hoverClass: 'breadcrumbs-droppable-hover',
tolerance: 'pointer'
},
/**
* Initialises the breadcrumbs for the current album
*
* @param {string} albumPath
* @param {int} availableWidth
*/
init: function (albumPath, availableWidth) {
this.albumPath = albumPath;
this.availableWidth = availableWidth;
this.breadcrumbs = [];
this._build();
this._resize(this.availableWidth);
},
/**
* Defines the maximum available width in which we can build the breadcrumb and resizes it
*
* @param {int} availableWidth
*/
setMaxWidth: function (availableWidth) {
if (this.availableWidth > availableWidth || this.ellipsis.is(":visible")) {
this.availableWidth = availableWidth;
this._resize(this.availableWidth);
}
},
/**
* Processes UI elements dropped on the breadcrumbs
*
* @param event
* @param ui
*/
onDrop: function (event, ui) {
var $item = ui.draggable;
var $clone = ui.helper;
var $target = $(event.target);
if (!$target.is('.crumb')) {
$target = $target.closest('.crumb');
}
var targetPath = $(event.target).data('dir').toString();
var dir = Gallery.currentAlbum;
while (dir.substr(0, 1) === '/') {//remove extra leading /'s
dir = dir.substr(1);
}
dir = '/' + dir;
if (dir.substr(-1, 1) !== '/') {
dir = dir + '/';
}
// Do nothing if dragged on current dir
if (targetPath === dir || targetPath + '/' === dir) {
return;
}
var filePath = $item.data('path').toString();
var fileName = OC.basename(filePath);
$clone.fadeOut("normal", function () {
Gallery.move($item, fileName, filePath, $target, targetPath);
});
},
/**
* Shows the dark spinner on the crumb
*/
showLoader: function () {
$(this).addClass("icon-loading-small-dark");
},
/**
* Builds the breadcrumbs array
*
* @private
*/
_build: function () {
var i, crumbs, name, path, currentAlbum;
var albumName = $('#app-content').data('albumname');
if (!albumName) {
albumName = t('gallery', 'Gallery');
}
path = '';
name = '';
crumbs = this.albumPath.split('/');
currentAlbum = crumbs.pop();
// This adds the home button
this._addHome(albumName, currentAlbum);
// We always add a hidden ellipsis
this._pushCrumb('...', '', null, 'ellipsis');
if (currentAlbum) {
// This builds the crumbs between home and the current folder
var crumbsLength = crumbs.length;
if (crumbsLength > 0) {
// We add all albums to the breadcrumbs array
for (i = 0; i < crumbsLength; i++) {
if (crumbs[i]) {
name = crumbs[i];
if (path) {
path += '/' + crumbs[i];
} else {
path += crumbs[i];
}
this._pushCrumb(name, path, null, '');
}
}
}
// We finally push the current folder
this._pushCrumb(currentAlbum, '', null, 'last');
}
this._render();
},
/**
* Adds the Home button
*
* @param {string} albumName
* @param {string} currentAlbum
* @private
*/
_addHome: function (albumName, currentAlbum) {
var crumbImg = {
imageSrc: OC.imagePath('core', 'places/home'),
title: albumName
};
var cssClass = 'home';
if (!currentAlbum) {
cssClass += ' last';
}
this._pushCrumb('', '', crumbImg, cssClass);
},
/**
* Pushes crumb objects to the breadcrumbs array
*
* @param {string} name
* @param {string|boolean} link
* @param {Object} img
* @param {string} cssClass
* @private
*/
_pushCrumb: function (name, link, img, cssClass) {
var hash = '';
// Prevent the last crumb from getting a link unless the last crumb is 'home'.
if ( cssClass.indexOf('last') === -1 || cssClass.indexOf('home') > -1 ) {
hash = '#' + encodeURIComponent(link);
}
this.breadcrumbs.push({
name: name,
dir: link,
link: hash,
img: img,
cssClass: cssClass
});
},
/**
* Renders the full breadcrumb based on crumbs we have collected
*
* @private
*/
_render: function () {
this.breadcrumbsElement.children().remove();
var breadcrumbs = Gallery.Templates.breadcrumb({
crumbs: this.breadcrumbs
});
this.breadcrumbsElement.append(breadcrumbs);
this.droppableOptions.drop = this.onDrop.bind(this);
this.breadcrumbsElement.find('.crumb:not(.last)').droppable(this.droppableOptions);
},
/**
* Alters the breadcrumb to make it fit within the asked dimensions
*
* @param {int} availableWidth
*
* @private
*/
_resize: function (availableWidth) {
var crumbs = this.breadcrumbsElement.children();
var shorten = false;
var ellipsisPath = '';
var self = this;
// Hide everything first, so that we can check the width after adding each crumb
crumbs.hide();
// We go through the array in reverse order
var crumbsElement = crumbs.get().reverse();
$(crumbsElement).each(function () {
if ($(this).hasClass('home')) {
$(this).show();
if (self.breadcrumbs.length > 2) {
$(this).click(self.showLoader);
}
return;
}
// 1st sub-album has no-parent and the breadcrumbs contain home, ellipsis and last
if (self.breadcrumbs.length > 3) {
$(this).click(self.showLoader);
}
if ($(this).hasClass('ellipsis')) {
self.ellipsis = $(this);
return;
}
if (!shorten) {
$(this).show();
}
// If we've reached the maximum width, we start hiding crumbs
if (self.breadcrumbsElement.width() > availableWidth) {
shorten = true;
$(this).hide();
if (!ellipsisPath) {
ellipsisPath = $(this).data('dir');
}
}
});
// If we had to hide crumbs, we add a way to go to the parent folder
if (shorten) {
this.ellipsis.show();
if (!ellipsisPath) {
ellipsisPath = OC.dirname(this.albumPath);
}
this.ellipsis.children('a').attr('href', '#' + encodeURIComponent(ellipsisPath));
this.ellipsis.attr('data-original-title', ellipsisPath).tooltip({
fade: true,
placement: 'bottom',
delay: {
hide: 5
}
});
}
}
};
Gallery.Breadcrumb = Breadcrumb;
})(jQuery, OC, t, Gallery);