Merge pull request #7051 from nextcloud/breadcrumbs-refactor
Breadcrumbs refactor
This commit is contained in:
commit
ff2d4432d8
|
@ -47,14 +47,6 @@
|
|||
top: 44px;
|
||||
}
|
||||
|
||||
/* make sure there's enough room for the file actions */
|
||||
#body-user #filestable {
|
||||
min-width: 688px; /* 768 (mobile break) - 80 (nav width) */
|
||||
}
|
||||
#body-user #controls {
|
||||
min-width: 688px; /* 768 (mobile break) - 80 (nav width) */
|
||||
}
|
||||
|
||||
#filestable tbody tr {
|
||||
height: 51px;
|
||||
}
|
||||
|
@ -74,12 +66,16 @@
|
|||
background-color: rgb(179, 230, 255)!important;
|
||||
}
|
||||
|
||||
.app-files #app-content.dir-drop, .file-drag #filestable tbody tr, .file-drag #filestable tbody tr:hover{
|
||||
background-color: rgba(0, 0, 0, 0)!important;
|
||||
.app-files #app-content.dir-drop {
|
||||
background-color: $color-main-background !important;
|
||||
}
|
||||
|
||||
.file-drag #filestable tbody tr, .file-drag #filestable tbody tr:hover{
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
.app-files #app-content.dir-drop #filestable tbody tr.dropping-to-dir{
|
||||
background-color: rgb(179, 230, 255)!important;
|
||||
background-color: rgb(179, 230, 255) !important;
|
||||
}
|
||||
|
||||
/* icons for sidebar */
|
||||
|
@ -740,9 +736,9 @@ table.dragshadow td.size {
|
|||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.canDrop,
|
||||
.breadcrumb .canDrop > a,
|
||||
#filestable tbody tr.canDrop {
|
||||
background-color: rgba(255, 255, 140, 1);
|
||||
background-color: rgb(179, 230, 255);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -33,6 +33,9 @@
|
|||
*/
|
||||
var BreadCrumb = function(options){
|
||||
this.$el = $('<div class="breadcrumb"></div>');
|
||||
this.$menu = $('<div class="popovermenu menu-center"><ul></ul></div>');
|
||||
|
||||
this.crumbSelector = '.crumb:not(.hidden):not(.crumbhome):not(.crumbmenu)';
|
||||
options = options || {};
|
||||
if (options.onClick) {
|
||||
this.onClick = options.onClick;
|
||||
|
@ -47,6 +50,7 @@
|
|||
}
|
||||
this._detailViews = [];
|
||||
};
|
||||
|
||||
/**
|
||||
* @memberof OCA.Files
|
||||
*/
|
||||
|
@ -110,19 +114,32 @@
|
|||
* Renders the breadcrumb elements
|
||||
*/
|
||||
render: function() {
|
||||
// Menu is destroyed on every change, we need to init it
|
||||
OC.unregisterMenu($('.crumbmenu'), $('.crumbmenu > .popovermenu'));
|
||||
|
||||
var parts = this._makeCrumbs(this.dir || '/');
|
||||
var $crumb;
|
||||
var $menuItem;
|
||||
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);
|
||||
var $link = $('<a></a>');
|
||||
$crumb = $('<div class="crumb svg"></div>');
|
||||
if(part.dir) {
|
||||
$link.attr('href', this.getCrumbUrl(part, i));
|
||||
}
|
||||
if(part.name) {
|
||||
$link.text(part.name);
|
||||
}
|
||||
$link.addClass(part.linkclass);
|
||||
$crumb.append($link);
|
||||
$crumb.attr('data-dir', part.dir);
|
||||
$crumb.data('dir', part.dir);
|
||||
// Ignore menu button
|
||||
$crumb.data('crumb-id', i - 1);
|
||||
$crumb.addClass(part.class);
|
||||
|
||||
if (part.img) {
|
||||
$image = $('<img class="svg"></img>');
|
||||
|
@ -132,12 +149,27 @@
|
|||
}
|
||||
this.breadcrumbs.push($crumb);
|
||||
this.$el.append($crumb);
|
||||
if (this.onClick) {
|
||||
$crumb.on('click', this.onClick);
|
||||
// Only add feedback if not menu
|
||||
if (this.onClick && i !== 0) {
|
||||
$link.on('click', this.onClick);
|
||||
}
|
||||
}
|
||||
$crumb.addClass('last');
|
||||
|
||||
// Menu creation
|
||||
this._createMenu();
|
||||
for (var j = 0; j < parts.length; j++) {
|
||||
var menuPart = parts[j];
|
||||
if(menuPart.dir) {
|
||||
$menuItem = $('<li class="crumblist"><a><span class="icon-folder"></span><span></span></a></li>');
|
||||
$menuItem.data('dir', menuPart.dir);
|
||||
$menuItem.find('a').attr('href', this.getCrumbUrl(part, j));
|
||||
$menuItem.find('span:eq(1)').text(menuPart.name);
|
||||
this.$menu.children('ul').append($menuItem);
|
||||
if (this.onClick) {
|
||||
$menuItem.on('click', this.onClick);
|
||||
}
|
||||
}
|
||||
}
|
||||
_.each(this._detailViews, function(view) {
|
||||
view.render({
|
||||
dirInfo: this.dirInfo
|
||||
|
@ -152,16 +184,20 @@
|
|||
|
||||
// setup drag and drop
|
||||
if (this.onDrop) {
|
||||
this.$el.find('.crumb:not(.last)').droppable({
|
||||
this.$el.find('.crumb:not(:last-child):not(.crumbmenu), .crumblist:not(:last-child)').droppable({
|
||||
drop: this.onDrop,
|
||||
over: this.onOver,
|
||||
out: this.onOut,
|
||||
tolerance: 'pointer',
|
||||
hoverClass: 'canDrop'
|
||||
hoverClass: 'canDrop',
|
||||
greedy: true
|
||||
});
|
||||
}
|
||||
|
||||
this._updateTotalWidth();
|
||||
// Menu is destroyed on every change, we need to init it
|
||||
OC.registerMenu($('.crumbmenu'), $('.crumbmenu > .popovermenu'));
|
||||
|
||||
this._resize();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -179,12 +215,17 @@
|
|||
if (dir === '') {
|
||||
parts = [];
|
||||
}
|
||||
// menu part
|
||||
crumbs.push({
|
||||
class: 'crumbmenu hidden',
|
||||
linkclass: 'icon-more'
|
||||
});
|
||||
// root part
|
||||
crumbs.push({
|
||||
name: t('core', 'Home'),
|
||||
dir: '/',
|
||||
name: '',
|
||||
alt: t('files', 'Home'),
|
||||
img: OC.imagePath('core', 'places/home.svg')
|
||||
class: 'crumbhome',
|
||||
linkclass: 'icon-home'
|
||||
});
|
||||
for (var i = 0; i < parts.length; i++) {
|
||||
var part = parts[i];
|
||||
|
@ -197,23 +238,10 @@
|
|||
return crumbs;
|
||||
},
|
||||
|
||||
/**
|
||||
* Calculate the total breadcrumb width when
|
||||
* all crumbs are expanded
|
||||
*/
|
||||
_updateTotalWidth: function () {
|
||||
this.totalWidth = 0;
|
||||
for (var i = 0; i < this.breadcrumbs.length; i++ ) {
|
||||
var $crumb = $(this.breadcrumbs[i]);
|
||||
$crumb.data('real-width', $crumb.width());
|
||||
this.totalWidth += $crumb.width();
|
||||
}
|
||||
this._resize();
|
||||
},
|
||||
|
||||
/**
|
||||
* Show/hide breadcrumbs to fit the given width
|
||||
*
|
||||
* Mostly used by tests
|
||||
*
|
||||
* @param {int} availableWidth available width
|
||||
*/
|
||||
setMaxWidth: function (availableWidth) {
|
||||
|
@ -223,74 +251,107 @@
|
|||
}
|
||||
},
|
||||
|
||||
_resize: function() {
|
||||
var i, $crumb, $ellipsisCrumb;
|
||||
|
||||
if (!this.availableWidth) {
|
||||
this.availableWidth = this.$el.width();
|
||||
}
|
||||
|
||||
if (this.breadcrumbs.length <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// reset crumbs
|
||||
this.$el.find('.crumb.ellipsized').remove();
|
||||
|
||||
// unhide all
|
||||
this.$el.find('.crumb.hidden').removeClass('hidden');
|
||||
|
||||
if (this.totalWidth <= this.availableWidth) {
|
||||
// no need to compute breadcrumbs, there is enough space
|
||||
return;
|
||||
}
|
||||
|
||||
// running width, considering the hidden crumbs
|
||||
var currentTotalWidth = $(this.breadcrumbs[0]).data('real-width');
|
||||
var firstHidden = true;
|
||||
|
||||
// insert ellipsis after root part (root part is always visible)
|
||||
$ellipsisCrumb = $('<div class="crumb ellipsized svg"><span class="ellipsis">...</span></div>');
|
||||
$(this.breadcrumbs[0]).after($ellipsisCrumb);
|
||||
currentTotalWidth += $ellipsisCrumb.width();
|
||||
|
||||
i = this.breadcrumbs.length - 1;
|
||||
|
||||
// find the first section that would cause the overflow
|
||||
// then hide everything in front of that
|
||||
//
|
||||
// this ensures that the last crumb section stays visible
|
||||
// for most of the cases and is always the last one to be
|
||||
// hidden when the screen becomes very narrow
|
||||
while (i > 0) {
|
||||
$crumb = $(this.breadcrumbs[i]);
|
||||
// if the current breadcrumb would cause overflow
|
||||
if (!firstHidden || currentTotalWidth + $crumb.data('real-width') > this.availableWidth) {
|
||||
// hide it
|
||||
$crumb.addClass('hidden');
|
||||
if (firstHidden) {
|
||||
// set the path of this one as title for the ellipsis
|
||||
this.$el.find('.crumb.ellipsized')
|
||||
.attr('title', $crumb.attr('data-dir'))
|
||||
.tooltip();
|
||||
this.$el.find('.ellipsis')
|
||||
.wrap('<a class="ellipsislink" href="' + encodeURI(OC.generateUrl('apps/files/?dir=' + $crumb.attr('data-dir'))) + '"></a>');
|
||||
}
|
||||
// and all the previous ones (going backwards)
|
||||
firstHidden = false;
|
||||
} else {
|
||||
// add to total width
|
||||
currentTotalWidth += $crumb.data('real-width');
|
||||
/**
|
||||
* Calculate real width based on individual crumbs
|
||||
* More accurate and works with tests
|
||||
*
|
||||
* @param {boolean} ignoreHidden ignore hidden crumbs
|
||||
*/
|
||||
getTotalWidth: function(ignoreHidden) {
|
||||
var totalWidth = 0;
|
||||
for (var i = 0; i < this.breadcrumbs.length; i++ ) {
|
||||
var $crumb = $(this.breadcrumbs[i]);
|
||||
if(!$crumb.hasClass('hidden') || ignoreHidden === true) {
|
||||
totalWidth += $crumb.outerWidth();
|
||||
}
|
||||
i--;
|
||||
}
|
||||
return totalWidth;
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the middle crumb
|
||||
*/
|
||||
_hideCrumb: function() {
|
||||
var length = this.$el.find(this.crumbSelector).length;
|
||||
// Get the middle one floored down
|
||||
var elmt = Math.floor(length / 2 - 0.5);
|
||||
this.$el.find(this.crumbSelector+':eq('+elmt+')').addClass('hidden');
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the crumb to show
|
||||
*/
|
||||
_getCrumbElement: function() {
|
||||
var hidden = this.$el.find('.crumb.hidden').length;
|
||||
var shown = this.$el.find(this.crumbSelector).length;
|
||||
// Get the outer one with priority to the highest
|
||||
var elmt = (1 - shown % 2) * (hidden - 1);
|
||||
return this.$el.find('.crumb.hidden:eq('+elmt+')');
|
||||
},
|
||||
|
||||
/**
|
||||
* Show the middle crumb
|
||||
*/
|
||||
_showCrumb: function() {
|
||||
if(this.$el.find('.crumb.hidden').length === 1) {
|
||||
this.$el.find('.crumb.hidden').removeClass('hidden');
|
||||
}
|
||||
this._getCrumbElement().removeClass('hidden');
|
||||
},
|
||||
|
||||
/**
|
||||
* Create and append the popovermenu
|
||||
*/
|
||||
_createMenu: function() {
|
||||
this.$el.find('.crumbmenu').append(this.$menu);
|
||||
this.$menu.children('ul').empty();
|
||||
},
|
||||
|
||||
/**
|
||||
* Update the popovermenu
|
||||
*/
|
||||
_updateMenu: function() {
|
||||
var menuItems = this.$el.find('.crumb.hidden');
|
||||
// Hide the crumb menu if no elements
|
||||
this.$el.find('.crumbmenu').toggleClass('hidden', menuItems.length === 0);
|
||||
|
||||
this.$menu.find('li').addClass('in-breadcrumb');
|
||||
for (var i = 0; i < menuItems.length; i++) {
|
||||
var crumbId = $(menuItems[i]).data('crumb-id');
|
||||
this.$menu.find('li:eq('+crumbId+')').removeClass('in-breadcrumb');
|
||||
}
|
||||
},
|
||||
|
||||
_resize: function() {
|
||||
|
||||
if (this.breadcrumbs.length <= 2) {
|
||||
// home & menu
|
||||
return;
|
||||
}
|
||||
|
||||
if (!OC.Util.hasSVGSupport()) {
|
||||
OC.Util.replaceSVG(this.$el);
|
||||
// Used for testing since this.$el.parent fails
|
||||
if (!this.availableWidth) {
|
||||
this.usedWidth = this.$el.parent().width() - (this.$el.parent().find('.button').length + 1) * 44;
|
||||
} else {
|
||||
this.usedWidth = this.availableWidth;
|
||||
}
|
||||
|
||||
// If container is smaller than content
|
||||
// AND if there are crumbs left to hide
|
||||
while (this.getTotalWidth() > this.usedWidth
|
||||
&& this.$el.find(this.crumbSelector).length > 0) {
|
||||
this._hideCrumb();
|
||||
}
|
||||
// If container is bigger than content + element to be shown
|
||||
// AND if there is at least one hidden crumb
|
||||
while (this.$el.find('.crumb.hidden').length > 0
|
||||
&& this.getTotalWidth() + this._getCrumbElement().width() < this.usedWidth) {
|
||||
this._showCrumb();
|
||||
}
|
||||
|
||||
this._updateMenu();
|
||||
}
|
||||
};
|
||||
|
||||
OCA.Files.BreadCrumb = BreadCrumb;
|
||||
})();
|
||||
|
||||
|
|
|
@ -322,7 +322,7 @@
|
|||
|
||||
this.$el.find('thead th .columntitle').click(_.bind(this._onClickHeader, this));
|
||||
|
||||
this._onResize = _.debounce(_.bind(this._onResize, this), 100);
|
||||
this._onResize = _.debounce(_.bind(this._onResize, this), 250);
|
||||
$('#app-content').on('appresized', this._onResize);
|
||||
$(window).resize(this._onResize);
|
||||
|
||||
|
@ -556,7 +556,7 @@
|
|||
// subtract app navigation toggle when visible
|
||||
containerWidth -= $('#app-navigation-toggle').width();
|
||||
|
||||
this.breadcrumb.setMaxWidth(containerWidth - actionsWidth - 10);
|
||||
this.breadcrumb._resize();
|
||||
|
||||
this.$table.find('>thead').width($('#app-content').width() - OC.Util.getScrollBarWidth());
|
||||
},
|
||||
|
@ -837,7 +837,8 @@
|
|||
* Event handler when clicking on a bread crumb
|
||||
*/
|
||||
_onClickBreadCrumb: function(e) {
|
||||
var $el = $(e.target).closest('.crumb'),
|
||||
// Select a crumb or a crumb in the menu
|
||||
var $el = $(e.target).closest('.crumb, .crumblist'),
|
||||
$targetDir = $el.data('dir');
|
||||
|
||||
if ($targetDir !== undefined && e.which === 1) {
|
||||
|
@ -863,8 +864,8 @@
|
|||
_onDropOnBreadCrumb: function( event, ui ) {
|
||||
var self = this;
|
||||
var $target = $(event.target);
|
||||
if (!$target.is('.crumb')) {
|
||||
$target = $target.closest('.crumb');
|
||||
if (!$target.is('.crumb, .crumblist')) {
|
||||
$target = $target.closest('.crumb, .crumblist');
|
||||
}
|
||||
var targetPath = $(event.target).data('dir');
|
||||
var dir = this.getCurrentDirectory();
|
||||
|
@ -1713,7 +1714,7 @@
|
|||
if (status === 500) {
|
||||
// Go home
|
||||
this.changeDirectory('/');
|
||||
OC.Notification.show(t('files', 'This directory is unavailable, please check the logs or contact the administrator'),
|
||||
OC.Notification.show(t('files', 'This directory is unavailable, please check the logs or contact the administrator'),
|
||||
{type: 'error'}
|
||||
);
|
||||
return false;
|
||||
|
@ -1724,7 +1725,7 @@
|
|||
if (this.getCurrentDirectory() !== '/') {
|
||||
this.changeDirectory('/');
|
||||
// TODO: read error message from exception
|
||||
OC.Notification.show(t('files', 'Storage is temporarily not available'),
|
||||
OC.Notification.show(t('files', 'Storage is temporarily not available'),
|
||||
{type: 'error'}
|
||||
);
|
||||
}
|
||||
|
@ -2040,11 +2041,11 @@
|
|||
.fail(function(status) {
|
||||
if (status === 412) {
|
||||
// TODO: some day here we should invoke the conflict dialog
|
||||
OC.Notification.show(t('files', 'Could not move "{file}", target exists',
|
||||
OC.Notification.show(t('files', 'Could not move "{file}", target exists',
|
||||
{file: fileName}), {type: 'error'}
|
||||
);
|
||||
} else {
|
||||
OC.Notification.show(t('files', 'Could not move "{file}"',
|
||||
OC.Notification.show(t('files', 'Could not move "{file}"',
|
||||
{file: fileName}), {type: 'error'}
|
||||
);
|
||||
}
|
||||
|
@ -2271,7 +2272,7 @@
|
|||
// TODO: 409 means current folder does not exist, redirect ?
|
||||
if (status === 404) {
|
||||
// source not found, so remove it from the list
|
||||
OC.Notification.show(t('files', 'Could not rename "{fileName}", it does not exist any more',
|
||||
OC.Notification.show(t('files', 'Could not rename "{fileName}", it does not exist any more',
|
||||
{fileName: oldName}), {timeout: 7, type: 'error'}
|
||||
);
|
||||
|
||||
|
@ -2291,7 +2292,7 @@
|
|||
);
|
||||
} else {
|
||||
// restore the item to its previous state
|
||||
OC.Notification.show(t('files', 'Could not rename "{fileName}"',
|
||||
OC.Notification.show(t('files', 'Could not rename "{fileName}"',
|
||||
{fileName: oldName}), {type: 'error'}
|
||||
);
|
||||
}
|
||||
|
@ -2376,18 +2377,18 @@
|
|||
self.addAndFetchFileInfo(targetPath, '', {scrollTo: true}).then(function(status, data) {
|
||||
deferred.resolve(status, data);
|
||||
}, function() {
|
||||
OC.Notification.show(t('files', 'Could not create file "{file}"',
|
||||
OC.Notification.show(t('files', 'Could not create file "{file}"',
|
||||
{file: name}), {type: 'error'}
|
||||
);
|
||||
});
|
||||
})
|
||||
.fail(function(status) {
|
||||
if (status === 412) {
|
||||
OC.Notification.show(t('files', 'Could not create file "{file}" because it already exists',
|
||||
OC.Notification.show(t('files', 'Could not create file "{file}" because it already exists',
|
||||
{file: name}), {type: 'error'}
|
||||
);
|
||||
} else {
|
||||
OC.Notification.show(t('files', 'Could not create file "{file}"',
|
||||
OC.Notification.show(t('files', 'Could not create file "{file}"',
|
||||
{file: name}), {type: 'error'}
|
||||
);
|
||||
}
|
||||
|
@ -2426,7 +2427,7 @@
|
|||
self.addAndFetchFileInfo(targetPath, '', {scrollTo:true}).then(function(status, data) {
|
||||
deferred.resolve(status, data);
|
||||
}, function() {
|
||||
OC.Notification.show(t('files', 'Could not create folder "{dir}"',
|
||||
OC.Notification.show(t('files', 'Could not create folder "{dir}"',
|
||||
{dir: name}), {type: 'error'}
|
||||
);
|
||||
});
|
||||
|
@ -2437,20 +2438,20 @@
|
|||
// add it to the list, for completeness
|
||||
self.addAndFetchFileInfo(targetPath, '', {scrollTo:true})
|
||||
.done(function(status, data) {
|
||||
OC.Notification.show(t('files', 'Could not create folder "{dir}" because it already exists',
|
||||
OC.Notification.show(t('files', 'Could not create folder "{dir}" because it already exists',
|
||||
{dir: name}), {type: 'error'}
|
||||
);
|
||||
// still consider a failure
|
||||
deferred.reject(createStatus, data);
|
||||
})
|
||||
.fail(function() {
|
||||
OC.Notification.show(t('files', 'Could not create folder "{dir}"',
|
||||
OC.Notification.show(t('files', 'Could not create folder "{dir}"',
|
||||
{dir: name}), {type: 'error'}
|
||||
);
|
||||
deferred.reject(status);
|
||||
});
|
||||
} else {
|
||||
OC.Notification.show(t('files', 'Could not create folder "{dir}"',
|
||||
OC.Notification.show(t('files', 'Could not create folder "{dir}"',
|
||||
{dir: name}), {type: 'error'}
|
||||
);
|
||||
deferred.reject(createStatus);
|
||||
|
@ -2507,7 +2508,7 @@
|
|||
deferred.resolve(status, data);
|
||||
})
|
||||
.fail(function(status) {
|
||||
OC.Notification.show(t('files', 'Could not create file "{file}"',
|
||||
OC.Notification.show(t('files', 'Could not create file "{file}"',
|
||||
{file: name}), {type: 'error'}
|
||||
);
|
||||
deferred.reject(status);
|
||||
|
@ -2616,7 +2617,7 @@
|
|||
removeFromList(file);
|
||||
} else {
|
||||
// only reset the spinner for that one file
|
||||
OC.Notification.show(t('files', 'Error deleting file "{fileName}".',
|
||||
OC.Notification.show(t('files', 'Error deleting file "{fileName}".',
|
||||
{fileName: file}), {type: 'error'}
|
||||
);
|
||||
var deleteAction = self.findFileEl(file).find('.action.delete');
|
||||
|
|
|
@ -117,32 +117,32 @@
|
|||
ownerDisplayName = $('#ownerDisplayName').val();
|
||||
if (usedSpacePercent > 98) {
|
||||
if (owner !== oc_current_user) {
|
||||
OC.Notification.show(t('files', 'Storage of {owner} is full, files can not be updated or synced anymore!',
|
||||
OC.Notification.show(t('files', 'Storage of {owner} is full, files can not be updated or synced anymore!',
|
||||
{owner: ownerDisplayName}), {type: 'error'}
|
||||
);
|
||||
return;
|
||||
}
|
||||
OC.Notification.show(t('files',
|
||||
'Your storage is full, files can not be updated or synced anymore!'),
|
||||
OC.Notification.show(t('files',
|
||||
'Your storage is full, files can not be updated or synced anymore!'),
|
||||
{type : 'error'}
|
||||
);
|
||||
return;
|
||||
}
|
||||
if (usedSpacePercent > 90) {
|
||||
if (owner !== oc_current_user) {
|
||||
OC.Notification.show(t('files', 'Storage of {owner} is almost full ({usedSpacePercent}%)',
|
||||
OC.Notification.show(t('files', 'Storage of {owner} is almost full ({usedSpacePercent}%)',
|
||||
{
|
||||
usedSpacePercent: usedSpacePercent,
|
||||
usedSpacePercent: usedSpacePercent,
|
||||
owner: ownerDisplayName
|
||||
}),
|
||||
{
|
||||
{
|
||||
type: 'error'
|
||||
}
|
||||
);
|
||||
return;
|
||||
}
|
||||
OC.Notification.show(t('files', 'Your storage is almost full ({usedSpacePercent}%)',
|
||||
{usedSpacePercent: usedSpacePercent}),
|
||||
{usedSpacePercent: usedSpacePercent}),
|
||||
{type : 'error'}
|
||||
);
|
||||
}
|
||||
|
@ -396,6 +396,8 @@ var dragOptions={
|
|||
}
|
||||
$selectedFiles.closest('tr').addClass('animate-opacity dragging');
|
||||
$selectedFiles.closest('tr').filter('.ui-droppable').droppable( 'disable' );
|
||||
// Show breadcrumbs menu
|
||||
$('.crumbmenu').addClass('canDropChildren');
|
||||
|
||||
},
|
||||
stop: function(event, ui) {
|
||||
|
@ -411,6 +413,8 @@ var dragOptions={
|
|||
setTimeout(function() {
|
||||
$tr.removeClass('animate-opacity');
|
||||
}, 300);
|
||||
// Hide breadcrumbs menu
|
||||
$('.crumbmenu').removeClass('canDropChildren');
|
||||
},
|
||||
drag: function(event, ui) {
|
||||
var scrollingArea = FileList.$container;
|
||||
|
|
|
@ -43,80 +43,93 @@ describe('OCA.Files.BreadCrumb tests', function() {
|
|||
var $crumbs;
|
||||
bc.render();
|
||||
$crumbs = bc.$el.find('.crumb');
|
||||
expect($crumbs.length).toEqual(1);
|
||||
expect($crumbs.eq(0).find('a').attr('href')).toEqual('/#0');
|
||||
expect($crumbs.eq(0).find('img').length).toEqual(1);
|
||||
expect($crumbs.eq(0).attr('data-dir')).toEqual('/');
|
||||
// menu and home
|
||||
expect($crumbs.length).toEqual(2);
|
||||
expect($crumbs.eq(0).find('a').hasClass('icon-more')).toEqual(true);
|
||||
expect($crumbs.eq(0).find('div.popovermenu').length).toEqual(1);
|
||||
expect($crumbs.eq(0).data('dir')).not.toBeDefined();
|
||||
expect($crumbs.eq(1).find('a').attr('href')).toEqual('/#1');
|
||||
expect($crumbs.eq(1).find('a').hasClass('icon-home')).toEqual(true);
|
||||
expect($crumbs.eq(1).data('dir')).toEqual('/');
|
||||
});
|
||||
it('Renders root when switching to root', function() {
|
||||
var $crumbs;
|
||||
bc.setDirectory('/somedir');
|
||||
bc.setDirectory('/');
|
||||
$crumbs = bc.$el.find('.crumb');
|
||||
expect($crumbs.length).toEqual(1);
|
||||
expect($crumbs.eq(0).attr('data-dir')).toEqual('/');
|
||||
});
|
||||
it('Renders last crumb with "last" class', function() {
|
||||
bc.setDirectory('/abc/def');
|
||||
expect(bc.$el.find('.crumb:last').hasClass('last')).toEqual(true);
|
||||
expect($crumbs.length).toEqual(2);
|
||||
expect($crumbs.eq(1).data('dir')).toEqual('/');
|
||||
});
|
||||
it('Renders single path section', function() {
|
||||
var $crumbs;
|
||||
bc.setDirectory('/somedir');
|
||||
$crumbs = bc.$el.find('.crumb');
|
||||
expect($crumbs.length).toEqual(2);
|
||||
expect($crumbs.eq(0).find('a').attr('href')).toEqual('/#0');
|
||||
expect($crumbs.eq(0).find('img').length).toEqual(1);
|
||||
expect($crumbs.eq(0).attr('data-dir')).toEqual('/');
|
||||
expect($crumbs.eq(1).find('a').attr('href')).toEqual('/somedir#1');
|
||||
expect($crumbs.eq(1).find('img').length).toEqual(0);
|
||||
expect($crumbs.eq(1).attr('data-dir')).toEqual('/somedir');
|
||||
expect($crumbs.length).toEqual(3);
|
||||
expect($crumbs.eq(0).find('a').hasClass('icon-more')).toEqual(true);
|
||||
expect($crumbs.eq(0).find('div.popovermenu').length).toEqual(1);
|
||||
expect($crumbs.eq(0).data('dir')).not.toBeDefined();
|
||||
|
||||
expect($crumbs.eq(1).find('a').attr('href')).toEqual('/#1');
|
||||
expect($crumbs.eq(1).find('a').hasClass('icon-home')).toEqual(true);
|
||||
expect($crumbs.eq(1).data('dir')).toEqual('/');
|
||||
|
||||
expect($crumbs.eq(2).find('a').attr('href')).toEqual('/somedir#2');
|
||||
expect($crumbs.eq(2).find('img').length).toEqual(0);
|
||||
expect($crumbs.eq(2).data('dir')).toEqual('/somedir');
|
||||
});
|
||||
it('Renders multiple path sections and special chars', function() {
|
||||
var $crumbs;
|
||||
bc.setDirectory('/somedir/with space/abc');
|
||||
$crumbs = bc.$el.find('.crumb');
|
||||
expect($crumbs.length).toEqual(4);
|
||||
expect($crumbs.eq(0).find('a').attr('href')).toEqual('/#0');
|
||||
expect($crumbs.eq(0).find('img').length).toEqual(1);
|
||||
expect($crumbs.eq(0).attr('data-dir')).toEqual('/');
|
||||
expect($crumbs.length).toEqual(5);
|
||||
expect($crumbs.eq(0).find('a').hasClass('icon-more')).toEqual(true);
|
||||
expect($crumbs.eq(0).find('div.popovermenu').length).toEqual(1);
|
||||
expect($crumbs.eq(0).data('dir')).not.toBeDefined();
|
||||
|
||||
expect($crumbs.eq(1).find('a').attr('href')).toEqual('/somedir#1');
|
||||
expect($crumbs.eq(1).find('img').length).toEqual(0);
|
||||
expect($crumbs.eq(1).attr('data-dir')).toEqual('/somedir');
|
||||
expect($crumbs.eq(1).find('a').attr('href')).toEqual('/#1');
|
||||
expect($crumbs.eq(1).find('a').hasClass('icon-home')).toEqual(true);
|
||||
expect($crumbs.eq(1).data('dir')).toEqual('/');
|
||||
|
||||
expect($crumbs.eq(2).find('a').attr('href')).toEqual('/somedir/with space#2');
|
||||
expect($crumbs.eq(2).find('a').attr('href')).toEqual('/somedir#2');
|
||||
expect($crumbs.eq(2).find('img').length).toEqual(0);
|
||||
expect($crumbs.eq(2).attr('data-dir')).toEqual('/somedir/with space');
|
||||
expect($crumbs.eq(2).data('dir')).toEqual('/somedir');
|
||||
|
||||
expect($crumbs.eq(3).find('a').attr('href')).toEqual('/somedir/with space/abc#3');
|
||||
expect($crumbs.eq(3).find('a').attr('href')).toEqual('/somedir/with space#3');
|
||||
expect($crumbs.eq(3).find('img').length).toEqual(0);
|
||||
expect($crumbs.eq(3).attr('data-dir')).toEqual('/somedir/with space/abc');
|
||||
expect($crumbs.eq(3).data('dir')).toEqual('/somedir/with space');
|
||||
|
||||
expect($crumbs.eq(4).find('a').attr('href')).toEqual('/somedir/with space/abc#4');
|
||||
expect($crumbs.eq(4).find('img').length).toEqual(0);
|
||||
expect($crumbs.eq(4).data('dir')).toEqual('/somedir/with space/abc');
|
||||
});
|
||||
it('Renders backslashes as regular directory separator', function() {
|
||||
var $crumbs;
|
||||
bc.setDirectory('/somedir\\with/mixed\\separators');
|
||||
$crumbs = bc.$el.find('.crumb');
|
||||
expect($crumbs.length).toEqual(5);
|
||||
expect($crumbs.eq(0).find('a').attr('href')).toEqual('/#0');
|
||||
expect($crumbs.eq(0).find('img').length).toEqual(1);
|
||||
expect($crumbs.eq(0).attr('data-dir')).toEqual('/');
|
||||
expect($crumbs.length).toEqual(6);
|
||||
expect($crumbs.eq(0).find('a').hasClass('icon-more')).toEqual(true);
|
||||
expect($crumbs.eq(0).find('div.popovermenu').length).toEqual(1);
|
||||
expect($crumbs.eq(0).data('dir')).not.toBeDefined();
|
||||
|
||||
expect($crumbs.eq(1).find('a').attr('href')).toEqual('/somedir#1');
|
||||
expect($crumbs.eq(1).find('img').length).toEqual(0);
|
||||
expect($crumbs.eq(1).attr('data-dir')).toEqual('/somedir');
|
||||
expect($crumbs.eq(1).find('a').attr('href')).toEqual('/#1');
|
||||
expect($crumbs.eq(1).find('a').hasClass('icon-home')).toEqual(true);
|
||||
expect($crumbs.eq(1).data('dir')).toEqual('/');
|
||||
|
||||
expect($crumbs.eq(2).find('a').attr('href')).toEqual('/somedir/with#2');
|
||||
expect($crumbs.eq(2).find('a').attr('href')).toEqual('/somedir#2');
|
||||
expect($crumbs.eq(2).find('img').length).toEqual(0);
|
||||
expect($crumbs.eq(2).attr('data-dir')).toEqual('/somedir/with');
|
||||
expect($crumbs.eq(2).data('dir')).toEqual('/somedir');
|
||||
|
||||
expect($crumbs.eq(3).find('a').attr('href')).toEqual('/somedir/with/mixed#3');
|
||||
expect($crumbs.eq(3).find('a').attr('href')).toEqual('/somedir/with#3');
|
||||
expect($crumbs.eq(3).find('img').length).toEqual(0);
|
||||
expect($crumbs.eq(3).attr('data-dir')).toEqual('/somedir/with/mixed');
|
||||
expect($crumbs.eq(3).data('dir')).toEqual('/somedir/with');
|
||||
|
||||
expect($crumbs.eq(4).find('a').attr('href')).toEqual('/somedir/with/mixed/separators#4');
|
||||
expect($crumbs.eq(4).find('a').attr('href')).toEqual('/somedir/with/mixed#4');
|
||||
expect($crumbs.eq(4).find('img').length).toEqual(0);
|
||||
expect($crumbs.eq(4).attr('data-dir')).toEqual('/somedir/with/mixed/separators');
|
||||
expect($crumbs.eq(4).data('dir')).toEqual('/somedir/with/mixed');
|
||||
|
||||
expect($crumbs.eq(5).find('a').attr('href')).toEqual('/somedir/with/mixed/separators#5');
|
||||
expect($crumbs.eq(5).find('img').length).toEqual(0);
|
||||
expect($crumbs.eq(5).data('dir')).toEqual('/somedir/with/mixed/separators');
|
||||
});
|
||||
});
|
||||
describe('Events', function() {
|
||||
|
@ -126,14 +139,15 @@ describe('OCA.Files.BreadCrumb tests', function() {
|
|||
onClick: handler
|
||||
});
|
||||
bc.setDirectory('/one/two/three/four');
|
||||
bc.$el.find('.crumb:eq(3)').click();
|
||||
expect(handler.calledOnce).toEqual(true);
|
||||
expect(handler.getCall(0).thisValue).toEqual(bc.$el.find('.crumb').get(3));
|
||||
// Click on crumb does not work, only link
|
||||
bc.$el.find('.crumb:eq(4)').click();
|
||||
expect(handler.calledOnce).toEqual(false);
|
||||
|
||||
handler.reset();
|
||||
bc.$el.find('.crumb:eq(0) a').click();
|
||||
// Click on crumb link works
|
||||
bc.$el.find('.crumb:eq(1) a').click();
|
||||
expect(handler.calledOnce).toEqual(true);
|
||||
expect(handler.getCall(0).thisValue).toEqual(bc.$el.find('.crumb').get(0));
|
||||
expect(handler.getCall(0).thisValue).toEqual(bc.$el.find('.crumb > a').get(1));
|
||||
});
|
||||
it('Calls onDrop handler when dropping on a crumb', function() {
|
||||
var droppableStub = sinon.stub($.fn, 'droppable');
|
||||
|
@ -154,8 +168,75 @@ describe('OCA.Files.BreadCrumb tests', function() {
|
|||
droppableStub.restore();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Menu tests', function() {
|
||||
var bc, dummyDir, $crumbmenuLink, $popovermenu;
|
||||
|
||||
beforeEach(function() {
|
||||
dummyDir = '/one/two/three/four/five'
|
||||
|
||||
$('div.crumb').each(function(index){
|
||||
$(this).css('width', 50);
|
||||
});
|
||||
|
||||
bc = new BreadCrumb();
|
||||
// append dummy navigation and controls
|
||||
// as they are currently used for measurements
|
||||
$('#testArea').append(
|
||||
'<div id="controls"></div>'
|
||||
);
|
||||
$('#controls').append(bc.$el);
|
||||
|
||||
// Shrink to show popovermenu
|
||||
bc.setMaxWidth(300);
|
||||
|
||||
// triggers resize implicitly
|
||||
bc.setDirectory(dummyDir);
|
||||
|
||||
$crumbmenuLink = bc.$el.find('.crumbmenu > a');
|
||||
$popovermenu = $crumbmenuLink.next('.popovermenu');
|
||||
});
|
||||
afterEach(function() {
|
||||
bc = null;
|
||||
});
|
||||
|
||||
it('Opens and closes the menu on click', function() {
|
||||
// Menu exists
|
||||
expect($popovermenu.length).toEqual(1);
|
||||
|
||||
// Disable jQuery delay
|
||||
jQuery.fx.off = true
|
||||
|
||||
// Click on menu
|
||||
$crumbmenuLink.click();
|
||||
expect($popovermenu.is(':visible')).toEqual(true);
|
||||
|
||||
// Click on home
|
||||
$(document).mouseup();
|
||||
expect($popovermenu.is(':visible')).toEqual(false);
|
||||
|
||||
// Change directory and reset elements
|
||||
bc.setDirectory('/one/two/three/four/five/six/seven/eight/nine/ten');
|
||||
$crumbmenuLink = bc.$el.find('.crumbmenu > a');
|
||||
$popovermenu = $crumbmenuLink.next('.popovermenu');
|
||||
|
||||
// Click on menu again
|
||||
$crumbmenuLink.click();
|
||||
expect($popovermenu.is(':visible')).toEqual(true);
|
||||
|
||||
// Click on home again
|
||||
$(document).mouseup();
|
||||
expect($popovermenu.is(':visible')).toEqual(false);
|
||||
|
||||
});
|
||||
it('Shows only items not in the breadcrumb', function() {
|
||||
var hiddenCrumbs = bc.$el.find('.crumb:not(.crumbmenu).hidden');
|
||||
expect($popovermenu.find('li:not(.in-breadcrumb)').length).toEqual(hiddenCrumbs.length);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Resizing', function() {
|
||||
var bc, dummyDir, widths, oldUpdateTotalWidth;
|
||||
var bc, dummyDir, widths;
|
||||
|
||||
beforeEach(function() {
|
||||
dummyDir = '/short name/longer name/looooooooooooonger/' +
|
||||
|
@ -163,17 +244,12 @@ describe('OCA.Files.BreadCrumb tests', function() {
|
|||
|
||||
// using hard-coded widths (pre-measured) to avoid getting different
|
||||
// results on different browsers due to font engine differences
|
||||
widths = [41, 106, 112, 160, 257, 251, 91];
|
||||
// 51px is default size for menu and home
|
||||
widths = [51, 51, 106, 112, 160, 257, 251, 91];
|
||||
|
||||
oldUpdateTotalWidth = BreadCrumb.prototype._updateTotalWidth;
|
||||
BreadCrumb.prototype._updateTotalWidth = function() {
|
||||
// pre-set a width to simulate consistent measurement
|
||||
$('div.crumb').each(function(index){
|
||||
$(this).css('width', widths[index]);
|
||||
});
|
||||
|
||||
return oldUpdateTotalWidth.apply(this, arguments);
|
||||
};
|
||||
$('div.crumb').each(function(index){
|
||||
$(this).css('width', widths[index]);
|
||||
});
|
||||
|
||||
bc = new BreadCrumb();
|
||||
// append dummy navigation and controls
|
||||
|
@ -184,30 +260,26 @@ describe('OCA.Files.BreadCrumb tests', function() {
|
|||
$('#controls').append(bc.$el);
|
||||
});
|
||||
afterEach(function() {
|
||||
BreadCrumb.prototype._updateTotalWidth = oldUpdateTotalWidth;
|
||||
bc = null;
|
||||
});
|
||||
it('Hides breadcrumbs to fit max allowed width', function() {
|
||||
var $crumbs;
|
||||
|
||||
bc.setMaxWidth(500);
|
||||
|
||||
// triggers resize implicitly
|
||||
bc.setDirectory(dummyDir);
|
||||
$crumbs = bc.$el.find('.crumb');
|
||||
|
||||
// first one is always visible
|
||||
// Menu and home are always visible
|
||||
expect($crumbs.eq(0).hasClass('hidden')).toEqual(false);
|
||||
// second one has ellipsis
|
||||
expect($crumbs.eq(1).hasClass('hidden')).toEqual(false);
|
||||
expect($crumbs.eq(1).find('.ellipsis').length).toEqual(1);
|
||||
// there is only one ellipsis in total
|
||||
expect($crumbs.find('.ellipsis').length).toEqual(1);
|
||||
// subsequent elements are hidden
|
||||
expect($crumbs.eq(2).hasClass('hidden')).toEqual(true);
|
||||
|
||||
expect($crumbs.eq(2).hasClass('hidden')).toEqual(false);
|
||||
expect($crumbs.eq(3).hasClass('hidden')).toEqual(true);
|
||||
expect($crumbs.eq(4).hasClass('hidden')).toEqual(true);
|
||||
expect($crumbs.eq(5).hasClass('hidden')).toEqual(true);
|
||||
expect($crumbs.eq(6).hasClass('hidden')).toEqual(false);
|
||||
expect($crumbs.eq(6).hasClass('hidden')).toEqual(true);
|
||||
expect($crumbs.eq(7).hasClass('hidden')).toEqual(false);
|
||||
});
|
||||
it('Updates the breadcrumbs when reducing max allowed width', function() {
|
||||
|
@ -215,56 +287,27 @@ describe('OCA.Files.BreadCrumb tests', function() {
|
|||
|
||||
// enough space
|
||||
bc.setMaxWidth(1800);
|
||||
$crumbs = bc.$el.find('.crumb');
|
||||
|
||||
expect(bc.$el.find('.ellipsis').length).toEqual(0);
|
||||
// Menu is hidden
|
||||
expect($crumbs.eq(0).hasClass('hidden')).toEqual(false);
|
||||
|
||||
// triggers resize implicitly
|
||||
bc.setDirectory(dummyDir);
|
||||
|
||||
// simulate increase
|
||||
// simulate decrease
|
||||
bc.setMaxWidth(950);
|
||||
|
||||
$crumbs = bc.$el.find('.crumb');
|
||||
// first one is always visible
|
||||
expect($crumbs.eq(0).hasClass('hidden')).toEqual(false);
|
||||
// second one has ellipsis
|
||||
expect($crumbs.eq(1).hasClass('hidden')).toEqual(false);
|
||||
expect($crumbs.eq(1).find('.ellipsis').length).toEqual(1);
|
||||
// there is only one ellipsis in total
|
||||
expect($crumbs.find('.ellipsis').length).toEqual(1);
|
||||
// subsequent elements are hidden
|
||||
expect($crumbs.eq(2).hasClass('hidden')).toEqual(true);
|
||||
expect($crumbs.eq(3).hasClass('hidden')).toEqual(true);
|
||||
// the rest is visible
|
||||
expect($crumbs.eq(4).hasClass('hidden')).toEqual(false);
|
||||
expect($crumbs.eq(5).hasClass('hidden')).toEqual(false);
|
||||
expect($crumbs.eq(6).hasClass('hidden')).toEqual(false);
|
||||
});
|
||||
it('Removes the ellipsis when there is enough space', function() {
|
||||
var $crumbs;
|
||||
|
||||
bc.setMaxWidth(500);
|
||||
// triggers resize implicitly
|
||||
bc.setDirectory(dummyDir);
|
||||
$crumbs = bc.$el.find('.crumb');
|
||||
|
||||
// ellipsis
|
||||
expect(bc.$el.find('.ellipsis').length).toEqual(1);
|
||||
|
||||
// simulate increase
|
||||
bc.setMaxWidth(1800);
|
||||
|
||||
// no ellipsis
|
||||
expect(bc.$el.find('.ellipsis').length).toEqual(0);
|
||||
|
||||
// all are visible
|
||||
// Menu and home are always visible
|
||||
expect($crumbs.eq(0).hasClass('hidden')).toEqual(false);
|
||||
expect($crumbs.eq(1).hasClass('hidden')).toEqual(false);
|
||||
|
||||
expect($crumbs.eq(2).hasClass('hidden')).toEqual(false);
|
||||
expect($crumbs.eq(3).hasClass('hidden')).toEqual(false);
|
||||
expect($crumbs.eq(4).hasClass('hidden')).toEqual(false);
|
||||
expect($crumbs.eq(5).hasClass('hidden')).toEqual(false);
|
||||
expect($crumbs.eq(6).hasClass('hidden')).toEqual(false);
|
||||
expect($crumbs.eq(7).hasClass('hidden')).toEqual(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -1657,7 +1657,7 @@ describe('OCA.Files.FileList tests', function() {
|
|||
fileList.changeDirectory('/subdir/two/three with space/four/five');
|
||||
deferredList.resolve(200, [testRoot].concat(testFiles));
|
||||
var changeDirStub = sinon.stub(fileList, 'changeDirectory');
|
||||
fileList.breadcrumb.$el.find('.crumb:eq(0)').trigger({type: 'click', which: 1});
|
||||
fileList.breadcrumb.$el.find('.crumb:eq(1) > a').trigger({type: 'click', which: 1});
|
||||
|
||||
expect(changeDirStub.calledOnce).toEqual(true);
|
||||
expect(changeDirStub.getCall(0).args[0]).toEqual('/');
|
||||
|
@ -1667,7 +1667,7 @@ describe('OCA.Files.FileList tests', function() {
|
|||
fileList.changeDirectory('/subdir/two/three with space/four/five');
|
||||
deferredList.resolve(200, [testRoot].concat(testFiles));
|
||||
var changeDirStub = sinon.stub(fileList, 'changeDirectory');
|
||||
fileList.breadcrumb.$el.find('.crumb:eq(3)').trigger({type: 'click', which: 1});
|
||||
fileList.breadcrumb.$el.find('.crumb:eq(4) > a').trigger({type: 'click', which: 1});
|
||||
|
||||
expect(changeDirStub.calledOnce).toEqual(true);
|
||||
expect(changeDirStub.getCall(0).args[0]).toEqual('/subdir/two/three with space');
|
||||
|
@ -1678,7 +1678,7 @@ describe('OCA.Files.FileList tests', function() {
|
|||
var moveStub = sinon.stub(filesClient, 'move').returns($.Deferred().promise());
|
||||
fileList.changeDirectory(testDir);
|
||||
deferredList.resolve(200, [testRoot].concat(testFiles));
|
||||
var $crumb = fileList.breadcrumb.$el.find('.crumb:eq(3)');
|
||||
var $crumb = fileList.breadcrumb.$el.find('.crumb:eq(4)');
|
||||
// no idea what this is but is required by the handler
|
||||
var ui = {
|
||||
helper: {
|
||||
|
@ -3013,7 +3013,7 @@ describe('OCA.Files.FileList tests', function() {
|
|||
it('drop on a breadcrumb inside the table triggers upload to target folder', function() {
|
||||
var ev;
|
||||
fileList.changeDirectory('a/b/c/d');
|
||||
ev = dropOn(fileList.$el.find('.crumb:eq(2)'), uploadData);
|
||||
ev = dropOn(fileList.$el.find('.crumb:eq(3)'), uploadData);
|
||||
|
||||
expect(ev).not.toEqual(false);
|
||||
expect(uploadData.targetDir).toEqual('/a/b');
|
||||
|
|
|
@ -132,12 +132,12 @@ describe('OCA.Trashbin.FileList tests', function() {
|
|||
fileList.changeDirectory('/subdir', false, true);
|
||||
fakeServer.respond();
|
||||
var $crumbs = fileList.$el.find('#controls .crumb');
|
||||
expect($crumbs.length).toEqual(2);
|
||||
expect($crumbs.eq(0).find('a').text()).toEqual('');
|
||||
expect($crumbs.eq(0).find('a').attr('href'))
|
||||
.toEqual(OC.webroot + '/index.php/apps/files?view=trashbin&dir=/');
|
||||
expect($crumbs.eq(1).find('a').text()).toEqual('subdir');
|
||||
expect($crumbs.length).toEqual(3);
|
||||
expect($crumbs.eq(1).find('a').text()).toEqual('Home');
|
||||
expect($crumbs.eq(1).find('a').attr('href'))
|
||||
.toEqual(OC.webroot + '/index.php/apps/files?view=trashbin&dir=/');
|
||||
expect($crumbs.eq(2).find('a').text()).toEqual('subdir');
|
||||
expect($crumbs.eq(2).find('a').attr('href'))
|
||||
.toEqual(OC.webroot + '/index.php/apps/files?view=trashbin&dir=/subdir');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -822,6 +822,7 @@ kbd {
|
|||
}
|
||||
li {
|
||||
display: flex;
|
||||
flex: 0 0 auto;
|
||||
> button,
|
||||
> a,
|
||||
> .menuitem {
|
||||
|
|
|
@ -22,30 +22,6 @@
|
|||
-ms-user-select: none;
|
||||
}
|
||||
|
||||
/* Header menu */
|
||||
.menu {
|
||||
position: absolute;
|
||||
top: 45px;
|
||||
background-color: $color-main-background;
|
||||
box-shadow: 0 1px 10px $color-box-shadow;
|
||||
border-radius: 0 0 3px 3px;
|
||||
display: none;
|
||||
box-sizing: border-box;
|
||||
z-index: 2000;
|
||||
|
||||
/* Dropdown arrow */
|
||||
&:after {
|
||||
border: 10px solid transparent;
|
||||
border-bottom-color: $color-main-background;
|
||||
bottom: 100%;
|
||||
content: ' ';
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* removed until content-focusing issue is fixed */
|
||||
#skip-to-content a {
|
||||
position: absolute;
|
||||
|
@ -96,6 +72,29 @@
|
|||
}
|
||||
|
||||
#header {
|
||||
/* Header menu */
|
||||
.menu {
|
||||
top: 45px;
|
||||
background-color: $color-main-background;
|
||||
filter: drop-shadow(0 1px 3px $color-box-shadow);
|
||||
border-radius: 0 0 3px 3px;
|
||||
display: none;
|
||||
box-sizing: border-box;
|
||||
z-index: 2000;
|
||||
position: absolute;
|
||||
|
||||
/* Dropdown arrow */
|
||||
&:after {
|
||||
border: 10px solid transparent;
|
||||
border-bottom-color: $color-main-background;
|
||||
bottom: 100%;
|
||||
content: ' ';
|
||||
height: 0;
|
||||
width: 0;
|
||||
position: absolute;
|
||||
pointer-events: none;
|
||||
}
|
||||
}
|
||||
.logo {
|
||||
display: inline-flex;
|
||||
background-image: url($image-logo);
|
||||
|
@ -204,14 +203,14 @@ nav {
|
|||
margin-left: -54px;
|
||||
}
|
||||
|
||||
#navigation,
|
||||
.header-left #navigation,
|
||||
.ui-datepicker,
|
||||
.ui-timepicker.ui-widget {
|
||||
position: relative;
|
||||
left: -100%;
|
||||
width: 160px;
|
||||
background-color: $color-main-background;
|
||||
box-shadow: 0 1px 10px $color-box-shadow;
|
||||
filter: drop-shadow(0 1px 3px $color-box-shadow);
|
||||
&:after {
|
||||
/* position of dropdown arrow */
|
||||
left: 47%;
|
||||
|
|
|
@ -81,16 +81,11 @@
|
|||
opacity: 1;
|
||||
}
|
||||
|
||||
|
||||
/* controls bar for mobile */
|
||||
#controls {
|
||||
min-width: initial !important;
|
||||
left: 0 !important;
|
||||
padding-left: 0;
|
||||
}
|
||||
/* position controls for apps with app-navigation */
|
||||
#app-navigation+#app-content #controls {
|
||||
left: 0 !important;
|
||||
padding-left: 44px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
/* .viewer-mode is when text editor, PDF viewer, etc is open */
|
||||
|
|
|
@ -228,7 +228,7 @@ body {
|
|||
right: 0;
|
||||
left: 0;
|
||||
height: 44px;
|
||||
width: 100%;
|
||||
width: calc(100% - 250px);
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: rgba($color-main-background, 0.95);
|
||||
|
@ -237,6 +237,7 @@ body {
|
|||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
/* position controls for apps with app-navigation */
|
||||
|
@ -1144,9 +1145,7 @@ code {
|
|||
#oc-dialog-filepicker-content {
|
||||
.dirtree {
|
||||
width: 92%;
|
||||
float: left;
|
||||
margin-left: 15px;
|
||||
overflow: hidden;
|
||||
flex-wrap: wrap;
|
||||
div:first-child a {
|
||||
background-image: url('../img/places/home.svg?v=1');
|
||||
background-repeat: no-repeat;
|
||||
|
@ -1181,7 +1180,7 @@ code {
|
|||
display: none;
|
||||
}
|
||||
.filelist {
|
||||
background-color: white;
|
||||
background-color: $color-main-background;
|
||||
width: 100%;
|
||||
}
|
||||
#filestable.filelist {
|
||||
|
@ -1388,46 +1387,88 @@ span.ui-icon {
|
|||
}
|
||||
|
||||
/* ---- BREADCRUMB ---- */
|
||||
|
||||
.breadcrumb {
|
||||
display: inline-flex;
|
||||
}
|
||||
div.crumb {
|
||||
float: left;
|
||||
display: block;
|
||||
display: inline-flex;
|
||||
background-image: url('../img/breadcrumb.svg?v=1');
|
||||
background-repeat: no-repeat;
|
||||
background-position: right center;
|
||||
height: 44px;
|
||||
background-size: auto 24px;
|
||||
flex: 0 0 auto;
|
||||
order: 1;
|
||||
padding-right: 7px;
|
||||
&.crumbmenu {
|
||||
order: 2;
|
||||
position: relative;
|
||||
a {
|
||||
opacity: 0.5
|
||||
}
|
||||
&.canDropChildren,
|
||||
&.canDrop {
|
||||
.popovermenu {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
// Fix because of the display flex
|
||||
.popovermenu {
|
||||
top: 100%;
|
||||
margin-right: 3px;
|
||||
ul {
|
||||
max-height: 345px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
padding-right: 5px;
|
||||
li.canDrop span:first-child {
|
||||
background-image: url('../img/filetypes/folder-drag-accept.svg?v=1') !important;
|
||||
}
|
||||
}
|
||||
.in-breadcrumb {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.hidden {
|
||||
display: none;
|
||||
~ .crumb {
|
||||
order: 3;
|
||||
}
|
||||
}
|
||||
a, > span {
|
||||
> a,
|
||||
> span {
|
||||
position: relative;
|
||||
top: 12px;
|
||||
padding: 14px 24px 14px 17px;
|
||||
color: nc-lighten($color-main-text, 33%);
|
||||
padding: 12px;
|
||||
opacity: 0.5;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
flex: 0 0 auto;
|
||||
&.icon-home {
|
||||
// Hide home text
|
||||
text-indent: -9999px;
|
||||
}
|
||||
}
|
||||
&.last a {
|
||||
padding-right: 0;
|
||||
> a[class^='icon-'] {
|
||||
padding: 0;
|
||||
width: 44px;
|
||||
}
|
||||
&:first-child a {
|
||||
position: relative;
|
||||
top: 13px;
|
||||
padding-right: 14px;
|
||||
&:not(:first-child) a {
|
||||
}
|
||||
&.last {
|
||||
&:last-child {
|
||||
font-weight: 600;
|
||||
margin-right: 10px;
|
||||
}
|
||||
&.ellipsized {
|
||||
padding: 0 10px 0 5px;
|
||||
}
|
||||
a.ellipsislink {
|
||||
padding: 0 !important;
|
||||
position: relative;
|
||||
top: 8px !important;
|
||||
// Allow multiple span next to the main 'a'
|
||||
a ~ span {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
&:hover, &:focus, a:focus, &:active {
|
||||
opacity: .7;
|
||||
> a,
|
||||
> span {
|
||||
opacity: .7;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1"><path color="#000" fill="none" d="M-62.897-32.993h163.31v97.986h-163.31z"/><path opacity=".5" d="M8 1.03L0 9h3v6h10V9h3l-3-3.03V2h-3v1.08L8 1.03z" fill-rule="evenodd"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="16" width="16" version="1"><path color="#000" fill="none" d="M-62.897-32.993h163.31v97.986h-163.31z"/><path d="M8 1.03L0 9h3v6h10V9h3l-3-3.03V2h-3v1.08L8 1.03z" fill-rule="evenodd"/></svg>
|
Before Width: | Height: | Size: 249 B After Width: | Height: | Size: 236 B |
|
@ -1625,39 +1625,6 @@ function initCore() {
|
|||
// initial call
|
||||
toggleSnapperOnSize();
|
||||
|
||||
// adjust controls bar width
|
||||
var adjustControlsWidth = function() {
|
||||
if($('#controls').length) {
|
||||
var controlsWidth;
|
||||
// if there is a scrollbar …
|
||||
if($('#app-content').get(0).scrollHeight > $('#app-content').height()) {
|
||||
if($(window).width() > 768) {
|
||||
controlsWidth = $('#content').width() - $('#app-navigation').width() - getScrollBarWidth();
|
||||
if (!$('#app-sidebar').hasClass('hidden') && !$('#app-sidebar').hasClass('disappear')) {
|
||||
controlsWidth -= $('#app-sidebar').width();
|
||||
}
|
||||
} else {
|
||||
controlsWidth = $('#content').width() - getScrollBarWidth();
|
||||
}
|
||||
} else { // if there is none
|
||||
if($(window).width() > 768) {
|
||||
controlsWidth = $('#content').width() - $('#app-navigation').width();
|
||||
if (!$('#app-sidebar').hasClass('hidden') && !$('#app-sidebar').hasClass('disappear')) {
|
||||
controlsWidth -= $('#app-sidebar').width();
|
||||
}
|
||||
} else {
|
||||
controlsWidth = $('#content').width();
|
||||
}
|
||||
}
|
||||
$('#controls').css('width', controlsWidth);
|
||||
$('#controls').css('min-width', controlsWidth);
|
||||
}
|
||||
};
|
||||
|
||||
$(window).resize(_.debounce(adjustControlsWidth, 250));
|
||||
|
||||
$('body').delegate('#app-content', 'apprendered appresized', _.debounce(adjustControlsWidth, 150));
|
||||
|
||||
}
|
||||
|
||||
// Update live timestamps every 30 seconds
|
||||
|
|
|
@ -929,7 +929,7 @@ var OCdialogs = {
|
|||
*/
|
||||
_handleTreeListSelect:function(event, type) {
|
||||
var self = event.data;
|
||||
var dir = $(event.target).parent().data('dir');
|
||||
var dir = $(event.target).closest('.crumb').data('dir');
|
||||
self._fillFilePicker(dir);
|
||||
var getOcDialog = (event.target).closest('.oc-dialog');
|
||||
var buttonEnableDisable = $('.primary', getOcDialog);
|
||||
|
|
Loading…
Reference in New Issue