Proyectos de Subversion Moodle

Rev

Autoría | Ultima modificación | Ver Log |

{"version":3,"file":"passwordunmask.min.js","sources":["../src/passwordunmask.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Password Unmask functionality.\n *\n * @module     core_form/passwordunmask\n * @copyright  2016 Andrew Nicols <andrew@nicols.co.uk>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since      3.2\n */\ndefine(['jquery', 'core/templates'], function($, Template) {\n\n    /**\n     * Constructor for PasswordUnmask.\n     *\n     * @class core_form/passwordunmask\n     * @param   {String}    elementid   The element to apply the PasswordUnmask to\n     */\n    var PasswordUnmask = function(elementid) {\n        // Setup variables.\n        this.wrapperSelector = '[data-passwordunmask=\"wrapper\"][data-passwordunmaskid=\"' + elementid + '\"]';\n        this.wrapper = $(this.wrapperSelector);\n        this.editorSpace = this.wrapper.find('[data-passwordunmask=\"editor\"]');\n        this.editLink = this.wrapper.find('a[data-passwordunmask=\"edit\"]');\n        this.editInstructions = this.wrapper.find('[data-passwordunmask=\"instructions\"]');\n        this.displayValue = this.wrapper.find('[data-passwordunmask=\"displayvalue\"]');\n        this.inputFieldLabel = $('label[for=\"' + elementid + '\"]');\n\n        this.inputField = this.editorSpace.find(document.getElementById(elementid));\n        // Hide the field.\n        this.inputField.addClass('d-none');\n        this.inputField.removeClass('hiddenifjs');\n\n        if (!this.editInstructions.attr('id')) {\n            this.editInstructions.attr('id', elementid + '_instructions');\n        }\n        this.editInstructions.hide();\n\n        this.setDisplayValue();\n\n        // Add the listeners.\n        this.addListeners();\n    };\n\n    /**\n     * Add the event listeners required for PasswordUnmask.\n     *\n     * @method  addListeners\n     * @return  {PasswordUnmask}\n     * @chainable\n     */\n    PasswordUnmask.prototype.addListeners = function() {\n        this.wrapper.on('click keypress', '[data-passwordunmask=\"edit\"]', $.proxy(function(e) {\n            if (e.type === 'keypress' && e.keyCode !== 13) {\n                return;\n            }\n            e.stopImmediatePropagation();\n            e.preventDefault();\n\n            if (this.isEditing()) {\n                // Only focus on the edit link if the event was not a click, and the new target is not an input field.\n                if (e.type !== 'click' && !$(e.relatedTarget).is(':input')) {\n                    this.turnEditingOff(true);\n                } else {\n                    this.turnEditingOff(false);\n                }\n            } else {\n                this.turnEditingOn();\n            }\n        }, this));\n\n        this.wrapper.on('click keypress', '[data-passwordunmask=\"unmask\"]', $.proxy(function(e) {\n            if (e.type === 'keypress' && e.keyCode !== 13) {\n                return;\n            }\n            e.stopImmediatePropagation();\n            e.preventDefault();\n\n            // Toggle the data attribute.\n            this.wrapper.data('unmasked', !this.wrapper.data('unmasked'));\n\n            this.setDisplayValue();\n        }, this));\n\n        this.wrapper.on('keydown', 'input', $.proxy(function(e) {\n            if (e.type === 'keydown' && e.keyCode !== 13) {\n                return;\n            }\n\n            e.stopImmediatePropagation();\n            e.preventDefault();\n\n            this.turnEditingOff(true);\n        }, this));\n\n        this.inputFieldLabel.on('click', $.proxy(function(e) {\n            e.preventDefault();\n\n            this.turnEditingOn();\n        }, this));\n\n        return this;\n    };\n\n    /**\n     * Check whether focus was lost from the PasswordUnmask and turn editing off if required.\n     *\n     * @method  checkFocusOut\n     * @param   {EventFacade}   e       The EventFacade generating the suspsected Focus Out\n     */\n    PasswordUnmask.prototype.checkFocusOut = function(e) {\n        if (!this.isEditing()) {\n            // Ignore - not editing.\n            return;\n        }\n\n        window.setTimeout($.proxy(function() {\n            // Firefox does not have the focusout event. Instead jQuery falls back to the 'blur' event.\n            // The blur event does not have a relatedTarget, so instead we use a timeout and the new activeElement.\n            var relatedTarget = e.relatedTarget || document.activeElement;\n            if (this.wrapper.has($(relatedTarget)).length) {\n                // Ignore, some part of the element is still active.\n                return;\n            }\n\n            // Only focus on the edit link if the new related target is not an input field or anchor.\n            this.turnEditingOff(!$(relatedTarget).is(':input,a'));\n        }, this), 100);\n    };\n\n    /**\n     * Whether the password is currently visible (unmasked).\n     *\n     * @method  passwordVisible\n     * @return  {Boolean}            True if the password is unmasked\n     */\n    PasswordUnmask.prototype.passwordVisible = function() {\n        return !!this.wrapper.data('unmasked');\n    };\n\n    /**\n     * Whether the user is currently editing the field.\n     *\n     * @method  isEditing\n     * @return  {Boolean}            True if edit mode is enabled\n     */\n    PasswordUnmask.prototype.isEditing = function() {\n        return this.inputField.hasClass('d-inline-block');\n    };\n\n    /**\n     * Enable the editing functionality.\n     *\n     * @method  turnEditingOn\n     * @return  {PasswordUnmask}\n     * @chainable\n     */\n    PasswordUnmask.prototype.turnEditingOn = function() {\n        var value = this.getDisplayValue();\n        if (this.passwordVisible()) {\n            this.inputField.attr('type', 'text');\n        } else {\n            this.inputField.attr('type', 'password');\n        }\n        this.inputField.val(value);\n        this.inputField.attr('size', this.inputField.attr('data-size'));\n        // Show the field.\n        this.inputField.addClass('d-inline-block');\n\n        if (this.editInstructions.length) {\n            this.inputField.attr('aria-describedby', this.editInstructions.attr('id'));\n            this.editInstructions.show();\n        }\n\n        this.wrapper.attr('data-passwordunmask-visible', 1);\n\n        this.editLink.hide();\n        this.inputField\n            .focus()\n            .select();\n\n        // Note, this cannot be added as a delegated listener on init because Firefox does not support the FocusOut\n        // event (https://bugzilla.mozilla.org/show_bug.cgi?id=687787) and the blur event does not identify the\n        // relatedTarget.\n        // The act of focusing the this.inputField means that in Firefox the focusout will be triggered on blur of the edit\n        // link anchor.\n        $('body').on('focusout', this.wrapperSelector, $.proxy(this.checkFocusOut, this));\n\n        return this;\n    };\n\n    /**\n     * Disable the editing functionality, optionally focusing on the edit link.\n     *\n     * @method  turnEditingOff\n     * @param   {Boolean}       focusOnEditLink     Whether to focus on the edit link after disabling the editor\n     * @return  {PasswordUnmask}\n     * @chainable\n     */\n    PasswordUnmask.prototype.turnEditingOff = function(focusOnEditLink) {\n        $('body').off('focusout', this.wrapperSelector, this.checkFocusOut);\n        var value = this.getDisplayValue();\n        this.inputField\n            // Ensure that the aria-describedby is removed.\n            .attr('aria-describedby', null);\n        this.inputField.val(value);\n        // Hide the field again.\n        this.inputField.removeClass('d-inline-block');\n\n        this.editInstructions.hide();\n\n        // Remove the visible attr.\n        this.wrapper.removeAttr('data-passwordunmask-visible');\n\n        // Remove the size attr.\n        this.inputField.removeAttr('size');\n\n        this.editLink.show();\n        this.setDisplayValue();\n\n        if (focusOnEditLink) {\n            this.editLink.focus();\n        }\n\n        return this;\n    };\n\n    /**\n     * Get the currently value.\n     *\n     * @method  getDisplayValue\n     * @return  {String}\n     */\n    PasswordUnmask.prototype.getDisplayValue = function() {\n        return this.inputField.val();\n    };\n\n    /**\n     * Set the currently value in the display, taking into account the current settings.\n     *\n     * @method  setDisplayValue\n     * @return  {PasswordUnmask}\n     * @chainable\n     */\n    PasswordUnmask.prototype.setDisplayValue = function() {\n        var value = this.getDisplayValue();\n        if (this.isEditing()) {\n            if (this.wrapper.data('unmasked')) {\n                this.inputField.attr('type', 'text');\n            } else {\n                this.inputField.attr('type', 'password');\n            }\n            this.inputField.val(value);\n        }\n\n        // Update the display value.\n        // Note: This must always be updated.\n        // The unmask value can be changed whilst editing and the editing can then be disabled.\n        if (value && this.wrapper.data('unmasked')) {\n            // There is a value, and we will show it.\n            this.displayValue.text(value);\n        } else {\n            if (!value) {\n                value = \"\";\n            }\n            // There is a value, but it will be disguised.\n            // We use the passwordunmask-fill to allow modification of the fill and to ensure that the display does not\n            // change as the page loads the JS.\n            Template.render('core_form/element-passwordunmask-fill', {\n                element: {\n                    frozen:     this.inputField.is('[readonly]'),\n                    value:      value,\n                    valuechars: value.split(''),\n                },\n            }).done($.proxy(function(html, js) {\n                this.displayValue.html(html);\n\n                Template.runTemplateJS(js);\n            }, this));\n        }\n\n        return this;\n    };\n\n    return PasswordUnmask;\n});\n"],"names":["define","$","Template","PasswordUnmask","elementid","wrapperSelector","wrapper","this","editorSpace","find","editLink","editInstructions","displayValue","inputFieldLabel","inputField","document","getElementById","addClass","removeClass","attr","hide","setDisplayValue","addListeners","prototype","on","proxy","e","type","keyCode","stopImmediatePropagation","preventDefault","isEditing","relatedTarget","is","turnEditingOff","turnEditingOn","data","checkFocusOut","window","setTimeout","activeElement","has","length","passwordVisible","hasClass","value","getDisplayValue","val","show","focus","select","focusOnEditLink","off","removeAttr","text","render","element","frozen","valuechars","split","done","html","js","runTemplateJS"],"mappings":"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"}