242 lines
6.3 KiB
JavaScript
242 lines
6.3 KiB
JavaScript
/**
|
|
* ownCloud
|
|
*
|
|
* @author Vincent Petry
|
|
* @copyright 2014 Vincent Petry <pvince81@owncloud.com>
|
|
*
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
|
|
* License as published by the Free Software Foundation; either
|
|
* version 3 of the License, or any later version.
|
|
*
|
|
* This library is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public
|
|
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
|
*
|
|
*/
|
|
|
|
/* global OC */
|
|
(function() {
|
|
/**
|
|
* Creates an breadcrumb element in the given container
|
|
*/
|
|
var BreadCrumb = function(options){
|
|
this.$el = $('<div class="breadcrumb"></div>');
|
|
options = options || {};
|
|
if (options.onClick) {
|
|
this.onClick = options.onClick;
|
|
}
|
|
if (options.onDrop) {
|
|
this.onDrop = options.onDrop;
|
|
}
|
|
if (options.getCrumbUrl) {
|
|
this.getCrumbUrl = options.getCrumbUrl;
|
|
}
|
|
};
|
|
BreadCrumb.prototype = {
|
|
$el: null,
|
|
dir: null,
|
|
|
|
lastWidth: 0,
|
|
hiddenBreadcrumbs: 0,
|
|
totalWidth: 0,
|
|
breadcrumbs: [],
|
|
onClick: null,
|
|
onDrop: null,
|
|
|
|
/**
|
|
* Sets the directory to be displayed as breadcrumb.
|
|
* This will re-render the breadcrumb.
|
|
* @param dir path to be displayed as breadcrumb
|
|
*/
|
|
setDirectory: function(dir) {
|
|
dir = dir || '/';
|
|
if (dir !== this.dir) {
|
|
this.dir = dir;
|
|
this.render();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Returns the full URL to the given directory
|
|
* @param part crumb data as map
|
|
* @param index crumb index
|
|
* @return full URL
|
|
*/
|
|
getCrumbUrl: function(part, index) {
|
|
return '#';
|
|
},
|
|
|
|
/**
|
|
* Renders the breadcrumb elements
|
|
*/
|
|
render: function() {
|
|
var parts = this._makeCrumbs(this.dir || '/');
|
|
var $crumb;
|
|
this.$el.empty();
|
|
this.breadcrumbs = [];
|
|
|
|
for (var i = 0; i < parts.length; i++) {
|
|
var part = parts[i];
|
|
var $image;
|
|
var $link = $('<a></a>').attr('href', this.getCrumbUrl(part, i));
|
|
$link.text(part.name);
|
|
$crumb = $('<div class="crumb svg"></div>');
|
|
$crumb.append($link);
|
|
$crumb.attr('data-dir', part.dir);
|
|
|
|
if (part.img) {
|
|
$image = $('<img class="svg"></img>');
|
|
$image.attr('src', part.img);
|
|
$link.append($image);
|
|
}
|
|
this.breadcrumbs.push($crumb);
|
|
this.$el.append($crumb);
|
|
if (this.onClick) {
|
|
$crumb.on('click', this.onClick);
|
|
}
|
|
}
|
|
$crumb.addClass('last');
|
|
|
|
// in case svg is not supported by the browser we need to execute the fallback mechanism
|
|
if (!OC.Util.hasSVGSupport()) {
|
|
OC.Util.replaceSVG(this.$el);
|
|
}
|
|
|
|
// setup drag and drop
|
|
if (this.onDrop) {
|
|
this.$el.find('.crumb:not(.last)').droppable({
|
|
drop: this.onDrop,
|
|
tolerance: 'pointer'
|
|
});
|
|
}
|
|
|
|
this._updateTotalWidth();
|
|
this.resize($(window).width(), true);
|
|
},
|
|
|
|
/**
|
|
* Makes a breadcrumb structure based on the given path
|
|
* @param dir path to split into a breadcrumb structure
|
|
* @return array of map {dir: path, name: displayName}
|
|
*/
|
|
_makeCrumbs: function(dir) {
|
|
var crumbs = [];
|
|
var pathToHere = '';
|
|
// trim leading and trailing slashes
|
|
dir = dir.replace(/^\/+|\/+$/g, '');
|
|
var parts = dir.split('/');
|
|
if (dir === '') {
|
|
parts = [];
|
|
}
|
|
// root part
|
|
crumbs.push({
|
|
dir: '/',
|
|
name: '',
|
|
img: OC.imagePath('core', 'places/home.svg')
|
|
});
|
|
for (var i = 0; i < parts.length; i++) {
|
|
var part = parts[i];
|
|
pathToHere = pathToHere + '/' + part;
|
|
crumbs.push({
|
|
dir: pathToHere,
|
|
name: part
|
|
});
|
|
}
|
|
return crumbs;
|
|
},
|
|
|
|
_updateTotalWidth: function () {
|
|
var self = this;
|
|
|
|
this.lastWidth = 0;
|
|
|
|
// initialize with some extra space
|
|
this.totalWidth = 64;
|
|
// FIXME: this class should not know about global elements
|
|
if ( $('#navigation').length ) {
|
|
this.totalWidth += $('#navigation').get(0).offsetWidth;
|
|
}
|
|
this.hiddenBreadcrumbs = 0;
|
|
|
|
for (var i = 0; i < this.breadcrumbs.length; i++ ) {
|
|
this.totalWidth += $(this.breadcrumbs[i]).get(0).offsetWidth;
|
|
}
|
|
|
|
$.each($('#controls .actions>div'), function(index, action) {
|
|
self.totalWidth += $(action).get(0).offsetWidth;
|
|
});
|
|
|
|
},
|
|
|
|
/**
|
|
* Show/hide breadcrumbs to fit the given width
|
|
*/
|
|
resize: function (width, firstRun) {
|
|
var i, $crumb;
|
|
|
|
if (width === this.lastWidth) {
|
|
return;
|
|
}
|
|
|
|
// window was shrinked since last time or first run ?
|
|
if ((width < this.lastWidth || firstRun) && width < this.totalWidth) {
|
|
if (this.hiddenBreadcrumbs === 0 && this.breadcrumbs.length > 1) {
|
|
// start by hiding the first breadcrumb after home,
|
|
// that one will have extra three dots displayed
|
|
$crumb = this.breadcrumbs[1];
|
|
this.totalWidth -= $crumb.get(0).offsetWidth;
|
|
$crumb.find('a').addClass('hidden');
|
|
$crumb.append('<span class="ellipsis">...</span>');
|
|
this.totalWidth += $crumb.get(0).offsetWidth;
|
|
this.hiddenBreadcrumbs = 2;
|
|
}
|
|
i = this.hiddenBreadcrumbs;
|
|
// hide subsequent breadcrumbs if the space is still not enough
|
|
while (width < this.totalWidth && i > 1 && i < this.breadcrumbs.length - 1) {
|
|
$crumb = this.breadcrumbs[i];
|
|
this.totalWidth -= $crumb.get(0).offsetWidth;
|
|
$crumb.addClass('hidden');
|
|
this.hiddenBreadcrumbs = i;
|
|
i++;
|
|
}
|
|
// window is bigger than last time
|
|
} else if (width > this.lastWidth && this.hiddenBreadcrumbs > 0) {
|
|
i = this.hiddenBreadcrumbs;
|
|
while (width > this.totalWidth && i > 0) {
|
|
if (this.hiddenBreadcrumbs === 1) {
|
|
// special handling for last one as it has the three dots
|
|
$crumb = this.breadcrumbs[1];
|
|
if ($crumb) {
|
|
this.totalWidth -= $crumb.get(0).offsetWidth;
|
|
$crumb.find('.ellipsis').remove();
|
|
$crumb.find('a').removeClass('hidden');
|
|
this.totalWidth += $crumb.get(0).offsetWidth;
|
|
}
|
|
} else {
|
|
$crumb = this.breadcrumbs[i];
|
|
$crumb.removeClass('hidden');
|
|
this.totalWidth += $crumb.get(0).offsetWidth;
|
|
if (this.totalWidth > width) {
|
|
this.totalWidth -= $crumb.get(0).offsetWidth;
|
|
$crumb.addClass('hidden');
|
|
break;
|
|
}
|
|
}
|
|
i--;
|
|
this.hiddenBreadcrumbs = i;
|
|
}
|
|
}
|
|
|
|
this.lastWidth = width;
|
|
}
|
|
};
|
|
|
|
window.BreadCrumb = BreadCrumb;
|
|
})();
|
|
|