summaryrefslogtreecommitdiffhomepage
path: root/modules/luci-base/htdocs/luci-static/resources
diff options
context:
space:
mode:
Diffstat (limited to 'modules/luci-base/htdocs/luci-static/resources')
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/form.js15
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/ui.js84
2 files changed, 76 insertions, 23 deletions
diff --git a/modules/luci-base/htdocs/luci-static/resources/form.js b/modules/luci-base/htdocs/luci-static/resources/form.js
index 3c538b88ca..317b49fdfe 100644
--- a/modules/luci-base/htdocs/luci-static/resources/form.js
+++ b/modules/luci-base/htdocs/luci-static/resources/form.js
@@ -281,7 +281,7 @@ var CBIAbstractElement = baseclass.extend(/** @lends LuCI.form.AbstractElement.p
* The input string to clean.
*
* @returns {string}
- * The cleaned input string with HTML removes removed.
+ * The cleaned input string with HTML tags removed.
*/
stripTags: function(s) {
if (typeof(s) == 'string' && !s.match(/[<>]/))
@@ -3211,8 +3211,17 @@ var CBITableSection = CBITypedSection.extend(/** @lends LuCI.form.TableSection.p
return (stackedMap ? activeMap.save(null, true) : Promise.resolve()).then(L.bind(function() {
section_id = sref['.name'];
- var m = new CBIMap(parent.config, null, null),
- s = m.section(CBINamedSection, section_id, this.sectiontype);
+ var m;
+
+ if (parent instanceof CBIJSONMap) {
+ m = new CBIJSONMap(null, null, null);
+ m.data = parent.data;
+ }
+ else {
+ m = new CBIMap(parent.config, null, null);
+ }
+
+ var s = m.section(CBINamedSection, section_id, this.sectiontype);
m.parent = parent;
m.section = section_id;
diff --git a/modules/luci-base/htdocs/luci-static/resources/ui.js b/modules/luci-base/htdocs/luci-static/resources/ui.js
index c7b7ccd773..51b6c0902d 100644
--- a/modules/luci-base/htdocs/luci-static/resources/ui.js
+++ b/modules/luci-base/htdocs/luci-static/resources/ui.js
@@ -1050,7 +1050,8 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
'class': 'cbi-dropdown',
'multiple': this.options.multiple ? '' : null,
'optional': this.options.optional ? '' : null,
- 'disabled': this.options.disabled ? '' : null
+ 'disabled': this.options.disabled ? '' : null,
+ 'tabindex': -1
}, E('ul'));
var keys = Object.keys(this.choices);
@@ -1186,11 +1187,11 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
}
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));
- window.addEventListener('mouseover', this.setFocus);
window.addEventListener('click', this.closeAllDropdowns);
}
@@ -1343,7 +1344,12 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
sb.lastElementChild.setAttribute('tabindex', 0);
- this.setFocus(sb, sel || li[0], true);
+ var focusFn = L.bind(function(el) {
+ this.setFocus(sb, el, true);
+ ul.removeEventListener('transitionend', focusFn);
+ }, this, sel || li[0]);
+
+ ul.addEventListener('transitionend', focusFn);
},
/** @private */
@@ -1559,26 +1565,33 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
/** @private */
setFocus: function(sb, elem, scroll) {
- if (sb && sb.hasAttribute && sb.hasAttribute('locked-in'))
+ if (sb.hasAttribute('locked-in'))
return;
- if (sb.target && findParent(sb.target, 'ul.dropdown'))
+ sb.querySelectorAll('.focus').forEach(function(e) {
+ e.classList.remove('focus');
+ });
+
+ elem.classList.add('focus');
+
+ if (scroll)
+ elem.parentNode.scrollTop = elem.offsetTop - elem.parentNode.offsetTop;
+
+ elem.focus();
+ },
+
+ /** @private */
+ handleMouseout: function(ev) {
+ var sb = ev.currentTarget;
+
+ if (!sb.hasAttribute('open'))
return;
- document.querySelectorAll('.focus').forEach(function(e) {
- if (!matchesElem(e, 'input')) {
- e.classList.remove('focus');
- e.blur();
- }
+ sb.querySelectorAll('.focus').forEach(function(e) {
+ e.classList.remove('focus');
});
- if (elem) {
- elem.focus();
- elem.classList.add('focus');
-
- if (scroll)
- elem.parentNode.scrollTop = elem.offsetTop - elem.parentNode.offsetTop;
- }
+ sb.querySelector('ul.dropdown').focus();
},
/** @private */
@@ -1758,7 +1771,8 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
/** @private */
handleKeydown: function(ev) {
- var sb = ev.currentTarget;
+ var sb = ev.currentTarget,
+ ul = sb.querySelector('ul.dropdown');
if (matchesElem(ev.target, 'input'))
return;
@@ -1779,6 +1793,7 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
switch (ev.keyCode) {
case 27:
this.closeDropdown(sb);
+ ev.stopPropagation();
break;
case 13:
@@ -1802,6 +1817,10 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
this.setFocus(sb, active.previousElementSibling);
ev.preventDefault();
}
+ else if (document.activeElement === ul) {
+ this.setFocus(sb, ul.lastElementChild);
+ ev.preventDefault();
+ }
break;
case 40:
@@ -1809,6 +1828,10 @@ var UIDropdown = UIElement.extend(/** @lends LuCI.ui.Dropdown.prototype */ {
this.setFocus(sb, active.nextElementSibling);
ev.preventDefault();
}
+ else if (document.activeElement === ul) {
+ this.setFocus(sb, ul.firstElementChild);
+ ev.preventDefault();
+ }
break;
}
}
@@ -3463,8 +3486,17 @@ var UITable = baseclass.extend(/** @lends LuCI.ui.table.prototype */ {
var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
__init__: function() {
modalDiv = document.body.appendChild(
- dom.create('div', { id: 'modal_overlay' },
- dom.create('div', { class: 'modal', role: 'dialog', 'aria-modal': true })));
+ dom.create('div', {
+ id: 'modal_overlay',
+ tabindex: -1,
+ keydown: this.cancelModal
+ }, [
+ dom.create('div', {
+ class: 'modal',
+ role: 'dialog',
+ 'aria-modal': true
+ })
+ ]));
tooltipDiv = document.body.appendChild(
dom.create('div', { class: 'cbi-tooltip' }));
@@ -3528,6 +3560,7 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
document.body.classList.add('modal-overlay-active');
modalDiv.scrollTop = 0;
+ modalDiv.focus();
return dlg;
},
@@ -3544,6 +3577,17 @@ var UI = baseclass.extend(/** @lends LuCI.ui.prototype */ {
*/
hideModal: function() {
document.body.classList.remove('modal-overlay-active');
+ modalDiv.blur();
+ },
+
+ /** @private */
+ cancelModal: function(ev) {
+ if (ev.key == 'Escape') {
+ var btn = modalDiv.querySelector('.right > button, .right > .btn');
+
+ if (btn)
+ btn.click();
+ }
},
/** @private */