summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-base/htdocs/luci-static
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2024-02-18 23:25:55 +0100
committerJo-Philipp Wich <jo@mein.io>2024-02-19 00:04:16 +0100
commit3980c192cda6985c2e2d2608e74677cf236005db (patch)
treed256483ce8967129ea2089d04808bfa3f4e3500b /modules/luci-base/htdocs/luci-static
parent01e55108889563563231e111f8fe1d4bf9b1b853 (diff)
luci-base: ui.js: rework dropdown focus behavior
Drop mouse following focus behavior as it interferes with custom value inputs, rely on CSS based hover effects instead. Also slightly improve keyboard navigation by auto-focussing the custom value input when entering the last dropdown choice via arrow down or tab key, and by allowing to leave the text input again with the arrow up key. Fixes: #6903 Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'modules/luci-base/htdocs/luci-static')
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/ui.js53
1 files changed, 20 insertions, 33 deletions
diff --git a/modules/luci-base/htdocs/luci-static/resources/ui.js b/modules/luci-base/htdocs/luci-static/resources/ui.js
index df66f2bb1d..9470130998 100644
--- a/modules/luci-base/htdocs/luci-static/resources/ui.js
+++ b/modules/luci-base/htdocs/luci-static/resources/ui.js
@@ -1187,8 +1187,6 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
window.addEventListener('touchstart', this.closeAllDropdowns);
}
else {
- sb.addEventListener('mouseover', this.handleMouseover.bind(this));
- sb.addEventListener('mouseout', this.handleMouseout.bind(this));
sb.addEventListener('focus', this.handleFocus.bind(this));
canary.addEventListener('focus', this.handleCanaryFocus.bind(this));
@@ -1340,7 +1338,8 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
sb.insertBefore(pv, ul.nextElementSibling);
li.forEach(function(l) {
- l.setAttribute('tabindex', 0);
+ if (!l.hasAttribute('unselectable'))
+ l.setAttribute('tabindex', 0);
});
sb.lastElementChild.setAttribute('tabindex', 0);
@@ -1582,20 +1581,6 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
},
/** @private */
- handleMouseout: function(ev) {
- var sb = ev.currentTarget;
-
- if (!sb.hasAttribute('open'))
- return;
-
- sb.querySelectorAll('.focus').forEach(function(e) {
- e.classList.remove('focus');
- });
-
- sb.querySelector('ul.dropdown').focus();
- },
-
- /** @private */
createChoiceElement: function(sb, value, label) {
var tpl = sb.querySelector(this.options.create_template),
markup = null;
@@ -1826,7 +1811,12 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
case 40:
if (active && active.nextElementSibling) {
- this.setFocus(sb, active.nextElementSibling);
+ var li = active.nextElementSibling;
+ this.setFocus(sb, li);
+ if (this.options.create && li == li.parentNode.lastElementChild) {
+ var input = li.querySelector('input');
+ if (input) input.focus();
+ }
ev.preventDefault();
}
else if (document.activeElement === ul) {
@@ -1858,19 +1848,6 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
},
/** @private */
- handleMouseover: function(ev) {
- var sb = ev.currentTarget;
-
- if (!sb.hasAttribute('open'))
- return;
-
- var li = findParent(ev.target, 'li');
-
- if (li && li.parentNode.classList.contains('dropdown'))
- this.setFocus(sb, li);
- },
-
- /** @private */
handleFocus: function(ev) {
var sb = ev.currentTarget;
@@ -1888,7 +1865,8 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
/** @private */
handleCreateKeydown: function(ev) {
var input = ev.currentTarget,
- sb = findParent(input, '.cbi-dropdown');
+ li = findParent(input, 'li'),
+ sb = findParent(li, '.cbi-dropdown');
switch (ev.keyCode) {
case 13:
@@ -1901,19 +1879,28 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
input.value = '';
input.blur();
break;
+
+ case 38:
+ if (li.previousElementSibling) {
+ this.handleCreateBlur(ev);
+ this.setFocus(sb, li.previousElementSibling, true);
+ }
+ break;
}
},
/** @private */
handleCreateFocus: function(ev) {
var input = ev.currentTarget,
- cbox = findParent(input, 'li').querySelector('input[type="checkbox"]'),
+ li = findParent(input, 'li'),
+ cbox = li.querySelector('input[type="checkbox"]'),
sb = findParent(input, '.cbi-dropdown');
if (cbox)
cbox.checked = true;
sb.setAttribute('locked-in', '');
+ this.setFocus(sb, li, true);
},
/** @private */