Skip to content

Commit

Permalink
luci: Make password reveal work with passsword managers
Browse files Browse the repository at this point in the history
Password managers (like LastPass etc) tend to add additional elements
into the DOM for their own context menus. If this happens between the
hide/reveal button and the password input, then the logic to reveal the
password breaks.

This change updates the onclick handler to look backward in the DOM for
the first sibling that is an input, and to then toggle the password/text
type on that element.

Signed-off-by: Andrew Dodd <andrew.john.dodd@gmail.com>
  • Loading branch information
andrewdodd committed Jan 13, 2025
1 parent 2520588 commit f294ee0
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,6 @@
ifattr(#self.keylist > 0, "data-choices", { self.keylist, self.vallist })
%> />
<%- if self.password then -%>
<div class="btn cbi-button cbi-button-neutral" title="<%:Reveal/hide password%>" onclick="var e = this.previousElementSibling; e.type = (e.type === 'password') ? 'text' : 'password'"></div>
<div class="btn cbi-button cbi-button-neutral" title="<%:Reveal/hide password%>" onclick="var e = this.previousElementSibling; while (e && e.tagName !== 'INPUT') { e = e.previousElementSibling; }; e.type = (e.type === 'password') ? 'text' : 'password'"></div>
<% end %>
</div>
14 changes: 12 additions & 2 deletions modules/luci-base/htdocs/luci-static/resources/ui.js
Original file line number Diff line number Diff line change
Expand Up @@ -384,8 +384,18 @@ const UITextfield = UIElement.extend(/** @lends LuCI.ui.Textfield.prototype */ {
'title': _('Reveal/hide password'),
'aria-label': _('Reveal/hide password'),
'click': function(ev) {
const e = this.previousElementSibling;
e.type = (e.type === 'password') ? 'text' : 'password';
let e = this.previousElementSibling;
// DOM manipulation (e.g. by password managers) may have inserted other
// elements between the reveal button and the input. This searches for
// the first previous sibling that is also an input.
while (e && e.tagName !== 'INPUT') {
e = e.previousElementSibling;
}
if (e) {
e.type = (e.type === 'password') ? 'text' : 'password';
} else {
console.error("unable to find input corresponding to reveal/hide button");
}
ev.preventDefault();
}
}, '∗')
Expand Down

0 comments on commit f294ee0

Please sign in to comment.