Start to replace jQuery with dom.

This commit is contained in:
Lars Jung 2016-06-26 01:03:24 +02:00
parent 9234e3f287
commit 7320592dc2
26 changed files with 566 additions and 301 deletions

View file

@ -149,7 +149,7 @@
- ignorecase: boolean, ignore case - ignorecase: boolean, ignore case
*/ */
"filter": { "filter": {
"enabled": false, "enabled": true,
"advanced": true, "advanced": true,
"debounceTime": 100, "debounceTime": 100,
"ignorecase": true "ignorecase": true
@ -319,7 +319,7 @@
- ignorecase: boolean, ignore case - ignorecase: boolean, ignore case
*/ */
"search": { "search": {
"enabled": true, "enabled": false,
"advanced": true, "advanced": true,
"debounceTime": 300, "debounceTime": 300,
"ignorecase": true "ignorecase": true

View file

@ -11,7 +11,7 @@ class Bootstrap {
session_start(); session_start();
$session = new Session($_SESSION); $session = new Session($_SESSION);
$request = new Request($_REQUEST); $request = new Request($_REQUEST, file_get_contents('php://input'));
$setup = new Setup($request->query_boolean('refresh', false)); $setup = new Setup($request->query_boolean('refresh', false));
$context = new Context($session, $request, $setup); $context = new Context($session, $request, $setup);

View file

@ -3,8 +3,9 @@
class Request { class Request {
private $params; private $params;
public function __construct($params) { public function __construct($params, $body) {
$this->params = $params; $data = json_decode($body, true);
$this->params = $data !== null ? $data : $params;
} }
public function query($keypath = '', $default = Util::NO_DEFAULT) { public function query($keypath = '', $default = Util::NO_DEFAULT) {

View file

@ -1,5 +1,4 @@
#sidebar { #sidebar {
display: none;
overflow-x: hidden; overflow-x: hidden;
overflow-y: auto; overflow-y: auto;
flex: 0 0 auto; flex: 0 0 auto;

View file

@ -150,8 +150,9 @@ const setLink = ($el, item) => {
$el.attr('href', item.absHref); $el.attr('href', item.absHref);
if (history && item.isFolder() && item.isManaged) { if (history && item.isFolder() && item.isManaged) {
$el.on('click', () => { $el.on('click', ev => {
setLocation(item.absHref); setLocation(item.absHref);
ev.preventDefault();
return false; return false;
}); });
} }

View file

@ -0,0 +1,274 @@
const {win} = require('./globals');
const {each, filter, hasLength, is, isStr, map, isInstanceOf, toArray} = require('./lo');
const doc = win.document;
const createElement = name => doc.createElement(name);
const CONTAINER_DIV = createElement('div');
const CONTAINER_TABLE = createElement('table');
const CONTAINER_TBODY = createElement('tbody');
const CONTAINER_TR = createElement('tr');
const CONTAINER_COLGROUP = createElement('colgroup');
const publish = (obj, arr) => {
each(arr, (el, idx) => {
obj[idx] = el;
});
obj.length = arr.length;
};
const findContainer = str => {
if (/^<t(head|body|foot)|^<c(ap|olg)/i.test(str)) {
return CONTAINER_TABLE;
}
if (/^<col/i.test(str)) {
return CONTAINER_COLGROUP;
}
if (/^<tr/i.test(str)) {
return CONTAINER_TBODY;
}
if (/^<t[dh]/i.test(str)) {
return CONTAINER_TR;
}
return CONTAINER_DIV;
};
const parseHtml = str => {
const container = findContainer(str);
container.innerHTML = str;
const res = toArray(container.childNodes);
each(res, el => container.removeChild(el));
container.innerHTML = '';
return res;
};
const queryAll = (selector, context) => {
try {
return toArray((context || doc).querySelectorAll(selector));
} catch (err) {/* ignore */}
return [];
};
const isElement = x => isInstanceOf(x, win.Element);
const isDocument = x => isInstanceOf(x, win.Document);
const isWindow = x => is(x) && x.window === x && isDocument(x.document);
const isElDocWin = x => isElement(x) || isDocument(x) || isWindow(x);
const addListener = (el, type, fn) => el.addEventListener(type, fn);
const removeListener = (el, type, fn) => el.removeEventListener(type, fn);
const onReady = fn => {
if (/^(i|c|loade)/.test(doc.readyState)) {
fn();
} else {
addListener(doc, 'DOMContentLoaded', fn);
}
};
const onLoad = fn => addListener(win, 'load', fn);
const onResize = fn => {
addListener(win, 'resize', fn);
};
const onPrint = (before, after) => {
win.matchMedia('print').addListener(mql => {
if (mql.matches) {
before();
} else {
after();
}
});
};
const dom = arg => {
if (isInstanceOf(arg, dom)) {
return arg;
}
let els;
if (isStr(arg)) {
arg = arg.trim();
els = arg[0] === '<' ? parseHtml(arg) : queryAll(arg);
} else if (isElDocWin(arg)) {
els = [arg];
} else {
els = hasLength(arg) ? arg : [arg];
}
els = filter(els, isElDocWin);
const inst = Object.create(dom.prototype);
publish(inst, els);
return inst;
};
dom.prototype = {
constructor: dom,
each(fn) {
each(this, fn);
return this;
},
map(fn) {
return map(this, fn);
},
find(selector) {
let els = [];
this.each(el => {
els = els.concat(queryAll(selector, el));
});
return dom(els);
},
on(type, fn) {
return this.each(el => addListener(el, type, fn));
},
off(type, fn) {
return this.each(el => removeListener(el, type, fn));
},
attr(key, value) {
if (value === undefined) {
return this.length ? this[0].getAttribute(key) : undefined;
}
return this.each(el => el.setAttribute(key, value));
},
rmAttr(key) {
return this.each(el => el.removeAttribute(key));
},
val(value) {
if (value === undefined) {
return this.length ? this[0].value : undefined;
}
return this.each(el => {
el.value = value;
});
},
html(str) {
if (str === undefined) {
return this.map(el => el.innerHTML).join('');
}
return this.each(el => {
el.innerHTML = str;
});
},
text(str) {
if (str === undefined) {
return this.map(el => el.textContent).join('');
}
return this.each(el => {
el.textContent = str;
});
},
clr() {
return this.html('');
},
rm() {
return this.each(el => {
const parent = el.parentNode;
if (parent) {
parent.removeChild(el);
}
});
},
rpl(arg) {
return this.each(el => {
el.outerHTML = dom(arg).map(rplEl => rplEl.outerHTML).join('');
});
},
app(arg) {
return this.each(el => {
dom(arg).each(child => el.appendChild(child));
});
},
appTo(arg) {
dom(arg).app(this);
return this;
},
pre(arg) {
return this.each(el => {
dom(arg).each(child => {
const firstChild = el.firstChild;
if (!firstChild) {
el.appendChild(child);
} else {
el.insertBefore(child, firstChild);
}
});
});
},
preTo(arg) {
dom(arg).pre(this);
return this;
},
cls(...names) {
if (!names.length) {
return this.length ? toArray(this[0].classList) : [];
}
this.each(el => {el.className = '';});
return this.addCls(...names);
},
hasCls(name) {
return toArray(this).every(el => el.classList.contains(name));
},
addCls(...names) {
return this.each(el => {
for (const name of names) {
el.classList.add(name);
}
});
},
rmCls(...names) {
return this.each(el => {
for (const name of names) {
el.classList.remove(name);
}
});
},
parent() {
return dom(this.map(el => el.parentNode));
},
children() {
return dom([].concat(...this.map(el => toArray(el.children))));
},
hide() {
return this.addCls('hidden');
},
show() {
return this.rmCls('hidden');
}
};
module.exports = {
isElement,
isDocument,
isWindow,
isElDocWin,
onReady,
onLoad,
onResize,
onPrint,
dom
};

View file

@ -1,5 +1,5 @@
const {each} = require('../lo'); const {each} = require('../lo');
const {jq} = require('../globals'); const {dom} = require('../dom');
const event = require('../core/event'); const event = require('../core/event');
const location = require('../core/location'); const location = require('../core/location');
const resource = require('../core/resource'); const resource = require('../core/resource');
@ -10,45 +10,47 @@ const base = require('../view/base');
const settings = Object.assign({ const settings = Object.assign({
enabled: false enabled: false
}, allsettings.crumb); }, allsettings.crumb);
const crumbTemplate = const crumbbarTpl = '<div id="crumbbar"></div>';
const crumbTpl =
`<a class="crumb"> `<a class="crumb">
<img class="sep" src="${resource.image('crumb')}" alt=">"/> <img class="sep" src="${resource.image('crumb')}" alt=">"/>
<span class="label"/> <span class="label"></span>
</a>`; </a>`;
const pageHintTemplate = const pageHintTpl =
`<img class="hint" src="${resource.icon('folder-page')}" alt="has index page"/>`; `<img class="hint" src="${resource.icon('folder-page')}" alt="has index page"/>`;
let $crumbbar; let $crumbbar;
const createHtml = item => { const createHtml = item => {
const $html = jq(crumbTemplate); const $html = dom(crumbTpl);
$html[0]._item = item;
item.elCrumb = $html[0];
location.setLink($html, item); location.setLink($html, item);
$html.find('.label').text(item.label); $html.find('.label').text(item.label);
if (item.isCurrentFolder()) { if (item.isCurrentFolder()) {
$html.addClass('active'); $html.addCls('active');
} }
if (!item.isManaged) { if (!item.isManaged) {
$html.append(jq(pageHintTemplate)); $html.app(dom(pageHintTpl));
} }
item.$crumb = $html;
$html[0]._item = item;
return $html; return $html;
}; };
const onLocationChanged = item => { const onLocationChanged = item => {
const $crumb = jq(item.elCrumb); const $crumb = item.$crumb;
if ($crumb && $crumb.parent()[0] === $crumbbar[0]) { if ($crumb && $crumb.parent()[0] === $crumbbar[0]) {
$crumbbar.children().removeClass('active'); $crumbbar.children().rmCls('active');
$crumb.addClass('active'); $crumb.addCls('active');
} else { } else {
$crumbbar.empty(); $crumbbar.clr();
each(item.getCrumb(), crumbItem => { each(item.getCrumb(), crumbItem => {
$crumbbar.append(createHtml(crumbItem)); $crumbbar.app(createHtml(crumbItem));
}); });
} }
}; };
@ -58,7 +60,7 @@ const init = () => {
return; return;
} }
$crumbbar = jq('<div id="crumbbar"/>').appendTo(base.$flowbar); $crumbbar = dom(crumbbarTpl).appTo(base.$flowbar);
event.sub('location.changed', onLocationChanged); event.sub('location.changed', onLocationChanged);
}; };

View file

@ -1,5 +1,5 @@
const {each, debounce} = require('../lo'); const {each, debounce} = require('../lo');
const {jq} = require('../globals'); const {dom} = require('../dom');
const event = require('../core/event'); const event = require('../core/event');
const location = require('../core/location'); const location = require('../core/location');
const resource = require('../core/resource'); const resource = require('../core/resource');
@ -25,7 +25,7 @@ let $filter;
let $input; let $input;
function filter(pattern) { const filter = pattern => {
pattern = pattern || ''; pattern = pattern || '';
if (pattern === prevPattern) { if (pattern === prevPattern) {
return; return;
@ -37,7 +37,7 @@ function filter(pattern) {
return; return;
} }
$filter.addClass('pending'); $filter.addCls('pending');
const re = new RegExp(pattern, settings.ignorecase ? 'i' : ''); const re = new RegExp(pattern, settings.ignorecase ? 'i' : '');
const matchedItems = []; const matchedItems = [];
@ -48,45 +48,45 @@ function filter(pattern) {
} }
}); });
$filter.removeClass('pending'); $filter.rmCls('pending');
view.setHint('noMatch'); view.setHint('noMatch');
view.setItems(matchedItems); view.setItems(matchedItems);
} };
function update() { const update = () => {
if (inputIsVisible) { if (inputIsVisible) {
$filter.addClass('active'); $filter.addCls('active');
$input.focus(); $input[0].focus();
filter(util.parsePattern($input.val(), settings.advanced)); filter(util.parsePattern($input.val(), settings.advanced));
} else { } else {
filter(); filter();
$filter.removeClass('active'); $filter.rmCls('active');
} }
} };
function toggle() { const toggle = () => {
inputIsVisible = !inputIsVisible; inputIsVisible = !inputIsVisible;
update(); update();
} };
function reset() { const reset = () => {
inputIsVisible = false; inputIsVisible = false;
$input.val(''); $input.val('');
update(); update();
} };
function init() { const init = () => {
if (!settings.enabled) { if (!settings.enabled) {
return; return;
} }
$filter = jq(template).appendTo('#toolbar'); $filter = dom(template).appTo('#toolbar');
$input = $filter.find('input'); $input = $filter.find('input');
$filter.on('click', 'img', toggle); $filter.find('img').on('click', toggle);
$input.on('keyup', debounce(update, settings.debounceTime, {trailing: true})); $input.on('keyup', debounce(update, settings.debounceTime));
event.sub('location.changed', reset); event.sub('location.changed', reset);
} };
init(); init();

View file

@ -1,4 +1,4 @@
const {keys, isStr} = require('../lo'); const {each, isStr} = require('../lo');
const {win, jq} = require('../globals'); const {win, jq} = require('../globals');
const server = require('../server'); const server = require('../server');
const event = require('../core/event'); const event = require('../core/event');
@ -50,7 +50,7 @@ const loaded = {
let currentLang = loaded.en; let currentLang = loaded.en;
function update(lang) { const update = lang => {
if (lang) { if (lang) {
currentLang = lang; currentLang = lang;
} }
@ -60,7 +60,7 @@ function update(lang) {
.filter('.' + currentLang.isoCode) .filter('.' + currentLang.isoCode)
.attr('selected', 'selected').prop('selected', 'selected'); .attr('selected', 'selected').prop('selected', 'selected');
jq.each(currentLang, (key, value) => { each(currentLang, (value, key) => {
jq('.l10n-' + key).text(value); jq('.l10n-' + key).text(value);
jq('.l10n_ph-' + key).attr('placeholder', value); jq('.l10n_ph-' + key).attr('placeholder', value);
}); });
@ -70,9 +70,9 @@ function update(lang) {
const $el = jq(el); const $el = jq(el);
$el.text(format.formatDate($el.data('time'))); $el.text(format.formatDate($el.data('time')));
}); });
} };
function loadLanguage(isoCode, callback) { const loadLanguage = (isoCode, callback) => {
if (loaded[isoCode]) { if (loaded[isoCode]) {
callback(loaded[isoCode]); callback(loaded[isoCode]);
} else { } else {
@ -82,9 +82,9 @@ function loadLanguage(isoCode, callback) {
callback(loaded[isoCode]); callback(loaded[isoCode]);
}); });
} }
} };
function localize(languages, isoCode, useBrowserLang) { const localize = (languages, isoCode, useBrowserLang) => {
const storedIsoCode = store.get(storekey); const storedIsoCode = store.get(storekey);
if (languages[storedIsoCode]) { if (languages[storedIsoCode]) {
@ -105,10 +105,9 @@ function localize(languages, isoCode, useBrowserLang) {
} }
loadLanguage(isoCode, update); loadLanguage(isoCode, update);
} };
function initLangSelector(languages) { const initLangSelector = languages => {
const isoCodes = keys(languages).sort();
const $block = jq(blockTemplate); const $block = jq(blockTemplate);
const $select = $block.find('select') const $select = $block.find('select')
.on('change', ev => { .on('change', ev => {
@ -117,18 +116,18 @@ function initLangSelector(languages) {
localize(languages, isoCode, false); localize(languages, isoCode, false);
}); });
jq.each(isoCodes, (idx, isoCode) => { each(languages, (language, isoCode) => {
jq(optionTemplate) jq(optionTemplate)
.attr('value', isoCode) .attr('value', isoCode)
.addClass(isoCode) .addClass(isoCode)
.text(isoCode + ' - ' + (isStr(languages[isoCode]) ? languages[isoCode] : languages[isoCode].lang)) .text(isoCode + ' - ' + (isStr(language) ? language : language.lang))
.appendTo($select); .appendTo($select);
}); });
$block.appendTo('#sidebar'); $block.appendTo('#sidebar');
} };
function init() { const init = () => {
if (settings.enabled) { if (settings.enabled) {
initLangSelector(langs); initLangSelector(langs);
} }
@ -136,7 +135,7 @@ function init() {
event.sub('view.changed', () => { event.sub('view.changed', () => {
localize(langs, settings.lang, settings.useBrowserLang); localize(langs, settings.lang, settings.useBrowserLang);
}); });
} };
init(); init();

View file

@ -1,5 +1,5 @@
const {map} = require('../lo'); const {win} = require('../globals');
const {win, jq} = require('../globals'); const {dom, onLoad} = require('../dom');
const event = require('../core/event'); const event = require('../core/event');
const allsettings = require('../core/settings'); const allsettings = require('../core/settings');
@ -10,7 +10,7 @@ const settings = Object.assign({
idSite: 0 idSite: 0
}, allsettings['piwik-analytics']); }, allsettings['piwik-analytics']);
function init() { const init = () => {
if (!settings.enabled) { if (!settings.enabled) {
return; return;
} }
@ -20,17 +20,17 @@ function init() {
const pkBaseURL = (win.location.protocol === 'https:' ? 'https://' : 'http://') + settings.baseURL + '/'; const pkBaseURL = (win.location.protocol === 'https:' ? 'https://' : 'http://') + settings.baseURL + '/';
let piwikTracker = null; let piwikTracker = null;
jq('<script/>').attr('src', pkBaseURL + 'piwik.js').appendTo('body'); dom('<script></script>').attr('src', pkBaseURL + 'piwik.js').appTo('body');
jq(win).load(() => { onLoad(() => {
piwikTracker = win.Piwik.getTracker(pkBaseURL + 'piwik.php', settings.idSite); piwikTracker = win.Piwik.getTracker(pkBaseURL + 'piwik.php', settings.idSite);
piwikTracker.enableLinkTracking(); piwikTracker.enableLinkTracking();
}); });
event.sub('location.changed', item => { event.sub('location.changed', item => {
const title = map(item.getCrumb(), i => i.label).join(' > '); const title = item.getCrumb().map(i => i.label).join(' > ');
piwikTracker.trackPageView(title); piwikTracker.trackPageView(title);
}); });
} };
init(); init();

View file

@ -1,5 +1,5 @@
const {map, debounce} = require('../lo'); const {map, debounce} = require('../lo');
const {jq} = require('../globals'); const {dom} = require('../dom');
const server = require('../server'); const server = require('../server');
const event = require('../core/event'); const event = require('../core/event');
const location = require('../core/location'); const location = require('../core/location');
@ -27,7 +27,7 @@ let $search;
let $input; let $input;
function search(pattern) { const search = pattern => {
pattern = pattern || ''; pattern = pattern || '';
if (pattern === prevPattern) { if (pattern === prevPattern) {
return; return;
@ -39,7 +39,7 @@ function search(pattern) {
return; return;
} }
$search.addClass('pending'); $search.addCls('pending');
server.request({ server.request({
action: 'get', action: 'get',
@ -49,46 +49,46 @@ function search(pattern) {
ignorecase: settings.ignorecase ignorecase: settings.ignorecase
} }
}).then(response => { }).then(response => {
$search.removeClass('pending'); $search.rmCls('pending');
view.setHint('noMatch'); view.setHint('noMatch');
view.setItems(map(response.search, item => Item.get(item))); view.setItems(map(response.search, item => Item.get(item)));
}); });
} };
function update() { const update = () => {
if (inputIsVisible) { if (inputIsVisible) {
$search.addClass('active'); $search.addCls('active');
$input.focus(); $input[0].focus();
search(util.parsePattern($input.val(), settings.advanced)); search(util.parsePattern($input.val(), settings.advanced));
} else { } else {
search(); search();
$search.removeClass('active'); $search.rmCls('active');
} }
} };
function toggle() { const toggle = () => {
inputIsVisible = !inputIsVisible; inputIsVisible = !inputIsVisible;
update(); update();
} };
function reset() { const reset = () => {
inputIsVisible = false; inputIsVisible = false;
$input.val(''); $input.val('');
update(); update();
} };
function init() { const init = () => {
if (!settings.enabled) { if (!settings.enabled) {
return; return;
} }
$search = jq(template).appendTo('#toolbar'); $search = dom(template).appTo('#toolbar');
$input = $search.find('input'); $input = $search.find('input');
$search.on('click', 'img', toggle); $search.find('img').on('click', toggle);
$input.on('keyup', debounce(update, settings.debounceTime, {trailing: true})); $input.on('keyup', debounce(update, settings.debounceTime));
event.sub('location.changed', reset); event.sub('location.changed', reset);
} };
init(); init();

View file

@ -161,7 +161,7 @@ function onViewChanged(added, removed) {
each(removed, item => { each(removed, item => {
if (item.$view) { if (item.$view) {
item.$view.removeClass('selected'); item.$view.rmCls('selected');
} }
}); });

View file

@ -1,4 +1,5 @@
const {jq} = require('../globals'); const {each, toArray} = require('../lo');
const {dom} = require('../dom');
const event = require('../core/event'); const event = require('../core/event');
const resource = require('../core/resource'); const resource = require('../core/resource');
const allsettings = require('../core/settings'); const allsettings = require('../core/settings');
@ -14,16 +15,16 @@ const settings = Object.assign({
folders: 0 folders: 0
}, allsettings.sort); }, allsettings.sort);
const storekey = 'ext/sort'; const storekey = 'ext/sort';
const template = '<img src="' + resource.image('sort') + '" class="sort" alt="sort order" />'; const template = '<img src="' + resource.image('sort') + '" class="sort" alt="sort order"/>';
function getType(item) { const getType = item => {
const $item = jq(item); const $item = dom(item);
if ($item.hasClass('folder-parent')) { if ($item.hasCls('folder-parent')) {
return 0; return 0;
} }
if ($item.hasClass('folder')) { if ($item.hasCls('folder')) {
if (settings.folders === 1) { if (settings.folders === 1) {
return 2; return 2;
} else if (settings.folders === 2) { } else if (settings.folders === 2) {
@ -32,25 +33,12 @@ function getType(item) {
return 1; return 1;
} }
return 2; return 2;
} };
function getName(item) {
return jq(item).find('.label').text();
}
function getTime(item) {
return jq(item).find('.date').data('time');
}
function getSize(item) {
return jq(item).find('.size').data('bytes');
}
const columnGetters = { const columnGetters = {
0: getName, 0: el => el._item.label,
1: getTime, 1: el => el._item.time,
2: getSize 2: el => el._item.size
}; };
const columnClasses = { const columnClasses = {
0: 'label', 0: 'label',
@ -59,7 +47,7 @@ const columnClasses = {
}; };
function cmpFn(getValue, reverse, ignorecase, natural) { const cmpFn = (getValue, reverse, ignorecase, natural) => {
return (item1, item2) => { return (item1, item2) => {
let res; let res;
let val1; let val1;
@ -86,66 +74,51 @@ function cmpFn(getValue, reverse, ignorecase, natural) {
res = natural ? util.naturalCmpFn(val1, val2) : util.regularCmpFn(val1, val2); res = natural ? util.naturalCmpFn(val1, val2) : util.regularCmpFn(val1, val2);
return reverse ? -res : res; return reverse ? -res : res;
}; };
} };
function sortItems(column, reverse) { const sortItems = (column, reverse) => {
const $headers = jq('#items li.header a'); const $headers = dom('#items li.header a');
const $header = jq('#items li.header a.' + columnClasses[column]); const $header = dom('#items li.header a.' + columnClasses[column]);
const fn = cmpFn(columnGetters[column], reverse, settings.ignorecase, column === 0 && settings.natural); const fn = cmpFn(columnGetters[column], reverse, settings.ignorecase, column === 0 && settings.natural);
const $current = jq('#items .item');
const $sorted = jq('#items .item').sort(fn);
store.put(storekey, {column, reverse}); store.put(storekey, {column, reverse});
$headers.removeClass('ascending descending'); $headers.rmCls('ascending').rmCls('descending');
$header.addClass(reverse ? 'descending' : 'ascending'); $header.addCls(reverse ? 'descending' : 'ascending');
for (let i = 0, l = $current.length; i < l; i += 1) { dom(toArray(dom('#items .item')).sort(fn)).appTo('#items');
if ($current[i] !== $sorted[i]) { };
$sorted.detach().sort(fn).appendTo('#items');
break;
}
}
}
function onContentChanged() { const onContentChanged = () => {
const order = store.get(storekey); const order = store.get(storekey);
const column = order && order.column || settings.column; const column = order && order.column || settings.column;
const reverse = order && order.reverse || settings.reverse; const reverse = order && order.reverse || settings.reverse;
sortItems(column, reverse); sortItems(column, reverse);
} };
function init() { const addToggles = () => {
const $header = dom('#items li.header');
each(columnClasses, (cls, idx) => {
const pos = idx === '0' ? 'app' : 'pre';
$header
.find('a.' + cls)[pos](template)
.on('click', ev => {
sortItems(idx, dom(ev.currentTarget).hasCls('ascending'));
ev.preventDefault();
});
});
};
const init = () => {
if (!settings.enabled) { if (!settings.enabled) {
return; return;
} }
const $header = jq('#items li.header'); addToggles();
$header.find('a.label')
.append(template)
.click(ev => {
sortItems(0, jq(ev.currentTarget).hasClass('ascending'));
ev.preventDefault();
});
$header.find('a.date')
.prepend(template)
.click(ev => {
sortItems(1, jq(ev.currentTarget).hasClass('ascending'));
ev.preventDefault();
});
$header.find('a.size')
.prepend(template)
.click(ev => {
sortItems(2, jq(ev.currentTarget).hasClass('ascending'));
ev.preventDefault();
});
event.sub('view.changed', onContentChanged); event.sub('view.changed', onContentChanged);
} };
init(); init();

View file

@ -15,7 +15,7 @@ const settings = Object.assign({
const landscapeRatio = 4 / 3; const landscapeRatio = 4 / 3;
function queueItem(queue, item) { const queueItem = (queue, item) => {
let type = null; let type = null;
if (includes(settings.img, item.type)) { if (includes(settings.img, item.type)) {
@ -29,7 +29,7 @@ function queueItem(queue, item) {
} }
if (item.thumbSquare) { if (item.thumbSquare) {
item.$view.find('.icon.square img').addClass('thumb').attr('src', item.thumbSquare); item.$view.find('.icon.square img').addCls('thumb').attr('src', item.thumbSquare);
} else { } else {
queue.push({ queue.push({
type, type,
@ -38,14 +38,14 @@ function queueItem(queue, item) {
callback: src => { callback: src => {
if (src && item.$view) { if (src && item.$view) {
item.thumbSquare = src; item.thumbSquare = src;
item.$view.find('.icon.square img').addClass('thumb').attr('src', src); item.$view.find('.icon.square img').addCls('thumb').attr('src', src);
} }
} }
}); });
} }
if (item.thumbRational) { if (item.thumbRational) {
item.$view.find('.icon.landscape img').addClass('thumb').attr('src', item.thumbRational); item.$view.find('.icon.landscape img').addCls('thumb').attr('src', item.thumbRational);
} else { } else {
queue.push({ queue.push({
type, type,
@ -54,14 +54,14 @@ function queueItem(queue, item) {
callback: src => { callback: src => {
if (src && item.$view) { if (src && item.$view) {
item.thumbRational = src; item.thumbRational = src;
item.$view.find('.icon.landscape img').addClass('thumb').attr('src', src); item.$view.find('.icon.landscape img').addCls('thumb').attr('src', src);
} }
} }
}); });
} }
} };
function requestQueue(queue) { const requestQueue = queue => {
const thumbs = map(queue, req => { const thumbs = map(queue, req => {
return { return {
type: req.type, type: req.type,
@ -79,33 +79,29 @@ function requestQueue(queue) {
req.callback(json && json.thumbs ? json.thumbs[idx] : null); req.callback(json && json.thumbs ? json.thumbs[idx] : null);
}); });
}); });
} };
function handleItems(items) { const handleItems = items => {
const queue = []; const queue = [];
each(items, item => { each(items, item => queueItem(queue, item));
queueItem(queue, item);
});
if (queue.length) { if (queue.length) {
requestQueue(queue); requestQueue(queue);
} }
} };
function onViewChanged(added) { const onViewChanged = added => {
setTimeout(() => { setTimeout(() => handleItems(added), settings.delay);
handleItems(added); };
}, settings.delay);
}
function init() { const init = () => {
if (!settings.enabled) { if (!settings.enabled) {
return; return;
} }
event.sub('view.changed', onViewChanged); event.sub('view.changed', onViewChanged);
} };
init(); init();

View file

@ -1,4 +1,3 @@
const {map} = require('../lo');
const {win} = require('../globals'); const {win} = require('../globals');
const event = require('../core/event'); const event = require('../core/event');
const allsettings = require('../core/settings'); const allsettings = require('../core/settings');
@ -10,7 +9,7 @@ const settings = Object.assign({
}, allsettings.title); }, allsettings.title);
const onLocationChanged = item => { const onLocationChanged = item => {
const labels = map(item.getCrumb(), i => i.label); const labels = item.getCrumb().map(i => i.label);
let title = labels.join(' > '); let title = labels.join(' > ');
if (labels.length > 1) { if (labels.length > 1) {

View file

@ -55,7 +55,6 @@ function update(item) {
const $label = $html.find('.label'); const $label = $html.find('.label');
$html.addClass(item.isFolder() ? 'folder' : 'file'); $html.addClass(item.isFolder() ? 'folder' : 'file');
$html[0]._item = item;
location.setLink($a, item); location.setLink($a, item);
$img.attr('src', resource.icon('folder')); $img.attr('src', resource.icon('folder'));
@ -108,10 +107,11 @@ function update(item) {
} }
} }
if (item.elTree) { if (item.$tree) {
jq(item.elTree).replaceWith($html); item.$tree.replaceWith($html);
} }
item.elTree = $html[0]; item.$tree = $html;
$html[0]._item = item;
return $html; return $html;
} }

View file

@ -1,7 +1,7 @@
const {jq} = require('./globals'); const {dom, onReady} = require('./dom');
const config = require('./config'); const config = require('./config');
const name = jq('script[data-module]').data('module'); const name = dom('script[data-module]').attr('data-module');
const query = { const query = {
action: 'get', action: 'get',
setup: true, setup: true,
@ -18,4 +18,4 @@ if (name === 'index') {
throw new Error(`no-main-module: '${name}'`); throw new Error(`no-main-module: '${name}'`);
} }
config._update(query).then(() => jq(() => require(`./main/${name}`))); config._update(query).then(() => onReady(() => require(`./main/${name}`)));

View file

@ -1,12 +1,14 @@
const is = x => x !== undefined && x !== null;
const tof = (x, str) => typeof x === str; const tof = (x, str) => typeof x === str;
const isStr = x => tof(x, 'string'); const isStr = x => tof(x, 'string');
const isFn = x => tof(x, 'function'); const isFn = x => tof(x, 'function');
const isNum = x => tof(x, 'number'); const isNum = x => tof(x, 'number');
const hasLength = x => x && x.hasOwnProperty('length');
const keys = obj => { const keys = obj => {
if (!obj || isStr(obj)) { if (!obj || isStr(obj)) {
return []; return [];
} }
if (obj.hasOwnProperty('length')) { if (hasLength(obj)) {
obj = Array.from(obj); obj = Array.from(obj);
} }
return Object.keys(obj); return Object.keys(obj);
@ -17,6 +19,10 @@ const filter = (obj, fn) => values(obj).filter(fn);
const map = (obj, fn) => values(obj).map(fn); const map = (obj, fn) => values(obj).map(fn);
const includes = (obj, x) => values(obj).indexOf(x) >= 0; const includes = (obj, x) => values(obj).indexOf(x) >= 0;
const compact = obj => filter(obj, x => !!x); const compact = obj => filter(obj, x => !!x);
const isInstanceOf = (x, constructor) => x ? x instanceof constructor : false;
const toArray = x => Array.from(x);
const difference = (obj1, obj2) => { const difference = (obj1, obj2) => {
obj2 = values(obj2); obj2 = values(obj2);
return filter(obj1, x => obj2.indexOf(x) < 0); return filter(obj1, x => obj2.indexOf(x) < 0);
@ -40,9 +46,11 @@ const debounce = (fn, delay) => {
}; };
module.exports = { module.exports = {
is,
isStr, isStr,
isFn, isFn,
isNum, isNum,
hasLength,
keys, keys,
values, values,
each, each,
@ -50,6 +58,8 @@ module.exports = {
map, map,
includes, includes,
compact, compact,
isInstanceOf,
toArray,
difference, difference,
intersection, intersection,
sortBy, sortBy,

View file

@ -1,11 +1,12 @@
const {win, jq} = require('../globals'); const {win} = require('../globals');
const {dom} = require('../dom');
const config = require('../config'); const config = require('../config');
const server = require('../server'); const server = require('../server');
const resource = require('../core/resource'); const resource = require('../core/resource');
const tplTests = const tplTests =
'<ul id="tests">'; '<ul id="tests"></ul>';
const tplTest = const tplTest =
`<li class="test"> `<li class="test">
<span class="label"></span> <span class="label"></span>
@ -27,9 +28,9 @@ const tplSupport =
Show your support with a donation! Show your support with a donation!
<div class="paypal"> <div class="paypal">
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank"> <form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
<input type="hidden" name="cmd" value="_s-xclick" /> <input type="hidden" name="cmd" value="_s-xclick"/>
<input type="hidden" name="hosted_button_id" value="8WSPKWT7YBTSQ" /> <input type="hidden" name="hosted_button_id" value="8WSPKWT7YBTSQ"/>
<input type="image" src="${resource.image('paypal')}" name="submit" alt="PayPal" /> <input type="image" src="${resource.image('paypal')}" name="submit" alt="PayPal"/>
</form> </form>
</div> </div>
</div>`; </div>`;
@ -37,10 +38,10 @@ const setup = config.setup;
const addTest = (label, info, passed, result) => { const addTest = (label, info, passed, result) => {
const $test = jq(tplTest).appendTo('#tests'); const $test = dom(tplTest).appTo('#tests');
$test.find('.label').text(label); $test.find('.label').text(label);
$test.find('.result') $test.find('.result')
.addClass(passed ? 'passed' : 'failed') .addCls(passed ? 'passed' : 'failed')
.text(result ? result : passed ? 'yes' : 'no'); .text(result ? result : passed ? 'yes' : 'no');
$test.find('.info').html(info); $test.find('.info').html(info);
}; };
@ -50,7 +51,7 @@ const addTests = () => {
return; return;
} }
jq(tplTests).appendTo('#content'); dom(tplTests).appTo('#content');
addTest( addTest(
'h5ai version', 'Only green if this is an official h5ai release', 'h5ai version', 'Only green if this is an official h5ai release',
@ -140,7 +141,7 @@ const reload = () => {
const onLogin = () => { const onLogin = () => {
server.request({ server.request({
action: 'login', action: 'login',
pass: jq('#pass').val() pass: dom('#pass').val()
}).then(reload); }).then(reload);
}; };
@ -157,23 +158,23 @@ const onKeydown = ev => {
}; };
const addSupport = () => { const addSupport = () => {
jq(tplSupport).appendTo('#content'); dom(tplSupport).appTo('#content');
}; };
const addLogin = () => { const addLogin = () => {
jq(tplLogin).appendTo('#content'); dom(tplLogin).appTo('#content');
if (setup.AS_ADMIN) { if (setup.AS_ADMIN) {
jq('#pass').remove(); dom('#pass').rm();
jq('#login').remove(); dom('#login').rm();
jq('#logout').on('click', onLogout); dom('#logout').on('click', onLogout);
} else { } else {
jq('#pass').on('keydown', onKeydown).focus(); dom('#pass').on('keydown', onKeydown)[0].focus();
jq('#login').on('click', onLogin); dom('#login').on('click', onLogin);
jq('#logout').remove(); dom('#logout').rm();
} }
if (config.options.hasCustomPasshash) { if (config.options.hasCustomPasshash) {
jq('#hint').remove(); dom('#hint').rm();
} }
}; };

View file

@ -1,30 +1,41 @@
const {jq} = require('./globals'); const {win} = require('./globals');
const {dom} = require('./dom');
const {each} = require('./lo'); const {each} = require('./lo');
const XHR = win.XMLHttpRequest;
const request = data => { const request = data => {
return new Promise(resolve => { return new Promise(resolve => {
jq.ajax({ const xhr = new XHR();
url: '?', const callback = () => {
data, if (xhr.readyState === XHR.DONE) {
type: 'post', try {
dataType: 'json' resolve(JSON.parse(xhr.responseText));
}) } catch (err) {
.done(json => resolve(json)) resolve({err, txt: xhr.responseText});
.fail(() => resolve()); }
}
};
xhr.open('POST', '?', true);
xhr.onreadystatechange = callback;
xhr.setRequestHeader('Content-Type', 'application/json;charset=utf-8');
xhr.send(JSON.stringify(data));
}); });
}; };
const formRequest = data => { const formRequest = data => {
const $form = jq('<form method="post" action="?" style="display:none;"/>'); const $form = dom('<form method="post" action="?" style="display:none;"/>');
each(data, (val, key) => { each(data, (val, key) => {
jq('<input type="hidden"/>') dom('<input type="hidden"/>')
.attr('name', key) .attr('name', key)
.attr('value', val) .attr('value', val)
.appendTo($form); .appTo($form);
}); });
$form.appendTo('body').submit().remove(); $form.appTo('body');
$form[0].submit();
$form.rm();
}; };
module.exports = { module.exports = {

View file

@ -1,10 +1,10 @@
const {jq} = require('../globals'); const {dom} = require('../dom');
const rootSelector = 'body'; const rootSelector = 'body';
const tplTopbar = const tplTopbar =
`<div id="topbar"> `<div id="topbar">
<div id="toolbar"/> <div id="toolbar"></div>
<div id="flowbar"/> <div id="flowbar"></div>
<a id="backlink" href="https://larsjung.de/h5ai/" title="powered by h5ai - https://larsjung.de/h5ai/"> <a id="backlink" href="https://larsjung.de/h5ai/" title="powered by h5ai - https://larsjung.de/h5ai/">
<div>powered</div> <div>powered</div>
<div>by h5ai</div> <div>by h5ai</div>
@ -12,16 +12,16 @@ const tplTopbar =
</div>`; </div>`;
const tplMainrow = const tplMainrow =
`<div id="mainrow"> `<div id="mainrow">
<div id="content"/> <div id="content"></div>
</div>`; </div>`;
const init = () => { const init = () => {
jq('#fallback, #fallback-hints').remove(); dom('#fallback, #fallback-hints').rm();
const $root = jq(rootSelector) const $root = dom(rootSelector)
.attr('id', 'root') .attr('id', 'root')
.append(tplTopbar) .app(tplTopbar)
.append(tplMainrow); .app(tplMainrow);
return { return {
$root, $root,

View file

@ -1,17 +1,20 @@
const {jq} = require('../globals'); const {dom} = require('../dom');
const base = require('./base'); const base = require('./base');
const $el = jq('<div id="notification"/>').hide().appendTo(base.$root); const init = () => {
const $el = dom('<div id="notification"></div>').hide().appTo(base.$root);
const set = content => { const set = content => {
if (content) { if (content) {
$el.stop(true, true).html(content).fadeIn(400); $el.html(content).show();
} else { } else {
$el.stop(true, true).fadeOut(400); $el.hide();
} }
};
return {
set
};
}; };
module.exports = { module.exports = init();
$el,
set
};

View file

@ -1,4 +1,4 @@
const {jq} = require('../globals'); const {dom} = require('../dom');
const resource = require('../core/resource'); const resource = require('../core/resource');
const allsettings = require('../core/settings'); const allsettings = require('../core/settings');
const store = require('../core/store'); const store = require('../core/store');
@ -9,7 +9,7 @@ const settings = Object.assign({
disableSidebar: false disableSidebar: false
}, allsettings.view); }, allsettings.view);
const storekey = 'sidebarIsVisible'; const storekey = 'sidebarIsVisible';
const tplSidebar = '<div id="sidebar"/>'; const tplSidebar = '<div id="sidebar"></div>';
const tplToggle = const tplToggle =
`<div id="sidebar-toggle" class="tool"> `<div id="sidebar-toggle" class="tool">
<img alt="sidebar"/> <img alt="sidebar"/>
@ -17,8 +17,8 @@ const tplToggle =
const init = () => { const init = () => {
const $sidebar = jq(tplSidebar); const $sidebar = dom(tplSidebar).hide();
const $toggle = jq(tplToggle); const $toggle = dom(tplToggle);
const $img = $toggle.find('img'); const $img = $toggle.find('img');
const update = toggle => { const update = toggle => {
@ -30,19 +30,19 @@ const init = () => {
} }
if (isVisible) { if (isVisible) {
$toggle.addClass('active'); $toggle.addCls('active');
$img.attr('src', resource.image('back')); $img.attr('src', resource.image('back'));
$sidebar.show(); $sidebar.show();
} else { } else {
$toggle.removeClass('active'); $toggle.rmCls('active');
$img.attr('src', resource.image('sidebar')); $img.attr('src', resource.image('sidebar'));
$sidebar.hide(); $sidebar.hide();
} }
}; };
if (!settings.disableSidebar) { if (!settings.disableSidebar) {
$sidebar.appendTo(base.$mainrow); $sidebar.appTo(base.$mainrow);
$toggle.appendTo(base.$toolbar).on('click', () => update(true)); $toggle.appTo(base.$toolbar).on('click', () => update(true));
update(); update();
} }

View file

@ -1,5 +1,5 @@
const {each, map, includes, intersection} = require('../lo'); const {each, map, includes, intersection} = require('../lo');
const {jq} = require('../globals'); const {dom} = require('../dom');
const event = require('../core/event'); const event = require('../core/event');
const format = require('../core/format'); const format = require('../core/format');
const location = require('../core/location'); const location = require('../core/location');
@ -26,25 +26,25 @@ const tplView =
`<div id="view"> `<div id="view">
<ul id="items" class="clearfix"> <ul id="items" class="clearfix">
<li class="header"> <li class="header">
<a class="icon"/> <a class="icon"></a>
<a class="label" href="#"><span class="l10n-name"/></a> <a class="label" href="#"><span class="l10n-name"/></a>
<a class="date" href="#"><span class="l10n-lastModified"/></a> <a class="date" href="#"><span class="l10n-lastModified"/></a>
<a class="size" href="#"><span class="l10n-size"/></a> <a class="size" href="#"><span class="l10n-size"/></a>
</li> </li>
</ul> </ul>
<div id="view-hint"/> <div id="view-hint"></div>
</div>`; </div>`;
const tplItem = const tplItem =
`<li class="item"> `<li class="item">
<a> <a>
<span class="icon square"><img/></span> <span class="icon square"><img/></span>
<span class="icon landscape"><img/></span> <span class="icon landscape"><img/></span>
<span class="label"/> <span class="label"></span>
<span class="date"/> <span class="date"></span>
<span class="size"/> <span class="size"></span>
</a> </a>
</li>`; </li>`;
const $view = jq(tplView); const $view = dom(tplView);
const $items = $view.find('#items'); const $items = $view.find('#items');
const $hint = $view.find('#view-hint'); const $hint = $view.find('#view-hint');
@ -80,7 +80,7 @@ const createStyles = size => {
const addCssStyles = () => { const addCssStyles = () => {
const styles = map(sortedSizes, size => createStyles(size)); const styles = map(sortedSizes, size => createStyles(size));
styles.push(`#view .icon img {max-width: ${settings.maxIconSize}px; max-height: ${settings.maxIconSize}px;}`); styles.push(`#view .icon img {max-width: ${settings.maxIconSize}px; max-height: ${settings.maxIconSize}px;}`);
jq('<style/>').text(styles.join('\n')).appendTo('head'); dom('<style></style>').text(styles.join('\n')).appTo('head');
}; };
const set = (mode, size) => { const set = (mode, size) => {
@ -94,17 +94,17 @@ const set = (mode, size) => {
each(checkedModes, m => { each(checkedModes, m => {
if (m === mode) { if (m === mode) {
$view.addClass('view-' + m); $view.addCls('view-' + m);
} else { } else {
$view.removeClass('view-' + m); $view.rmCls('view-' + m);
} }
}); });
each(sortedSizes, s => { each(sortedSizes, s => {
if (s === size) { if (s === size) {
$view.addClass('view-size-' + s); $view.addCls('view-size-' + s);
} else { } else {
$view.removeClass('view-size-' + s); $view.rmCls('view-size-' + s);
} }
}); });
@ -119,56 +119,58 @@ const getSizes = () => sortedSizes;
const getSize = () => store.get(storekey).size; const getSize = () => store.get(storekey).size;
const setSize = size => set(null, size); const setSize = size => set(null, size);
const onMouseenter = ev => {
const item = ev.target._item;
event.pub('item.mouseenter', item);
};
const onMouseleave = ev => {
const item = ev.target._item;
event.pub('item.mouseleave', item);
};
const createHtml = item => { const createHtml = item => {
const $html = jq(tplItem); const $html = dom(tplItem);
const $a = $html.find('a'); const $a = $html.find('a');
const $iconImg = $html.find('.icon img'); const $iconImg = $html.find('.icon img');
const $label = $html.find('.label'); const $label = $html.find('.label');
const $date = $html.find('.date'); const $date = $html.find('.date');
const $size = $html.find('.size'); const $size = $html.find('.size');
$html.addClass(item.isFolder() ? 'folder' : 'file'); $html
$html[0]._item = item; .addCls(item.isFolder() ? 'folder' : 'file')
.on('mouseenter', onMouseenter)
.on('mouseleave', onMouseleave);
location.setLink($a, item); location.setLink($a, item);
$label.text(item.label).attr('title', item.label); $label.text(item.label).attr('title', item.label);
$date.data('time', item.time).text(format.formatDate(item.time)); $date.attr('data-time', item.time).text(format.formatDate(item.time));
$size.data('bytes', item.size).text(format.formatSize(item.size)); $size.attr('data-bytes', item.size).text(format.formatSize(item.size));
item.icon = resource.icon(item.type); item.icon = resource.icon(item.type);
if (item.isFolder() && !item.isManaged) { if (item.isFolder() && !item.isManaged) {
$html.addClass('page'); $html.addCls('page');
item.icon = resource.icon('folder-page'); item.icon = resource.icon('folder-page');
} }
if (item.isCurrentParentFolder()) { if (item.isCurrentParentFolder()) {
item.icon = resource.icon('folder-parent'); item.icon = resource.icon('folder-parent');
if (!settings.setParentFolderLabels) { if (!settings.setParentFolderLabels) {
$label.addClass('l10n-parentDirectory'); $label.addCls('l10n-parentDirectory');
} }
$html.addClass('folder-parent'); $html.addCls('folder-parent');
} }
$iconImg.attr('src', item.icon).attr('alt', item.type); $iconImg.attr('src', item.icon).attr('alt', item.type);
item.$view = $html; item.$view = $html;
item.elView = $html[0]; $html[0]._item = item;
return $html; return $html;
}; };
const onMouseenter = ev => {
const item = jq(ev.currentTarget).closest('.item')[0]._item;
event.pub('item.mouseenter', item);
};
const onMouseleave = ev => {
const item = jq(ev.currentTarget).closest('.item')[0]._item;
event.pub('item.mouseleave', item);
};
const checkHint = () => { const checkHint = () => {
const hasNoItems = $items.find('.item').not('.folder-parent').length === 0; const hasNoItems = $items.find('.item').length === $items.find('.folder-parent').length;
if (hasNoItems) { if (hasNoItems) {
$hint.show(); $hint.show();
@ -180,24 +182,23 @@ const checkHint = () => {
const setItems = items => { const setItems = items => {
const removed = map($items.find('.item'), el => el._item); const removed = map($items.find('.item'), el => el._item);
$items.find('.item').remove(); $items.find('.item').rm();
each(items, item => $items.append(createHtml(item))); each(items, item => $items.app(createHtml(item)));
base.$content.scrollLeft(0).scrollTop(0); base.$content[0].scrollLeft = 0;
base.$content[0].scrollTop = 0;
checkHint(); checkHint();
event.pub('view.changed', items, removed); event.pub('view.changed', items, removed);
}; };
const changeItems = (add, remove) => { const changeItems = (add, remove) => {
each(add, item => { each(add, item => {
createHtml(item).hide().appendTo($items).fadeIn(400); createHtml(item).hide().appTo($items).show();
}); });
each(remove, item => { each(remove, item => {
item.$view.fadeOut(400, () => { item.$view.hide().rm();
item.$view.remove();
});
}); });
checkHint(); checkHint();
@ -205,7 +206,7 @@ const changeItems = (add, remove) => {
}; };
const setHint = l10nKey => { const setHint = l10nKey => {
$hint.removeClass().addClass('l10n-' + l10nKey); $hint.rmCls().addCls('l10n-' + l10nKey);
checkHint(); checkHint();
}; };
@ -247,15 +248,11 @@ const init = () => {
addCssStyles(); addCssStyles();
set(); set();
$view.appendTo(base.$content); $view.appTo(base.$content);
$hint.hide(); $hint.hide();
format.setDefaultMetric(settings.binaryPrefix); format.setDefaultMetric(settings.binaryPrefix);
$items
.on('mouseenter', '.item a', onMouseenter)
.on('mouseleave', '.item a', onMouseleave);
event.sub('location.changed', onLocationChanged); event.sub('location.changed', onLocationChanged);
event.sub('location.refreshed', onLocationRefreshed); event.sub('location.refreshed', onLocationRefreshed);
}; };
@ -265,7 +262,6 @@ init();
module.exports = { module.exports = {
$el: $view, $el: $view,
$items,
setItems, setItems,
changeItems, changeItems,
setLocation: onLocationChanged, setLocation: onLocationChanged,

View file

@ -1,5 +1,5 @@
const {each} = require('../lo'); const {each} = require('../lo');
const {jq} = require('../globals'); const {dom} = require('../dom');
const event = require('../core/event'); const event = require('../core/event');
const resource = require('../core/resource'); const resource = require('../core/resource');
const allsettings = require('../core/settings'); const allsettings = require('../core/settings');
@ -28,14 +28,14 @@ let sizes;
const onChanged = (mode, size) => { const onChanged = (mode, size) => {
jq('#viewmode-settings .mode').removeClass('active'); dom('#viewmode-settings .mode').rmCls('active');
jq('#viewmode-' + mode).addClass('active'); dom('#viewmode-' + mode).addCls('active');
jq('#viewmode-size').val(sizes.indexOf(size)); dom('#viewmode-size').val(sizes.indexOf(size));
if (settings.modeToggle === 'next') { if (settings.modeToggle === 'next') {
mode = modes[(modes.indexOf(mode) + 1) % modes.length]; mode = modes[(modes.indexOf(mode) + 1) % modes.length];
} }
jq('#viewmode-toggle img').attr('src', resource.image('view-' + mode)); dom('#viewmode-toggle img').attr('src', resource.image('view-' + mode));
}; };
const addSettings = () => { const addSettings = () => {
@ -43,29 +43,28 @@ const addSettings = () => {
return; return;
} }
const $viewBlock = jq(tplSettings); const $viewBlock = dom(tplSettings);
if (modes.length > 1) { if (modes.length > 1) {
each(modes, mode => { each(modes, mode => {
jq(tplMode.replace(/\[MODE\]/g, mode)) dom(tplMode.replace(/\[MODE\]/g, mode))
.on('click', () => { .on('click', () => {
view.setMode(mode); view.setMode(mode);
}) })
.appendTo($viewBlock); .appTo($viewBlock);
}); });
} }
if (sizes.length > 1) { if (sizes.length > 1) {
const max = sizes.length - 1; const max = sizes.length - 1;
jq(tplSize) dom(tplSize)
.prop('max', max).attr('max', max) .attr('max', max)
.on('input change', ev => { .on('input', ev => view.setSize(sizes[ev.target.valueAsNumber]))
view.setSize(sizes[ev.target.valueAsNumber]); .on('change', ev => view.setSize(sizes[ev.target.valueAsNumber]))
}) .appTo($viewBlock);
.appendTo($viewBlock);
} }
$viewBlock.appendTo(sidebar.$el); $viewBlock.appTo(sidebar.$el);
}; };
const onToggle = () => { const onToggle = () => {
@ -78,9 +77,9 @@ const onToggle = () => {
const addToggle = () => { const addToggle = () => {
if (settings.modeToggle && modes.length > 1) { if (settings.modeToggle && modes.length > 1) {
jq(tplToggle) dom(tplToggle)
.on('click', onToggle) .on('click', onToggle)
.appendTo(base.$toolbar); .appTo(base.$toolbar);
} }
}; };

View file

@ -22,6 +22,7 @@
assert('console', win.console && isFn(win.console.log)); assert('console', win.console && isFn(win.console.log));
assert('assign', win.Object && isFn(win.Object.assign)); assert('assign', win.Object && isFn(win.Object.assign));
assert('promise', isFn(win.Promise)); assert('promise', isFn(win.Promise));
assert('xhr', isFn(win.XMLHttpRequest));
}(this)); }(this));
/* eslint-enable */ /* eslint-enable */