summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2018-10-20 17:56:02 +0200
committerJo-Philipp Wich <jo@mein.io>2018-11-05 11:05:12 +0100
commit7c78218339ac914f097db79c343b07ea86c7313a (patch)
tree4607442d001a841964fbbedbb23a99bfbdfe7faa
parentbd614de514a7dd43a25f432dc1a9f9f66e7eec2b (diff)
luci-base, themes: rework dynlist and dropdown widgets
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r--modules/luci-base/htdocs/luci-static/resources/cbi.js418
-rw-r--r--themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css54
-rw-r--r--themes/luci-theme-material/htdocs/luci-static/material/cascade.css90
-rw-r--r--themes/luci-theme-openwrt/htdocs/luci-static/openwrt.org/cascade.css64
4 files changed, 337 insertions, 289 deletions
diff --git a/modules/luci-base/htdocs/luci-static/resources/cbi.js b/modules/luci-base/htdocs/luci-static/resources/cbi.js
index 2efa024859..3ace96f322 100644
--- a/modules/luci-base/htdocs/luci-static/resources/cbi.js
+++ b/modules/luci-base/htdocs/luci-static/resources/cbi.js
@@ -794,95 +794,41 @@ function cbi_init() {
cbi_d_update();
}
-function cbi_combobox(id, values, def, man, focus) {
- var selid = "cbi.combobox." + id;
- if (document.getElementById(selid)) {
- return
- }
-
- var obj = document.getElementById(id)
- var sel = document.createElement("select");
- sel.id = selid;
- sel.index = obj.index;
- sel.classList.remove('cbi-input-text');
- sel.classList.add('cbi-input-select');
-
- if (obj.nextSibling)
- obj.parentNode.insertBefore(sel, obj.nextSibling);
- else
- obj.parentNode.appendChild(sel);
-
- var dt = obj.getAttribute('cbi_datatype');
- var op = obj.getAttribute('cbi_optional');
-
- if (!values[obj.value]) {
- if (obj.value == "") {
- var optdef = document.createElement("option");
- optdef.value = "";
- optdef.appendChild(document.createTextNode(typeof(def) === 'string' ? def : _('-- Please choose --')));
- sel.appendChild(optdef);
- }
- else {
- var opt = document.createElement("option");
- opt.value = obj.value;
- opt.selected = "selected";
- opt.appendChild(document.createTextNode(obj.value));
- sel.appendChild(opt);
- }
+function cbi_combobox_init(id, values, def, man) {
+ var obj = (typeof(id) === 'string') ? document.getElementById(id) : id;
+ var sb = E('div', {
+ 'name': obj.name,
+ 'class': 'cbi-dropdown',
+ 'display-items': 5,
+ 'optional': obj.getAttribute('data-optional'),
+ 'placeholder': _('-- Please choose --')
+ }, [ E('ul') ]);
+
+ if (!(obj.value in values) && obj.value.length) {
+ sb.lastElementChild.appendChild(E('li', {
+ 'data-value': obj.value,
+ 'selected': ''
+ }, obj.value.length ? obj.value : (def || _('-- Please choose --'))));
}
for (var i in values) {
- var opt = document.createElement("option");
- opt.value = i;
-
- if (obj.value == i)
- opt.selected = "selected";
-
- opt.appendChild(document.createTextNode(values[i]));
- sel.appendChild(opt);
- }
-
- var optman = document.createElement("option");
- optman.value = "";
- optman.appendChild(document.createTextNode(typeof(man) === 'string' ? man : _('-- custom --')));
- sel.appendChild(optman);
-
- obj.style.display = "none";
-
- if (dt)
- cbi_validate_field(sel, op == 'true', dt);
-
- sel.addEventListener("change", function() {
- if (sel.selectedIndex == sel.options.length - 1) {
- obj.style.display = "inline";
- sel.blur();
- sel.parentNode.removeChild(sel);
- obj.focus();
- }
- else {
- obj.value = sel.options[sel.selectedIndex].value;
- }
-
- try {
- cbi_d_update();
- } catch (e) {
- //Do nothing
- }
- })
-
- // Retrigger validation in select
- if (focus) {
- sel.focus();
- sel.blur();
+ sb.lastElementChild.appendChild(E('li', {
+ 'data-value': i,
+ 'selected': (i == obj.value) ? '' : null
+ }, values[i]));
}
-}
-function cbi_combobox_init(id, values, def, man) {
- var obj = (typeof(id) === 'string') ? document.getElementById(id) : id;
- obj.addEventListener("blur", function() {
- cbi_combobox(obj.id, values, def, man, true);
- });
- cbi_combobox(obj.id, values, def, man, false);
+ sb.lastElementChild.appendChild(E('li', { 'data-value': '-' }, [
+ E('input', {
+ 'type': 'text',
+ 'class': 'create-item-input',
+ 'data-type': obj.getAttribute('data-type'),
+ 'data-optional': true,
+ 'placeholder': (man || _('-- custom --'))
+ })
+ ]));
+
+ obj.parentNode.replaceChild(sb, obj);
}
function cbi_filebrowser(id, defpath) {
@@ -912,229 +858,151 @@ function cbi_browser_init(id, resource, defpath)
btn.addEventListener('click', cbi_browser_btnclick);
}
-function cbi_dynlist_init(parent, datatype, optional, choices)
-{
- var prefix = parent.getAttribute('data-prefix');
- var holder = parent.getAttribute('data-placeholder');
-
- var values;
-
- function cbi_dynlist_redraw(focus, add, del)
- {
- values = [ ];
+CBIDynamicList = {
+ addItem: function(dl, value, text, flash) {
+ var exists = false,
+ new_item = E('div', { 'class': flash ? 'item flash' : 'item', 'tabindex': 0 }, [
+ E('span', {}, text || value),
+ E('input', {
+ 'type': 'hidden',
+ 'name': dl.getAttribute('data-prefix'),
+ 'value': value })]);
+
+ dl.querySelectorAll('.item, .add-item').forEach(function(item) {
+ if (exists)
+ return;
- while (parent.firstChild) {
- var n = parent.firstChild;
- var i = +n.index;
+ var hidden = item.querySelector('input[type="hidden"]');
- if (i != del) {
- if (matchesElem(n, 'input'))
- values.push(n.value || '');
- else if (matchesElem(n, 'select'))
- values[values.length-1] = n.options[n.selectedIndex].value;
- }
+ if (hidden && hidden.value === value)
+ exists = true;
+ else if (!hidden || hidden.value >= value)
+ exists = !!item.parentNode.insertBefore(new_item, item);
+ });
+ },
- parent.removeChild(n);
- }
+ removeItem: function(dl, item) {
+ var sb = dl.querySelector('.cbi-dropdown');
+ if (sb) {
+ var value = item.querySelector('input[type="hidden"]').value;
- if (add >= 0) {
- focus = add+1;
- values.splice(focus, 0, '');
- }
- else if (values.length == 0) {
- focus = 0;
- values.push('');
+ sb.querySelectorAll('ul > li').forEach(function(li) {
+ if (li.getAttribute('data-value') === value)
+ li.removeAttribute('unselectable');
+ });
}
- for (var i = 0; i < values.length; i++) {
- var t = document.createElement('input');
- t.id = prefix + '.' + (i+1);
- t.name = prefix;
- t.value = values[i];
- t.type = 'text';
- t.index = i;
- t.className = 'cbi-input-text';
-
- if (i == 0 && holder)
- t.placeholder = holder;
-
- var b = E('div', {
- class: 'cbi-button cbi-button-' + ((i+1) < values.length ? 'remove' : 'add')
- }, (i+1) < values.length ? '×' : '+');
-
- parent.appendChild(t);
- parent.appendChild(b);
-
- if (datatype == 'file')
- cbi_browser_init(t.id, null, parent.getAttribute('data-browser-path'));
-
- parent.appendChild(document.createElement('br'));
-
- if (datatype)
- cbi_validate_field(t.id, ((i+1) == values.length) || optional, datatype);
-
- if (choices) {
- cbi_combobox_init(t.id, choices, '', _('-- custom --'));
- b.index = i;
-
- b.addEventListener('keydown', cbi_dynlist_keydown);
- b.addEventListener('keypress', cbi_dynlist_keypress);
-
- if (i == focus || -i == focus)
- b.focus();
- }
- else {
- t.addEventListener('keydown', cbi_dynlist_keydown);
- t.addEventListener('keypress', cbi_dynlist_keypress);
-
- if (i == focus) {
- t.focus();
- }
- else if (-i == focus) {
- t.focus();
+ item.parentNode.removeChild(item);
+ },
- /* force cursor to end */
- var v = t.value;
- t.value = ' '
- t.value = v;
- }
- }
+ handleClick: function(ev) {
+ var dl = ev.currentTarget,
+ item = findParent(ev.target, '.item');
- b.addEventListener('click', cbi_dynlist_btnclick);
+ if (item) {
+ this.removeItem(dl, item);
}
- }
-
- function cbi_dynlist_keypress(ev)
- {
- ev = ev ? ev : window.event;
-
- var se = ev.target ? ev.target : ev.srcElement;
-
- if (se.nodeType == 3)
- se = se.parentNode;
-
- switch (ev.keyCode) {
- /* backspace, delete */
- case 8:
- case 46:
- if (se.value.length == 0) {
- if (ev.preventDefault)
- ev.preventDefault();
-
- return false;
- }
-
- return true;
-
- /* enter, arrow up, arrow down */
- case 13:
- case 38:
- case 40:
- if (ev.preventDefault)
- ev.preventDefault();
-
- return false;
+ else if (matchesElem(ev.target, '.cbi-button-add')) {
+ var input = ev.target.previousElementSibling;
+ if (input.value.length && !input.classList.contains('cbi-input-invalid')) {
+ this.addItem(dl, input.value, null, true);
+ input.value = '';
+ }
}
+ },
- return true;
- }
-
- function cbi_dynlist_keydown(ev)
- {
- ev = ev ? ev : window.event;
-
- var se = ev.target ? ev.target : ev.srcElement;
-
- if (se.nodeType == 3)
- se = se.parentNode;
-
- var prev = se.previousSibling;
- while (prev && prev.name != prefix)
- prev = prev.previousSibling;
-
- var next = se.nextSibling;
- while (next && next.name != prefix)
- next = next.nextSibling;
-
- /* advance one further in combobox case */
- if (next && next.nextSibling.name == prefix)
- next = next.nextSibling;
-
- switch (ev.keyCode) {
- /* backspace, delete */
- case 8:
- case 46:
- var del = (matchesElem(se, 'select'))
- ? true : (se.value.length == 0);
+ handleDropdownChange: function(ev) {
+ var dl = ev.currentTarget,
+ sbIn = ev.detail.instance,
+ sbEl = ev.detail.element,
+ sbVal = ev.detail.value;
- if (del) {
- if (ev.preventDefault)
- ev.preventDefault();
+ if (sbVal === null)
+ return;
- var focus = se.index;
- if (ev.keyCode == 8)
- focus = -focus+1;
+ sbIn.setValues(sbEl, null);
+ sbVal.element.setAttribute('unselectable', '');
- cbi_dynlist_redraw(focus, -1, se.index);
+ this.addItem(dl, sbVal.value, sbVal.text, true);
+ },
- return false;
- }
+ handleKeydown: function(ev) {
+ var dl = ev.currentTarget,
+ item = findParent(ev.target, '.item');
- break;
+ if (item) {
+ switch (ev.keyCode) {
+ case 8: /* backspace */
+ if (item.previousElementSibling)
+ item.previousElementSibling.focus();
- /* enter */
- case 13:
- cbi_dynlist_redraw(-1, se.index, -1);
+ this.removeItem(dl, item);
break;
- /* arrow up */
- case 38:
- if (prev)
- prev.focus();
+ case 46: /* delete */
+ if (item.nextElementSibling) {
+ if (item.nextElementSibling.classList.contains('item'))
+ item.nextElementSibling.focus();
+ else
+ item.nextElementSibling.firstElementChild.focus();
+ }
+ this.removeItem(dl, item);
break;
+ }
+ }
+ else if (matchesElem(ev.target, '.cbi-input-text')) {
+ switch (ev.keyCode) {
+ case 13: /* enter */
+ if (ev.target.value.length && !ev.target.classList.contains('cbi-input-invalid')) {
+ this.addItem(dl, ev.target.value, null, true);
+ ev.target.value = '';
+ ev.target.blur();
+ ev.target.focus();
+ }
- /* arrow down */
- case 40:
- if (next)
- next.focus();
-
+ ev.preventDefault();
break;
+ }
}
-
- return true;
}
+};
- function cbi_dynlist_btnclick(ev)
- {
- ev = ev ? ev : window.event;
+function cbi_dynlist_init(dl, datatype, optional, choices)
+{
+ if (!(this instanceof cbi_dynlist_init))
+ return new cbi_dynlist_init(dl, datatype, optional, choices);
+
+ dl.classList.add('cbi-dynlist');
+ dl.appendChild(E('div', { 'class': 'add-item' }, E('input', {
+ 'type': 'text',
+ 'name': 'cbi.dynlist.' + dl.getAttribute('data-prefix'),
+ 'class': 'cbi-input-text',
+ 'data-type': datatype,
+ 'data-optional': true
+ })));
+
+ if (choices)
+ cbi_combobox_init(dl.lastElementChild.lastElementChild, choices, '', _('-- custom --'));
+ else
+ dl.lastElementChild.appendChild(E('div', { 'class': 'cbi-button cbi-button-add' }, '+'));
- var se = ev.target ? ev.target : ev.srcElement;
- var input = se.previousSibling;
- while (input && input.name != prefix)
- input = input.previousSibling;
+ dl.addEventListener('click', this.handleClick.bind(this));
+ dl.addEventListener('keydown', this.handleKeydown.bind(this));
+ dl.addEventListener('cbi-dropdown-change', this.handleDropdownChange.bind(this));
- if (se.classList.contains('cbi-button-remove')) {
- input.value = '';
-
- cbi_dynlist_keydown({
- target: input,
- keyCode: 8
- });
- }
- else {
- cbi_dynlist_keydown({
- target: input,
- keyCode: 13
- });
- }
+ try {
+ var values = JSON.parse(dl.getAttribute('data-values') || '[]');
- return false;
+ if (typeof(values) === 'object' && Array.isArray(values))
+ for (var i = 0; i < values.length; i++)
+ this.addItem(dl, values[i], choices ? choices[values[i]] : null);
}
-
- cbi_dynlist_redraw(NaN, -1, -1);
+ catch (e) {}
}
+cbi_dynlist_init.prototype = CBIDynamicList;
+
function cbi_t_add(section, tab) {
var t = document.getElementById('tab.' + section + '.' + tab);
diff --git a/themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css b/themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css
index 67e19e7d07..73e6c3bed6 100644
--- a/themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css
+++ b/themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css
@@ -492,12 +492,47 @@ select,
box-sizing: border-box;
}
-.cbi-dropdown {
+.cbi-dropdown,
+.cbi-dynlist {
min-width: 210px;
max-width: 400px;
width: auto;
}
+.cbi-dynlist {
+ height: auto;
+ min-height: 30px;
+ display: inline-flex;
+ flex-direction: column;
+}
+
+.cbi-dynlist > .item {
+ margin-bottom: 4px;
+ box-shadow: 0 0 2px #ccc;
+ background: #fff;
+ padding: 2px 2em 2px 4px;
+ border: 1px solid #ccc;
+ border-radius: 3px;
+ position: relative;
+ pointer-events: none;
+}
+
+.cbi-dynlist > .item::after {
+ content: "×";
+ position: absolute;
+ display: inline-flex;
+ align-items: center;
+ top: -1px;
+ right: -1px;
+ bottom: -1px;
+ padding: 0 6px;
+ border: 1px solid #ccc;
+ border-radius: 0 3px 3px 0;
+ font-weight: bold;
+ color: #c44;
+ pointer-events: auto;
+}
+
select {
padding: initial;
background: #fff;
@@ -548,7 +583,8 @@ textarea {
.td > input[type=text],
.td > input[type=password],
.td > select,
-.td > .cbi-dropdown {
+.td > .cbi-dropdown,
+.cbi-dynlist > .add-item > .cbi-dropdown {
width: 100%;
}
@@ -568,11 +604,12 @@ textarea {
color: #bfbfbf;
}
-.btn, .cbi-button, input, textarea {
+.item::after, .btn, .cbi-button, input, textarea {
transition: border linear 0.2s, box-shadow linear 0.2s;
box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.1);
}
+.item:hover::after,
.btn:hover, .cbi-button:hover,
input:focus, textarea:focus {
outline: 0;
@@ -1206,6 +1243,7 @@ footer {
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
}
+.item::after,
.btn,
.cbi-button {
cursor: pointer;
@@ -1318,6 +1356,7 @@ footer {
color: #404040;
}
+.cbi-dynlist > .item:focus,
.cbi-dropdown:focus {
outline: 2px solid #4b6e9b;
}
@@ -1354,6 +1393,7 @@ footer {
font-weight: bold;
text-shadow: 1px 1px 0px #fff;
display: none;
+ justify-content: center;
}
.cbi-dropdown > ul > li {
@@ -1454,6 +1494,14 @@ footer {
border-bottom: none;
}
+.cbi-dropdown[open] > ul.dropdown > li[unselectable] {
+ opacity: 0.7;
+}
+
+.cbi-dropdown[open] > ul.dropdown > li > input.create-item-input:first-child:last-child {
+ width: 100%;
+}
+
.cbi-dropdown[disabled] {
pointer-events: none;
opacity: .6;
diff --git a/themes/luci-theme-material/htdocs/luci-static/material/cascade.css b/themes/luci-theme-material/htdocs/luci-static/material/cascade.css
index a4d71eeb67..e62c9be216 100644
--- a/themes/luci-theme-material/htdocs/luci-static/material/cascade.css
+++ b/themes/luci-theme-material/htdocs/luci-static/material/cascade.css
@@ -153,7 +153,9 @@ input,
}
select:not([multiple="multiple"]):focus,
-input:focus {
+input:focus,
+.cbi-dropdown:focus,
+.cbi-dynlist > .item:focus {
border-color: var(--main-color, #0099CC);
}
@@ -642,7 +644,7 @@ td > table > tbody > tr > td,
/* button style */
-.btn, .cbi-button {
+.btn, .cbi-button, .item::after {
-webkit-appearance: none;
text-transform: uppercase;
color: rgba(0, 0, 0, 0.87);
@@ -675,6 +677,7 @@ td > table > tbody > tr > td,
.cbi-button:hover,
.cbi-button:focus,
.cbi-button:active,
+.item:hover::after,
.cbi-page-actions .cbi-button-apply + .cbi-button-save:hover,
.cbi-page-actions .cbi-button-apply + .cbi-button-save:focus,
.cbi-page-actions .cbi-button-apply + .cbi-button-save:active {
@@ -958,6 +961,7 @@ td > table > tbody > tr > td,
}
+.cbi-dynlist,
.cbi-dropdown {
display: inline-flex;
cursor: pointer;
@@ -966,10 +970,6 @@ td > table > tbody > tr > td,
height: auto;
}
-.cbi-dropdown:focus {
- outline: 2px solid #4b6e9b;
-}
-
.cbi-dropdown > ul {
margin: 0 !important;
padding: 0;
@@ -1109,6 +1109,22 @@ td > table > tbody > tr > td,
border-bottom: none;
}
+.cbi-dropdown[open] > ul.dropdown > li[unselectable] {
+ opacity: 0.7;
+}
+
+.cbi-dropdown[open] > ul.dropdown > li > input.create-item-input:first-child:last-child {
+ width: 100%;
+}
+
+.cbi-dropdown[open] > ul.dropdown > li[unselectable] {
+ opacity: 0.7;
+}
+
+.cbi-dropdown[open] > ul.dropdown > li > input.create-item-input:first-child:last-child {
+ width: 100%;
+}
+
.cbi-dropdown[disabled] {
pointer-events: none;
opacity: .6;
@@ -1122,6 +1138,68 @@ td > table > tbody > tr > td,
width: auto;
}
+.cbi-dynlist {
+ height: auto;
+ min-height: 30px;
+ display: inline-flex;
+ flex-direction: column;
+}
+
+.cbi-dynlist > .item {
+ margin: 0 2em 4px 0;
+ padding: 2px 4px;
+ border-bottom: 2px solid rgba(0, 0, 0, .26);
+ position: relative;
+ pointer-events: none;
+ cursor: default;
+}
+
+.cbi-dynlist > .item::after {
+ content: "×";
+ position: absolute;
+ display: inline-flex;
+ align-items: center;
+ top: 0;
+ right: -2em;
+ bottom: 0;
+ padding: 0 6px;
+ border: 1px solid #c44;
+ font-weight: bold;
+ color: #c44;
+ pointer-events: auto;
+}
+
+.cbi-dynlist {
+ height: auto;
+ min-height: 30px;
+ display: inline-flex;
+ flex-direction: column;
+}
+
+.cbi-dynlist > .item {
+ margin: 0 2em 4px 0;
+ padding: 2px 4px;
+ border-bottom: 2px solid rgba(0, 0, 0, .26);
+ position: relative;
+ pointer-events: none;
+ cursor: default;
+}
+
+.cbi-dynlist > .item::after {
+ content: "×";
+ position: absolute;
+ display: inline-flex;
+ align-items: center;
+ top: 0;
+ right: -2em;
+ bottom: 0;
+ padding: 0 6px;
+ border: 1px solid #c44;
+ font-weight: bold;
+ color: #c44;
+ pointer-events: auto;
+}
+
/* luci */
diff --git a/themes/luci-theme-openwrt/htdocs/luci-static/openwrt.org/cascade.css b/themes/luci-theme-openwrt/htdocs/luci-static/openwrt.org/cascade.css
index 94d6b57296..e650aa55a9 100644
--- a/themes/luci-theme-openwrt/htdocs/luci-static/openwrt.org/cascade.css
+++ b/themes/luci-theme-openwrt/htdocs/luci-static/openwrt.org/cascade.css
@@ -516,7 +516,8 @@ input.cbi-input-password + img {
.td select,
.td .cbi-dropdown,
-.td input[type=text] {
+.td input[type=text],
+.cbi-dynlist > .add-item > .cbi-dropdown {
width: 100%;
}
@@ -531,7 +532,7 @@ img.cbi-image-button {
vertical-align: middle;
}
-.btn, .cbi-button {
+.btn, .cbi-button, .item::after {
padding: 0 .5em;
border-radius: 3px;
border: 1px solid #aaa;
@@ -545,9 +546,11 @@ img.cbi-image-button {
font-weight: bold;
line-height: 13pt;
height: 16pt;
+ box-sizing: border-box;
+ cursor: pointer;
}
-.btn:hover, .cbi-button:hover {
+.btn:hover, .cbi-button:hover, .item:hover::after {
box-shadow: 0 0 3px #37c;
}
@@ -1009,7 +1012,8 @@ ul.cbi-tabmenu li.cbi-tab {
background: #fff;
}
-.cbi-dropdown:focus {
+.cbi-dropdown:focus,
+.cbi-dynlist > .item:focus {
outline: 2px solid #4b6e9b;
}
@@ -1150,11 +1154,60 @@ ul.cbi-tabmenu li.cbi-tab {
border-bottom: none;
}
+.cbi-dropdown[open] > ul.dropdown > li[unselectable] {
+ opacity: 0.7;
+}
+
+.cbi-dropdown[open] > ul.dropdown > li > input.create-item-input:first-child:last-child {
+ width: 100%;
+}
+
.cbi-dropdown[disabled] {
pointer-events: none;
opacity: .6;
}
+.cbi-dynlist {
+ height: auto;
+ min-height: 30px;
+ min-width: 210px;
+ max-width: 100%;
+ width: auto;
+ display: inline-flex;
+ flex-direction: column;
+}
+
+.cbi-dynlist > .item {
+ margin-bottom: 4px;
+ background: #eee;
+ padding: 2px 2em 2px 4px;
+ border: 1px outset #000;
+ border-radius: 3px;
+ position: relative;
+ pointer-events: none;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.cbi-dynlist > .item::after {
+ content: "×";
+ position: absolute;
+ display: inline-flex;
+ align-items: center;
+ top: -1px;
+ right: -1px;
+ bottom: -1px;
+ padding: 0 6px;
+ border: 1px outset #000;
+ background: #fff;
+ border-radius: 0 3px 3px 0;
+ font-weight: bold;
+ color: #c44;
+ pointer-events: auto;
+ height: auto;
+}
+
input[type="text"] + .cbi-button,
input[type="password"] + .cbi-button,
select + .cbi-button {
@@ -1695,13 +1748,14 @@ select + .cbi-button {
height: 1.4em;
}
- [data-dynlist] > input,
input.cbi-input-password {
width: calc(100% - 20px);
}
+ .cbi-dynlist,
.cbi-dropdown {
min-width: 100%;
+ display: flex;
}
.btn, .cbi-button {