aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2017-11-13 12:19:05 +0100
committerGitHub <noreply@github.com>2017-11-13 12:19:05 +0100
commitff2d4432d8af7f8d1d17d9740f985bb36db531fc (patch)
tree3bae3c8530c0e1cf9bce78e2b1d02966660e6be4
parent26bcf40e9e0b35b851ff1aecab8dd9fd2b1be80e (diff)
parent8c2dbeb13a71ca320f6953302f75ce491c4f1aff (diff)
downloadnextcloud-server-ff2d4432d8af7f8d1d17d9740f985bb36db531fc.tar.gz
nextcloud-server-ff2d4432d8af7f8d1d17d9740f985bb36db531fc.zip
Merge pull request #7051 from nextcloud/breadcrumbs-refactor
Breadcrumbs refactor
-rw-r--r--apps/files/css/files.scss22
-rw-r--r--apps/files/js/breadcrumb.js223
-rw-r--r--apps/files/js/filelist.js41
-rw-r--r--apps/files/js/files.js18
-rw-r--r--apps/files/tests/js/breadcrumbSpec.js245
-rw-r--r--apps/files/tests/js/filelistSpec.js8
-rw-r--r--apps/files_trashbin/tests/js/filelistSpec.js10
-rw-r--r--core/css/apps.scss1
-rw-r--r--core/css/header.scss51
-rw-r--r--core/css/mobile.scss9
-rw-r--r--core/css/styles.scss97
-rw-r--r--core/img/places/home.svg2
-rw-r--r--core/js/js.js33
-rw-r--r--core/js/oc-dialogs.js2
14 files changed, 435 insertions, 327 deletions
diff --git a/apps/files/css/files.scss b/apps/files/css/files.scss
index d1405517f13..1be3c9216f0 100644
--- a/apps/files/css/files.scss
+++ b/apps/files/css/files.scss
@@ -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);
}
diff --git a/apps/files/js/breadcrumb.js b/apps/files/js/breadcrumb.js
index 2a4c2bc8a52..35aeb8d357d 100644
--- a/apps/files/js/breadcrumb.js
+++ b/apps/files/js/breadcrumb.js
@@ -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];
@@ -198,22 +239,9 @@
},
/**
- * 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();
+ /**
+ * 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();
+ }
}
+ return totalWidth;
+ },
- if (this.breadcrumbs.length <= 1) {
- return;
+ /**
+ * 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);
- // reset crumbs
- this.$el.find('.crumb.ellipsized').remove();
+ 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');
+ }
+ },
- // unhide all
- this.$el.find('.crumb.hidden').removeClass('hidden');
+ _resize: function() {
- if (this.totalWidth <= this.availableWidth) {
- // no need to compute breadcrumbs, there is enough space
+ if (this.breadcrumbs.length <= 2) {
+ // home & menu
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');
- }
- i--;
+ // 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 (!OC.Util.hasSVGSupport()) {
- OC.Util.replaceSVG(this.$el);
+ // 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;
})();
-
diff --git a/apps/files/js/filelist.js b/apps/files/js/filelist.js
index af5e9c013f0..6e90f30fcf1 100644
--- a/apps/files/js/filelist.js
+++ b/apps/files/js/filelist.js
@@ -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');
diff --git a/apps/files/js/files.js b/apps/files/js/files.js
index e34d7fe2550..017bf7ecf41 100644
--- a/apps/files/js/files.js
+++ b/apps/files/js/files.js
@@ -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;
diff --git a/apps/files/tests/js/breadcrumbSpec.js b/apps/files/tests/js/breadcrumbSpec.js
index a26f0176f15..dd3eac017ec 100644
--- a/apps/files/tests/js/breadcrumbSpec.js
+++ b/apps/files/tests/js/breadcrumbSpec.js
@@ -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
+ // 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(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
- 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);
});
});
});
diff --git a/apps/files/tests/js/filelistSpec.js b/apps/files/tests/js/filelistSpec.js
index fd011474eb1..c590275e1cf 100644
--- a/apps/files/tests/js/filelistSpec.js
+++ b/apps/files/tests/js/filelistSpec.js
@@ -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');
diff --git a/apps/files_trashbin/tests/js/filelistSpec.js b/apps/files_trashbin/tests/js/filelistSpec.js
index 5e9a4cf27d1..04ff243d07b 100644
--- a/apps/files_trashbin/tests/js/filelistSpec.js
+++ b/apps/files_trashbin/tests/js/filelistSpec.js
@@ -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');
});
});
diff --git a/core/css/apps.scss b/core/css/apps.scss
index 5493375b5ae..8f49df7fdaf 100644
--- a/core/css/apps.scss
+++ b/core/css/apps.scss
@@ -822,6 +822,7 @@ kbd {
}
li {
display: flex;
+ flex: 0 0 auto;
> button,
> a,
> .menuitem {
diff --git a/core/css/header.scss b/core/css/header.scss
index 952389882c3..1844022e8a3 100644
--- a/core/css/header.scss
+++ b/core/css/header.scss
@@ -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%;
diff --git a/core/css/mobile.scss b/core/css/mobile.scss
index aad3070e79a..19518479987 100644
--- a/core/css/mobile.scss
+++ b/core/css/mobile.scss
@@ -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 */
diff --git a/core/css/styles.scss b/core/css/styles.scss
index e5e0145cddb..ed72b32113f 100644
--- a/core/css/styles.scss
+++ b/core/css/styles.scss
@@ -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;
+ }
}
}
diff --git a/core/img/places/home.svg b/core/img/places/home.svg
index 30ef3e31ad4..7ef6db0fde1 100644
--- a/core/img/places/home.svg
+++ b/core/img/places/home.svg
@@ -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> \ No newline at end of file
+<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> \ No newline at end of file
diff --git a/core/js/js.js b/core/js/js.js
index 1f84b40a35a..730586713a0 100644
--- a/core/js/js.js
+++ b/core/js/js.js
@@ -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
diff --git a/core/js/oc-dialogs.js b/core/js/oc-dialogs.js
index 1bc1399466d..9cd806720b8 100644
--- a/core/js/oc-dialogs.js
+++ b/core/js/oc-dialogs.js
@@ -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);