luci-base: ui.js: rework password input handling

- Get rid of dummy element
 - Render password field as text input initially and later transform
   it to a password field
 - Use .control-group markup to allow better styling

Signed-off-by: Jo-Philipp Wich <jo@mein.io>
This commit is contained in:
Jo-Philipp Wich 2020-04-28 23:34:33 +02:00
parent 34c06b4704
commit d02c26772b

View file

@ -310,32 +310,22 @@ var UITextfield = UIElement.extend(/** @lends LuCI.ui.Textfield.prototype */ {
/** @override */ /** @override */
render: function() { render: function() {
var frameEl = E('div', { 'id': this.options.id }); var frameEl = E('div', { 'id': this.options.id });
var inputEl = E('input', {
if (this.options.password) {
frameEl.classList.add('nowrap');
frameEl.appendChild(E('input', {
'type': 'password',
'style': 'position:absolute; left:-100000px',
'aria-hidden': true,
'tabindex': -1,
'name': this.options.name ? 'password.%s'.format(this.options.name) : null
}));
}
frameEl.appendChild(E('input', {
'id': this.options.id ? 'widget.' + this.options.id : null, 'id': this.options.id ? 'widget.' + this.options.id : null,
'name': this.options.name, 'name': this.options.name,
'type': this.options.password ? 'password' : 'text', 'type': 'text',
'class': this.options.password ? 'cbi-input-password' : 'cbi-input-text', 'class': this.options.password ? 'cbi-input-password' : 'cbi-input-text',
'readonly': this.options.readonly ? '' : null, 'readonly': this.options.readonly ? '' : null,
'disabled': this.options.disabled ? '' : null, 'disabled': this.options.disabled ? '' : null,
'maxlength': this.options.maxlength, 'maxlength': this.options.maxlength,
'placeholder': this.options.placeholder, 'placeholder': this.options.placeholder,
'value': this.value, 'value': this.value,
})); });
if (this.options.password) if (this.options.password) {
frameEl.appendChild(E('button', { frameEl.appendChild(E('div', { 'class': 'control-group' }, [
inputEl,
E('button', {
'class': 'cbi-button cbi-button-neutral', 'class': 'cbi-button cbi-button-neutral',
'title': _('Reveal/hide password'), 'title': _('Reveal/hide password'),
'aria-label': _('Reveal/hide password'), 'aria-label': _('Reveal/hide password'),
@ -344,14 +334,21 @@ var UITextfield = UIElement.extend(/** @lends LuCI.ui.Textfield.prototype */ {
e.type = (e.type === 'password') ? 'text' : 'password'; e.type = (e.type === 'password') ? 'text' : 'password';
ev.preventDefault(); ev.preventDefault();
} }
}, '')); }, '')
]));
window.requestAnimationFrame(function() { inputEl.type = 'password' });
}
else {
frameEl.appendChild(inputEl);
}
return this.bind(frameEl); return this.bind(frameEl);
}, },
/** @private */ /** @private */
bind: function(frameEl) { bind: function(frameEl) {
var inputEl = frameEl.childNodes[+!!this.options.password]; var inputEl = frameEl.querySelector('input');
this.node = frameEl; this.node = frameEl;
@ -365,7 +362,7 @@ var UITextfield = UIElement.extend(/** @lends LuCI.ui.Textfield.prototype */ {
/** @override */ /** @override */
getValue: function() { getValue: function() {
var inputEl = this.node.childNodes[+!!this.options.password]; var inputEl = this.node.querySelector('input');
return inputEl.value; return inputEl.value;
}, },