Implement file actions dropdown
File actions now have two types "inline" and "dropdown". The default is "dropdown". The file actions will now be shown in a dropdown menu.
This commit is contained in:
parent
15e16d335d
commit
ca34921cdf
|
@ -517,6 +517,9 @@ table td.filename .uploadtext {
|
||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.busy .fileactions, .busy .action {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
/* force show the loading icon, not only on hover */
|
/* force show the loading icon, not only on hover */
|
||||||
#fileList .icon-loading-small {
|
#fileList .icon-loading-small {
|
||||||
|
@ -527,11 +530,6 @@ table td.filename .uploadtext {
|
||||||
}
|
}
|
||||||
|
|
||||||
#fileList img.move2trash { display:inline; margin:-8px 0; padding:16px 8px 16px 8px !important; float:right; }
|
#fileList img.move2trash { display:inline; margin:-8px 0; padding:16px 8px 16px 8px !important; float:right; }
|
||||||
#fileList a.action.delete {
|
|
||||||
position: absolute;
|
|
||||||
right: 15px;
|
|
||||||
padding: 17px 14px;
|
|
||||||
}
|
|
||||||
|
|
||||||
#fileList .action.action-share-notification span, #fileList a.name {
|
#fileList .action.action-share-notification span, #fileList a.name {
|
||||||
cursor: default !important;
|
cursor: default !important;
|
||||||
|
@ -578,10 +576,6 @@ a.action>img {
|
||||||
display:none;
|
display:none;
|
||||||
}
|
}
|
||||||
|
|
||||||
#fileList a.action[data-action="Rename"] {
|
|
||||||
padding: 16px 14px 17px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ie8 #fileList a.action img,
|
.ie8 #fileList a.action img,
|
||||||
#fileList tr:hover a.action,
|
#fileList tr:hover a.action,
|
||||||
#fileList a.action.permanent,
|
#fileList a.action.permanent,
|
||||||
|
@ -693,3 +687,36 @@ table.dragshadow td.size {
|
||||||
.mask.transparent{
|
.mask.transparent{
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fileActionsMenu {
|
||||||
|
/* FIXME: should be variable width, but default one is too big */
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fileActionsMenu.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fileList .fileActionsMenu .action {
|
||||||
|
display: block;
|
||||||
|
line-height: 30px;
|
||||||
|
padding-left: 5px;
|
||||||
|
color: #000;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fileActionsMenu .action img,
|
||||||
|
.fileActionsMenu .action .no-icon {
|
||||||
|
display: inline-block;
|
||||||
|
width: 16px;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fileActionsMenu .action {
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fileActionsMenu li:hover .action {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -138,6 +138,7 @@ foreach ($navItems as $item) {
|
||||||
}
|
}
|
||||||
|
|
||||||
OCP\Util::addscript('files', 'fileactions');
|
OCP\Util::addscript('files', 'fileactions');
|
||||||
|
OCP\Util::addscript('files', 'fileactionsmenu');
|
||||||
OCP\Util::addscript('files', 'files');
|
OCP\Util::addscript('files', 'files');
|
||||||
OCP\Util::addscript('files', 'navigation');
|
OCP\Util::addscript('files', 'navigation');
|
||||||
OCP\Util::addscript('files', 'keyboardshortcuts');
|
OCP\Util::addscript('files', 'keyboardshortcuts');
|
||||||
|
|
|
@ -10,6 +10,12 @@
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
|
|
||||||
|
var TEMPLATE_FILE_ACTION_TRIGGER =
|
||||||
|
'<a class="action action-{{nameLowerCase}}" href="#" data-action="{{name}}">' +
|
||||||
|
'{{#if icon}}<img class="svg" alt="{{altText}}" src="{{icon}}" />{{/if}}' +
|
||||||
|
'{{#if displayName}}<span> {{displayName}}</span>{{/if}}' +
|
||||||
|
'</a>';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new FileActions instance
|
* Construct a new FileActions instance
|
||||||
* @constructs FileActions
|
* @constructs FileActions
|
||||||
|
@ -18,6 +24,8 @@
|
||||||
var FileActions = function() {
|
var FileActions = function() {
|
||||||
this.initialize();
|
this.initialize();
|
||||||
};
|
};
|
||||||
|
FileActions.TYPE_DROPDOWN = 0;
|
||||||
|
FileActions.TYPE_INLINE = 1;
|
||||||
FileActions.prototype = {
|
FileActions.prototype = {
|
||||||
/** @lends FileActions.prototype */
|
/** @lends FileActions.prototype */
|
||||||
actions: {},
|
actions: {},
|
||||||
|
@ -38,6 +46,15 @@
|
||||||
*/
|
*/
|
||||||
_updateListeners: {},
|
_updateListeners: {},
|
||||||
|
|
||||||
|
_fileActionTriggerTemplate: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* File actions menu
|
||||||
|
*
|
||||||
|
* @type OCA.Files.FileActionsMenu
|
||||||
|
*/
|
||||||
|
_menu: null,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
@ -46,6 +63,8 @@
|
||||||
// abusing jquery for events until we get a real event lib
|
// abusing jquery for events until we get a real event lib
|
||||||
this.$el = $('<div class="dummy-fileactions hidden"></div>');
|
this.$el = $('<div class="dummy-fileactions hidden"></div>');
|
||||||
$('body').append(this.$el);
|
$('body').append(this.$el);
|
||||||
|
|
||||||
|
this._showMenuClosure = _.bind(this._showMenu, this);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -111,6 +130,7 @@
|
||||||
displayName: displayName || name
|
displayName: displayName || name
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register action
|
* Register action
|
||||||
*
|
*
|
||||||
|
@ -125,15 +145,14 @@
|
||||||
displayName: action.displayName,
|
displayName: action.displayName,
|
||||||
mime: mime,
|
mime: mime,
|
||||||
icon: action.icon,
|
icon: action.icon,
|
||||||
permissions: action.permissions
|
permissions: action.permissions,
|
||||||
|
type: action.type || FileActions.TYPE_DROPDOWN
|
||||||
};
|
};
|
||||||
if (_.isUndefined(action.displayName)) {
|
if (_.isUndefined(action.displayName)) {
|
||||||
actionSpec.displayName = t('files', name);
|
actionSpec.displayName = t('files', name);
|
||||||
}
|
}
|
||||||
if (_.isFunction(action.render)) {
|
if (_.isFunction(action.render)) {
|
||||||
actionSpec.render = action.render;
|
actionSpec.render = action.render;
|
||||||
} else {
|
|
||||||
actionSpec.render = _.bind(this._defaultRenderAction, this);
|
|
||||||
}
|
}
|
||||||
if (!this.actions[mime]) {
|
if (!this.actions[mime]) {
|
||||||
this.actions[mime] = {};
|
this.actions[mime] = {};
|
||||||
|
@ -162,6 +181,16 @@
|
||||||
this.defaults[mime] = name;
|
this.defaults[mime] = name;
|
||||||
this._notifyUpdateListeners('setDefault', {defaultAction: {mime: mime, name: name}});
|
this._notifyUpdateListeners('setDefault', {defaultAction: {mime: mime, name: name}});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a map of file actions handlers matching the given conditions
|
||||||
|
*
|
||||||
|
* @param {string} mime mime type
|
||||||
|
* @param {string} type "dir" or "file"
|
||||||
|
* @param {int} permissions permissions
|
||||||
|
*
|
||||||
|
* @return {Object.<string,OCA.Files.FileActions~actionHandler>} map of action name to action spec
|
||||||
|
*/
|
||||||
get: function (mime, type, permissions) {
|
get: function (mime, type, permissions) {
|
||||||
var actions = this.getActions(mime, type, permissions);
|
var actions = this.getActions(mime, type, permissions);
|
||||||
var filteredActions = {};
|
var filteredActions = {};
|
||||||
|
@ -170,6 +199,16 @@
|
||||||
});
|
});
|
||||||
return filteredActions;
|
return filteredActions;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of file actions matching the given conditions
|
||||||
|
*
|
||||||
|
* @param {string} mime mime type
|
||||||
|
* @param {string} type "dir" or "file"
|
||||||
|
* @param {int} permissions permissions
|
||||||
|
*
|
||||||
|
* @return {Array.<OCA.Files.FileAction>} array of action specs
|
||||||
|
*/
|
||||||
getActions: function (mime, type, permissions) {
|
getActions: function (mime, type, permissions) {
|
||||||
var actions = {};
|
var actions = {};
|
||||||
if (this.actions.all) {
|
if (this.actions.all) {
|
||||||
|
@ -197,7 +236,37 @@
|
||||||
});
|
});
|
||||||
return filteredActions;
|
return filteredActions;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the default file action handler for the given conditions
|
||||||
|
*
|
||||||
|
* @param {string} mime mime type
|
||||||
|
* @param {string} type "dir" or "file"
|
||||||
|
* @param {int} permissions permissions
|
||||||
|
*
|
||||||
|
* @return {OCA.Files.FileActions~actionHandler} action handler
|
||||||
|
*
|
||||||
|
* @deprecated use getDefaultFileAction instead
|
||||||
|
*/
|
||||||
getDefault: function (mime, type, permissions) {
|
getDefault: function (mime, type, permissions) {
|
||||||
|
var defaultActionSpec = this.getDefaultFileAction(mime, type, permissions);
|
||||||
|
if (defaultActionSpec) {
|
||||||
|
return defaultActionSpec.action;
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the default file action handler for the given conditions
|
||||||
|
*
|
||||||
|
* @param {string} mime mime type
|
||||||
|
* @param {string} type "dir" or "file"
|
||||||
|
* @param {int} permissions permissions
|
||||||
|
*
|
||||||
|
* @return {OCA.Files.FileActions~actionHandler} action handler
|
||||||
|
* @since 8.2
|
||||||
|
*/
|
||||||
|
getDefaultFileAction: function(mime, type, permissions) {
|
||||||
var mimePart;
|
var mimePart;
|
||||||
if (mime) {
|
if (mime) {
|
||||||
mimePart = mime.substr(0, mime.indexOf('/'));
|
mimePart = mime.substr(0, mime.indexOf('/'));
|
||||||
|
@ -212,9 +281,10 @@
|
||||||
} else {
|
} else {
|
||||||
name = this.defaults.all;
|
name = this.defaults.all;
|
||||||
}
|
}
|
||||||
var actions = this.get(mime, type, permissions);
|
var actions = this.getActions(mime, type, permissions);
|
||||||
return actions[name];
|
return actions[name];
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default function to render actions
|
* Default function to render actions
|
||||||
*
|
*
|
||||||
|
@ -225,86 +295,68 @@
|
||||||
*/
|
*/
|
||||||
_defaultRenderAction: function(actionSpec, isDefault, context) {
|
_defaultRenderAction: function(actionSpec, isDefault, context) {
|
||||||
var name = actionSpec.name;
|
var name = actionSpec.name;
|
||||||
if (name === 'Download' || !isDefault) {
|
if (!isDefault) {
|
||||||
var $actionLink = this._makeActionLink(actionSpec, context);
|
var params = {
|
||||||
|
name: actionSpec.name,
|
||||||
|
nameLowerCase: actionSpec.name.toLowerCase(),
|
||||||
|
displayName: actionSpec.displayName,
|
||||||
|
icon: actionSpec.icon,
|
||||||
|
altText: actionSpec.altText,
|
||||||
|
};
|
||||||
|
if (_.isFunction(actionSpec.icon)) {
|
||||||
|
params.icon = actionSpec.icon(context.$file.attr('data-file'));
|
||||||
|
}
|
||||||
|
|
||||||
|
var $actionLink = this._makeActionLink(params, context);
|
||||||
context.$file.find('a.name>span.fileactions').append($actionLink);
|
context.$file.find('a.name>span.fileactions').append($actionLink);
|
||||||
return $actionLink;
|
return $actionLink;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the action link element
|
* Renders the action link element
|
||||||
*
|
*
|
||||||
* @param {OCA.Files.FileAction} actionSpec action object
|
* @param {Object} params action params
|
||||||
* @param {OCA.Files.FileActionContext} context action context
|
|
||||||
*/
|
*/
|
||||||
_makeActionLink: function(actionSpec, context) {
|
_makeActionLink: function(params) {
|
||||||
var img = actionSpec.icon;
|
if (!this._fileActionTriggerTemplate) {
|
||||||
if (img && img.call) {
|
this._fileActionTriggerTemplate = Handlebars.compile(TEMPLATE_FILE_ACTION_TRIGGER);
|
||||||
img = img(context.$file.attr('data-file'));
|
|
||||||
}
|
}
|
||||||
var html = '<a href="#">';
|
|
||||||
if (img) {
|
|
||||||
html += '<img class="svg" alt="" src="' + img + '" />';
|
|
||||||
}
|
|
||||||
if (actionSpec.displayName) {
|
|
||||||
html += '<span> ' + actionSpec.displayName + '</span>';
|
|
||||||
}
|
|
||||||
html += '</a>';
|
|
||||||
|
|
||||||
return $(html);
|
return $(this._fileActionTriggerTemplate(params));
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom renderer for the "Rename" action.
|
* Displays the file actions dropdown menu
|
||||||
* Displays the rename action as an icon behind the file name.
|
|
||||||
*
|
*
|
||||||
* @param {OCA.Files.FileAction} actionSpec file action to render
|
* @param {string} fileName file name
|
||||||
* @param {boolean} isDefault true if the action is a default action,
|
* @param {OCA.Files.FileActionContext} context rendering context
|
||||||
* false otherwise
|
|
||||||
* @param {OCAFiles.FileActionContext} context rendering context
|
|
||||||
*/
|
*/
|
||||||
_renderRenameAction: function(actionSpec, isDefault, context) {
|
_showMenu: function(fileName, context) {
|
||||||
var $actionEl = this._makeActionLink(actionSpec, context);
|
var $actionEl = context.$file.find('.action-menu');
|
||||||
var $container = context.$file.find('a.name span.nametext');
|
|
||||||
$actionEl.find('img').attr('alt', t('files', 'Rename'));
|
this._menu = new OCA.Files.FileActionsMenu();
|
||||||
$container.find('.action-rename').remove();
|
this._menu.showAt($actionEl, context);
|
||||||
$container.append($actionEl);
|
|
||||||
return $actionEl;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Custom renderer for the "Delete" action.
|
* Renders the menu trigger on the given file list row
|
||||||
* Displays the "Delete" action as a trash icon at the end of
|
*
|
||||||
* the table row.
|
* @param {Object} $tr file list row element
|
||||||
*
|
* @param {OCA.Files.FileActionContext} context rendering context
|
||||||
* @param {OCA.Files.FileAction} actionSpec file action to render
|
|
||||||
* @param {boolean} isDefault true if the action is a default action,
|
|
||||||
* false otherwise
|
|
||||||
* @param {OCAFiles.FileActionContext} context rendering context
|
|
||||||
*/
|
*/
|
||||||
_renderDeleteAction: function(actionSpec, isDefault, context) {
|
_renderMenuTrigger: function($tr, context) {
|
||||||
var mountType = context.$file.attr('data-mounttype');
|
// remove previous
|
||||||
var deleteTitle = t('files', 'Delete');
|
$tr.find('.action-menu').remove();
|
||||||
if (mountType === 'external-root') {
|
$tr.find('.fileactions').append(this._renderInlineAction({
|
||||||
deleteTitle = t('files', 'Disconnect storage');
|
name: 'menu',
|
||||||
} else if (mountType === 'shared-root') {
|
displayName: '',
|
||||||
deleteTitle = t('files', 'Unshare');
|
icon: OC.imagePath('core', 'actions/more'),
|
||||||
}
|
altText: t('files', 'Actions'),
|
||||||
var cssClasses = 'action delete icon-delete';
|
action: this._showMenuClosure
|
||||||
if((context.$file.data('permissions') & OC.PERMISSION_DELETE) === 0) {
|
}, false, context));
|
||||||
// add css class no-permission to delete icon
|
|
||||||
cssClasses += ' no-permission';
|
|
||||||
deleteTitle = t('files', 'No permission to delete');
|
|
||||||
}
|
|
||||||
var $actionLink = $('<a href="#" original-title="' +
|
|
||||||
escapeHTML(deleteTitle) +
|
|
||||||
'" class="' +cssClasses + '">' +
|
|
||||||
'<span class="hidden-visually">' + escapeHTML(deleteTitle) + '</span>' +
|
|
||||||
'</a>'
|
|
||||||
);
|
|
||||||
var $container = context.$file.find('td:last');
|
|
||||||
$container.find('.delete').remove();
|
|
||||||
$container.append($actionLink);
|
|
||||||
return $actionLink;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the action element by calling actionSpec.render() and
|
* Renders the action element by calling actionSpec.render() and
|
||||||
* registers the click event to process the action.
|
* registers the click event to process the action.
|
||||||
|
@ -312,21 +364,23 @@
|
||||||
* @param {OCA.Files.FileAction} actionSpec file action to render
|
* @param {OCA.Files.FileAction} actionSpec file action to render
|
||||||
* @param {boolean} isDefault true if the action is a default action,
|
* @param {boolean} isDefault true if the action is a default action,
|
||||||
* false otherwise
|
* false otherwise
|
||||||
* @param {OCAFiles.FileActionContext} context rendering context
|
* @param {OCA.Files.FileActionContext} context rendering context
|
||||||
*/
|
*/
|
||||||
_renderAction: function(actionSpec, isDefault, context) {
|
_renderInlineAction: function(actionSpec, isDefault, context) {
|
||||||
var $actionEl = actionSpec.render(actionSpec, isDefault, context);
|
var renderFunc = actionSpec.render || _.bind(this._defaultRenderAction, this);
|
||||||
|
var $actionEl = renderFunc(actionSpec, isDefault, context);
|
||||||
if (!$actionEl || !$actionEl.length) {
|
if (!$actionEl || !$actionEl.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
$actionEl.addClass('action action-' + actionSpec.name.toLowerCase());
|
|
||||||
$actionEl.attr('data-action', actionSpec.name);
|
|
||||||
$actionEl.on(
|
$actionEl.on(
|
||||||
'click', {
|
'click', {
|
||||||
a: null
|
a: null
|
||||||
},
|
},
|
||||||
function(event) {
|
function(event) {
|
||||||
var $file = $(event.target).closest('tr');
|
var $file = $(event.target).closest('tr');
|
||||||
|
if ($file.hasClass('busy')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
var currentFile = $file.find('td.filename');
|
var currentFile = $file.find('td.filename');
|
||||||
var fileName = $file.attr('data-file');
|
var fileName = $file.attr('data-file');
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
|
@ -346,6 +400,7 @@
|
||||||
);
|
);
|
||||||
return $actionEl;
|
return $actionEl;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display file actions for the given element
|
* Display file actions for the given element
|
||||||
* @param parent "td" element of the file for which to display actions
|
* @param parent "td" element of the file for which to display actions
|
||||||
|
@ -382,30 +437,23 @@
|
||||||
this.getCurrentPermissions()
|
this.getCurrentPermissions()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
var context = {
|
||||||
|
$file: $tr,
|
||||||
|
fileActions: this,
|
||||||
|
fileList: fileList
|
||||||
|
};
|
||||||
|
|
||||||
$.each(actions, function (name, actionSpec) {
|
$.each(actions, function (name, actionSpec) {
|
||||||
if (name !== 'Share') {
|
if (actionSpec.type === FileActions.TYPE_INLINE) {
|
||||||
self._renderAction(
|
self._renderInlineAction(
|
||||||
actionSpec,
|
actionSpec,
|
||||||
actionSpec.action === defaultAction, {
|
actionSpec.action === defaultAction,
|
||||||
$file: $tr,
|
context
|
||||||
fileActions: this,
|
|
||||||
fileList : fileList
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// added here to make sure it's always the last action
|
|
||||||
var shareActionSpec = actions.Share;
|
this._renderMenuTrigger($tr, context);
|
||||||
if (shareActionSpec){
|
|
||||||
this._renderAction(
|
|
||||||
shareActionSpec,
|
|
||||||
shareActionSpec.action === defaultAction, {
|
|
||||||
$file: $tr,
|
|
||||||
fileActions: this,
|
|
||||||
fileList: fileList
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (triggerEvent){
|
if (triggerEvent){
|
||||||
fileList.$fileList.trigger(jQuery.Event("fileActionsReady", {fileList: fileList, $files: $tr}));
|
fileList.$fileList.trigger(jQuery.Event("fileActionsReady", {fileList: fileList, $files: $tr}));
|
||||||
|
@ -429,35 +477,42 @@
|
||||||
*/
|
*/
|
||||||
registerDefaultActions: function() {
|
registerDefaultActions: function() {
|
||||||
this.registerAction({
|
this.registerAction({
|
||||||
name: 'Delete',
|
name: 'Download',
|
||||||
displayName: '',
|
displayName: t('files', 'Download'),
|
||||||
mime: 'all',
|
mime: 'all',
|
||||||
// permission is READ because we show a hint instead if there is no permission
|
|
||||||
permissions: OC.PERMISSION_READ,
|
permissions: OC.PERMISSION_READ,
|
||||||
icon: function() {
|
icon: function () {
|
||||||
return OC.imagePath('core', 'actions/delete');
|
return OC.imagePath('core', 'actions/download');
|
||||||
},
|
},
|
||||||
render: _.bind(this._renderDeleteAction, this),
|
actionHandler: function (filename, context) {
|
||||||
actionHandler: function(fileName, context) {
|
var dir = context.dir || context.fileList.getCurrentDirectory();
|
||||||
// if there is no permission to delete do nothing
|
var url = context.fileList.getDownloadUrl(filename, dir);
|
||||||
if((context.$file.data('permissions') & OC.PERMISSION_DELETE) === 0) {
|
|
||||||
|
var downloadFileaction = $(context.$file).find('.fileactions .action-download');
|
||||||
|
|
||||||
|
// don't allow a second click on the download action
|
||||||
|
if(downloadFileaction.hasClass('disabled')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
context.fileList.do_delete(fileName, context.dir);
|
|
||||||
$('.tipsy').remove();
|
if (url) {
|
||||||
|
var disableLoadingState = function() {
|
||||||
|
context.fileList.showFileBusyState(filename, false);
|
||||||
|
};
|
||||||
|
|
||||||
|
context.fileList.showFileBusyState(downloadFileaction, true);
|
||||||
|
OCA.Files.Files.handleDownload(url, disableLoadingState);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// t('files', 'Rename')
|
|
||||||
this.registerAction({
|
this.registerAction({
|
||||||
name: 'Rename',
|
name: 'Rename',
|
||||||
displayName: '',
|
|
||||||
mime: 'all',
|
mime: 'all',
|
||||||
permissions: OC.PERMISSION_UPDATE,
|
permissions: OC.PERMISSION_UPDATE,
|
||||||
icon: function() {
|
icon: function() {
|
||||||
return OC.imagePath('core', 'actions/rename');
|
return OC.imagePath('core', 'actions/rename');
|
||||||
},
|
},
|
||||||
render: _.bind(this._renderRenameAction, this),
|
|
||||||
actionHandler: function (filename, context) {
|
actionHandler: function (filename, context) {
|
||||||
context.fileList.rename(filename);
|
context.fileList.rename(filename);
|
||||||
}
|
}
|
||||||
|
@ -471,30 +526,25 @@
|
||||||
context.fileList.changeDirectory(dir + filename);
|
context.fileList.changeDirectory(dir + filename);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.registerAction({
|
||||||
|
name: 'Delete',
|
||||||
|
mime: 'all',
|
||||||
|
// permission is READ because we show a hint instead if there is no permission
|
||||||
|
permissions: OC.PERMISSION_READ,
|
||||||
|
icon: function() {
|
||||||
|
return OC.imagePath('core', 'actions/delete');
|
||||||
|
},
|
||||||
|
actionHandler: function(fileName, context) {
|
||||||
|
// if there is no permission to delete do nothing
|
||||||
|
if((context.$file.data('permissions') & OC.PERMISSION_DELETE) === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
context.fileList.do_delete(fileName, context.dir);
|
||||||
|
$('.tipsy').remove();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
this.setDefault('dir', 'Open');
|
this.setDefault('dir', 'Open');
|
||||||
|
|
||||||
this.register('all', 'Download', OC.PERMISSION_READ, function () {
|
|
||||||
return OC.imagePath('core', 'actions/download');
|
|
||||||
}, function (filename, context) {
|
|
||||||
var dir = context.dir || context.fileList.getCurrentDirectory();
|
|
||||||
var url = context.fileList.getDownloadUrl(filename, dir);
|
|
||||||
|
|
||||||
var downloadFileaction = $(context.$file).find('.fileactions .action-download');
|
|
||||||
|
|
||||||
// don't allow a second click on the download action
|
|
||||||
if(downloadFileaction.hasClass('disabled')) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url) {
|
|
||||||
var disableLoadingState = function(){
|
|
||||||
OCA.Files.FileActions.updateFileActionSpinner(downloadFileaction, false);
|
|
||||||
};
|
|
||||||
|
|
||||||
OCA.Files.FileActions.updateFileActionSpinner(downloadFileaction, true);
|
|
||||||
OCA.Files.Files.handleDownload(url, disableLoadingState);
|
|
||||||
}
|
|
||||||
}, t('files', 'Download'));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,149 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014
|
||||||
|
*
|
||||||
|
* This file is licensed under the Affero General Public License version 3
|
||||||
|
* or later.
|
||||||
|
*
|
||||||
|
* See the COPYING-README file.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function() {
|
||||||
|
|
||||||
|
var TEMPLATE_MENU =
|
||||||
|
'<ul>' +
|
||||||
|
'{{#each items}}' +
|
||||||
|
'<li>' +
|
||||||
|
'<a href="#" class="action action-{{nameLowerCase}} permanent" data-action="{{name}}">{{#if icon}}<img src="{{icon}}"/>{{else}}<span class="no-icon"></span>{{/if}}<span>{{displayName}}</span></a>' +
|
||||||
|
'</li>' +
|
||||||
|
'{{/each}}' +
|
||||||
|
'</ul>';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new FileActionsMenu instance
|
||||||
|
* @constructs FileActionsMenu
|
||||||
|
* @memberof OCA.Files
|
||||||
|
*/
|
||||||
|
var FileActionsMenu = function() {
|
||||||
|
this.initialize();
|
||||||
|
};
|
||||||
|
|
||||||
|
FileActionsMenu.prototype = {
|
||||||
|
$el: null,
|
||||||
|
_template: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Current context
|
||||||
|
*
|
||||||
|
* @type OCA.Files.FileActionContext
|
||||||
|
*/
|
||||||
|
_context: null,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
initialize: function(fileActions, fileList) {
|
||||||
|
this.$el = $('<div class="fileActionsMenu dropdown hidden menu"></div>');
|
||||||
|
this._template = Handlebars.compile(TEMPLATE_MENU);
|
||||||
|
|
||||||
|
this.$el.on('click', 'a.action', _.bind(this._onClickAction, this));
|
||||||
|
this.$el.on('afterHide', _.bind(this._onHide, this));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Event handler whenever an action has been clicked within the menu
|
||||||
|
*
|
||||||
|
* @param {Object} event event object
|
||||||
|
*/
|
||||||
|
_onClickAction: function(event) {
|
||||||
|
var $target = $(event.target);
|
||||||
|
if (!$target.is('a')) {
|
||||||
|
$target = $target.closest('a');
|
||||||
|
}
|
||||||
|
var fileActions = this._context.fileActions;
|
||||||
|
var actionName = $target.attr('data-action');
|
||||||
|
var actions = fileActions.getActions(
|
||||||
|
fileActions.getCurrentMimeType(),
|
||||||
|
fileActions.getCurrentType(),
|
||||||
|
fileActions.getCurrentPermissions()
|
||||||
|
);
|
||||||
|
var actionSpec = actions[actionName];
|
||||||
|
var fileName = this._context.$file.attr('data-file');
|
||||||
|
|
||||||
|
event.stopPropagation();
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
OC.hideMenus();
|
||||||
|
|
||||||
|
actionSpec.action(
|
||||||
|
fileName,
|
||||||
|
this._context
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Renders the menu with the currently set items
|
||||||
|
*/
|
||||||
|
render: function() {
|
||||||
|
var fileActions = this._context.fileActions;
|
||||||
|
var actions = fileActions.getActions(
|
||||||
|
fileActions.getCurrentMimeType(),
|
||||||
|
fileActions.getCurrentType(),
|
||||||
|
fileActions.getCurrentPermissions()
|
||||||
|
);
|
||||||
|
|
||||||
|
var defaultAction = fileActions.getDefaultFileAction(
|
||||||
|
fileActions.getCurrentMimeType(),
|
||||||
|
fileActions.getCurrentType(),
|
||||||
|
fileActions.getCurrentPermissions()
|
||||||
|
);
|
||||||
|
|
||||||
|
var items = _.filter(actions, function(actionSpec) {
|
||||||
|
return (
|
||||||
|
actionSpec.type === OCA.Files.FileActions.TYPE_DROPDOWN &&
|
||||||
|
(!defaultAction || actionSpec.name !== defaultAction.name)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
items = _.map(items, function(item) {
|
||||||
|
item.nameLowerCase = item.name.toLowerCase();
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$el.empty();
|
||||||
|
this.$el.append(this._template({
|
||||||
|
items: items
|
||||||
|
}));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the menu under the given element
|
||||||
|
*
|
||||||
|
* @param {Object} $el target element
|
||||||
|
* @param {OCA.Files.FileActionContext} context context
|
||||||
|
*/
|
||||||
|
showAt: function($el, context) {
|
||||||
|
this._context = context;
|
||||||
|
|
||||||
|
this.render();
|
||||||
|
this.$el.removeClass('hidden');
|
||||||
|
|
||||||
|
$el.closest('td').append(this.$el);
|
||||||
|
|
||||||
|
context.$file.addClass('mouseOver');
|
||||||
|
|
||||||
|
OC.showMenu(null, this.$el);
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whenever the menu is hidden
|
||||||
|
*/
|
||||||
|
_onHide: function() {
|
||||||
|
this._context.$file.removeClass('mouseOver');
|
||||||
|
this.$el.remove();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
OCA.Files.FileActionsMenu = FileActionsMenu;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
|
@ -1444,9 +1444,7 @@
|
||||||
}
|
}
|
||||||
_.each(fileNames, function(fileName) {
|
_.each(fileNames, function(fileName) {
|
||||||
var $tr = self.findFileEl(fileName);
|
var $tr = self.findFileEl(fileName);
|
||||||
var $thumbEl = $tr.find('.thumbnail');
|
self.showFileBusyState($tr, true);
|
||||||
var oldBackgroundImage = $thumbEl.css('background-image');
|
|
||||||
$thumbEl.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')');
|
|
||||||
// TODO: improve performance by sending all file names in a single call
|
// TODO: improve performance by sending all file names in a single call
|
||||||
$.post(
|
$.post(
|
||||||
OC.filePath('files', 'ajax', 'move.php'),
|
OC.filePath('files', 'ajax', 'move.php'),
|
||||||
|
@ -1488,7 +1486,7 @@
|
||||||
} else {
|
} else {
|
||||||
OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error'));
|
OC.dialogs.alert(t('files', 'Error moving file'), t('files', 'Error'));
|
||||||
}
|
}
|
||||||
$thumbEl.css('background-image', oldBackgroundImage);
|
self.showFileBusyState($tr, false);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
@ -1549,14 +1547,13 @@
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var newName = input.val();
|
var newName = input.val();
|
||||||
var $thumbEl = tr.find('.thumbnail');
|
|
||||||
input.tipsy('hide');
|
input.tipsy('hide');
|
||||||
form.remove();
|
form.remove();
|
||||||
|
|
||||||
if (newName !== oldname) {
|
if (newName !== oldname) {
|
||||||
checkInput();
|
checkInput();
|
||||||
// mark as loading (temp element)
|
// mark as loading (temp element)
|
||||||
$thumbEl.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')');
|
self.showFileBusyState(tr, true);
|
||||||
tr.attr('data-file', newName);
|
tr.attr('data-file', newName);
|
||||||
var basename = newName;
|
var basename = newName;
|
||||||
if (newName.indexOf('.') > 0 && tr.data('type') !== 'dir') {
|
if (newName.indexOf('.') > 0 && tr.data('type') !== 'dir') {
|
||||||
|
@ -1564,7 +1561,6 @@
|
||||||
}
|
}
|
||||||
td.find('a.name span.nametext').text(basename);
|
td.find('a.name span.nametext').text(basename);
|
||||||
td.children('a.name').show();
|
td.children('a.name').show();
|
||||||
tr.find('.fileactions, .action').addClass('hidden');
|
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: OC.filePath('files','ajax','rename.php'),
|
url: OC.filePath('files','ajax','rename.php'),
|
||||||
|
@ -1636,6 +1632,44 @@
|
||||||
inList:function(file) {
|
inList:function(file) {
|
||||||
return this.findFileEl(file).length;
|
return this.findFileEl(file).length;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows busy state on a given file row or multiple
|
||||||
|
*
|
||||||
|
* @param {string|Array.<string>} files file name or array of file names
|
||||||
|
* @param {bool} [busy=true] busy state, true for busy, false to remove busy state
|
||||||
|
*
|
||||||
|
* @since 8.2
|
||||||
|
*/
|
||||||
|
showFileBusyState: function(files, state) {
|
||||||
|
var self = this;
|
||||||
|
if (!_.isArray(files)) {
|
||||||
|
files = [files];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_.isUndefined(state)) {
|
||||||
|
state = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
_.each(files, function($tr) {
|
||||||
|
// jquery element already ?
|
||||||
|
if (!$tr.is) {
|
||||||
|
$tr = self.findFileEl($tr);
|
||||||
|
}
|
||||||
|
|
||||||
|
var $thumbEl = $tr.find('.thumbnail');
|
||||||
|
$tr.toggleClass('busy', state);
|
||||||
|
|
||||||
|
if (state) {
|
||||||
|
$thumbEl.attr('data-oldimage', $thumbEl.css('background-image'));
|
||||||
|
$thumbEl.css('background-image', 'url('+ OC.imagePath('core', 'loading.gif') + ')');
|
||||||
|
} else {
|
||||||
|
$thumbEl.css('background-image', $thumbEl.attr('data-oldimage'));
|
||||||
|
$thumbEl.removeAttr('data-oldimage');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Delete the given files from the given dir
|
* Delete the given files from the given dir
|
||||||
* @param files file names list (without path)
|
* @param files file names list (without path)
|
||||||
|
@ -1649,9 +1683,8 @@
|
||||||
files=[files];
|
files=[files];
|
||||||
}
|
}
|
||||||
if (files) {
|
if (files) {
|
||||||
|
this.showFileBusyState(files, true);
|
||||||
for (var i=0; i<files.length; i++) {
|
for (var i=0; i<files.length; i++) {
|
||||||
var deleteAction = this.findFileEl(files[i]).children("td.date").children(".action.delete");
|
|
||||||
deleteAction.removeClass('icon-delete').addClass('icon-loading-small');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Finish any existing actions
|
// Finish any existing actions
|
||||||
|
@ -1669,7 +1702,7 @@
|
||||||
// no files passed, delete all in current dir
|
// no files passed, delete all in current dir
|
||||||
params.allfiles = true;
|
params.allfiles = true;
|
||||||
// show spinner for all files
|
// show spinner for all files
|
||||||
this.$fileList.find('tr>td.date .action.delete').removeClass('icon-delete').addClass('icon-loading-small');
|
this.$fileList.find('tr').addClass('busy');
|
||||||
}
|
}
|
||||||
|
|
||||||
$.post(OC.filePath('files', 'ajax', 'delete.php'),
|
$.post(OC.filePath('files', 'ajax', 'delete.php'),
|
||||||
|
@ -1712,8 +1745,7 @@
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$.each(files,function(index,file) {
|
$.each(files,function(index,file) {
|
||||||
var deleteAction = self.findFileEl(file).find('.action.delete');
|
self.$fileList.find('tr').removeClass('busy');
|
||||||
deleteAction.removeClass('icon-loading-small').addClass('icon-delete');
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,6 +81,7 @@
|
||||||
displayName: 'Favorite',
|
displayName: 'Favorite',
|
||||||
mime: 'all',
|
mime: 'all',
|
||||||
permissions: OC.PERMISSION_READ,
|
permissions: OC.PERMISSION_READ,
|
||||||
|
type: OCA.Files.FileActions.TYPE_INLINE,
|
||||||
render: function(actionSpec, isDefault, context) {
|
render: function(actionSpec, isDefault, context) {
|
||||||
var $file = context.$file;
|
var $file = context.$file;
|
||||||
var isFavorite = $file.data('favorite') === true;
|
var isFavorite = $file.data('favorite') === true;
|
||||||
|
|
|
@ -89,57 +89,59 @@
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
fileActions.register(
|
fileActions.registerAction({
|
||||||
'all',
|
name: 'Share',
|
||||||
'Share',
|
displayName: t('files_sharing', 'Share'),
|
||||||
OC.PERMISSION_SHARE,
|
mime: 'all',
|
||||||
OC.imagePath('core', 'actions/share'),
|
permissions: OC.PERMISSION_SHARE,
|
||||||
function(filename, context) {
|
icon: OC.imagePath('core', 'actions/share'),
|
||||||
|
type: OCA.Files.FileActions.TYPE_INLINE,
|
||||||
|
actionHandler: function(filename, context) {
|
||||||
|
var $tr = context.$file;
|
||||||
|
var itemType = 'file';
|
||||||
|
if ($tr.data('type') === 'dir') {
|
||||||
|
itemType = 'folder';
|
||||||
|
}
|
||||||
|
var possiblePermissions = $tr.data('share-permissions');
|
||||||
|
if (_.isUndefined(possiblePermissions)) {
|
||||||
|
possiblePermissions = $tr.data('permissions');
|
||||||
|
}
|
||||||
|
|
||||||
var $tr = context.$file;
|
var appendTo = $tr.find('td.filename');
|
||||||
var itemType = 'file';
|
// Check if drop down is already visible for a different file
|
||||||
if ($tr.data('type') === 'dir') {
|
if (OC.Share.droppedDown) {
|
||||||
itemType = 'folder';
|
if ($tr.attr('data-id') !== $('#dropdown').attr('data-item-source')) {
|
||||||
}
|
OC.Share.hideDropDown(function () {
|
||||||
var possiblePermissions = $tr.data('share-permissions');
|
$tr.addClass('mouseOver');
|
||||||
if (_.isUndefined(possiblePermissions)) {
|
OC.Share.showDropDown(itemType, $tr.data('id'), appendTo, true, possiblePermissions, filename);
|
||||||
possiblePermissions = $tr.data('permissions');
|
});
|
||||||
}
|
} else {
|
||||||
|
OC.Share.hideDropDown();
|
||||||
var appendTo = $tr.find('td.filename');
|
}
|
||||||
// Check if drop down is already visible for a different file
|
|
||||||
if (OC.Share.droppedDown) {
|
|
||||||
if ($tr.attr('data-id') !== $('#dropdown').attr('data-item-source')) {
|
|
||||||
OC.Share.hideDropDown(function () {
|
|
||||||
$tr.addClass('mouseOver');
|
|
||||||
OC.Share.showDropDown(itemType, $tr.data('id'), appendTo, true, possiblePermissions, filename);
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
OC.Share.hideDropDown();
|
$tr.addClass('mouseOver');
|
||||||
|
OC.Share.showDropDown(itemType, $tr.data('id'), appendTo, true, possiblePermissions, filename);
|
||||||
}
|
}
|
||||||
} else {
|
$('#dropdown').on('sharesChanged', function(ev) {
|
||||||
$tr.addClass('mouseOver');
|
// files app current cannot show recipients on load, so we don't update the
|
||||||
OC.Share.showDropDown(itemType, $tr.data('id'), appendTo, true, possiblePermissions, filename);
|
// icon when changed for consistency
|
||||||
|
if (context.fileList.$el.closest('#app-content-files').length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var recipients = _.pluck(ev.shares[OC.Share.SHARE_TYPE_USER], 'share_with_displayname');
|
||||||
|
var groupRecipients = _.pluck(ev.shares[OC.Share.SHARE_TYPE_GROUP], 'share_with_displayname');
|
||||||
|
recipients = recipients.concat(groupRecipients);
|
||||||
|
// note: we only update the data attribute because updateIcon()
|
||||||
|
// is called automatically after this event
|
||||||
|
if (recipients.length) {
|
||||||
|
$tr.attr('data-share-recipients', OCA.Sharing.Util.formatRecipients(recipients));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$tr.removeAttr('data-share-recipients');
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
$('#dropdown').on('sharesChanged', function(ev) {
|
});
|
||||||
// files app current cannot show recipients on load, so we don't update the
|
|
||||||
// icon when changed for consistency
|
|
||||||
if (context.fileList.$el.closest('#app-content-files').length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var recipients = _.pluck(ev.shares[OC.Share.SHARE_TYPE_USER], 'share_with_displayname');
|
|
||||||
var groupRecipients = _.pluck(ev.shares[OC.Share.SHARE_TYPE_GROUP], 'share_with_displayname');
|
|
||||||
recipients = recipients.concat(groupRecipients);
|
|
||||||
// note: we only update the data attribute because updateIcon()
|
|
||||||
// is called automatically after this event
|
|
||||||
if (recipients.length) {
|
|
||||||
$tr.attr('data-share-recipients', OCA.Sharing.Util.formatRecipients(recipients));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$tr.removeAttr('data-share-recipients');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}, t('files_sharing', 'Share'));
|
|
||||||
|
|
||||||
OC.addScript('files_sharing', 'sharetabview').done(function() {
|
OC.addScript('files_sharing', 'sharetabview').done(function() {
|
||||||
fileList.registerTabView(new OCA.Sharing.ShareTabView('shareTabView'));
|
fileList.registerTabView(new OCA.Sharing.ShareTabView('shareTabView'));
|
||||||
|
|
|
@ -7,6 +7,7 @@ OCP\Util::addStyle('files_sharing', 'public');
|
||||||
OCP\Util::addStyle('files_sharing', 'mobile');
|
OCP\Util::addStyle('files_sharing', 'mobile');
|
||||||
OCP\Util::addScript('files_sharing', 'public');
|
OCP\Util::addScript('files_sharing', 'public');
|
||||||
OCP\Util::addScript('files', 'fileactions');
|
OCP\Util::addScript('files', 'fileactions');
|
||||||
|
OCP\Util::addScript('files', 'fileactionsmenu');
|
||||||
OCP\Util::addScript('files', 'jquery.iframe-transport');
|
OCP\Util::addScript('files', 'jquery.iframe-transport');
|
||||||
OCP\Util::addScript('files', 'jquery.fileupload');
|
OCP\Util::addScript('files', 'jquery.fileupload');
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,6 @@ OCA.Trashbin.App = {
|
||||||
|
|
||||||
fileActions.registerAction({
|
fileActions.registerAction({
|
||||||
name: 'Delete',
|
name: 'Delete',
|
||||||
displayName: '',
|
|
||||||
mime: 'all',
|
mime: 'all',
|
||||||
permissions: OC.PERMISSION_READ,
|
permissions: OC.PERMISSION_READ,
|
||||||
icon: function() {
|
icon: function() {
|
||||||
|
|
|
@ -571,21 +571,20 @@ var OC={
|
||||||
* @todo Write documentation
|
* @todo Write documentation
|
||||||
*/
|
*/
|
||||||
registerMenu: function($toggle, $menuEl) {
|
registerMenu: function($toggle, $menuEl) {
|
||||||
|
var self = this;
|
||||||
$menuEl.addClass('menu');
|
$menuEl.addClass('menu');
|
||||||
$toggle.on('click.menu', function(event) {
|
$toggle.on('click.menu', function(event) {
|
||||||
// prevent the link event (append anchor to URL)
|
// prevent the link event (append anchor to URL)
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
if ($menuEl.is(OC._currentMenu)) {
|
if ($menuEl.is(OC._currentMenu)) {
|
||||||
$menuEl.slideUp(OC.menuSpeed);
|
self.hideMenus();
|
||||||
OC._currentMenu = null;
|
|
||||||
OC._currentMenuToggle = null;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// another menu was open?
|
// another menu was open?
|
||||||
else if (OC._currentMenu) {
|
else if (OC._currentMenu) {
|
||||||
// close it
|
// close it
|
||||||
OC._currentMenu.hide();
|
self.hideMenus();
|
||||||
}
|
}
|
||||||
$menuEl.slideToggle(OC.menuSpeed);
|
$menuEl.slideToggle(OC.menuSpeed);
|
||||||
OC._currentMenu = $menuEl;
|
OC._currentMenu = $menuEl;
|
||||||
|
@ -599,14 +598,50 @@ var OC={
|
||||||
unregisterMenu: function($toggle, $menuEl) {
|
unregisterMenu: function($toggle, $menuEl) {
|
||||||
// close menu if opened
|
// close menu if opened
|
||||||
if ($menuEl.is(OC._currentMenu)) {
|
if ($menuEl.is(OC._currentMenu)) {
|
||||||
$menuEl.slideUp(OC.menuSpeed);
|
this.hideMenus();
|
||||||
OC._currentMenu = null;
|
|
||||||
OC._currentMenuToggle = null;
|
|
||||||
}
|
}
|
||||||
$toggle.off('click.menu').removeClass('menutoggle');
|
$toggle.off('click.menu').removeClass('menutoggle');
|
||||||
$menuEl.removeClass('menu');
|
$menuEl.removeClass('menu');
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides any open menus
|
||||||
|
*
|
||||||
|
* @param {Function} complete callback when the hiding animation is done
|
||||||
|
*/
|
||||||
|
hideMenus: function(complete) {
|
||||||
|
if (OC._currentMenu) {
|
||||||
|
OC._currentMenu.trigger(new $.Event('beforeHide'));
|
||||||
|
OC._currentMenu.slideUp(OC.menuSpeed, complete);
|
||||||
|
OC._currentMenu.trigger(new $.Event('afterHide'));
|
||||||
|
}
|
||||||
|
OC._currentMenu = null;
|
||||||
|
OC._currentMenuToggle = null;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows a given element as menu
|
||||||
|
*
|
||||||
|
* @param {Object} [$toggle=null] menu toggle
|
||||||
|
* @param {Object} $menuEl menu element
|
||||||
|
* @param {Function} complete callback when the showing animation is done
|
||||||
|
*/
|
||||||
|
showMenu: function($toggle, $menuEl, complete) {
|
||||||
|
if ($menuEl.is(OC._currentMenu)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.hideMenus();
|
||||||
|
OC._currentMenu = $menuEl;
|
||||||
|
OC._currentMenuToggle = $toggle;
|
||||||
|
$menuEl.trigger(new $.Event('beforeShow'));
|
||||||
|
$menuEl.show();
|
||||||
|
$menuEl.trigger(new $.Event('afterShow'));
|
||||||
|
// no animation
|
||||||
|
if (_.isFunction()) {
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper for matchMedia
|
* Wrapper for matchMedia
|
||||||
*
|
*
|
||||||
|
@ -1256,11 +1291,8 @@ function initCore() {
|
||||||
// don't close when clicking on the menu directly or a menu toggle
|
// don't close when clicking on the menu directly or a menu toggle
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (OC._currentMenu) {
|
|
||||||
OC._currentMenu.slideUp(OC.menuSpeed);
|
OC.hideMenus();
|
||||||
}
|
|
||||||
OC._currentMenu = null;
|
|
||||||
OC._currentMenuToggle = null;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue