From: Jo-Philipp Wich Date: Thu, 8 Nov 2018 12:02:24 +0000 (+0100) Subject: luci-base, themes: dropdown behaviour improvements X-Git-Url: http://git.openwrt.org/?p=project%2Fluci.git;a=commitdiff_plain;h=4791180eb3253381b4bc69342ee58605a15431dd luci-base, themes: dropdown behaviour improvements Signed-off-by: Jo-Philipp Wich --- diff --git a/modules/luci-base/htdocs/luci-static/resources/cbi.js b/modules/luci-base/htdocs/luci-static/resources/cbi.js index 9c8341cc54..b3ba8259f9 100644 --- a/modules/luci-base/htdocs/luci-static/resources/cbi.js +++ b/modules/luci-base/htdocs/luci-static/resources/cbi.js @@ -1436,6 +1436,14 @@ if (window.NodeList && !NodeList.prototype.forEach) { }; } +if (!window.requestAnimationFrame) { + window.requestAnimationFrame = function(f) { + window.setTimeout(function() { + f(new Date().getTime()) + }, 1000/30); + }; +} + var dummyElem, domParser; @@ -1556,11 +1564,10 @@ CBIDropdown = { var st = window.getComputedStyle(sb, null), ul = sb.querySelector('ul'), li = ul.querySelectorAll('li'), + fl = findParent(sb, '.cbi-value-field'), sel = ul.querySelector('[selected]'), rect = sb.getBoundingClientRect(), - h = sb.clientHeight - parseFloat(st.paddingTop) - parseFloat(st.paddingBottom), - mh = this.dropdown_items * h, - eh = Math.min(mh, li.length * h); + items = Math.min(this.dropdown_items, li.length); document.querySelectorAll('.cbi-dropdown[open]').forEach(function(s) { s.dispatchEvent(new CustomEvent('cbi-dropdown-close', {})); @@ -1568,22 +1575,54 @@ CBIDropdown = { sb.setAttribute('open', ''); + var pv = ul.cloneNode(true); + pv.classList.add('preview'); + + if (fl) + fl.classList.add('cbi-dropdown-open'); + if ('ontouchstart' in window) { - var scroll = document.documentElement.scrollTop, - vpWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0), - vpHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0); + var vpWidth = Math.max(document.documentElement.clientWidth, window.innerWidth || 0), + vpHeight = Math.max(document.documentElement.clientHeight, window.innerHeight || 0), + scrollFrom = window.pageYOffset, + scrollTo = scrollFrom + rect.top - vpHeight * 0.5, + start = null; - ul.style.top = h + 'px'; + ul.style.top = sb.offsetHeight + 'px'; ul.style.left = -rect.left + 'px'; ul.style.right = (rect.right - vpWidth) + 'px'; + ul.style.maxHeight = (vpHeight * 0.5) + 'px'; + ul.style.WebkitOverflowScrolling = 'touch'; + + var scrollStep = function(timestamp) { + if (!start) { + start = timestamp; + ul.scrollTop = sel ? Math.max(sel.offsetTop - sel.offsetHeight, 0) : 0; + } + + var duration = Math.max(timestamp - start, 1); + if (duration < 100) { + document.body.scrollTop = scrollFrom + (scrollTo - scrollFrom) * (duration / 100); + window.requestAnimationFrame(scrollStep); + } + else { + document.body.scrollTop = scrollTo; + } + }; - window.scrollTo(0, (scroll + rect.top - vpHeight * 0.6)); + window.requestAnimationFrame(scrollStep); } else { - ul.style.maxHeight = mh + 'px'; - ul.scrollTop = sel ? Math.max(sel.offsetTop - sel.offsetHeight, 0) : 0; + ul.style.maxHeight = '1px'; ul.style.top = ul.style.bottom = ''; - ul.style[((rect.top + rect.height + eh) > window.innerHeight) ? 'bottom' : 'top'] = rect.height + 'px'; + + window.requestAnimationFrame(function() { + var height = items * li[Math.max(0, li.length - 2)].offsetHeight; + + ul.scrollTop = sel ? Math.max(sel.offsetTop - sel.offsetHeight, 0) : 0; + ul.style[((rect.top + rect.height + height) > window.innerHeight) ? 'bottom' : 'top'] = rect.height + 'px'; + ul.style.maxHeight = height + 'px'; + }); } ul.querySelectorAll('[selected] input[type="checkbox"]').forEach(function(c) { @@ -1592,10 +1631,6 @@ CBIDropdown = { ul.classList.add('dropdown'); - var pv = ul.cloneNode(true); - pv.classList.remove('dropdown'); - pv.classList.add('preview'); - sb.insertBefore(pv, ul.nextElementSibling); li.forEach(function(l) { @@ -1613,7 +1648,8 @@ CBIDropdown = { var pv = sb.querySelector('ul.preview'), ul = sb.querySelector('ul.dropdown'), - li = ul.querySelectorAll('li'); + li = ul.querySelectorAll('li'), + fl = findParent(sb, '.cbi-value-field'); li.forEach(function(l) { l.removeAttribute('tabindex'); }); sb.lastElementChild.removeAttribute('tabindex'); @@ -1623,6 +1659,10 @@ CBIDropdown = { sb.style.width = sb.style.height = ''; ul.classList.remove('dropdown'); + ul.style.top = ul.style.bottom = ul.style.maxHeight = ''; + + if (fl) + fl.classList.remove('cbi-dropdown-open'); if (!no_focus) this.setFocus(sb, sb); @@ -1817,14 +1857,13 @@ CBIDropdown = { createItems: function(sb, value) { var sbox = this, - val = (value || '').trim().split(/\s+/), + val = (value || '').trim(), ul = sb.querySelector('ul'); if (!sbox.multi) - val.length = Math.min(val.length, 1); - - if (val.length === 1 && val[0].length === 0) - val.length = 0; + val = val.length ? [ val ] : []; + else + val = val.length ? val.split(/\s+/) : []; val.forEach(function(item) { var new_item = null; @@ -1881,6 +1920,8 @@ CBIDropdown = { var li = findParent(ev.target, 'li'); if (li && li.parentNode.classList.contains('dropdown')) this.toggleItem(sb, li); + else if (li && li.parentNode.classList.contains('preview')) + this.closeDropdown(sb); } ev.preventDefault(); 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 22c49fdde1..e64744994e 100644 --- a/themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css +++ b/themes/luci-theme-bootstrap/htdocs/luci-static/bootstrap/cascade.css @@ -60,7 +60,6 @@ blockquote:after { } html { - overflow-y: scroll; font-size: 100%; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; @@ -1457,6 +1456,7 @@ footer { max-width: none; min-width: 100%; width: auto; + transition: max-height .125s ease-in; } .cbi-dropdown > ul > li[display], 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 f24493c993..a88d678f6d 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 @@ -491,16 +491,16 @@ select:hover { input[type=text], input[type=password] { - padding: 0 3px; + padding: .25em; } select, input[type=text], -input[type=password] { +input[type=password], +.cbi-dropdown { width: 20em; - font-size: inherit; - line-height: 13pt; - height: 14pt; + font-size: 10pt; + height: 22px; } select[multiple] { @@ -521,7 +521,6 @@ input.cbi-input-password + img { width: 100%; } -.td [data-dynlist] > input, .td input.cbi-input-password { width: calc(100% - 20px); } @@ -1050,6 +1049,7 @@ ul.cbi-tabmenu li.cbi-tab { font-weight: bold; text-shadow: 1px 1px 0px #fff; display: none; + min-height: 22px; } .cbi-dropdown > ul > li { @@ -1062,7 +1062,7 @@ ul.cbi-tabmenu li.cbi-tab { flex-grow: 1; align-items: center; align-self: center; - min-height: 20px; + min-height: 22px; } .cbi-dropdown > ul > li .hide-open { display: initial; } @@ -1092,10 +1092,6 @@ ul.cbi-tabmenu li.cbi-tab { margin: 0; } -.cbi-dropdown > ul > li input[type="text"] { - height: 20px; -} - .cbi-dropdown[open] { position: relative; } @@ -1110,6 +1106,7 @@ ul.cbi-tabmenu li.cbi-tab { max-width: none; min-width: 100%; width: auto; + transition: max-height .125s ease-in; } .cbi-dropdown > ul > li[display], @@ -1125,7 +1122,6 @@ ul.cbi-tabmenu li.cbi-tab { } .cbi-dropdown[empty] > ul > li, -.cbi-dropdown[optional][open] > ul.dropdown > li[placeholder], .cbi-dropdown[multiple][open] > ul.dropdown > li > form { display: block; } @@ -1213,9 +1209,9 @@ select + .cbi-button { padding: 0 6px; vertical-align: top; display: inline-block; - height: 14pt; + height: 22px; font-size: 10pt; - line-height: 12pt; + line-height: 20px; } .cbi-tooltip-container { @@ -1240,6 +1236,7 @@ select + .cbi-button { left: auto; opacity: 1; transition: opacity .25s ease-in; + white-space: normal; } .zonebadge .cbi-tooltip { @@ -1652,6 +1649,10 @@ select + .cbi-button { display: inline-block; } + .td.cbi-dropdown-open { + overflow: visible; + } + .td select { word-wrap: normal; } @@ -1734,26 +1735,41 @@ select + .cbi-button { font-size: 12pt; } - input, textarea, select { + input, textarea, select, .cbi-button { font-size: 12pt !important; - line-height: 1.4em; + line-height: 30px; } select, input[type="text"], input[type="password"] { width: 100%; - height: 1.4em; + height: 30px; } - input.cbi-input-password { + input[type="text"] + .cbi-button, + input[type="password"] + .cbi-button, + select + .cbi-button { + height: 30px; + line-height: 28px; + } + + input.cbi-input-password, + [data-dynlist] > .add-item > input { width: calc(100% - 20px); } .cbi-dynlist, .cbi-dropdown { min-width: 100%; + height: auto; display: flex; } + .cbi-dropdown > .more, + .cbi-dropdown > ul > li, + .cbi-dropdown > ul > li[placeholder] { + min-height: 30px; + } + .btn, .cbi-button { font-size: 9pt !important; line-height: 13pt;