Clean code.

This commit is contained in:
Lars Jung 2016-06-30 02:19:49 +02:00
parent f547d95f30
commit 3761a40e50
7 changed files with 252 additions and 228 deletions

View file

@ -1,5 +1,4 @@
#pv-overlay {
display: none;
position: fixed;
left: 0;
top: 0;

View file

@ -1,5 +1,5 @@
const {each, map, includes, compact} = require('../util');
const {win, jq} = require('../globals');
const {each, includes, compact, dom} = require('../util');
const {win} = require('../globals');
const event = require('../core/event');
const format = require('../core/format');
const allsettings = require('../core/settings');
@ -10,30 +10,32 @@ const settings = Object.assign({
types: []
}, allsettings['preview-aud']);
function preloadAudio(src, callback) {
const $audio = jq('<audio/>')
.one('loadedmetadata', () => {
callback($audio);
// win.setTimeout(function () { callback($img); }, 1000); // for testing
})
const preloadAudio = (src, callback) => {
const $audio = dom('<audio/>')
.on('loadedmetadata', () => callback($audio))
.attr('autoplay', 'autoplay')
.attr('controls', 'controls')
.attr('src', src);
}
};
function onEnter(items, idx) {
const onEnter = (items, idx) => {
const currentItems = items;
let currentIdx = idx;
let currentItem = items[idx];
function onAdjustSize() {
const $content = jq('#pv-content');
const $audio = jq('#pv-aud-audio');
const onAdjustSize = () => {
const $content = dom('#pv-content');
const $audio = dom('#pv-aud-audio');
if ($audio.length) {
const contentW = $content[0].offsetWidth;
const contentH = $content[0].offsetHeight;
const audioW = $audio[0].offsetWidth;
const audioH = $audio[0].offsetHeight;
$audio.css({
left: String(($content.width() - $audio.width()) * 0.5) + 'px',
top: String(($content.height() - $audio.height()) * 0.5) + 'px'
left: (contentW - audioW) * 0.5 + 'px',
top: (contentH - audioH) * 0.5 + 'px'
});
preview.setLabels([
@ -41,52 +43,52 @@ function onEnter(items, idx) {
format.formatDate($audio[0].duration * 1000, 'm:ss')
]);
}
}
};
function onIdxChange(rel) {
const onIdxChange = rel => {
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
currentItem = currentItems[currentIdx];
const spinnerTimeout = win.setTimeout(() => preview.showSpinner(true), 200);
if (jq('#pv-aud-audio').length) {
jq('#pv-aud-audio')[0].pause();
if (dom('#pv-aud-audio').length) {
dom('#pv-aud-audio')[0].pause();
}
function updateMeta() {
const updateMeta = () => {
onAdjustSize();
preview.setIndex(currentIdx + 1, currentItems.length);
preview.setRawLink(currentItem.absHref);
}
};
function swap(nuContent) {
jq('#pv-content').empty().append(nuContent.attr('id', 'pv-vid-audio')).fadeIn(200);
// small timeout, so nuContent is visible and therefore its width is available
win.setTimeout(updateMeta, 10);
}
const swap = nuContent => {
dom('#pv-content').clr().app(nuContent.attr('id', 'pv-aud-audio')).show();
updateMeta();
};
function onReady($preloadedContent) {
const onReady = $preloadedContent => {
win.clearTimeout(spinnerTimeout);
preview.showSpinner(false);
jq('#pv-content').fadeOut(100, () => swap($preloadedContent));
}
dom('#pv-content').hide();
swap($preloadedContent);
};
preloadAudio(currentItem.absHref, onReady);
}
};
onIdxChange(0);
preview.setOnIndexChange(onIdxChange);
preview.setOnAdjustSize(onAdjustSize);
preview.enter();
}
};
function initItem(item) {
const initItem = item => {
if (item.$view && includes(settings.types, item.type)) {
item.$view.find('a').on('click', ev => {
ev.preventDefault();
const matchedItems = compact(map(jq('#items .item'), el => {
const matchedItems = compact(dom('#items .item').map(el => {
const matchedItem = el._item;
return includes(settings.types, matchedItem.type) ? matchedItem : null;
}));
@ -94,18 +96,16 @@ function initItem(item) {
onEnter(matchedItems, matchedItems.indexOf(item));
});
}
}
};
function onViewChanged(added) {
each(added, initItem);
}
const onViewChanged = added => each(added, initItem);
function init() {
const init = () => {
if (!settings.enabled) {
return;
}
event.sub('view.changed', onViewChanged);
}
};
init();

View file

@ -1,5 +1,5 @@
const {each, map, includes, compact} = require('../util');
const {win, jq} = require('../globals');
const {each, includes, compact, dom} = require('../util');
const {win} = require('../globals');
const server = require('../server');
const event = require('../core/event');
const allsettings = require('../core/settings');
@ -17,7 +17,7 @@ let currentIdx;
let currentItem;
function requestSample(href, callback) {
const requestSample = (href, callback) => {
if (!settings.size) {
callback(href);
return;
@ -34,43 +34,50 @@ function requestSample(href, callback) {
}).then(json => {
callback(json && json.thumbs && json.thumbs[0] ? json.thumbs[0] : null);
});
}
};
function preloadImage(item, callback) {
const preloadImage = (item, callback) => {
requestSample(item.absHref, src => {
jq('<img/>')
.one('load', ev => {
callback(item, ev.target);
const $img = dom('<img/>')
.on('load', () => {
callback(item, $img);
// for testing
// win.setTimeout(function () { callback(item, ev.target); }, 1000);
// win.setTimeout(() => callback(item, $img), 1000);
})
.attr('src', src);
});
}
};
function onAdjustSize() {
const $content = jq('#pv-content');
const $img = jq('#pv-img-image');
const onAdjustSize = () => {
const $content = dom('#pv-content');
const $img = dom('#pv-img-image');
const contentW = $content[0].offsetWidth;
const contentH = $content[0].offsetHeight;
const imgW = ($img[0] || {}).offsetWidth;
const imgH = ($img[0] || {}).offsetHeight;
if ($img.length === 0) {
return;
}
$img.css({
left: ($content.width() - $img.width()) * 0.5,
top: ($content.height() - $img.height()) * 0.5
left: (contentW - imgW) * 0.5 + 'px',
top: (contentH - imgH) * 0.5 + 'px'
});
const labels = [currentItem.label];
if (!settings.size) {
labels.push(String($img[0].naturalWidth) + 'x' + String($img[0].naturalHeight));
labels.push(String((100 * $img.width() / $img[0].naturalWidth).toFixed(0)) + '%');
const imgNW = $img[0].naturalWidth;
const imgNH = $img[0].naturalHeight;
labels.push(String(imgNW) + 'x' + String(imgNH));
labels.push(String((100 * imgW / imgNW).toFixed(0)) + '%');
}
preview.setLabels(labels);
}
};
function onIdxChange(rel) {
const onIdxChange = rel => {
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
currentItem = currentItems[currentIdx];
@ -78,7 +85,7 @@ function onIdxChange(rel) {
preview.setIndex(currentIdx + 1, currentItems.length);
preview.setRawLink(currentItem.absHref);
jq('#pv-content').hide();
dom('#pv-content').hide();
if (preview.isSpinnerVisible()) {
preview.showSpinner(true, currentItem.thumbSquare);
} else {
@ -95,29 +102,29 @@ function onIdxChange(rel) {
win.clearTimeout(spinnerTimeoutId);
preview.showSpinner(false);
jq('#pv-content')
.empty()
.append(jq(preloadedImage).attr('id', 'pv-img-image'))
dom('#pv-content')
.clr()
.app(dom(preloadedImage).attr('id', 'pv-img-image'))
.show();
onAdjustSize();
});
}
};
function onEnter(items, idx) {
const onEnter = (items, idx) => {
currentItems = items;
currentIdx = idx;
preview.setOnIndexChange(onIdxChange);
preview.setOnAdjustSize(onAdjustSize);
preview.enter();
onIdxChange(0);
}
};
function initItem(item) {
const initItem = item => {
if (item.$view && includes(settings.types, item.type)) {
item.$view.find('a').on('click', ev => {
ev.preventDefault();
const matchedItems = compact(map(jq('#items .item'), el => {
const matchedItems = compact(dom('#items .item').map(el => {
const matchedItem = el._item;
return includes(settings.types, matchedItem.type) ? matchedItem : null;
}));
@ -125,19 +132,19 @@ function initItem(item) {
onEnter(matchedItems, matchedItems.indexOf(item));
});
}
}
};
function onViewChanged(added) {
const onViewChanged = added => {
each(added, initItem);
}
};
function init() {
const init = () => {
if (!settings.enabled) {
return;
}
event.sub('view.changed', onViewChanged);
}
};
init();

View file

@ -1,10 +1,11 @@
const {each, map, keys, includes, compact} = require('../util');
const {win, jq, marked, prism} = require('../globals');
const {each, keys, includes, compact, dom} = require('../util');
const {win, marked, prism} = require('../globals');
const event = require('../core/event');
const allsettings = require('../core/settings');
const preview = require('./preview');
const XHR = win.XMLHttpRequest;
const settings = Object.assign({
enabled: false,
types: {}
@ -12,38 +13,53 @@ const settings = Object.assign({
const tplText = '<pre id="pv-txt-text" class="highlighted"/>';
const tplMarkdown = '<div id="pv-txt-text" class="markdown"/>';
const spinnerThreshold = 200;
let spinnerTimeoutId;
let currentItems;
let currentIdx;
let currentItem;
function preloadText(item, callback) {
jq.ajax({
url: item.absHref,
dataType: 'text'
})
.done(content => {
callback(item, content);
const request = href => {
return new Promise((resolve, reject) => {
const xhr = new XHR();
const callback = () => {
if (xhr.readyState === XHR.DONE) {
try {
resolve(xhr.responseText);
} catch (err) {
reject(String(err));
}
}
};
// for testing
// win.setTimeout(function () { callback(item, content); }, 1000);
})
.fail((jqXHR, textStatus) => {
callback(item, '[ajax error] ' + textStatus);
xhr.open('GET', href, true);
xhr.onreadystatechange = callback;
xhr.send();
});
}
};
function onAdjustSize() {
const $content = jq('#pv-content');
const $text = jq('#pv-txt-text');
const preloadText = (item, callback) => {
request(item.absHref)
.then(content => {
callback(item, content);
// for testing
// win.setTimeout(() => callback(item, content), 1000);
})
.catch(err => callback(item, '[ajax error] ' + err));
};
const onAdjustSize = () => {
const $content = dom('#pv-content');
const $text = dom('#pv-txt-text');
if ($text.length) {
$text.height($content.height() - 16);
$text[0].style.height = $content[0].offsetHeight - 16 + 'px';
}
}
};
function onIdxChange(rel) {
const onIdxChange = rel => {
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
currentItem = currentItems[currentIdx];
@ -54,7 +70,7 @@ function onIdxChange(rel) {
preview.setIndex(currentIdx + 1, currentItems.length);
preview.setRawLink(currentItem.absHref);
jq('#pv-content').hide();
dom('#pv-content').hide();
if (preview.isSpinnerVisible()) {
preview.showSpinner(true, currentItem.icon);
} else {
@ -74,36 +90,36 @@ function onIdxChange(rel) {
let $code;
if (type === 'none') {
$text = jq(tplMarkdown).text(textContent);
$text = dom(tplMarkdown).text(textContent);
} else if (type === 'fixed') {
$text = jq(tplText).text(textContent);
$text = dom(tplText).text(textContent);
} else if (type === 'markdown') {
$text = jq(tplMarkdown).html(marked(textContent));
$text = dom(tplMarkdown).html(marked(textContent));
} else {
$text = jq(tplText);
$code = jq('<code/>').appendTo($text);
$text = dom(tplText);
$code = dom('<code/>').appTo($text);
if (textContent.length < 20000) {
$code.empty().html(prism.highlight(textContent, prism.languages[type]));
$code.clr().html(prism.highlight(textContent, prism.languages[type]));
} else {
$code.empty().text(textContent);
$code.clr().text(textContent);
win.setTimeout(() => {
$code.empty().html(prism.highlight(textContent, prism.languages[type]));
$code.clr().html(prism.highlight(textContent, prism.languages[type]));
}, 300);
}
}
win.clearTimeout(spinnerTimeoutId);
preview.showSpinner(false);
jq('#pv-content')
.empty()
.append($text)
dom('#pv-content')
.clr()
.app($text)
.show();
onAdjustSize();
});
}
};
function onEnter(items, idx) {
const onEnter = (items, idx) => {
currentItems = items;
currentIdx = idx;
currentItem = items[idx];
@ -111,14 +127,14 @@ function onEnter(items, idx) {
preview.setOnAdjustSize(onAdjustSize);
preview.enter();
onIdxChange(0);
}
};
function initItem(item) {
const initItem = item => {
if (item.$view && includes(keys(settings.types), item.type)) {
item.$view.find('a').on('click', ev => {
ev.preventDefault();
const matchedItems = compact(map(jq('#items .item'), el => {
const matchedItems = compact(dom('#items .item').map(el => {
const matchedItem = el._item;
return includes(keys(settings.types), matchedItem.type) ? matchedItem : null;
}));
@ -126,19 +142,17 @@ function initItem(item) {
onEnter(matchedItems, matchedItems.indexOf(item));
});
}
}
};
function onViewChanged(added) {
each(added, initItem);
}
const onViewChanged = added => each(added, initItem);
function init() {
const init = () => {
if (!settings.enabled) {
return;
}
event.sub('view.changed', onViewChanged);
}
};
init();

View file

@ -1,5 +1,5 @@
const {each, isFn, isNum} = require('../util');
const {win, jq} = require('../globals');
const {each, isFn, isNum, dom} = require('../util');
const {win} = require('../globals');
const resource = require('../core/resource');
const allsettings = require('../core/settings');
const store = require('../core/store');
@ -8,10 +8,9 @@ const store = require('../core/store');
const settings = Object.assign({
enabled: true
}, allsettings.preview);
const $window = jq(win);
const tplOverlay =
`<div id="pv-overlay">
<div id="pv-content"/>
<div id="pv-content"></div>
<div id="pv-spinner"><img class="back"/><img class="spinner" src="${resource.image('spinner')}"/></div>
<div id="pv-prev-area" class="hof"><img src="${resource.image('preview-prev')}"/></div>
<div id="pv-next-area" class="hof"><img src="${resource.image('preview-next')}"/></div>
@ -34,193 +33,194 @@ let onAdjustSize = null;
let spinnerVisible = false;
function adjustSize() {
const winWidth = $window.width();
const winHeight = $window.height();
const $container = jq('#pv-content');
const $spinner = jq('#pv-spinner');
const adjustSize = () => {
const docEl = win.document.documentElement;
const winWidth = docEl.clientWidth;
const winHeight = docEl.clientHeight;
const margin = isFullscreen ? 0 : 20;
const barHeight = isFullscreen ? 0 : 48;
$container.css({
width: winWidth - 2 * margin,
height: winHeight - 2 * margin - barHeight,
left: margin,
top: margin
dom('#pv-content').css({
width: winWidth - 2 * margin + 'px',
height: winHeight - 2 * margin - barHeight + 'px',
left: margin + 'px',
top: margin + 'px'
});
$spinner.css({
left: winWidth * 0.5,
top: winHeight * 0.5
dom('#pv-spinner').css({
left: winWidth * 0.5 + 'px',
top: winHeight * 0.5 + 'px'
});
if (isFullscreen) {
jq('#pv-overlay').addClass('fullscreen');
jq('#pv-bar-fullscreen').find('img').attr('src', resource.image('preview-no-fullscreen'));
dom('#pv-overlay').addCls('fullscreen');
dom('#pv-bar-fullscreen').find('img').attr('src', resource.image('preview-no-fullscreen'));
} else {
jq('#pv-overlay').removeClass('fullscreen');
jq('#pv-bar-fullscreen').find('img').attr('src', resource.image('preview-fullscreen'));
dom('#pv-overlay').rmCls('fullscreen');
dom('#pv-bar-fullscreen').find('img').attr('src', resource.image('preview-fullscreen'));
}
if (isFn(onAdjustSize)) {
onAdjustSize(1);
}
}
};
function setLabels(labels) {
jq('#pv-buttons .bar-left').remove();
const setLabels = labels => {
dom('#pv-buttons .bar-left').rm();
each(labels, label => {
jq('<li/>')
.addClass('bar-left bar-label')
dom('<li></li>')
.addCls('bar-left')
.addCls('bar-label')
.text(label)
.appendTo('#pv-buttons');
.appTo('#pv-buttons');
});
}
};
function onNext() {
const onNext = () => {
if (isFn(onIndexChange)) {
onIndexChange(1);
}
}
};
function onPrevious() {
const onPrevious = () => {
if (isFn(onIndexChange)) {
onIndexChange(-1);
}
}
};
function userAlive() {
const userAlive = () => {
const $hof = dom('#pv-overlay .hof');
win.clearTimeout(userAliveTimeoutId);
jq('#pv-overlay .hof').stop(true, true).fadeIn(200);
$hof.show();
if (isFullscreen) {
userAliveTimeoutId = win.setTimeout(() => {
jq('#pv-overlay .hof').stop(true, true).fadeOut(2000);
}, 2000);
userAliveTimeoutId = win.setTimeout(() => $hof.hide(), 2000);
}
}
};
function onFullscreen() {
const onFullscreen = () => {
isFullscreen = !isFullscreen;
store.put(storekey, isFullscreen);
userAlive();
adjustSize();
}
};
function onKeydown(ev) {
const key = ev.which;
const dropEvent = ev => {
ev.stopPropagation();
ev.preventDefault();
};
const onKeydown = ev => {
const key = ev.keyCode;
if (key === 27) { // esc
ev.preventDefault();
ev.stopImmediatePropagation();
dropEvent(ev);
onExit(); // eslint-disable-line no-use-before-define
} else if (key === 8 || key === 37) { // backspace, left
ev.preventDefault();
ev.stopImmediatePropagation();
dropEvent(ev);
onPrevious();
} else if (key === 13 || key === 32 || key === 39) { // enter, space, right
ev.preventDefault();
ev.stopImmediatePropagation();
dropEvent(ev);
onNext();
} else if (key === 70) { // f
ev.preventDefault();
ev.stopImmediatePropagation();
dropEvent(ev);
onFullscreen();
}
}
};
function onEnter() {
const onEnter = () => {
setLabels([]);
jq('#pv-content').empty();
jq('#pv-overlay').stop(true, true).fadeIn(200);
$window.on('keydown', onKeydown);
dom('#pv-content').clr();
dom('#pv-overlay').show();
dom(win).on('keydown', onKeydown);
adjustSize();
}
};
function onExit() {
$window.off('keydown', onKeydown);
jq('#pv-overlay').stop(true, true).fadeOut(200, () => {
jq('#pv-content').empty();
setLabels([]);
});
}
const onExit = () => {
setLabels([]);
dom('#pv-content').clr();
dom('#pv-overlay').hide();
dom(win).off('keydown', onKeydown);
};
function setIndex(idx, total) {
const setIndex = (idx, total) => {
if (isNum(idx)) {
jq('#pv-bar-idx').text(String(idx) + (isNum(total) ? '/' + String(total) : '')).show();
dom('#pv-bar-idx').text(String(idx) + (isNum(total) ? '/' + String(total) : '')).show();
} else {
jq('#pv-bar-idx').text('').hide();
dom('#pv-bar-idx').text('').hide();
}
}
};
function setRawLink(href) {
const setRawLink = href => {
if (href) {
jq('#pv-bar-raw').show().find('a').attr('href', href);
dom('#pv-bar-raw').show().find('a').attr('href', href);
} else {
jq('#pv-bar-raw').hide().find('a').attr('href', '#');
dom('#pv-bar-raw').hide().find('a').attr('href', '#');
}
}
};
function setOnIndexChange(fn) {
const setOnIndexChange = fn => {
onIndexChange = fn;
}
};
function setOnAdjustSize(fn) {
const setOnAdjustSize = fn => {
onAdjustSize = fn;
}
};
function showSpinner(show, src, millis) {
if (!isNum(millis)) {
millis = 300;
}
const $spinner = jq('#pv-spinner').stop(true, true);
const $back = $spinner.find('.back');
const showSpinner = (show, src) => {
const $spinner = dom('#pv-spinner');
if (show) {
const $back = $spinner.find('.back');
if (src) {
$back.attr('src', src).show();
} else {
$back.hide();
}
spinnerVisible = true;
$spinner.fadeIn(millis);
$spinner.show();
} else {
spinnerVisible = false;
$spinner.fadeOut(millis);
$spinner.hide();
}
}
};
function isSpinnerVisible() {
const isSpinnerVisible = () => {
return spinnerVisible;
}
};
function init() {
const init = () => {
if (!settings.enabled) {
return;
}
jq(tplOverlay).appendTo('body');
jq('#pv-spinner').hide();
jq('#pv-bar-prev, #pv-prev-area').on('click', onPrevious);
jq('#pv-bar-next, #pv-next-area').on('click', onNext);
jq('#pv-bar-close').on('click', onExit);
jq('#pv-bar-fullscreen').on('click', onFullscreen);
jq('#pv-overlay')
dom(tplOverlay)
.hide()
.appTo('body')
.on('keydown', onKeydown)
.on('mousemove mousedown', userAlive)
.on('click mousedown mousemove keydown keypress', ev => {
if (ev.type === 'click' && (ev.target.id === 'pv-overlay' || ev.target.id === 'pv-content')) {
.on('mousemove', userAlive)
.on('mousedown', userAlive)
.on('click', ev => {
if (ev.target.id === 'pv-overlay' || ev.target.id === 'pv-content') {
onExit();
}
ev.stopImmediatePropagation();
});
dropEvent(ev);
})
.on('mousedown', dropEvent)
.on('mousemove', dropEvent)
.on('keydown', dropEvent)
.on('keypress', dropEvent);
$window.on('resize load', adjustSize);
}
dom('#pv-spinner').hide();
dom('#pv-bar-prev, #pv-prev-area').on('click', onPrevious);
dom('#pv-bar-next, #pv-next-area').on('click', onNext);
dom('#pv-bar-close').on('click', onExit);
dom('#pv-bar-fullscreen').on('click', onFullscreen);
dom(win)
.on('resize', adjustSize)
.on('load', adjustSize);
};
init();

View file

@ -87,12 +87,12 @@ const selectionUpdate = ev => {
$html.addCls('drag-select');
$selectionRect.show();
const style = $selectionRect[0].style;
style.left = left + 'px';
style.top = top + 'px';
style.width = width + 'px';
style.height = height + 'px';
$selectionRect.show().css({
left: left + 'px',
top: top + 'px',
width: width + 'px',
height: height + 'px'
});
const selRect = elRect($selectionRect);
const $items = dom('#items .item:not(.folder-parent)');

View file

@ -273,6 +273,10 @@ dom.prototype = {
isHidden() {
return this.hasCls('hidden');
},
css(styles) {
return this.each(el => Object.assign(el.style, styles));
}
};