/* * 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() { /** * Construct a new NewFileMenu instance * @constructs NewFileMenu * * @memberof OCA.Files */ var NewFileMenu = OC.Backbone.View.extend({ tagName: 'div', // Menu is opened by default because it's rendered on "add-button" click className: 'newFileMenu popovermenu bubble menu open menu-left', events: { 'click .menuitem': '_onClickAction' }, /** * @type OCA.Files.FileList */ fileList: null, 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: 'folder', displayName: t('files', 'New folder'), templateName: t('files', 'New folder'), iconClass: 'icon-folder', fileType: 'folder', actionLabel: t('files', 'Create new folder'), actionHandler: function(name) { self.fileList.createDirectory(name); } }]; OC.Plugins.attach('OCA.Files.NewFileMenu', this); }, template: function(data) { return OCA.Files.Templates['newfilemenu'](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 { var actionItem = _.filter(this._menuItems, function(item) { return item.id === action }).pop(); if (typeof actionItem.useInput === 'undefined' || actionItem.useInput === true) { event.preventDefault(); this.$el.find('.menuitem.active').removeClass('active'); $target.addClass('active'); this._promptFileName($target); } else { actionItem.actionHandler(); OC.hideMenus(); } } }, _promptFileName: function($target) { var self = this; if ($target.find('form').length) { $target.find('input[type=\'text\']').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 actionLabel = $target.attr('data-action-label'); var $form = $(OCA.Files.Templates['newfilemenu_filename_form']({ fileName: newName, cid: this.cid, fileType: fileType, actionLabel, })); //this.trigger('actionPerformed', action); $target.append($form); // here comes the OLD code var $input = $form.find('input[type=\'text\']'); var $submit = $form.find('input[type=\'submit\']'); var lastPos; var checkInput = function () { // Special handling for the setup template directory if ($target.attr('data-action') === 'template-init') { return true; } 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}, undefined, { escape: false }); } else { return true; } } catch (error) { $input.attr('title', error); $input.addClass('error'); } return false; }; // verify filename on typing $input.keyup(function() { if (checkInput()) { $input.removeClass('error'); } }); $submit.click(function(event) { event.stopPropagation(); event.preventDefault(); $form.submit(); }); $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().trim(); /* Find the right actionHandler that should be called. * Actions is retrieved by using `actionSpec.id` */ var 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 item’s properties */ addMenuEntry: function(actionSpec) { this._menuItems.push({ id: actionSpec.id, displayName: actionSpec.displayName, templateName: actionSpec.templateName, iconClass: actionSpec.iconClass, fileType: actionSpec.fileType, useInput: actionSpec.useInput, actionLabel: actionSpec.actionLabel, actionHandler: actionSpec.actionHandler, checkFilename: actionSpec.checkFilename, shouldShow: actionSpec.shouldShow, }); }, /** * Remove a menu item from the "New" file menu * @param {string} actionId */ removeMenuEntry: function(actionId) { var index = this._menuItems.findIndex(function (actionSpec) { return actionSpec.id === actionId; }); if (index > -1) { this._menuItems.splice(index, 1); } }, /** * Renders the menu with the currently set items */ render: function() { const menuItems = this._menuItems.filter(item => !item.shouldShow || (item.shouldShow instanceof Function && item.shouldShow() === true)) this.$el.html(this.template({ uploadMaxHumanFileSize: 'TODO', uploadLabel: t('files', 'Upload file'), items: menuItems })); // Trigger upload action also with keyboard navigation on enter this.$el.find('[for="file_upload_start"]').on('keyup', function(event) { if (event.key === " " || event.key === "Enter") { $('#file_upload_start').trigger('click'); } }); }, /** * Displays the menu under the given element * * @param {Object} $target target element */ showAt: function($target) { this.render(); OC.showMenu($target, this.$el); } }); OCA.Files.NewFileMenu = NewFileMenu; })();