From b440eafb692354df18efac8f8e7e024d91ffde1b Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Mon, 30 Dec 2019 14:04:18 +0100 Subject: [PATCH] luci-base: ui.js: implement UIDropdown.{add,clear}Choices() The new `addChoices()` and `clearChoices()` functions allow clearing and adding new options to existing dropdown instances respectively. Signed-off-by: Jo-Philipp Wich (cherry picked from commit b0836b037e55bfc9201e60a9446f2f7800d7f195) --- .../htdocs/luci-static/resources/ui.js | 90 ++++++++++++++++--- 1 file changed, 77 insertions(+), 13 deletions(-) diff --git a/modules/luci-base/htdocs/luci-static/resources/ui.js b/modules/luci-base/htdocs/luci-static/resources/ui.js index e1a90373a..570fc2109 100644 --- a/modules/luci-base/htdocs/luci-static/resources/ui.js +++ b/modules/luci-base/htdocs/luci-static/resources/ui.js @@ -917,6 +917,33 @@ var UIDropdown = UIElement.extend({ } }, + createChoiceElement: function(sb, value, label) { + var tpl = sb.querySelector(this.options.create_template), + markup = null; + + if (tpl) + markup = (tpl.textContent || tpl.innerHTML || tpl.firstChild.data).replace(/^$/, '').trim(); + else + markup = '
  • '; + + var new_item = E(markup.replace(/{{value}}/g, '%h'.format(value))), + placeholder = new_item.querySelector('[data-label-placeholder]'); + + if (placeholder) { + var content = E('span', {}, label || this.choices[value] || [ value ]); + + while (content.firstChild) + placeholder.parentNode.insertBefore(content.firstChild, placeholder); + + placeholder.parentNode.removeChild(placeholder); + } + + if (this.options.multiple) + this.transformItem(sb, new_item); + + return new_item; + }, + createItems: function(sb, value) { var sbox = this, val = (value || '').trim(), @@ -936,20 +963,9 @@ var UIDropdown = UIElement.extend({ }); if (!new_item) { - var markup, - tpl = sb.querySelector(sbox.options.create_template); - - if (tpl) - markup = (tpl.textContent || tpl.innerHTML || tpl.firstChild.data).replace(/^$/, '').trim(); - else - markup = '
  • {{value}}
  • '; - - new_item = E(markup.replace(/{{value}}/g, '%h'.format(item))); + new_item = sbox.createChoiceElement(sb, item); - if (sbox.options.multiple) { - sbox.transformItem(sb, new_item); - } - else { + if (!sbox.options.multiple) { var old = ul.querySelector('li[created]'); if (old) ul.removeChild(old); @@ -965,6 +981,54 @@ var UIDropdown = UIElement.extend({ }); }, + clearChoices: function(reset_value) { + var ul = this.node.querySelector('ul'), + lis = ul ? ul.querySelectorAll('li[data-value]') : [], + len = lis.length - (this.options.create ? 1 : 0), + val = reset_value ? null : this.getValue(); + + for (var i = 0; i < len; i++) { + var lival = lis[i].getAttribute('data-value'); + if (val == null || + (!this.options.multiple && val != lival) || + (this.options.multiple && val.indexOf(lival) == -1)) + ul.removeChild(lis[i]); + } + + if (reset_value) + this.setValues(this.node, {}); + }, + + addChoices: function(values, labels) { + var sb = this.node, + ul = sb.querySelector('ul'), + lis = ul ? ul.querySelectorAll('li[data-value]') : []; + + if (!Array.isArray(values)) + values = L.toArray(values); + + if (!L.isObject(labels)) + labels = {}; + + for (var i = 0; i < values.length; i++) { + var found = false; + + for (var j = 0; j < lis.length; j++) { + if (lis[j].getAttribute('data-value') === values[i]) { + found = true; + break; + } + } + + if (found) + continue; + + ul.insertBefore( + this.createChoiceElement(sb, values[i], labels[values[i]]), + ul.lastElementChild); + } + }, + closeAllDropdowns: function() { document.querySelectorAll('.cbi-dropdown[open]').forEach(function(s) { s.dispatchEvent(new CustomEvent('cbi-dropdown-close', {})); -- 2.25.1