server/apps/files/js/newfilemenu.js
Olivier Tétard d386168504 Allow apps to add new items in the “New” filemenu.
Owncloud apps can now add new items to the “new” file menu. A new
`addMenuEntry()` was added to `NewFileMenu`. To add a new item, you
have to attach a plugin to `OCA.Files.NewFileMenu` that will call
`addMenuEntry()`.
2015-10-26 15:03:27 +01:00

253 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* Copyright (c) 2014
*
* This file is licensed under the Affero General Public License version 3
* or later.
*
* See the COPYING-README file.
*
*/
/* global Files */
(function() {
var TEMPLATE_MENU =
'<ul>' +
'<li>' +
'<label for="file_upload_start" class="menuitem" data-action="upload" title="{{uploadMaxHumanFilesize}}"><span class="svg icon icon-upload"></span><span class="displayname">{{uploadLabel}}</span></label>' +
'</li>' +
'{{#each items}}' +
'<li>' +
'<a href="#" class="menuitem" data-templatename="{{templateName}}" data-filetype="{{fileType}}" data-action="{{id}}"><span class="icon {{iconClass}} svg"></span><span class="displayname">{{displayName}}</span></a>' +
'</li>' +
'{{/each}}' +
'</ul>';
var TEMPLATE_FILENAME_FORM =
'<form class="filenameform">' +
'<label class="hidden-visually" for="{{cid}}-input-{{fileType}}">{{fileName}}</label>' +
'<input id="{{cid}}-input-{{fileType}}" type="text" value="{{fileName}}">' +
'</form>';
/**
* Construct a new NewFileMenu instance
* @constructs NewFileMenu
*
* @memberof OCA.Files
*/
var NewFileMenu = OC.Backbone.View.extend({
tagName: 'div',
className: 'newFileMenu popovermenu bubble hidden open menu',
events: {
'click .menuitem': '_onClickAction'
},
initialize: function(options) {
var self = this;
var $uploadEl = $('#file_upload_start');
if ($uploadEl.length) {
$uploadEl.on('fileuploadstart', function() {
self.trigger('actionPerformed', 'upload');
});
} else {
console.warn('Missing upload element "file_upload_start"');
}
this._fileList = options && options.fileList;
this._menuItems = [{
id: 'file',
displayName: t('files', 'Text file'),
templateName: t('files', 'New text file.txt'),
iconClass: 'icon-filetype-text',
fileType: 'file',
actionHandler: function(name) {
self._fileList.createFile(name);
}
}, {
id: 'folder',
displayName: t('files', 'Folder'),
templateName: t('files', 'New folder'),
iconClass: 'icon-folder',
fileType: 'folder',
actionHandler: function(name) {
self._fileList.createDirectory(name);
}
}];
OC.Plugins.attach('OCA.Files.NewFileMenu', this);
},
template: function(data) {
if (!OCA.Files.NewFileMenu._TEMPLATE) {
OCA.Files.NewFileMenu._TEMPLATE = Handlebars.compile(TEMPLATE_MENU);
}
return OCA.Files.NewFileMenu._TEMPLATE(data);
},
/**
* 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.hasClass('menuitem')) {
$target = $target.closest('.menuitem');
}
var action = $target.attr('data-action');
// note: clicking the upload label will automatically
// set the focus on the "file_upload_start" hidden field
// which itself triggers the upload dialog.
// Currently the upload logic is still in file-upload.js and filelist.js
if (action === 'upload') {
OC.hideMenus();
} else {
event.preventDefault();
this.$el.find('.menuitem.active').removeClass('active');
$target.addClass('active');
this._promptFileName($target);
}
},
_promptFileName: function($target) {
var self = this;
if (!OCA.Files.NewFileMenu._TEMPLATE_FORM) {
OCA.Files.NewFileMenu._TEMPLATE_FORM = Handlebars.compile(TEMPLATE_FILENAME_FORM);
}
if ($target.find('form').length) {
$target.find('input').focus();
return;
}
// discard other forms
this.$el.find('form').remove();
this.$el.find('.displayname').removeClass('hidden');
$target.find('.displayname').addClass('hidden');
var newName = $target.attr('data-templatename');
var fileType = $target.attr('data-filetype');
var $form = $(OCA.Files.NewFileMenu._TEMPLATE_FORM({
fileName: newName,
cid: this.cid,
fileType: fileType
}));
//this.trigger('actionPerformed', action);
$target.append($form);
// here comes the OLD code
var $input = $form.find('input');
var lastPos;
var checkInput = function () {
var filename = $input.val();
try {
if (!Files.isFileNameValid(filename)) {
// Files.isFileNameValid(filename) throws an exception itself
} else if (self._fileList.inList(filename)) {
throw t('files', '{newname} already exists', {newname: filename});
} else {
return true;
}
} catch (error) {
$input.attr('title', error);
$input.tooltip({placement: 'right', trigger: 'manual'});
$input.tooltip('show');
$input.addClass('error');
}
return false;
};
// verify filename on typing
$input.keyup(function() {
if (checkInput()) {
$input.tooltip('hide');
$input.removeClass('error');
}
});
$input.focus();
// pre select name up to the extension
lastPos = newName.lastIndexOf('.');
if (lastPos === -1) {
lastPos = newName.length;
}
$input.selectRange(0, lastPos);
$form.submit(function(event) {
event.stopPropagation();
event.preventDefault();
if (checkInput()) {
var newname = $input.val();
/* Find the right actionHandler that should be called.
* Actions is retrieved by using `actionSpec.id` */
action = _.filter(self._menuItems, function(item) {
return item.id == $target.attr('data-action');
}).pop();
action.actionHandler(newname);
$form.remove();
$target.find('.displayname').removeClass('hidden');
OC.hideMenus();
}
});
},
/**
* Add a new item menu entry in the “New” file menu (in
* last position). By clicking on the item, the
* `actionHandler` function is called.
*
* @param {Object} actionSpec items properties
*/
addMenuEntry: function(actionSpec) {
this._menuItems.push({
id: actionSpec.id,
displayName: actionSpec.displayName,
templateName: actionSpec.templateName,
iconClass: actionSpec.iconClass,
fileType: actionSpec.fileType,
actionHandler: actionSpec.actionHandler,
});
},
/**
* Renders the menu with the currently set items
*/
render: function() {
this.$el.html(this.template({
uploadMaxHumanFileSize: 'TODO',
uploadLabel: t('files', 'Upload'),
items: this._menuItems
}));
OC.Util.scaleFixForIE8(this.$('.svg'));
},
/**
* Displays the menu under the given element
*
* @param {Object} $target target element
*/
showAt: function($target) {
this.render();
var targetOffset = $target.offset();
this.$el.css({
left: targetOffset.left,
top: targetOffset.top + $target.height()
});
this.$el.removeClass('hidden');
OC.showMenu(null, this.$el);
}
});
OCA.Files.NewFileMenu = NewFileMenu;
})();