diff --git a/src/_h5ai/public/css/lib/ext/info.less b/src/_h5ai/public/css/lib/ext/info.less index 82f4d919..d21e3870 100644 --- a/src/_h5ai/public/css/lib/ext/info.less +++ b/src/_h5ai/public/css/lib/ext/info.less @@ -1,6 +1,4 @@ #info { - display: none; - overflow: auto; flex: 0 0 auto; order: 99; diff --git a/src/_h5ai/public/css/lib/ext/tree.less b/src/_h5ai/public/css/lib/ext/tree.less index 0b203d31..1f190950 100644 --- a/src/_h5ai/public/css/lib/ext/tree.less +++ b/src/_h5ai/public/css/lib/ext/tree.less @@ -1,6 +1,4 @@ #tree { - display: none; - overflow: auto; flex: 0 0 auto; order: 1; diff --git a/src/_h5ai/public/js/lib/ext/download.js b/src/_h5ai/public/js/lib/ext/download.js index 0f014d96..331c35af 100644 --- a/src/_h5ai/public/js/lib/ext/download.js +++ b/src/_h5ai/public/js/lib/ext/download.js @@ -1,5 +1,4 @@ -const {each} = require('../util'); -const {jq} = require('../globals'); +const {each, dom} = require('../util'); const server = require('../server'); const event = require('../core/event'); const location = require('../core/location'); @@ -20,16 +19,16 @@ let selectedItems = []; let $download; -function onSelection(items) { +const onSelection = items => { selectedItems = items.slice(0); if (selectedItems.length) { $download.show(); } else if (!settings.alwaysVisible) { $download.hide(); } -} +}; -function onClick() { +const onClick = () => { const type = settings.type; let name = settings.packageName; const extension = type === 'shell-zip' ? 'zip' : 'tar'; @@ -54,16 +53,16 @@ function onClick() { }); server.formRequest(query); -} +}; -function init() { +const init = () => { if (!settings.enabled) { return; } - $download = jq(template) + $download = dom(template) .hide() - .appendTo('#toolbar') + .appTo('#toolbar') .on('click', onClick); if (settings.alwaysVisible) { @@ -71,7 +70,7 @@ function init() { } event.sub('selection', onSelection); -} +}; init(); diff --git a/src/_h5ai/public/js/lib/ext/info.js b/src/_h5ai/public/js/lib/ext/info.js index 164db3a3..af58ad41 100644 --- a/src/_h5ai/public/js/lib/ext/info.js +++ b/src/_h5ai/public/js/lib/ext/info.js @@ -1,5 +1,5 @@ -const {isNum} = require('../util'); -const {win, jq, kjua} = require('../globals'); +const {isNum, dom} = require('../util'); +const {win, kjua} = require('../globals'); const event = require('../core/event'); const format = require('../core/format'); const resource = require('../core/resource'); @@ -17,12 +17,12 @@ const template = `
-
-
-
+
+
+
- , - + , +
@@ -46,19 +46,19 @@ let $qrcode; let currentFolder; -function updateSettings() { +const updateSettings = () => { if (store.get(storekey)) { - jq('#view-info').addClass('active'); - jq('#info').show(); + dom('#view-info').addCls('active'); + dom('#info').show(); } else { - jq('#view-info').removeClass('active'); - jq('#info').hide(); + dom('#view-info').rmCls('active'); + dom('#info').hide(); } -} +}; -function update(item) { +const update = item => { let src = item.thumbRational || item.icon; - const isThumb = Boolean(item.thumbRational); + const isThumb = !!item.thumbRational; if (item.isCurrentFolder() || !src) { src = resource.icon('folder'); @@ -66,9 +66,9 @@ function update(item) { $img.attr('src', src); if (isThumb) { - $img.addClass('thumb'); + $img.addCls('thumb'); } else { - $img.removeClass('thumb'); + $img.rmCls('thumb'); } $label.text(item.label); @@ -96,7 +96,7 @@ function update(item) { if (settings.qrcode) { const loc = win.location; - $qrcode.empty().append(kjua({ + $qrcode.clr().app(kjua({ render: 'image', size: 200, fill: settings.qrFill, @@ -106,27 +106,27 @@ function update(item) { quiet: 1 })); } -} +}; -function onMouseenter(item) { +const onMouseenter = item => { update(item); -} +}; -function onMouseleave() { +const onMouseleave = () => { update(currentFolder); -} +}; -function onLocationChanged(item) { +const onLocationChanged = item => { currentFolder = item; update(currentFolder); -} +}; -function init() { +const init = () => { if (!settings.enabled) { return; } - const $info = jq(template).appendTo('#mainrow'); + const $info = dom(template).hide().appTo('#mainrow'); $img = $info.find('.icon img'); $label = $info.find('.label'); $time = $info.find('.time'); @@ -137,11 +137,11 @@ function init() { $qrcode = $info.find('.qrcode'); if (!settings.qrcode) { - $qrcode.remove(); + $qrcode.rm(); } - jq(settingsTemplate) - .appendTo('#sidebar') + dom(settingsTemplate) + .appTo('#sidebar') .find('#view-info') .on('click', ev => { store.put(storekey, !store.get(storekey)); @@ -158,7 +158,7 @@ function init() { event.sub('location.changed', onLocationChanged); event.sub('item.mouseenter', onMouseenter); event.sub('item.mouseleave', onMouseleave); -} +}; init(); diff --git a/src/_h5ai/public/js/lib/ext/l10n.js b/src/_h5ai/public/js/lib/ext/l10n.js index d5ee514f..89db01ee 100644 --- a/src/_h5ai/public/js/lib/ext/l10n.js +++ b/src/_h5ai/public/js/lib/ext/l10n.js @@ -1,5 +1,5 @@ -const {each, isStr} = require('../util'); -const {win, jq} = require('../globals'); +const {each, isStr, dom} = require('../util'); +const {win} = require('../globals'); const server = require('../server'); const event = require('../core/event'); const format = require('../core/format'); @@ -55,20 +55,18 @@ const update = lang => { currentLang = lang; } - jq('#langs option') - .removeAttr('selected').removeProp('selected') - .filter('.' + currentLang.isoCode) - .attr('selected', 'selected').prop('selected', 'selected'); + const sel = 'selected'; + dom('#langs option').rmAttr(sel).rmProp(sel); + dom('#langs .' + currentLang.isoCode).attr(sel, sel).prop(sel, sel); each(currentLang, (value, key) => { - jq('.l10n-' + key).text(value); - jq('.l10n_ph-' + key).attr('placeholder', value); + dom('.l10n-' + key).text(value); + dom('.l10n_ph-' + key).attr('placeholder', value); }); format.setDefaultDateFormat(currentLang.dateFormat); - jq('#items .item .date').each((idx, el) => { - const $el = jq(el); - $el.text(format.formatDate($el.data('time'))); + dom('#items .item').each(el => { + dom(el).find('.date').text(format.formatDate(el._item.time)); }); }; @@ -108,7 +106,7 @@ const localize = (languages, isoCode, useBrowserLang) => { }; const initLangSelector = languages => { - const $block = jq(blockTemplate); + const $block = dom(blockTemplate); const $select = $block.find('select') .on('change', ev => { const isoCode = ev.target.value; @@ -117,14 +115,14 @@ const initLangSelector = languages => { }); each(languages, (language, isoCode) => { - jq(optionTemplate) + dom(optionTemplate) .attr('value', isoCode) - .addClass(isoCode) + .addCls(isoCode) .text(isoCode + ' - ' + (isStr(language) ? language : language.lang)) - .appendTo($select); + .appTo($select); }); - $block.appendTo('#sidebar'); + $block.appTo('#sidebar'); }; const init = () => { diff --git a/src/_h5ai/public/js/lib/ext/tree.js b/src/_h5ai/public/js/lib/ext/tree.js index d75c099f..90646767 100644 --- a/src/_h5ai/public/js/lib/ext/tree.js +++ b/src/_h5ai/public/js/lib/ext/tree.js @@ -1,5 +1,4 @@ -const {each, regularCmp, naturalCmp} = require('../util'); -const {jq} = require('../globals'); +const {each, dom, regularCmp, naturalCmp} = require('../util'); const event = require('../core/event'); const location = require('../core/location'); const resource = require('../core/resource'); @@ -14,17 +13,17 @@ const settings = Object.assign({ naturalSort: false, ignorecase: true }, allsettings.tree); -const template = +const itemTpl = `
- + `; -const settingsTemplate = +const settingsTpl = `

Tree

@@ -34,7 +33,7 @@ const settingsTemplate = const storekey = 'ext/tree'; -function cmpFn(item1, item2) { +const cmpFn = (item1, item2) => { let val1 = item1.label; let val2 = item2.label; @@ -44,16 +43,17 @@ function cmpFn(item1, item2) { } return settings.natural ? naturalCmp(val1, val2) : regularCmp(val1, val2); -} +}; -function update(item) { - const $html = jq(template); +const update = item => { + const $html = dom(itemTpl); const $indicator = $html.find('.indicator'); const $a = $html.find('a'); const $img = $html.find('.icon img'); const $label = $html.find('.label'); - $html.addClass(item.isFolder() ? 'folder' : 'file'); + $html.addCls(item.isFolder() ? 'folder' : 'file'); + $indicator.on('click', createOnIndicatorClick()); // eslint-disable-line no-use-before-define location.setLink($a, item); $img.attr('src', resource.icon('folder')); @@ -64,36 +64,36 @@ function update(item) { // indicator if (item.isManaged && !item.isContentFetched || subfolders.length) { - $indicator.removeClass('none'); + $indicator.rmCls('none'); if (item.isManaged && !item.isContentFetched) { - $indicator.addClass('unknown'); + $indicator.addCls('unknown'); } else if (item.isContentVisible) { - $indicator.addClass('open'); + $indicator.addCls('open'); } else { - $indicator.addClass('close'); + $indicator.addCls('close'); } } // is it the current folder? if (item.isCurrentFolder()) { - $html.addClass('active'); + $html.addCls('active'); } // does it have subfolders? if (subfolders.length) { subfolders.sort(cmpFn); - const $ul = jq('
    ').appendTo($html); + const $ul = dom('
      ').appTo($html); let counter = 0; each(subfolders, e => { counter += 1; if (counter <= settings.maxSubfolders) { - jq('
    • ').append(update(e)).appendTo($ul); + dom('
    • ').app(update(e)).appTo($ul); } }); if (subfolders.length > settings.maxSubfolders) { - jq('
    • … ' + (subfolders.length - settings.maxSubfolders) + ' more subfolders
    • ').appendTo($ul); + dom('
    • … ' + (subfolders.length - settings.maxSubfolders) + ' more subfolders
    • ').appTo($ul); } if (!item.isContentVisible) { $ul.hide(); @@ -107,48 +107,58 @@ function update(item) { } if (item.$tree) { - item.$tree.replaceWith($html); + item.$tree.rpl($html); } + item.$tree = $html; $html[0]._item = item; return $html; -} +}; -function createOnIndicatorClick() { - function slide(item, $indicator, $content, down) { - item.isContentVisible = down; - $indicator.removeClass('open close').addClass(down ? 'open' : 'close'); - $content[down ? 'slideDown' : 'slideUp'](); +const closestItem = el => { + while (!el._item && el.parentNode) { + el = el.parentNode; } + return el._item; +}; + +const createOnIndicatorClick = () => { + const slide = ($indicator, $content, down) => { + const item = closestItem($indicator[0]); + item.isContentVisible = down; + $indicator.rmCls('open').rmCls('close').addCls(down ? 'open' : 'close'); + // $content[down ? 'slideDown' : 'slideUp'](); + $content[down ? 'show' : 'hide'](); + }; return ev => { - let $indicator = jq(ev.currentTarget); - let $item = $indicator.closest('.item'); - const item = $item[0]._item; - let $content = $item.find('> ul.content'); + const item = closestItem(ev.target); + let $item = item.$tree; + let $indicator = dom($item.find('.indicator')[0]); + let $content = dom($item.find('ul.content')[0]); - if ($indicator.hasClass('unknown')) { + if ($indicator.hasCls('unknown')) { item.fetchContent(() => { item.isContentVisible = false; $item = update(item); - $indicator = $item.find('> .indicator'); - $content = $item.find('> ul.content'); + $indicator = dom($item.find('.indicator')[0]); + $content = dom($item.find('ul.content')[0]); - if (!$indicator.hasClass('none')) { - slide(item, $indicator, $content, true); + if (!$indicator.hasCls('none')) { + slide($indicator, $content, true); } }); - } else if ($indicator.hasClass('open')) { - slide(item, $indicator, $content, false); - } else if ($indicator.hasClass('close')) { - slide(item, $indicator, $content, true); + } else if ($indicator.hasCls('open')) { + slide($indicator, $content, false); + } else if ($indicator.hasCls('close')) { + slide($indicator, $content, true); } }; -} +}; -function fetchTree(item, callback) { +const fetchTree = (item, callback) => { item.isContentVisible = true; item.fetchContent(() => { if (item.parent) { @@ -157,36 +167,34 @@ function fetchTree(item, callback) { callback(item); } }); -} +}; -function updateSettings() { +const updateSettings = () => { if (store.get(storekey)) { - jq('#view-tree').addClass('active'); - jq('#tree').show(); + dom('#view-tree').addCls('active'); + dom('#tree').show(); } else { - jq('#view-tree').removeClass('active'); - jq('#tree').hide(); + dom('#view-tree').rmCls('active'); + dom('#tree').hide(); } -} +}; -function onLocationChanged(item) { +const onLocationChanged = item => { fetchTree(item, root => { - jq('#tree').append(update(root)); + dom('#tree').clr().app(update(root)); updateSettings(); }); -} +}; -function init() { +const init = () => { if (!settings.enabled) { return; } - jq('
      ') - .appendTo('#mainrow') - .on('click', '.indicator', createOnIndicatorClick()); + dom('
      ').hide().appTo('#mainrow'); - jq(settingsTemplate) - .appendTo('#sidebar') + dom(settingsTpl) + .appTo('#sidebar') .find('#view-tree') .on('click', ev => { store.put(storekey, !store.get(storekey)); @@ -201,7 +209,7 @@ function init() { updateSettings(); event.sub('location.changed', onLocationChanged); -} +}; init(); diff --git a/src/_h5ai/public/js/lib/util/dom.js b/src/_h5ai/public/js/lib/util/dom.js index 909751fc..312defc2 100644 --- a/src/_h5ai/public/js/lib/util/dom.js +++ b/src/_h5ai/public/js/lib/util/dom.js @@ -126,6 +126,17 @@ dom.prototype = { return this.each(el => el.removeAttribute(key)); }, + prop(key, value) { + if (value === undefined) { + return this.length ? this[0][key] : undefined; + } + return this.each(el => {el[key] = value;}); + }, + + rmProp(key) { + return this.each(el => delete el[key]); + }, + val(value) { if (value === undefined) { return this.length ? this[0].value : undefined; @@ -168,7 +179,10 @@ dom.prototype = { rpl(arg) { return this.each(el => { - el.outerHTML = dom(arg).map(rplEl => rplEl.outerHTML).join(''); + const parent = el.parentNode; + if (parent) { + parent.replaceChild(dom(arg)[0], el); + } }); },