AutorÃa | Ultima modificación | Ver Log |
// This file is part of Moodle - http://moodle.org///// Moodle is free software: you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation, either version 3 of the License, or// (at your option) any later version.//// Moodle is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with Moodle. If not, see <http://www.gnu.org/licenses/>./*** This module allows to enhance the form elements MoodleQuickForm_filetypes** @module core_form/filetypes* @copyright 2017 David Mudrak <david@moodle.com>* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later* @since 3.3*/define(['jquery', 'core/log', 'core/modal_events', 'core/modal_save_cancel', 'core/ajax','core/templates', 'core/tree'],function($, Log, ModalEvents, ModalSaveCancel, Ajax, Templates, Tree) {"use strict";/*** Constructor of the FileTypes instances.** @constructor* @param {String} elementId The id of the form element to enhance* @param {String} elementLabel The label of the form element used as the modal selector title* @param {String} onlyTypes Limit the list of offered types to this* @param {Bool} allowAll Allow presence of the "All file types" item*/var FileTypes = function(elementId, elementLabel, onlyTypes, allowAll) {this.elementId = elementId;this.elementLabel = elementLabel;this.onlyTypes = onlyTypes;this.allowAll = allowAll;this.inputField = $('#' + elementId);this.wrapperBrowserTrigger = $('[data-filetypesbrowser="' + elementId + '"]');this.wrapperDescriptions = $('[data-filetypesdescriptions="' + elementId + '"]');if (!this.wrapperBrowserTrigger.length) {// This is a valid case. Most probably the element is frozen and// the filetypes browser should not be available.return;}if (!this.inputField.length || !this.wrapperDescriptions.length) {Log.error('core_form/filetypes: Unexpected DOM structure, unable to enhance filetypes field ' + elementId);return;}this.prepareBrowserTrigger().then(function() {return this.prepareBrowserModal();}.bind(this)).then(function() {return this.prepareBrowserTree();}.bind(this));};/*** Create and set the browser trigger widget (this.browserTrigger).** @method prepareBrowserTrigger* @returns {Promise}*/FileTypes.prototype.prepareBrowserTrigger = function() {return Templates.render('core_form/filetypes-trigger', {}).then(function(html) {this.wrapperBrowserTrigger.html(html);this.browserTrigger = this.wrapperBrowserTrigger.find('[data-filetypeswidget="browsertrigger"]');}.bind(this));};/*** Create and set the modal for displaying the browser (this.browserModal).** @method prepareBrowserModal* @returns {Promise}*/FileTypes.prototype.prepareBrowserModal = function() {return ModalSaveCancel.create({title: this.elementLabel,}).then(function(modal) {this.browserModal = modal;return modal;}.bind(this)).then(function() {// Because we have custom conditional modal trigger, we need to// handle the focus after closing ourselves, too.this.browserModal.getRoot().on(ModalEvents.hidden, function() {this.browserTrigger.focus();}.bind(this));this.browserModal.getRoot().on(ModalEvents.save, function() {this.saveBrowserModal();}.bind(this));}.bind(this));};/*** Create and set the tree in the browser modal's body.** @method prepareBrowserTree* @returns {Promise}*/FileTypes.prototype.prepareBrowserTree = function() {this.browserTrigger.on('click', function(e) {e.preventDefault();// We want to display the browser modal only when the associated input// field is not frozen (disabled).if (this.inputField.is('[disabled]')) {return;}var bodyContent = this.loadBrowserModalBody();bodyContent.then(function() {// Turn the list of groups and extensions into the tree.this.browserTree = new Tree(this.browserModal.getBody());// Override the behaviour of the Enter and Space keys to toggle our checkbox,// rather than toggle the tree node expansion status.this.browserTree.handleKeyDown = function(item, e) {if (e.keyCode == this.browserTree.keys.enter || e.keyCode == this.browserTree.keys.space) {e.preventDefault();e.stopPropagation();this.toggleCheckbox(item.attr('data-filetypesbrowserkey'));} else {Tree.prototype.handleKeyDown.call(this.browserTree, item, e);}}.bind(this);if (this.allowAll) {// Hide all other items if "All file types" is enabled.this.hideOrShowItemsDependingOnAllowAll(this.browserModal.getRoot().find('input[type="checkbox"][data-filetypesbrowserkey="*"]').first());// And do the same whenever we click that checkbox.this.browserModal.getRoot().on('change', 'input[type="checkbox"][data-filetypesbrowserkey="*"]', function(e) {this.hideOrShowItemsDependingOnAllowAll($(e.currentTarget));}.bind(this));}// Synchronize checked status if the file extension is present in multiple groups.this.browserModal.getRoot().on('change', 'input[type="checkbox"][data-filetypesbrowserkey]', function(e) {var checkbox = $(e.currentTarget);var key = checkbox.attr('data-filetypesbrowserkey');this.browserModal.getRoot().find('input[type="checkbox"][data-filetypesbrowserkey="' + key + '"]').prop('checked', checkbox.prop('checked'));}.bind(this));}.bind(this)).then(function() {this.browserModal.show();}.bind(this));this.browserModal.setBody(bodyContent);}.bind(this));// Return a resolved promise.return $.when();};/*** Load the browser modal body contents.** @returns {Promise}*/FileTypes.prototype.loadBrowserModalBody = function() {var args = {onlytypes: this.onlyTypes.join(),allowall: this.allowAll,current: this.inputField.val()};return Ajax.call([{methodname: 'core_form_get_filetypes_browser_data',args: args}])[0].then(function(browserData) {return Templates.render('core_form/filetypes-browser', {elementid: this.elementId,groups: browserData.groups});}.bind(this));};/*** Change the checked status of the given file type (group or extension).** @method toggleCheckbox* @param {String} key*/FileTypes.prototype.toggleCheckbox = function(key) {var checkbox = this.browserModal.getRoot().find('input[type="checkbox"][data-filetypesbrowserkey="' + key + '"]').first();checkbox.prop('checked', !checkbox.prop('checked'));};/*** Update the associated input field with selected file types.** @method saveBrowserModal*/FileTypes.prototype.saveBrowserModal = function() {// Check the "All file types" first.if (this.allowAll) {var allcheckbox = this.browserModal.getRoot().find('input[type="checkbox"][data-filetypesbrowserkey="*"]');if (allcheckbox.length && allcheckbox.prop('checked')) {this.inputField.val('*');this.updateDescriptions(['*']);return;}}// Iterate over all checked boxes and populate the list.var newvalue = [];this.browserModal.getRoot().find('input[type="checkbox"]').each(/** @this represents the checkbox */ function() {var checkbox = $(this);var key = checkbox.attr('data-filetypesbrowserkey');if (checkbox.prop('checked')) {newvalue.push(key);}});// Remove duplicates (e.g. file types present in multiple groups).newvalue = newvalue.filter(function(x, i, a) {return a.indexOf(x) == i;});this.inputField.val(newvalue.join(' '));this.updateDescriptions(newvalue);};/*** Describe the selected filetypes in the form when saving the browser.** @param {Array} keys List of keys to describe* @returns {Promise}*/FileTypes.prototype.updateDescriptions = function(keys) {var descriptions = [];keys.forEach(function(key) {descriptions.push({description: this.browserModal.getRoot().find('[data-filetypesname="' + key + '"]').first().text().trim(),extensions: this.browserModal.getRoot().find('[data-filetypesextensions="' + key + '"]').first().text().trim()});}.bind(this));var templatedata = {hasdescriptions: (descriptions.length > 0),descriptions: descriptions};return Templates.render('core_form/filetypes-descriptions', templatedata).then(function(html) {this.wrapperDescriptions.html(html);}.bind(this));};/*** If "All file types" is checked, all other browser items are made hidden, and vice versa.** @param {jQuery} allcheckbox The "All file types" checkbox.*/FileTypes.prototype.hideOrShowItemsDependingOnAllowAll = function(allcheckbox) {var others = this.browserModal.getRoot().find('[role="treeitem"][data-filetypesbrowserkey!="*"]');if (allcheckbox.prop('checked')) {others.hide();} else {others.show();}};return {init: function(elementId, elementLabel, onlyTypes, allowAll) {new FileTypes(elementId, elementLabel, onlyTypes, allowAll);}};});