Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
// This file is part of Moodle - http://moodle.org/
2
//
3
// Moodle is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, either version 3 of the License, or
6
// (at your option) any later version.
7
//
8
// Moodle is distributed in the hope that it will be useful,
9
// but WITHOUT ANY WARRANTY; without even the implied warranty of
10
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
// GNU General Public License for more details.
12
//
13
// You should have received a copy of the GNU General Public License
14
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
15
 
16
/**
17
 * JS module for toggling the sensitive input visibility (e.g. passwords, keys).
18
 *
19
 * @module     core/togglesensitive
20
 * @copyright  2023 David Woloszyn <david.woloszyn@moodle.com>
21
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22
 */
23
 
24
import {isExtraSmall} from 'core/pagehelpers';
25
import Templates from 'core/templates';
26
import Pending from 'core/pending';
27
import Prefetch from 'core/prefetch';
28
import Notification from 'core/notification';
29
import {notifyFieldStructureChanged} from 'core_form/events';
30
 
31
const SELECTORS = {
32
    BUTTON: '.toggle-sensitive-btn',
33
    ICON: '.toggle-sensitive-btn .icon',
34
};
35
 
36
const PIX = {
37
    EYE: 't/hide',
38
    EYE_SLASH: 't/show',
39
};
40
 
41
let sensitiveElementId;
42
let smallScreensOnly;
43
 
44
/**
45
 * Entrypoint of the js.
46
 *
47
 * @method init
48
 * @param {String} elementId Form button element.
49
 * @param {boolean} isSmallScreensOnly Is this for small screens only?
50
 */
51
export const init = (elementId, isSmallScreensOnly = false) => {
52
    const sensitiveInput = document.getElementById(elementId);
53
    if (sensitiveInput === null) {
54
        // Exit early if invalid element id passed.
55
        return;
56
    }
57
    sensitiveElementId = elementId;
58
    smallScreensOnly = isSmallScreensOnly;
59
    Prefetch.prefetchTemplate('core/form_input_toggle_sensitive');
60
    // Render the sensitive input with a toggle button.
61
    renderSensitiveToggle(sensitiveInput);
62
    // Register event listeners.
63
    registerListenerEvents();
64
};
65
 
66
/**
67
 * Render the new input html with toggle button and update the incoming html.
68
 *
69
 * @method renderSensitiveToggle
70
 * @param {HTMLElement} sensitiveInput HTML element for the sensitive input.
71
 */
72
const renderSensitiveToggle = (sensitiveInput) => {
73
    Templates.render(
74
        'core/form_input_toggle_sensitive',
75
        {
76
            smallscreensonly: smallScreensOnly,
77
            sensitiveinput: sensitiveInput.outerHTML,
78
        }
79
    ).then((html) => {
80
        sensitiveInput.outerHTML = html;
81
        // Dispatch the event indicating the sensitive input has changed.
82
        notifyFieldStructureChanged(sensitiveInput.id);
83
        return;
84
    }).catch(Notification.exception);
85
};
86
 
87
/**
88
 * Register event listeners.
89
 *
90
 * @method registerListenerEvents
91
 */
92
const registerListenerEvents = () => {
93
    // Toggle the sensitive input visibility when interacting with the toggle button.
94
    document.addEventListener('click', handleButtonInteraction);
95
    // For small screens only, hide all sensitive inputs when the screen is enlarged.
96
    if (smallScreensOnly) {
97
        window.addEventListener('resize', handleScreenResizing);
98
    }
99
};
100
 
101
/**
102
 * Handle events trigger by interacting with the toggle button.
103
 *
104
 * @method handleButtonInteraction
105
 * @param {Event} event The button event.
106
 */
107
const handleButtonInteraction = (event) => {
108
    const toggleButton = event.target.closest(SELECTORS.BUTTON);
109
    if (toggleButton) {
110
        const sensitiveInput = document.getElementById(sensitiveElementId);
111
        if (sensitiveInput) {
112
            toggleSensitiveVisibility(sensitiveInput, toggleButton);
113
        }
114
    }
115
};
116
 
117
/**
118
 * Handle events trigger by resizing the screen.
119
 *
120
 * @method handleScreenResizing
121
 */
122
const handleScreenResizing = () => {
123
    if (!isExtraSmall()) {
124
        const sensitiveInput = document.getElementById(sensitiveElementId);
125
        if (sensitiveInput) {
126
            const toggleButton = sensitiveInput.parentNode.querySelector(SELECTORS.BUTTON);
127
            if (toggleButton) {
128
                toggleSensitiveVisibility(sensitiveInput, toggleButton, true);
129
            }
130
        }
131
    }
132
};
133
 
134
/**
135
 * Toggle the sensitive input visibility and its associated icon.
136
 *
137
 * @method toggleSensitiveVisibility
138
 * @param {HTMLInputElement} sensitiveInput The sensitive input element.
139
 * @param {HTMLElement} toggleButton The toggle button.
140
 * @param {boolean} force Force the input back to password type.
141
 */
142
const toggleSensitiveVisibility = (sensitiveInput, toggleButton, force = false) => {
143
    const pendingPromise = new Pending('core/togglesensitive:toggle');
144
    let type;
145
    let icon;
146
    if (force === true) {
147
        type = 'password';
148
        icon = PIX.EYE;
149
    } else {
150
        type = sensitiveInput.getAttribute('type') === 'password' ? 'text' : 'password';
151
        icon = sensitiveInput.getAttribute('type') === 'password' ? PIX.EYE_SLASH : PIX.EYE;
152
    }
153
    sensitiveInput.setAttribute('type', type);
154
    Templates.renderPix(icon, 'core').then((icon) => {
155
        toggleButton.innerHTML = icon;
156
        pendingPromise.resolve();
157
        return;
158
    }).catch(Notification.exception);
159
};