Begin to move all src javascript to es6. Add search/filter ignore case option.

This commit is contained in:
Lars Jung 2016-06-02 23:16:23 +02:00
parent f37e8e7b89
commit 7ec2bdf16a
58 changed files with 3546 additions and 3420 deletions

View file

@ -1,37 +1,41 @@
modulejs.define('ext/autorefresh', ['_', '$', 'core/event', 'core/location', 'core/settings'], function (_, $, event, location, allsettings) {
var settings = _.extend({
enabled: false,
interval: 5000
}, allsettings.autorefresh);
var timeoutId = null;
const {setTimeout} = require('../win');
const event = require('../core/event');
const location = require('../core/location');
const allsettings = require('../core/settings');
function heartbeat() {
location.refresh();
const settings = Object.assign({
enabled: false,
interval: 5000
}, allsettings.autorefresh);
let timeoutId = null;
function heartbeat() {
location.refresh();
}
function before() {
clearTimeout(timeoutId);
}
function after() {
clearTimeout(timeoutId);
timeoutId = setTimeout(heartbeat, settings.interval);
}
function init() {
if (!settings.enabled) {
return;
}
function before() {
clearTimeout(timeoutId);
}
settings.interval = Math.max(1000, settings.interval);
function after() {
clearTimeout(timeoutId);
timeoutId = setTimeout(heartbeat, settings.interval);
}
function init() {
if (!settings.enabled) {
return;
}
settings.interval = Math.max(1000, settings.interval);
event.sub('location.beforeChange', before);
event.sub('location.beforeRefresh', before);
event.sub('location.changed', after);
event.sub('location.refreshed', after);
}
event.sub('location.beforeChange', before);
event.sub('location.beforeRefresh', before);
event.sub('location.changed', after);
event.sub('location.refreshed', after);
}
init();
});
init();

View file

@ -1,163 +1,162 @@
modulejs.define('ext/contextmenu', ['_', '$', 'core/resource', 'core/settings'], function (_, $, resource, allsettings) {
var settings = _.extend({
enabled: false
}, allsettings.contextmenu);
var templateOverlay = '<div id="cm-overlay"/>';
var templatePanel = '<div class="cm-panel"><ul/></div>';
var templateSep = '<li class="cm-sep"/>';
var templateEntry = '<li class="cm-entry"><span class="cm-icon"><img/></span><span class="cm-text"/></li>';
var templateLabel = '<li class="cm-label"><span class="cm-text"/></li>';
const {document: doc, jQuery: jq, _: lo} = require('../win');
const resource = require('../core/resource');
const allsettings = require('../core/settings');
const settings = lo.extend({
enabled: false
}, allsettings.contextmenu);
const templateOverlay = '<div id="cm-overlay"/>';
const templatePanel = '<div class="cm-panel"><ul/></div>';
const templateSep = '<li class="cm-sep"/>';
const templateEntry = '<li class="cm-entry"><span class="cm-icon"><img/></span><span class="cm-text"/></li>';
const templateLabel = '<li class="cm-label"><span class="cm-text"/></li>';
function createOverlay(callback) {
var $overlay = $(templateOverlay);
function createOverlay(callback) {
const $overlay = jq(templateOverlay);
$overlay
.on('click contextmenu', function (ev) {
ev.stopPropagation();
ev.preventDefault();
$overlay
.on('click contextmenu', ev => {
ev.stopPropagation();
ev.preventDefault();
var cmId = $(ev.target).closest('.cm-entry').data('cm-id');
const cmId = jq(ev.target).closest('.cm-entry').data('cm-id');
if (ev.target === $overlay[0] || cmId !== undefined) {
$overlay.remove();
callback(cmId);
}
});
return $overlay;
}
function createPanel(menu) {
var $panel = $(templatePanel);
var $ul = $panel.find('ul');
var $li;
_.each(menu, function (entry) {
if (entry.type === '-') {
$(templateSep).appendTo($ul);
} else if (entry.type === 'l') {
$(templateLabel).appendTo($ul)
.find('.cm-text').text(entry.text);
} else if (entry.type === 'e') {
$li = $(templateEntry).appendTo($ul);
$li.data('cm-id', entry.id);
$li.find('.cm-text').text(entry.text);
if (entry.icon) {
$li.find('.cm-icon img').attr('src', resource.icon(entry.icon));
} else {
$li.find('.cm-icon').addClass('no-icon');
}
if (ev.target === $overlay[0] || cmId !== undefined) {
$overlay.remove();
callback(cmId);
}
});
return $panel;
return $overlay;
}
function createPanel(menu) {
const $panel = jq(templatePanel);
const $ul = $panel.find('ul');
let $li;
lo.each(menu, entry => {
if (entry.type === '-') {
jq(templateSep).appendTo($ul);
} else if (entry.type === 'l') {
jq(templateLabel).appendTo($ul)
.find('.cm-text').text(entry.text);
} else if (entry.type === 'e') {
$li = jq(templateEntry).appendTo($ul);
$li.data('cm-id', entry.id);
$li.find('.cm-text').text(entry.text);
if (entry.icon) {
$li.find('.cm-icon img').attr('src', resource.icon(entry.icon));
} else {
$li.find('.cm-icon').addClass('no-icon');
}
}
});
return $panel;
}
function positionPanel($overlay, $panel, x, y) {
const margin = 4;
$panel.css({
left: 0,
top: 0,
opacity: 0
});
$overlay.show();
const overlayOffset = $overlay.offset();
const overlayLeft = overlayOffset.left;
const overlayTop = overlayOffset.top;
const overlayWidth = $overlay.outerWidth(true);
const overlayHeight = $overlay.outerHeight(true);
// const panelOffset = $panel.offset();
// const panelLeft = panelOffset.left;
// const panelTop = panelOffset.top;
let panelWidth = $panel.outerWidth(true);
let panelHeight = $panel.outerHeight(true);
let posLeft = x;
let posTop = y;
if (panelWidth > overlayWidth - 2 * margin) {
posLeft = margin;
panelWidth = overlayWidth - 2 * margin;
}
function positionPanel($overlay, $panel, x, y) {
var margin = 4;
$panel.css({
left: 0,
top: 0,
opacity: 0
});
$overlay.show();
var overlayOffset = $overlay.offset();
var overlayLeft = overlayOffset.left;
var overlayTop = overlayOffset.top;
var overlayWidth = $overlay.outerWidth(true);
var overlayHeight = $overlay.outerHeight(true);
// var panelOffset = $panel.offset();
// var panelLeft = panelOffset.left;
// var panelTop = panelOffset.top;
var panelWidth = $panel.outerWidth(true);
var panelHeight = $panel.outerHeight(true);
var posLeft = x;
var posTop = y;
if (panelWidth > overlayWidth - 2 * margin) {
posLeft = margin;
panelWidth = overlayWidth - 2 * margin;
}
if (panelHeight > overlayHeight - 2 * margin) {
posTop = margin;
panelHeight = overlayHeight - 2 * margin;
}
if (posLeft < overlayLeft + margin) {
posLeft = overlayLeft + margin;
}
if (posLeft + panelWidth > overlayLeft + overlayWidth - margin) {
posLeft = overlayLeft + overlayWidth - margin - panelWidth;
}
if (posTop < overlayTop + margin) {
posTop = overlayTop + margin;
}
if (posTop + panelHeight > overlayTop + overlayHeight - margin) {
posTop = overlayTop + overlayHeight - margin - panelHeight;
}
$panel.css({
left: posLeft,
top: posTop,
width: panelWidth,
height: panelHeight,
opacity: 1
});
if (panelHeight > overlayHeight - 2 * margin) {
posTop = margin;
panelHeight = overlayHeight - 2 * margin;
}
function showMenuAt(x, y, menu, callback) {
var $overlay = createOverlay(callback);
var $panel = createPanel(menu);
$overlay.append($panel).appendTo('body');
positionPanel($overlay, $panel, x, y);
if (posLeft < overlayLeft + margin) {
posLeft = overlayLeft + margin;
}
function init() {
// settings.enabled = true;
if (!settings.enabled) {
return;
}
$(document).on('contextmenu', function (ev) {
ev.stopPropagation();
ev.preventDefault();
$(ev.target).trigger($.Event('h5ai-contextmenu', {
originalEvent: ev,
showMenu: function (menu, callback) {
showMenuAt(ev.pageX, ev.pageY, menu, callback);
}
}));
});
// var menu = [
// {type: 'e', id: 'e1', text: 'testing context menus'},
// {type: 'e', id: 'e2', text: 'another entry'},
// {type: 'e', id: 'e3', text: 'one with icon', icon: 'folder'},
// {type: '-'},
// {type: 'e', id: 'e4', text: 'one with icon', icon: 'x'},
// {type: 'e', id: 'e5', text: 'one with icon', icon: 'img'}
// ];
// var callback = function (res) {
// window.console.log('>> CB-RESULT >> ' + res);
// };
// $(document).on('h5ai-contextmenu', '#items .item.folder', function (ev) {
// window.console.log('CM', ev);
// ev.showMenu(menu, callback);
// });
if (posLeft + panelWidth > overlayLeft + overlayWidth - margin) {
posLeft = overlayLeft + overlayWidth - margin - panelWidth;
}
if (posTop < overlayTop + margin) {
posTop = overlayTop + margin;
}
init();
});
if (posTop + panelHeight > overlayTop + overlayHeight - margin) {
posTop = overlayTop + overlayHeight - margin - panelHeight;
}
$panel.css({
left: posLeft,
top: posTop,
width: panelWidth,
height: panelHeight,
opacity: 1
});
}
function showMenuAt(x, y, menu, callback) {
const $overlay = createOverlay(callback);
const $panel = createPanel(menu);
$overlay.append($panel).appendTo('body');
positionPanel($overlay, $panel, x, y);
}
function init() {
if (!settings.enabled) {
return;
}
jq(doc).on('contextmenu', ev => {
ev.stopPropagation();
ev.preventDefault();
jq(ev.target).trigger(jq.Event('h5ai-contextmenu', {
originalEvent: ev,
showMenu: (menu, callback) => {
showMenuAt(ev.pageX, ev.pageY, menu, callback);
}
}));
});
// const menu = [
// {type: 'e', id: 'e1', text: 'testing context menus'},
// {type: 'e', id: 'e2', text: 'another entry'},
// {type: 'e', id: 'e3', text: 'one with icon', icon: 'folder'},
// {type: '-'},
// {type: 'e', id: 'e4', text: 'one with icon', icon: 'x'},
// {type: 'e', id: 'e5', text: 'one with icon', icon: 'img'}
// ];
// const callback = res => {
// console.log('>> CB-RESULT >> ' + res);
// };
//
// jq(doc).on('h5ai-contextmenu', '#items .item.folder', ev => {
// console.log('CM', ev);
// ev.showMenu(menu, callback);
// });
}
init();

View file

@ -1,58 +1,65 @@
modulejs.define('ext/crumb', ['_', '$', 'core/event', 'core/location', 'core/resource', 'core/settings', 'view/topbar'], function (_, $, event, location, resource, allsettings, topbar) {
var settings = _.extend({
enabled: false
}, allsettings.crumb);
var crumbTemplate =
'<a class="crumb">' +
'<img class="sep" src="' + resource.image('crumb') + '" alt=">"/>' +
'<span class="label"/>' +
'</a>';
var pageHintTemplate = '<img class="hint" src="' + resource.icon('folder-page') + '" alt="has index page"/>';
var $crumbbar;
const {jQuery: jq, _: lo} = require('../win');
const event = require('../core/event');
const location = require('../core/location');
const resource = require('../core/resource');
const allsettings = require('../core/settings');
const topbar = require('../view/topbar');
function createHtml(item) {
var $html = $(crumbTemplate).data('item', item);
item.$crumb = $html;
location.setLink($html, item);
const settings = lo.extend({
enabled: false
}, allsettings.crumb);
const crumbTemplate =
`<a class="crumb">
<img class="sep" src="${resource.image('crumb')}" alt=">"/>
<span class="label"/>
</a>`;
const pageHintTemplate =
`<img class="hint" src="${resource.icon('folder-page')}" alt="has index page"/>`;
let $crumbbar;
$html.find('.label').text(item.label);
if (item.isCurrentFolder()) {
$html.addClass('active');
}
function createHtml(item) {
const $html = jq(crumbTemplate).data('item', item);
item.$crumb = $html;
location.setLink($html, item);
if (!item.isManaged) {
$html.append($(pageHintTemplate));
}
$html.find('.label').text(item.label);
return $html;
if (item.isCurrentFolder()) {
$html.addClass('active');
}
function onLocationChanged(item) {
var $crumb = item.$crumb;
if ($crumb && $crumb.parent()[0] === $crumbbar[0]) {
$crumbbar.children().removeClass('active');
$crumb.addClass('active');
} else {
$crumbbar.empty();
_.each(item.getCrumb(), function (crumbItem) {
$crumbbar.append(createHtml(crumbItem));
});
}
if (!item.isManaged) {
$html.append(jq(pageHintTemplate));
}
function init() {
if (!settings.enabled) {
return;
}
return $html;
}
$crumbbar = $('<div id="crumbbar"/>').appendTo(topbar.$flowbar);
function onLocationChanged(item) {
const $crumb = item.$crumb;
event.sub('location.changed', onLocationChanged);
if ($crumb && $crumb.parent()[0] === $crumbbar[0]) {
$crumbbar.children().removeClass('active');
$crumb.addClass('active');
} else {
$crumbbar.empty();
lo.each(item.getCrumb(), crumbItem => {
$crumbbar.append(createHtml(crumbItem));
});
}
}
function init() {
if (!settings.enabled) {
return;
}
$crumbbar = jq('<div id="crumbbar"/>').appendTo(topbar.$flowbar);
init();
});
event.sub('location.changed', onLocationChanged);
}
init();

View file

@ -1,62 +1,66 @@
modulejs.define('ext/custom', ['_', '$', 'marked', 'core/event', 'core/server', 'core/settings'], function (_, $, marked, event, server, allsettings) {
var settings = _.extend({
enabled: false
}, allsettings.custom);
var $header;
var $footer;
var duration = 200;
const {jQuery: jq, _: lo, marked} = require('../win');
const event = require('../core/event');
const server = require('../core/server');
const allsettings = require('../core/settings');
function onLocationChanged(item) {
server.request({action: 'get', custom: item.absHref}, function (response) {
var custom = response && response.custom;
var hasHeader;
var hasFooter;
const settings = lo.extend({
enabled: false
}, allsettings.custom);
let $header;
let $footer;
const duration = 200;
if (custom) {
var header = custom.header;
var footer = custom.footer;
var content;
if (header.content) {
content = header.content;
if (header.type === 'md') {
content = marked(content);
}
$header.html(content).stop().slideDown(duration);
hasHeader = true;
function onLocationChanged(item) {
server.request({action: 'get', custom: item.absHref}).then(response => {
const custom = response && response.custom;
let hasHeader;
let hasFooter;
if (custom) {
const header = custom.header;
const footer = custom.footer;
let content;
if (header.content) {
content = header.content;
if (header.type === 'md') {
content = marked(content);
}
$header.html(content).stop().slideDown(duration);
hasHeader = true;
}
if (footer.content) {
content = footer.content;
if (footer.type === 'md') {
content = marked(content);
}
$footer.html(content).stop().slideDown(duration);
hasFooter = true;
if (footer.content) {
content = footer.content;
if (footer.type === 'md') {
content = marked(content);
}
$footer.html(content).stop().slideDown(duration);
hasFooter = true;
}
if (!hasHeader) {
$header.stop().slideUp(duration);
}
if (!hasFooter) {
$footer.stop().slideUp(duration);
}
});
}
function init() {
if (!settings.enabled) {
return;
}
$header = $('<div id="content-header"/>').hide().prependTo('#content');
$footer = $('<div id="content-footer"/>').hide().appendTo('#content');
if (!hasHeader) {
$header.stop().slideUp(duration);
}
if (!hasFooter) {
$footer.stop().slideUp(duration);
}
});
}
event.sub('location.changed', onLocationChanged);
function init() {
if (!settings.enabled) {
return;
}
$header = jq('<div id="content-header"/>').hide().prependTo('#content');
$footer = jq('<div id="content-footer"/>').hide().appendTo('#content');
init();
});
event.sub('location.changed', onLocationChanged);
}
init();

View file

@ -1,71 +1,76 @@
modulejs.define('ext/download', ['_', '$', 'core/event', 'core/location', 'core/resource', 'core/server', 'core/settings'], function (_, $, event, location, resource, server, allsettings) {
var settings = _.extend({
enabled: false,
type: 'php-tar',
packageName: 'package',
alwaysVisible: false
}, allsettings.download);
var template =
'<div id="download" class="tool">' +
'<img src="' + resource.image('download') + '" alt="download"/>' +
'</div>';
var selectedItems = [];
var $download;
const {jQuery: jq, _: lo} = require('../win');
const event = require('../core/event');
const location = require('../core/location');
const resource = require('../core/resource');
const server = require('../core/server');
const allsettings = require('../core/settings');
const settings = lo.extend({
enabled: false,
type: 'php-tar',
packageName: 'package',
alwaysVisible: false
}, allsettings.download);
const template =
`<div id="download" class="tool">
<img src="${resource.image('download')}" alt="download"/>
</div>`;
let selectedItems = [];
let $download;
function onSelection(items) {
selectedItems = items.slice(0);
if (selectedItems.length) {
$download.show();
} else if (!settings.alwaysVisible) {
$download.hide();
function onSelection(items) {
selectedItems = items.slice(0);
if (selectedItems.length) {
$download.show();
} else if (!settings.alwaysVisible) {
$download.hide();
}
}
function onClick() {
const type = settings.type;
let name = settings.packageName;
const extension = type === 'shell-zip' ? 'zip' : 'tar';
if (!name) {
if (selectedItems.length === 1) {
name = selectedItems[0].label;
} else {
name = location.getItem().label;
}
}
function onClick() {
var type = settings.type;
var name = settings.packageName;
var extension = type === 'shell-zip' ? 'zip' : 'tar';
const query = {
action: 'download',
as: name + '.' + extension,
type,
baseHref: location.getAbsHref()
};
if (!name) {
if (selectedItems.length === 1) {
name = selectedItems[0].label;
} else {
name = location.getItem().label;
}
}
lo.each(selectedItems, (item, idx) => {
query['hrefs[' + idx + ']'] = item.absHref;
});
var query = {
action: 'download',
as: name + '.' + extension,
type: type,
baseHref: location.getAbsHref()
};
server.formRequest(query);
}
_.each(selectedItems, function (item, idx) {
query['hrefs[' + idx + ']'] = item.absHref;
});
server.formRequest(query);
function init() {
if (!settings.enabled) {
return;
}
function init() {
if (!settings.enabled) {
return;
}
$download = jq(template)
.hide()
.appendTo('#toolbar')
.on('click', onClick);
$download = $(template)
.hide()
.appendTo('#toolbar')
.on('click', onClick);
if (settings.alwaysVisible) {
$download.show();
}
event.sub('selection', onSelection);
if (settings.alwaysVisible) {
$download.show();
}
event.sub('selection', onSelection);
}
init();
});
init();

View file

@ -1,83 +1,91 @@
modulejs.define('ext/filter', ['_', '$', 'core/event', 'core/location', 'core/resource', 'core/settings', 'core/util', 'view/view'], function (_, $, event, location, resource, allsettings, util, view) {
var settings = _.extend({
enabled: false,
advanced: false,
debounceTime: 100
}, allsettings.filter);
var template =
'<div id="filter" class="tool">' +
'<img src="' + resource.image('filter') + '" alt="filter"/>' +
'<input class="l10n_ph-filter" type="text" value=""/>' +
'</div>';
var inputIsVisible = false;
var prevPattern = '';
var $filter;
var $input;
const {jQuery: jq, _: lo} = require('../win');
const event = require('../core/event');
const location = require('../core/location');
const resource = require('../core/resource');
const allsettings = require('../core/settings');
const util = require('../core/util');
const view = require('../view/view');
function filter(pattern) {
pattern = pattern || '';
if (pattern === prevPattern) {
return;
const settings = lo.extend({
enabled: false,
advanced: false,
debounceTime: 100,
ignorecase: true
}, allsettings.filter);
const template =
`<div id="filter" class="tool">
<img src="${resource.image('filter')}" alt="filter"/>
<input class="l10n_ph-filter" type="text" value=""/>
</div>`;
let inputIsVisible = false;
let prevPattern = '';
let $filter;
let $input;
function filter(pattern) {
pattern = pattern || '';
if (pattern === prevPattern) {
return;
}
prevPattern = pattern;
if (!pattern) {
view.setLocation();
return;
}
$filter.addClass('pending');
const re = new RegExp(pattern, settings.ignorecase ? 'i' : '');
const matchedItems = [];
lo.each(location.getItem().content, item => {
if (re.test(item.label)) {
matchedItems.push(item);
}
prevPattern = pattern;
});
if (!pattern) {
view.setLocation();
return;
}
$filter.removeClass('pending');
view.setHint('noMatch');
view.setItems(matchedItems);
}
$filter.addClass('pending');
function update() {
if (inputIsVisible) {
$filter.addClass('active');
$input.focus();
filter(util.parsePattern($input.val(), settings.advanced));
} else {
filter();
$filter.removeClass('active');
}
}
var re = new RegExp(pattern);
var matchedItems = [];
function toggle() {
inputIsVisible = !inputIsVisible;
update();
}
_.each(location.getItem().content, function (item) {
if (re.test(item.label)) {
matchedItems.push(item);
}
});
function reset() {
inputIsVisible = false;
$input.val('');
update();
}
$filter.removeClass('pending');
view.setHint('noMatch');
view.setItems(matchedItems);
function init() {
if (!settings.enabled) {
return;
}
function update() {
if (inputIsVisible) {
$filter.addClass('active');
$input.focus();
filter(util.parsePattern($input.val(), settings.advanced));
} else {
filter();
$filter.removeClass('active');
}
}
$filter = jq(template).appendTo('#toolbar');
$input = $filter.find('input');
function toggle() {
inputIsVisible = !inputIsVisible;
update();
}
function reset() {
inputIsVisible = false;
$input.val('');
update();
}
function init() {
if (!settings.enabled) {
return;
}
$filter = $(template).appendTo('#toolbar');
$input = $filter.find('input');
$filter.on('click', 'img', toggle);
$input.on('keyup', _.debounce(update, settings.debounceTime, {trailing: true}));
event.sub('location.changed', reset);
}
$filter.on('click', 'img', toggle);
$input.on('keyup', lo.debounce(update, settings.debounceTime, {trailing: true}));
event.sub('location.changed', reset);
}
init();
});
init();

View file

@ -1,37 +1,38 @@
modulejs.define('ext/google-analytics-ua', ['_', 'core/event', 'core/settings'], function (_, event, allsettings) {
var settings = _.extend({
enabled: false,
id: 'UA-000000-0'
}, allsettings['google-analytics-ua']);
const {window: win, _: lo} = require('../win');
const event = require('../core/event');
const allsettings = require('../core/settings');
function snippet() {
/* eslint-disable */
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
/* eslint-enable */
const settings = lo.extend({
enabled: false,
id: 'UA-000000-0'
}, allsettings['google-analytics-ua']);
function snippet() {
/* eslint-disable */
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
/* eslint-enable */
}
function init() {
if (!settings.enabled) {
return;
}
function init() {
if (!settings.enabled) {
return;
}
snippet();
snippet();
win.ga('create', settings.id, 'auto');
var WIN = window;
var GA = 'ga';
WIN[GA]('create', settings.id, 'auto');
event.sub('location.changed', function (item) {
var loc = WIN.location;
WIN[GA]('send', 'pageview', {
location: loc.protocol + '//' + loc.host + item.absHref,
title: _.map(item.getCrumb(), 'label').join(' > ')
});
event.sub('location.changed', item => {
const loc = win.location;
win.ga('send', 'pageview', {
location: loc.protocol + '//' + loc.host + item.absHref,
title: lo.map(item.getCrumb(), 'label').join(' > ')
});
}
});
}
init();
});
init();

View file

@ -1,154 +1,161 @@
modulejs.define('ext/info', ['_', '$', 'core/event', 'core/format', 'core/modernizr', 'core/resource', 'core/settings', 'core/store'], function (_, $, event, format, modernizr, resource, allsettings, store) {
var settings = _.extend({
enabled: false,
show: false,
qrcode: true,
qrColor: '#999'
}, allsettings.info);
var template =
'<div id="info">' +
'<div class="icon"><img/></div>' +
'<div class="block">' +
'<div class="label"/>' +
'<div class="time"/>' +
'<div class="size"/>' +
'<div class="content">' +
'<span class="folders"/> <span class="l10n-folders"/>, ' +
'<span class="files"/> <span class="l10n-files"/>' +
'</div>' +
'</div>' +
'<div class="qrcode"/>' +
'</div>';
var settingsTemplate =
'<div class="block">' +
'<h1 class="l10n-info">Info</h1>' +
'<div id="view-info" class="button view">' +
'<img src="' + resource.image('info-toggle') + '" alt="view-info"/>' +
'</div>' +
'</div>';
var storekey = 'ext/info';
var $img;
var $label;
var $time;
var $size;
var $content;
var $folders;
var $files;
var $qrcode;
var currentFolder;
const {window: win, jQuery: jq, _: lo} = require('../win');
const event = require('../core/event');
const format = require('../core/format');
const modernizr = require('../core/modernizr');
const resource = require('../core/resource');
const allsettings = require('../core/settings');
const store = require('../core/store');
function updateSettings() {
if (store.get(storekey)) {
$('#view-info').addClass('active');
$('#info').show();
} else {
$('#view-info').removeClass('active');
$('#info').hide();
}
const settings = lo.extend({
enabled: false,
show: false,
qrcode: true,
qrColor: '#999'
}, allsettings.info);
const template =
`<div id="info">
<div class="icon"><img/></div>
<div class="block">
<div class="label"/>
<div class="time"/>
<div class="size"/>
<div class="content">
<span class="folders"/> <span class="l10n-folders"/>,
<span class="files"/> <span class="l10n-files"/>
</div>
</div>
<div class="qrcode"/>
</div>`;
const settingsTemplate =
`<div class="block">
<h1 class="l10n-info">Info</h1>
<div id="view-info" class="button view">
<img src="${resource.image('info-toggle')}" alt="view-info"/>
</div>
</div>`;
const storekey = 'ext/info';
let $img;
let $label;
let $time;
let $size;
let $content;
let $folders;
let $files;
let $qrcode;
let currentFolder;
function updateSettings() {
if (store.get(storekey)) {
jq('#view-info').addClass('active');
jq('#info').show();
} else {
jq('#view-info').removeClass('active');
jq('#info').hide();
}
}
function update(item) {
let src = item.thumbRational || item.icon;
const isThumb = Boolean(item.thumbRational);
if (item.isCurrentFolder() || !src) {
src = resource.icon('folder');
}
function update(item) {
var src = item.thumbRational || item.icon;
var isThumb = Boolean(item.thumbRational);
if (item.isCurrentFolder() || !src) {
src = resource.icon('folder');
}
$img.attr('src', src);
if (isThumb) {
$img.addClass('thumb');
} else {
$img.removeClass('thumb');
}
$label.text(item.label);
if (_.isNumber(item.time)) {
$time.text(format.formatDate(item.time));
} else {
$time.text('.');
}
if (_.isNumber(item.size)) {
$size.text(format.formatSize(item.size));
$size.show();
} else {
$size.hide();
}
if (item.isContentFetched) {
var stats = item.getStats();
$folders.text(stats.folders);
$files.text(stats.files);
$content.show();
} else {
$content.hide();
}
if (settings.qrcode) {
$qrcode.empty().qrcode({
render: modernizr.canvas ? 'canvas' : 'div',
size: 200,
fill: settings.qrColor,
background: null,
text: window.location.protocol + '//' + window.location.host + item.absHref
});
}
$img.attr('src', src);
if (isThumb) {
$img.addClass('thumb');
} else {
$img.removeClass('thumb');
}
function onMouseenter(item) {
update(item);
$label.text(item.label);
if (lo.isNumber(item.time)) {
$time.text(format.formatDate(item.time));
} else {
$time.text('.');
}
function onMouseleave() {
update(currentFolder);
if (lo.isNumber(item.size)) {
$size.text(format.formatSize(item.size));
$size.show();
} else {
$size.hide();
}
function onLocationChanged(item) {
currentFolder = item;
update(currentFolder);
if (item.isContentFetched) {
const stats = item.getStats();
$folders.text(stats.folders);
$files.text(stats.files);
$content.show();
} else {
$content.hide();
}
function init() {
if (!settings.enabled) {
return;
}
if (settings.qrcode) {
$qrcode.empty().qrcode({
render: modernizr.canvas ? 'canvas' : 'div',
size: 200,
fill: settings.qrColor,
background: null,
text: win.location.protocol + '//' + win.location.host + item.absHref
});
}
}
var $info = $(template).appendTo('#mainrow');
$img = $info.find('.icon img');
$label = $info.find('.label');
$time = $info.find('.time');
$size = $info.find('.size');
$content = $info.find('.content');
$folders = $info.find('.folders');
$files = $info.find('.files');
$qrcode = $info.find('.qrcode');
function onMouseenter(item) {
update(item);
}
if (!settings.qrcode) {
$qrcode.remove();
}
function onMouseleave() {
update(currentFolder);
}
$(settingsTemplate)
.appendTo('#sidebar')
.find('#view-info')
.on('click', function (ev) {
store.put(storekey, !store.get(storekey));
updateSettings();
ev.preventDefault();
});
function onLocationChanged(item) {
currentFolder = item;
update(currentFolder);
}
// ensure stored value is boolean, otherwise set default
if (typeof store.get(storekey) !== 'boolean') {
store.put(storekey, settings.show);
}
updateSettings();
event.sub('location.changed', onLocationChanged);
event.sub('item.mouseenter', onMouseenter);
event.sub('item.mouseleave', onMouseleave);
function init() {
if (!settings.enabled) {
return;
}
const $info = jq(template).appendTo('#mainrow');
$img = $info.find('.icon img');
$label = $info.find('.label');
$time = $info.find('.time');
$size = $info.find('.size');
$content = $info.find('.content');
$folders = $info.find('.folders');
$files = $info.find('.files');
$qrcode = $info.find('.qrcode');
init();
});
if (!settings.qrcode) {
$qrcode.remove();
}
jq(settingsTemplate)
.appendTo('#sidebar')
.find('#view-info')
.on('click', ev => {
store.put(storekey, !store.get(storekey));
updateSettings();
ev.preventDefault();
});
// ensure stored value is boolean, otherwise set default
if (typeof store.get(storekey) !== 'boolean') {
store.put(storekey, settings.show);
}
updateSettings();
event.sub('location.changed', onLocationChanged);
event.sub('item.mouseenter', onMouseenter);
event.sub('item.mouseleave', onMouseleave);
}
init();

View file

@ -1,131 +1,141 @@
modulejs.define('ext/l10n', ['_', '$', 'core/event', 'core/format', 'core/langs', 'core/server', 'core/settings', 'core/store'],
function (_, $, event, format, langs, server, allsettings, store) {
var settings = _.extend({
enabled: false,
lang: 'en',
useBrowserLang: true
}, allsettings.l10n);
var defaultTranslations = {
isoCode: 'en',
lang: 'english',
const {navigator, jQuery: jq, _: lo} = require('../win');
const event = require('../core/event');
const format = require('../core/format');
const langs = require('../core/langs');
const server = require('../core/server');
const allsettings = require('../core/settings');
const store = require('../core/store');
dateFormat: 'YYYY-MM-DD HH:mm',
details: 'details',
download: 'download',
empty: 'empty',
files: 'files',
filter: 'filter',
folders: 'folders',
grid: 'grid',
icons: 'icons',
language: 'Language',
lastModified: 'Last modified',
name: 'Name',
noMatch: 'no match',
parentDirectory: 'Parent Directory',
search: 'search',
size: 'Size',
tree: 'Tree',
view: 'View'
};
var blockTemplate = '<div class="block"><h1 class="l10n-language">Language</h1><div class="select"><select id="langs"/></div></div>';
var optionTemplate = '<option/>';
var storekey = 'ext/l10n';
var loaded = {
en: _.extend({}, defaultTranslations)
};
var currentLang = loaded.en;
const settings = lo.extend({
enabled: false,
lang: 'en',
useBrowserLang: true
}, allsettings.l10n);
const defaultTranslations = {
isoCode: 'en',
lang: 'english',
dateFormat: 'YYYY-MM-DD HH:mm',
details: 'details',
download: 'download',
empty: 'empty',
files: 'files',
filter: 'filter',
folders: 'folders',
grid: 'grid',
icons: 'icons',
language: 'Language',
lastModified: 'Last modified',
name: 'Name',
noMatch: 'no match',
parentDirectory: 'Parent Directory',
search: 'search',
size: 'Size',
tree: 'Tree',
view: 'View'
};
const blockTemplate =
`<div class="block">
<h1 class="l10n-language">Language</h1>
<div class="select">
<select id="langs"/>
</div>
</div>`;
const optionTemplate = '<option/>';
const storekey = 'ext/l10n';
const loaded = {
en: lo.extend({}, defaultTranslations)
};
let currentLang = loaded.en;
function update(lang) {
if (lang) {
currentLang = lang;
}
$('#langs option')
.removeAttr('selected').removeProp('selected')
.filter('.' + currentLang.isoCode)
.attr('selected', 'selected').prop('selected', 'selected');
$.each(currentLang, function (key, value) {
$('.l10n-' + key).text(value);
$('.l10n_ph-' + key).attr('placeholder', value);
});
format.setDefaultDateFormat(currentLang.dateFormat);
$('#items .item .date').each(function () {
var $this = $(this);
$this.text(format.formatDate($this.data('time')));
});
function update(lang) {
if (lang) {
currentLang = lang;
}
function loadLanguage(isoCode, callback) {
if (loaded[isoCode]) {
jq('#langs option')
.removeAttr('selected').removeProp('selected')
.filter('.' + currentLang.isoCode)
.attr('selected', 'selected').prop('selected', 'selected');
jq.each(currentLang, (key, value) => {
jq('.l10n-' + key).text(value);
jq('.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')));
});
}
function loadLanguage(isoCode, callback) {
if (loaded[isoCode]) {
callback(loaded[isoCode]);
} else {
server.request({action: 'get', l10n: [isoCode]}).then(response => {
const json = response.l10n && response.l10n[isoCode] ? response.l10n[isoCode] : {};
loaded[isoCode] = lo.extend({}, defaultTranslations, json, {isoCode});
callback(loaded[isoCode]);
} else {
server.request({action: 'get', l10n: [isoCode]}, function (response) {
var json = response.l10n && response.l10n[isoCode] ? response.l10n[isoCode] : {};
loaded[isoCode] = _.extend({}, defaultTranslations, json, {isoCode: isoCode});
callback(loaded[isoCode]);
});
}
});
}
}
function localize(languages, isoCode, useBrowserLang) {
var storedIsoCode = store.get(storekey);
function localize(languages, isoCode, useBrowserLang) {
const storedIsoCode = store.get(storekey);
if (languages[storedIsoCode]) {
isoCode = storedIsoCode;
} else if (useBrowserLang) {
var browserLang = navigator.language || navigator.browserLanguage;
if (browserLang) {
if (languages[browserLang]) {
isoCode = browserLang;
} else if (browserLang.length > 2 && languages[browserLang.substr(0, 2)]) {
isoCode = browserLang.substr(0, 2);
}
if (languages[storedIsoCode]) {
isoCode = storedIsoCode;
} else if (useBrowserLang) {
const browserLang = navigator.language || navigator.browserLanguage;
if (browserLang) {
if (languages[browserLang]) {
isoCode = browserLang;
} else if (browserLang.length > 2 && languages[browserLang.substr(0, 2)]) {
isoCode = browserLang.substr(0, 2);
}
}
if (!languages[isoCode]) {
isoCode = 'en';
}
loadLanguage(isoCode, update);
}
function initLangSelector(languages) {
var isoCodes = _.keys(languages).sort();
var $block = $(blockTemplate);
var $select = $block.find('select')
.on('change', function (ev) {
var isoCode = ev.target.value;
store.put(storekey, isoCode);
localize(languages, isoCode, false);
});
if (!languages[isoCode]) {
isoCode = 'en';
}
$.each(isoCodes, function (idx, isoCode) {
$(optionTemplate)
.attr('value', isoCode)
.addClass(isoCode)
.text(isoCode + ' - ' + (_.isString(languages[isoCode]) ? languages[isoCode] : languages[isoCode].lang))
.appendTo($select);
loadLanguage(isoCode, update);
}
function initLangSelector(languages) {
const isoCodes = lo.keys(languages).sort();
const $block = jq(blockTemplate);
const $select = $block.find('select')
.on('change', ev => {
const isoCode = ev.target.value;
store.put(storekey, isoCode);
localize(languages, isoCode, false);
});
$block.appendTo('#sidebar');
jq.each(isoCodes, (idx, isoCode) => {
jq(optionTemplate)
.attr('value', isoCode)
.addClass(isoCode)
.text(isoCode + ' - ' + (lo.isString(languages[isoCode]) ? languages[isoCode] : languages[isoCode].lang))
.appendTo($select);
});
$block.appendTo('#sidebar');
}
function init() {
if (settings.enabled) {
initLangSelector(langs);
}
function init() {
if (settings.enabled) {
initLangSelector(langs);
}
event.sub('view.changed', function () {
localize(langs, settings.lang, settings.useBrowserLang);
});
}
event.sub('view.changed', () => {
localize(langs, settings.lang, settings.useBrowserLang);
});
}
init();
});
init();

View file

@ -1,37 +1,37 @@
modulejs.define('ext/peer5', ['_', '$', 'core/settings'], function (_, $, allsettings) {
var settings = _.extend({
enabled: false,
id: 'z142i5n5qypq4cxr'
}, allsettings.peer5);
const {window: win, jQuery: jq, _: lo} = require('../win');
const allsettings = require('../core/settings');
const settings = lo.extend({
enabled: false,
id: 'z142i5n5qypq4cxr'
}, allsettings.peer5);
function init() {
if (!settings.enabled) {
return;
}
var peer5js = '//api.peer5.com/peer5.js?id=' + settings.id;
// load peer5 with caching
$.ajax({
url: peer5js,
dataType: 'script',
cache: true
});
// attach to file items, once the DOM is ready
$(function () {
$('body').on('click', '.item.file > a', function (ev) { // eslint-disable-line consistent-return
if (window.peer5) {
ev.preventDefault();
var url = ev.currentTarget.href;
window.peer5.download(url);
return false;
}
});
});
function init() {
if (!settings.enabled) {
return;
}
const peer5js = '//api.peer5.com/peer5.js?id=' + settings.id;
init();
});
jq.ajax({
url: peer5js,
dataType: 'script',
cache: true
});
// attach to file items, once the DOM is ready
jq(() => {
jq('body').on('click', '.item.file > a', ev => { // eslint-disable-line consistent-return
if (win.peer5) {
ev.preventDefault();
const url = ev.currentTarget.href;
win.peer5.download(url);
return false;
}
});
});
}
init();

53
src/_h5ai/public/js/lib/ext/piwik-analytics.js Executable file → Normal file
View file

@ -1,30 +1,35 @@
modulejs.define('ext/piwik-analytics', ['_', '$', 'core/settings'], function (_, $, allsettings) {
var settings = _.extend({
enabled: false,
baseURL: 'not-set',
idSite: 0
}, allsettings['piwik-analytics']);
const {window: win, jQuery: jq, _: lo} = require('../win');
const event = require('../core/event');
const allsettings = require('../core/settings');
function init() {
if (!settings.enabled) {
return;
}
const settings = lo.extend({
enabled: false,
baseURL: 'not-set',
idSite: 0
}, allsettings['piwik-analytics']);
// reference: http://piwik.org/docs/javascript-tracking/
var pkBaseURL = (document.location.protocol === 'https:' ? 'https://' : 'http://') + settings.baseURL + '/';
$('<script/>').attr('src', pkBaseURL + 'piwik.js').appendTo('body');
$(window).load(function () {
/* global Piwik */
var piwikTracker = Piwik.getTracker(pkBaseURL + 'piwik.php', settings.idSite);
piwikTracker.trackPageView();
piwikTracker.enableLinkTracking();
});
function init() {
if (!settings.enabled) {
return;
}
// reference: http://piwik.org/docs/javascript-tracking/
init();
});
const pkBaseURL = (win.location.protocol === 'https:' ? 'https://' : 'http://') + settings.baseURL + '/';
let piwikTracker = null;
jq('<script/>').attr('src', pkBaseURL + 'piwik.js').appendTo('body');
jq(win).load(() => {
piwikTracker = win.Piwik.getTracker(pkBaseURL + 'piwik.php', settings.idSite);
piwikTracker.enableLinkTracking();
});
event.sub('location.changed', item => {
const title = lo.map(item.getCrumb(), 'label').join(' > ');
piwikTracker.trackPageView(title);
});
}
init();

View file

@ -1,108 +1,110 @@
modulejs.define('ext/preview-audio', ['_', '$', 'core/event', 'core/format', 'core/settings', 'ext/preview'], function (_, $, event, format, allsettings, preview) {
var settings = _.extend({
enabled: false,
types: []
}, allsettings['preview-aud']);
const {setTimeout, jQuery: jq, _: lo} = require('../win');
const event = require('../core/event');
const format = require('../core/format');
const allsettings = require('../core/settings');
const preview = require('./preview');
function preloadAudio(src, callback) {
var $audio = $('<audio/>')
.one('loadedmetadata', function () {
callback($audio);
// setTimeout(function () { callback($img); }, 1000); // for testing
})
.attr('autoplay', 'autoplay')
.attr('controls', 'controls')
.attr('src', src);
}
const settings = lo.extend({
enabled: false,
types: []
}, allsettings['preview-aud']);
function onEnter(items, idx) {
var currentItems = items;
var currentIdx = idx;
var currentItem = items[idx];
function preloadAudio(src, callback) {
const $audio = jq('<audio/>')
.one('loadedmetadata', () => {
callback($audio);
// setTimeout(function () { callback($img); }, 1000); // for testing
})
.attr('autoplay', 'autoplay')
.attr('controls', 'controls')
.attr('src', src);
}
function onAdjustSize() {
var $content = $('#pv-content');
var $audio = $('#pv-aud-audio');
function onEnter(items, idx) {
const currentItems = items;
let currentIdx = idx;
let currentItem = items[idx];
if ($audio.length) {
$audio.css({
left: String(($content.width() - $audio.width()) * 0.5) + 'px',
top: String(($content.height() - $audio.height()) * 0.5) + 'px'
});
function onAdjustSize() {
const $content = jq('#pv-content');
const $audio = jq('#pv-aud-audio');
preview.setLabels([
currentItem.label,
format.formatDate($audio[0].duration * 1000, 'm:ss')
]);
}
}
function onIdxChange(rel) {
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
currentItem = currentItems[currentIdx];
var spinnerTimeout = setTimeout(function () { preview.showSpinner(true); }, 200);
if ($('#pv-aud-audio').length) {
$('#pv-aud-audio')[0].pause();
}
function updateMeta() {
onAdjustSize();
preview.setIndex(currentIdx + 1, currentItems.length);
preview.setRawLink(currentItem.absHref);
}
function swap(nuContent) {
$('#pv-content').empty().append(nuContent.attr('id', 'pv-vid-audio')).fadeIn(200);
// small timeout, so nuContent is visible and therefore its width is available
setTimeout(updateMeta, 10);
}
function onReady($preloadedContent) {
clearTimeout(spinnerTimeout);
preview.showSpinner(false);
$('#pv-content').fadeOut(100, function () {
swap($preloadedContent);
});
}
preloadAudio(currentItem.absHref, onReady);
}
onIdxChange(0);
preview.setOnIndexChange(onIdxChange);
preview.setOnAdjustSize(onAdjustSize);
preview.enter();
}
function initItem(item) {
if (item.$view && _.includes(settings.types, item.type)) {
item.$view.find('a').on('click', function (ev) {
ev.preventDefault();
var matchedItems = _.compact(_.map($('#items .item'), function (matchedItem) {
matchedItem = $(matchedItem).data('item');
return _.includes(settings.types, matchedItem.type) ? matchedItem : null;
}));
onEnter(matchedItems, _.indexOf(matchedItems, item));
if ($audio.length) {
$audio.css({
left: String(($content.width() - $audio.width()) * 0.5) + 'px',
top: String(($content.height() - $audio.height()) * 0.5) + 'px'
});
preview.setLabels([
currentItem.label,
format.formatDate($audio[0].duration * 1000, 'm:ss')
]);
}
}
function onViewChanged(added) {
_.each(added, initItem);
}
function onIdxChange(rel) {
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
currentItem = currentItems[currentIdx];
function init() {
if (!settings.enabled) {
return;
const spinnerTimeout = setTimeout(() => preview.showSpinner(true), 200);
if (jq('#pv-aud-audio').length) {
jq('#pv-aud-audio')[0].pause();
}
event.sub('view.changed', onViewChanged);
function 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
setTimeout(updateMeta, 10);
}
function onReady($preloadedContent) {
clearTimeout(spinnerTimeout);
preview.showSpinner(false);
jq('#pv-content').fadeOut(100, () => swap($preloadedContent));
}
preloadAudio(currentItem.absHref, onReady);
}
init();
});
onIdxChange(0);
preview.setOnIndexChange(onIdxChange);
preview.setOnAdjustSize(onAdjustSize);
preview.enter();
}
function initItem(item) {
if (item.$view && lo.includes(settings.types, item.type)) {
item.$view.find('a').on('click', ev => {
ev.preventDefault();
const matchedItems = lo.compact(lo.map(jq('#items .item'), matchedItem => {
matchedItem = jq(matchedItem).data('item');
return lo.includes(settings.types, matchedItem.type) ? matchedItem : null;
}));
onEnter(matchedItems, lo.indexOf(matchedItems, item));
});
}
}
function onViewChanged(added) {
lo.each(added, initItem);
}
function init() {
if (!settings.enabled) {
return;
}
event.sub('view.changed', onViewChanged);
}
init();

View file

@ -1,138 +1,142 @@
modulejs.define('ext/preview-img', ['_', '$', 'core/event', 'core/server', 'core/settings', 'ext/preview'], function (_, $, event, server, allsettings, preview) {
var settings = _.extend({
enabled: false,
size: null,
types: []
}, allsettings['preview-img']);
var spinnerThreshold = 200;
var spinnerTimeoutId;
var currentItems;
var currentIdx;
var currentItem;
const {setTimeout, jQuery: jq, _: lo} = require('../win');
const event = require('../core/event');
const server = require('../core/server');
const allsettings = require('../core/settings');
const preview = require('./preview');
const settings = lo.extend({
enabled: false,
size: null,
types: []
}, allsettings['preview-img']);
const spinnerThreshold = 200;
let spinnerTimeoutId;
let currentItems;
let currentIdx;
let currentItem;
function requestSample(href, callback) {
if (!settings.size) {
callback(href);
return;
}
server.request({
action: 'get',
thumbs: [{
type: 'img',
href: href,
width: settings.size,
height: 0
}]
}, function (json) {
callback(json && json.thumbs && json.thumbs[0] ? json.thumbs[0] : null);
});
function requestSample(href, callback) {
if (!settings.size) {
callback(href);
return;
}
function preloadImage(item, callback) {
requestSample(item.absHref, function (src) {
$('<img/>')
.one('load', function (ev) {
callback(item, ev.target);
server.request({
action: 'get',
thumbs: [{
type: 'img',
href,
width: settings.size,
height: 0
}]
}).then(json => {
callback(json && json.thumbs && json.thumbs[0] ? json.thumbs[0] : null);
});
}
// for testing
// setTimeout(function () { callback(item, ev.target); }, 1000);
})
.attr('src', src);
});
function preloadImage(item, callback) {
requestSample(item.absHref, src => {
jq('<img/>')
.one('load', ev => {
callback(item, ev.target);
// for testing
// setTimeout(function () { callback(item, ev.target); }, 1000);
})
.attr('src', src);
});
}
function onAdjustSize() {
const $content = jq('#pv-content');
const $img = jq('#pv-img-image');
if ($img.length === 0) {
return;
}
function onAdjustSize() {
var $content = $('#pv-content');
var $img = $('#pv-img-image');
$img.css({
left: ($content.width() - $img.width()) * 0.5,
top: ($content.height() - $img.height()) * 0.5
});
if ($img.length === 0) {
return;
}
$img.css({
left: ($content.width() - $img.width()) * 0.5,
top: ($content.height() - $img.height()) * 0.5
});
var 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)) + '%');
}
preview.setLabels(labels);
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)) + '%');
}
preview.setLabels(labels);
}
function onIdxChange(rel) {
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
currentItem = currentItems[currentIdx];
function onIdxChange(rel) {
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
currentItem = currentItems[currentIdx];
preview.setLabels([currentItem.label]);
preview.setIndex(currentIdx + 1, currentItems.length);
preview.setRawLink(currentItem.absHref);
preview.setLabels([currentItem.label]);
preview.setIndex(currentIdx + 1, currentItems.length);
preview.setRawLink(currentItem.absHref);
$('#pv-content').hide();
if (preview.isSpinnerVisible()) {
jq('#pv-content').hide();
if (preview.isSpinnerVisible()) {
preview.showSpinner(true, currentItem.thumbSquare);
} else {
clearTimeout(spinnerTimeoutId);
spinnerTimeoutId = setTimeout(() => {
preview.showSpinner(true, currentItem.thumbSquare);
} else {
clearTimeout(spinnerTimeoutId);
spinnerTimeoutId = setTimeout(function () {
preview.showSpinner(true, currentItem.thumbSquare);
}, spinnerThreshold);
}
preloadImage(currentItem, function (item, preloadedImage) {
if (item !== currentItem) {
return;
}
clearTimeout(spinnerTimeoutId);
preview.showSpinner(false);
$('#pv-content')
.empty()
.append($(preloadedImage).attr('id', 'pv-img-image'))
.show();
onAdjustSize();
});
}, spinnerThreshold);
}
function onEnter(items, idx) {
currentItems = items;
currentIdx = idx;
preview.setOnIndexChange(onIdxChange);
preview.setOnAdjustSize(onAdjustSize);
preview.enter();
onIdxChange(0);
}
function initItem(item) {
if (item.$view && _.includes(settings.types, item.type)) {
item.$view.find('a').on('click', function (ev) {
ev.preventDefault();
var matchedItems = _.compact(_.map($('#items .item'), function (matchedItem) {
matchedItem = $(matchedItem).data('item');
return _.includes(settings.types, matchedItem.type) ? matchedItem : null;
}));
onEnter(matchedItems, _.indexOf(matchedItems, item));
});
}
}
function onViewChanged(added) {
_.each(added, initItem);
}
function init() {
if (!settings.enabled) {
preloadImage(currentItem, (item, preloadedImage) => {
if (item !== currentItem) {
return;
}
event.sub('view.changed', onViewChanged);
clearTimeout(spinnerTimeoutId);
preview.showSpinner(false);
jq('#pv-content')
.empty()
.append(jq(preloadedImage).attr('id', 'pv-img-image'))
.show();
onAdjustSize();
});
}
function onEnter(items, idx) {
currentItems = items;
currentIdx = idx;
preview.setOnIndexChange(onIdxChange);
preview.setOnAdjustSize(onAdjustSize);
preview.enter();
onIdxChange(0);
}
function initItem(item) {
if (item.$view && lo.includes(settings.types, item.type)) {
item.$view.find('a').on('click', ev => {
ev.preventDefault();
const matchedItems = lo.compact(lo.map(jq('#items .item'), matchedItem => {
matchedItem = jq(matchedItem).data('item');
return lo.includes(settings.types, matchedItem.type) ? matchedItem : null;
}));
onEnter(matchedItems, lo.indexOf(matchedItems, item));
});
}
}
function onViewChanged(added) {
lo.each(added, initItem);
}
function init() {
if (!settings.enabled) {
return;
}
event.sub('view.changed', onViewChanged);
}
init();
});
init();

View file

@ -1,137 +1,143 @@
modulejs.define('ext/preview-txt', ['_', '$', 'marked', 'prism', 'core/event', 'core/settings', 'ext/preview'], function (_, $, marked, prism, event, allsettings, preview) {
var settings = _.extend({
enabled: false,
types: {}
}, allsettings['preview-txt']);
var tplText = '<pre id="pv-txt-text" class="highlighted"/>';
var tplMarkdown = '<div id="pv-txt-text" class="markdown"/>';
var spinnerThreshold = 200;
var spinnerTimeoutId;
var currentItems;
var currentIdx;
var currentItem;
const {setTimeout, jQuery: jq, _: lo, marked, Prism: prism} = require('../win');
const event = require('../core/event');
const allsettings = require('../core/settings');
const preview = require('./preview');
function preloadText(item, callback) {
$.ajax({
url: item.absHref,
dataType: 'text'
})
.done(function (content) {
callback(item, content);
const settings = lo.extend({
enabled: false,
types: {}
}, allsettings['preview-txt']);
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;
// for testing
// setTimeout(function () { callback(item, content); }, 1000);
})
.fail(function (jqXHR, textStatus) {
callback(item, '[ajax error] ' + textStatus);
});
function preloadText(item, callback) {
jq.ajax({
url: item.absHref,
dataType: 'text'
})
.done(content => {
callback(item, content);
// for testing
// setTimeout(function () { callback(item, content); }, 1000);
})
.fail((jqXHR, textStatus) => {
callback(item, '[ajax error] ' + textStatus);
});
}
function onAdjustSize() {
const $content = jq('#pv-content');
const $text = jq('#pv-txt-text');
if ($text.length) {
$text.height($content.height() - 16);
}
}
function onAdjustSize() {
var $content = $('#pv-content');
var $text = $('#pv-txt-text');
function onIdxChange(rel) {
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
currentItem = currentItems[currentIdx];
if ($text.length) {
$text.height($content.height() - 16);
}
}
preview.setLabels([
currentItem.label,
String(currentItem.size) + ' bytes'
]);
preview.setIndex(currentIdx + 1, currentItems.length);
preview.setRawLink(currentItem.absHref);
function onIdxChange(rel) {
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
currentItem = currentItems[currentIdx];
preview.setLabels([
currentItem.label,
String(currentItem.size) + ' bytes'
]);
preview.setIndex(currentIdx + 1, currentItems.length);
preview.setRawLink(currentItem.absHref);
$('#pv-content').hide();
if (preview.isSpinnerVisible()) {
jq('#pv-content').hide();
if (preview.isSpinnerVisible()) {
preview.showSpinner(true, currentItem.icon);
} else {
clearTimeout(spinnerTimeoutId);
spinnerTimeoutId = setTimeout(() => {
preview.showSpinner(true, currentItem.icon);
} else {
clearTimeout(spinnerTimeoutId);
spinnerTimeoutId = setTimeout(function () {
preview.showSpinner(true, currentItem.icon);
}, spinnerThreshold);
}
preloadText(currentItem, function (item, textContent) {
if (item !== currentItem) {
return;
}
var type = settings.types[currentItem.type];
var $text;
var $code;
if (type === 'none') {
$text = $(tplMarkdown).text(textContent);
} else if (type === 'fixed') {
$text = $(tplText).text(textContent);
} else if (type === 'markdown') {
$text = $(tplMarkdown).html(marked(textContent));
} else {
$text = $(tplText);
$code = $('<code/>').appendTo($text);
if (textContent.length < 20000) {
$code.empty().html(prism.highlight(textContent, prism.languages[type]));
} else {
$code.empty().text(textContent);
setTimeout(function () { $code.empty().html(prism.highlight(textContent, prism.languages[type])); }, 300);
}
}
clearTimeout(spinnerTimeoutId);
preview.showSpinner(false);
$('#pv-content')
.empty()
.append($text)
.show();
onAdjustSize();
});
}, spinnerThreshold);
}
function onEnter(items, idx) {
currentItems = items;
currentIdx = idx;
currentItem = items[idx];
preview.setOnIndexChange(onIdxChange);
preview.setOnAdjustSize(onAdjustSize);
preview.enter();
onIdxChange(0);
}
function initItem(item) {
if (item.$view && _.includes(_.keys(settings.types), item.type)) {
item.$view.find('a').on('click', function (ev) {
ev.preventDefault();
var matchedItems = _.compact(_.map($('#items .item'), function (matchedItem) {
matchedItem = $(matchedItem).data('item');
return _.includes(_.keys(settings.types), matchedItem.type) ? matchedItem : null;
}));
onEnter(matchedItems, _.indexOf(matchedItems, item));
});
}
}
function onViewChanged(added) {
_.each(added, initItem);
}
function init() {
if (!settings.enabled) {
preloadText(currentItem, (item, textContent) => {
if (item !== currentItem) {
return;
}
event.sub('view.changed', onViewChanged);
const type = settings.types[currentItem.type];
let $text;
let $code;
if (type === 'none') {
$text = jq(tplMarkdown).text(textContent);
} else if (type === 'fixed') {
$text = jq(tplText).text(textContent);
} else if (type === 'markdown') {
$text = jq(tplMarkdown).html(marked(textContent));
} else {
$text = jq(tplText);
$code = jq('<code/>').appendTo($text);
if (textContent.length < 20000) {
$code.empty().html(prism.highlight(textContent, prism.languages[type]));
} else {
$code.empty().text(textContent);
setTimeout(() => {
$code.empty().html(prism.highlight(textContent, prism.languages[type]));
}, 300);
}
}
clearTimeout(spinnerTimeoutId);
preview.showSpinner(false);
jq('#pv-content')
.empty()
.append($text)
.show();
onAdjustSize();
});
}
function onEnter(items, idx) {
currentItems = items;
currentIdx = idx;
currentItem = items[idx];
preview.setOnIndexChange(onIdxChange);
preview.setOnAdjustSize(onAdjustSize);
preview.enter();
onIdxChange(0);
}
function initItem(item) {
if (item.$view && lo.includes(lo.keys(settings.types), item.type)) {
item.$view.find('a').on('click', ev => {
ev.preventDefault();
const matchedItems = lo.compact(lo.map(jq('#items .item'), matchedItem => {
matchedItem = jq(matchedItem).data('item');
return lo.includes(lo.keys(settings.types), matchedItem.type) ? matchedItem : null;
}));
onEnter(matchedItems, lo.indexOf(matchedItems, item));
});
}
}
function onViewChanged(added) {
lo.each(added, initItem);
}
function init() {
if (!settings.enabled) {
return;
}
event.sub('view.changed', onViewChanged);
}
init();
});
init();

View file

@ -1,109 +1,110 @@
modulejs.define('ext/preview-vid', ['_', '$', 'core/event', 'core/settings', 'ext/preview'], function (_, $, event, allsettings, preview) {
var settings = _.extend({
enabled: false,
types: []
}, allsettings['preview-vid']);
const {setTimeout, jQuery: jq, _: lo} = require('../win');
const event = require('../core/event');
const allsettings = require('../core/settings');
const preview = require('./preview');
function preloadVideo(src, callback) {
var $video = $('<video/>')
.one('loadedmetadata', function () {
callback($video);
// setTimeout(function () { callback($video); }, 1000); // for testing
})
.attr('autoplay', 'autoplay')
.attr('controls', 'controls')
.attr('src', src);
}
const settings = lo.extend({
enabled: false,
types: []
}, allsettings['preview-vid']);
function onEnter(items, idx) {
var currentItems = items;
var currentIdx = idx;
var currentItem = items[idx];
function preloadVideo(src, callback) {
const $video = jq('<video/>')
.one('loadedmetadata', () => {
callback($video);
// setTimeout(function () { callback($video); }, 1000); // for testing
})
.attr('autoplay', 'autoplay')
.attr('controls', 'controls')
.attr('src', src);
}
function onAdjustSize() {
var $content = $('#pv-content');
var $vid = $('#pv-vid-video');
function onEnter(items, idx) {
const currentItems = items;
let currentIdx = idx;
let currentItem = items[idx];
if ($vid.length) {
$vid.css({
left: String(($content.width() - $vid.width()) * 0.5) + 'px',
top: String(($content.height() - $vid.height()) * 0.5) + 'px'
});
function onAdjustSize() {
const $content = jq('#pv-content');
const $vid = jq('#pv-vid-video');
preview.setLabels([
currentItem.label,
String($vid[0].videoWidth) + 'x' + String($vid[0].videoHeight),
String((100 * $vid.width() / $vid[0].videoWidth).toFixed(0)) + '%'
]);
}
}
function onIdxChange(rel) {
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
currentItem = currentItems[currentIdx];
var spinnerTimeout = setTimeout(function () { preview.showSpinner(true); }, 200);
if ($('#pv-vid-video').length) {
$('#pv-vid-video')[0].pause();
}
function updateMeta() {
onAdjustSize();
preview.setIndex(currentIdx + 1, currentItems.length);
preview.setRawLink(currentItem.absHref);
}
function swap(nuContent) {
$('#pv-content').empty().append(nuContent.attr('id', 'pv-vid-video')).fadeIn(200);
// small timeout, so nuContent is visible and therefore its width is available
setTimeout(updateMeta, 10);
}
function onReady($preloadedContent) {
clearTimeout(spinnerTimeout);
preview.showSpinner(false);
$('#pv-content').fadeOut(100, function () {
swap($preloadedContent);
});
}
preloadVideo(currentItem.absHref, onReady);
}
onIdxChange(0);
preview.setOnIndexChange(onIdxChange);
preview.setOnAdjustSize(onAdjustSize);
preview.enter();
}
function initItem(item) {
if (item.$view && _.includes(settings.types, item.type)) {
item.$view.find('a').on('click', function (ev) {
ev.preventDefault();
var matchedItems = _.compact(_.map($('#items .item'), function (matchedItem) {
matchedItem = $(matchedItem).data('item');
return _.includes(settings.types, matchedItem.type) ? matchedItem : null;
}));
onEnter(matchedItems, _.indexOf(matchedItems, item));
if ($vid.length) {
$vid.css({
left: String(($content.width() - $vid.width()) * 0.5) + 'px',
top: String(($content.height() - $vid.height()) * 0.5) + 'px'
});
preview.setLabels([
currentItem.label,
String($vid[0].videoWidth) + 'x' + String($vid[0].videoHeight),
String((100 * $vid.width() / $vid[0].videoWidth).toFixed(0)) + '%'
]);
}
}
function onViewChanged(added) {
_.each(added, initItem);
}
function onIdxChange(rel) {
currentIdx = (currentIdx + rel + currentItems.length) % currentItems.length;
currentItem = currentItems[currentIdx];
function init() {
if (!settings.enabled) {
return;
const spinnerTimeout = setTimeout(() => preview.showSpinner(true), 200);
if (jq('#pv-vid-video').length) {
jq('#pv-vid-video')[0].pause();
}
event.sub('view.changed', onViewChanged);
function 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-video')).fadeIn(200);
// small timeout, so nuContent is visible and therefore its width is available
setTimeout(updateMeta, 10);
}
function onReady($preloadedContent) {
clearTimeout(spinnerTimeout);
preview.showSpinner(false);
jq('#pv-content').fadeOut(100, () => swap($preloadedContent));
}
preloadVideo(currentItem.absHref, onReady);
}
init();
});
onIdxChange(0);
preview.setOnIndexChange(onIdxChange);
preview.setOnAdjustSize(onAdjustSize);
preview.enter();
}
function initItem(item) {
if (item.$view && lo.includes(settings.types, item.type)) {
item.$view.find('a').on('click', ev => {
ev.preventDefault();
const matchedItems = lo.compact(lo.map(jq('#items .item'), matchedItem => {
matchedItem = jq(matchedItem).data('item');
return lo.includes(settings.types, matchedItem.type) ? matchedItem : null;
}));
onEnter(matchedItems, lo.indexOf(matchedItems, item));
});
}
}
function onViewChanged(added) {
lo.each(added, initItem);
}
function init() {
if (!settings.enabled) {
return;
}
event.sub('view.changed', onViewChanged);
}
init();

View file

@ -1,233 +1,237 @@
modulejs.define('ext/preview', ['_', '$', 'core/resource', 'core/settings', 'core/store'], function (_, $, resource, allsettings, store) {
var settings = _.extend({
enabled: true
}, allsettings.preview);
var $window = $(window);
var tplOverlay =
'<div id="pv-overlay">' +
'<div id="pv-content"/>' +
'<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>' +
'<div id="pv-bottombar" class="clearfix hof">' +
'<ul id="pv-buttons">' +
'<li id="pv-bar-close" class="bar-right bar-button"><img src="' + resource.image('preview-close') + '"/></li>' +
'<li id="pv-bar-raw" class="bar-right"><a class="bar-button" target="_blank"><img src="' + resource.image('preview-raw') + '"/></a></li>' +
'<li id="pv-bar-fullscreen" class="bar-right bar-button"><img src="' + resource.image('preview-fullscreen') + '"/></li>' +
'<li id="pv-bar-next" class="bar-right bar-button"><img src="' + resource.image('preview-next') + '"/></li>' +
'<li id="pv-bar-idx" class="bar-right bar-label"/>' +
'<li id="pv-bar-prev" class="bar-right bar-button"><img src="' + resource.image('preview-prev') + '"/></li>' +
'</ul>' +
'</div>' +
'</div>';
var storekey = 'ext/preview';
var isFullscreen = store.get(storekey) || false;
var userAliveTimeoutId = null;
var onIndexChange = null;
var onAdjustSize = null;
var spinnerVisible = false;
const {window: win, setTimeout, jQuery: jq, _: lo} = require('../win');
const resource = require('../core/resource');
const allsettings = require('../core/settings');
const store = require('../core/store');
function adjustSize() {
var winWidth = $window.width();
var winHeight = $window.height();
var $container = $('#pv-content');
var $spinner = $('#pv-spinner');
var margin = isFullscreen ? 0 : 20;
var barHeight = isFullscreen ? 0 : 48;
const settings = lo.extend({
enabled: true
}, allsettings.preview);
const $window = jq(win);
const tplOverlay =
`<div id="pv-overlay">
<div id="pv-content"/>
<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>
<div id="pv-bottombar" class="clearfix hof">
<ul id="pv-buttons">
<li id="pv-bar-close" class="bar-right bar-button"><img src="${resource.image('preview-close')}"/></li>
<li id="pv-bar-raw" class="bar-right"><a class="bar-button" target="_blank"><img src="${resource.image('preview-raw')}"/></a></li>
<li id="pv-bar-fullscreen" class="bar-right bar-button"><img src="${resource.image('preview-fullscreen')}"/></li>
<li id="pv-bar-next" class="bar-right bar-button"><img src="${resource.image('preview-next')}"/></li>
<li id="pv-bar-idx" class="bar-right bar-label"/>
<li id="pv-bar-prev" class="bar-right bar-button"><img src="${resource.image('preview-prev')}"/></li>
</ul>
</div>
</div>`;
const storekey = 'ext/preview';
let isFullscreen = store.get(storekey) || false;
let userAliveTimeoutId = null;
let onIndexChange = null;
let onAdjustSize = null;
let spinnerVisible = false;
$container.css({
width: winWidth - 2 * margin,
height: winHeight - 2 * margin - barHeight,
left: margin,
top: margin
});
$spinner.css({
left: winWidth * 0.5,
top: winHeight * 0.5
});
function adjustSize() {
const winWidth = $window.width();
const winHeight = $window.height();
const $container = jq('#pv-content');
const $spinner = jq('#pv-spinner');
const margin = isFullscreen ? 0 : 20;
const barHeight = isFullscreen ? 0 : 48;
if (isFullscreen) {
$('#pv-overlay').addClass('fullscreen');
$('#pv-bar-fullscreen').find('img').attr('src', resource.image('preview-no-fullscreen'));
} else {
$('#pv-overlay').removeClass('fullscreen');
$('#pv-bar-fullscreen').find('img').attr('src', resource.image('preview-fullscreen'));
}
$container.css({
width: winWidth - 2 * margin,
height: winHeight - 2 * margin - barHeight,
left: margin,
top: margin
});
if (_.isFunction(onAdjustSize)) {
onAdjustSize(1);
}
$spinner.css({
left: winWidth * 0.5,
top: winHeight * 0.5
});
if (isFullscreen) {
jq('#pv-overlay').addClass('fullscreen');
jq('#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'));
}
function setLabels(labels) {
$('#pv-buttons .bar-left').remove();
_.each(labels, function (label) {
$('<li/>')
.addClass('bar-left bar-label')
.text(label)
.appendTo('#pv-buttons');
});
if (lo.isFunction(onAdjustSize)) {
onAdjustSize(1);
}
}
function onNext() {
if (_.isFunction(onIndexChange)) {
onIndexChange(1);
}
function setLabels(labels) {
jq('#pv-buttons .bar-left').remove();
lo.each(labels, label => {
jq('<li/>')
.addClass('bar-left bar-label')
.text(label)
.appendTo('#pv-buttons');
});
}
function onNext() {
if (lo.isFunction(onIndexChange)) {
onIndexChange(1);
}
}
function onPrevious() {
if (_.isFunction(onIndexChange)) {
onIndexChange(-1);
}
function onPrevious() {
if (lo.isFunction(onIndexChange)) {
onIndexChange(-1);
}
}
function userAlive() {
clearTimeout(userAliveTimeoutId);
$('#pv-overlay .hof').stop(true, true).fadeIn(200);
function userAlive() {
clearTimeout(userAliveTimeoutId);
jq('#pv-overlay .hof').stop(true, true).fadeIn(200);
if (isFullscreen) {
userAliveTimeoutId = setTimeout(function () {
$('#pv-overlay .hof').stop(true, true).fadeOut(2000);
}, 2000);
}
if (isFullscreen) {
userAliveTimeoutId = setTimeout(() => {
jq('#pv-overlay .hof').stop(true, true).fadeOut(2000);
}, 2000);
}
}
function onFullscreen() {
isFullscreen = !isFullscreen;
store.put(storekey, isFullscreen);
function onFullscreen() {
isFullscreen = !isFullscreen;
store.put(storekey, isFullscreen);
userAlive();
adjustSize();
userAlive();
adjustSize();
}
function onKeydown(ev) {
const key = ev.which;
if (key === 27) { // esc
ev.preventDefault();
ev.stopImmediatePropagation();
onExit(); // eslint-disable-line no-use-before-define
} else if (key === 8 || key === 37) { // backspace, left
ev.preventDefault();
ev.stopImmediatePropagation();
onPrevious();
} else if (key === 13 || key === 32 || key === 39) { // enter, space, right
ev.preventDefault();
ev.stopImmediatePropagation();
onNext();
} else if (key === 70) { // f
ev.preventDefault();
ev.stopImmediatePropagation();
onFullscreen();
}
}
function onKeydown(ev) {
var key = ev.which;
function onEnter() {
setLabels([]);
jq('#pv-content').empty();
jq('#pv-overlay').stop(true, true).fadeIn(200);
$window.on('keydown', onKeydown);
adjustSize();
}
if (key === 27) { // esc
ev.preventDefault();
ev.stopImmediatePropagation();
onExit(); // eslint-disable-line no-use-before-define
} else if (key === 8 || key === 37) { // backspace, left
ev.preventDefault();
ev.stopImmediatePropagation();
onPrevious();
} else if (key === 13 || key === 32 || key === 39) { // enter, space, right
ev.preventDefault();
ev.stopImmediatePropagation();
onNext();
} else if (key === 70) { // f
ev.preventDefault();
ev.stopImmediatePropagation();
onFullscreen();
}
}
function onEnter() {
function onExit() {
$window.off('keydown', onKeydown);
jq('#pv-overlay').stop(true, true).fadeOut(200, () => {
jq('#pv-content').empty();
setLabels([]);
$('#pv-content').empty();
$('#pv-overlay').stop(true, true).fadeIn(200);
$window.on('keydown', onKeydown);
adjustSize();
});
}
function setIndex(idx, total) {
if (lo.isNumber(idx)) {
jq('#pv-bar-idx').text(String(idx) + (lo.isNumber(total) ? '/' + String(total) : '')).show();
} else {
jq('#pv-bar-idx').text('').hide();
}
}
function setRawLink(href) {
if (href) {
jq('#pv-bar-raw').show().find('a').attr('href', href);
} else {
jq('#pv-bar-raw').hide().find('a').attr('href', '#');
}
}
function setOnIndexChange(fn) {
onIndexChange = fn;
}
function setOnAdjustSize(fn) {
onAdjustSize = fn;
}
function showSpinner(show, src, millis) {
if (!lo.isNumber(millis)) {
millis = 300;
}
function onExit() {
$window.off('keydown', onKeydown);
$('#pv-overlay').stop(true, true).fadeOut(200, function () {
$('#pv-content').empty();
setLabels([]);
});
}
const $spinner = jq('#pv-spinner').stop(true, true);
const $back = $spinner.find('.back');
function setIndex(idx, total) {
if (_.isNumber(idx)) {
$('#pv-bar-idx').text(String(idx) + (_.isNumber(total) ? '/' + String(total) : '')).show();
if (show) {
if (src) {
$back.attr('src', src).show();
} else {
$('#pv-bar-idx').text('').hide();
$back.hide();
}
spinnerVisible = true;
$spinner.fadeIn(millis);
} else {
spinnerVisible = false;
$spinner.fadeOut(millis);
}
}
function isSpinnerVisible() {
return spinnerVisible;
}
function init() {
if (!settings.enabled) {
return;
}
function setRawLink(href) {
if (href) {
$('#pv-bar-raw').show().find('a').attr('href', href);
} else {
$('#pv-bar-raw').hide().find('a').attr('href', '#');
}
}
jq(tplOverlay).appendTo('body');
function setOnIndexChange(fn) {
onIndexChange = fn;
}
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);
function setOnAdjustSize(fn) {
onAdjustSize = fn;
}
function showSpinner(show, src, millis) {
if (!_.isNumber(millis)) {
millis = 300;
}
var $spinner = $('#pv-spinner').stop(true, true);
var $back = $spinner.find('.back');
if (show) {
if (src) {
$back.attr('src', src).show();
} else {
$back.hide();
jq('#pv-overlay')
.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')) {
onExit();
}
spinnerVisible = true;
$spinner.fadeIn(millis);
} else {
spinnerVisible = false;
$spinner.fadeOut(millis);
}
}
ev.stopImmediatePropagation();
});
function isSpinnerVisible() {
return spinnerVisible;
}
function init() {
if (!settings.enabled) {
return;
}
$(tplOverlay).appendTo('body');
$('#pv-spinner').hide();
$('#pv-bar-prev, #pv-prev-area').on('click', onPrevious);
$('#pv-bar-next, #pv-next-area').on('click', onNext);
$('#pv-bar-close').on('click', onExit);
$('#pv-bar-fullscreen').on('click', onFullscreen);
$('#pv-overlay')
.on('keydown', onKeydown)
.on('mousemove mousedown', userAlive)
.on('click mousedown mousemove keydown keypress', function (ev) {
if (ev.type === 'click' && (ev.target.id === 'pv-overlay' || ev.target.id === 'pv-content')) {
onExit();
}
ev.stopImmediatePropagation();
});
$window.on('resize load', adjustSize);
}
$window.on('resize load', adjustSize);
}
init();
init();
return {
enter: onEnter,
exit: onExit,
setIndex: setIndex,
setRawLink: setRawLink,
setLabels: setLabels,
setOnIndexChange: setOnIndexChange,
setOnAdjustSize: setOnAdjustSize,
showSpinner: showSpinner,
isSpinnerVisible: isSpinnerVisible
};
});
module.exports = {
enter: onEnter,
exit: onExit,
setIndex,
setRawLink,
setLabels,
setOnIndexChange,
setOnAdjustSize,
showSpinner,
isSpinnerVisible
};

View file

@ -1,84 +1,95 @@
modulejs.define('ext/search', ['_', '$', 'core/event', 'core/location', 'core/resource', 'core/server', 'core/settings', 'core/util', 'model/item', 'view/view'], function (_, $, event, location, resource, server, allsettings, util, Item, view) {
var settings = _.extend({
enabled: false,
advanced: false,
debounceTime: 300
}, allsettings.search);
var template =
'<div id="search" class="tool">' +
'<img src="' + resource.image('search') + '" alt="search"/>' +
'<input class="l10n_ph-search" type="text" value=""/>' +
'</div>';
var inputIsVisible = false;
var prevPattern = '';
var $search;
var $input;
const {jQuery: jq, _: lo} = require('../win');
const event = require('../core/event');
const location = require('../core/location');
const resource = require('../core/resource');
const server = require('../core/server');
const allsettings = require('../core/settings');
const util = require('../core/util');
const Item = require('../model/item');
const view = require('../view/view');
function search(pattern) {
pattern = pattern || '';
if (pattern === prevPattern) {
return;
const settings = lo.extend({
enabled: false,
advanced: false,
debounceTime: 300,
ignorecase: true
}, allsettings.search);
const template =
`<div id="search" class="tool">
<img src="${resource.image('search')}" alt="search"/>
<input class="l10n_ph-search" type="text" value=""/>
</div>`;
let inputIsVisible = false;
let prevPattern = '';
let $search;
let $input;
function search(pattern) {
pattern = pattern || '';
if (pattern === prevPattern) {
return;
}
prevPattern = pattern;
if (!pattern) {
view.setLocation();
return;
}
$search.addClass('pending');
server.request({
action: 'get',
search: {
href: location.getAbsHref(),
pattern,
ignorecase: settings.ignorecase
}
prevPattern = pattern;
}).then(response => {
$search.removeClass('pending');
view.setHint('noMatch');
view.setItems(lo.map(response.search, item => {
return Item.get(item);
}));
});
}
if (!pattern) {
view.setLocation();
return;
}
function update() {
if (inputIsVisible) {
$search.addClass('active');
$input.focus();
search(util.parsePattern($input.val(), settings.advanced));
} else {
search();
$search.removeClass('active');
}
}
$search.addClass('pending');
function toggle() {
inputIsVisible = !inputIsVisible;
update();
}
server.request({
action: 'get',
search: {
href: location.getAbsHref(),
pattern: pattern
}
}, function (response) {
$search.removeClass('pending');
view.setHint('noMatch');
view.setItems(_.map(response.search, function (item) {
return Item.get(item);
}));
});
function reset() {
inputIsVisible = false;
$input.val('');
update();
}
function init() {
if (!settings.enabled) {
return;
}
function update() {
if (inputIsVisible) {
$search.addClass('active');
$input.focus();
search(util.parsePattern($input.val(), settings.advanced));
} else {
search();
$search.removeClass('active');
}
}
$search = jq(template).appendTo('#toolbar');
$input = $search.find('input');
function toggle() {
inputIsVisible = !inputIsVisible;
update();
}
function reset() {
inputIsVisible = false;
$input.val('');
update();
}
function init() {
if (!settings.enabled) {
return;
}
$search = $(template).appendTo('#toolbar');
$input = $search.find('input');
$search.on('click', 'img', toggle);
$input.on('keyup', _.debounce(update, settings.debounceTime, {trailing: true}));
event.sub('location.changed', reset);
}
$search.on('click', 'img', toggle);
$input.on('keyup', lo.debounce(update, settings.debounceTime, {trailing: true}));
event.sub('location.changed', reset);
}
init();
});
init();

View file

@ -1,191 +1,195 @@
modulejs.define('ext/select', ['_', '$', 'core/event', 'core/resource', 'core/settings'], function (_, $, event, resource, allsettings) {
var settings = _.extend({
enabled: false,
clickndrag: false,
checkboxes: false
}, allsettings.select);
var template = '<span class="selector"><img src="' + resource.image('selected') + '" alt="selected"/></span>';
var x = 0;
var y = 0;
var l = 0;
var t = 0;
var w = 0;
var h = 0;
var isDragSelect;
var isCtrlPressed;
var shrink = 1 / 3;
var $document = $(document);
var $html = $('html');
var $selectionRect = $('<div id="selection-rect"/>');
const {document: doc, jQuery: jq, _: lo} = require('../win');
const event = require('../core/event');
const resource = require('../core/resource');
const allsettings = require('../core/settings');
function publish() {
var items = _.map($('#items .item.selected'), function (itemElement) {
return $(itemElement).data('item');
});
event.pub('selection', items);
const settings = lo.extend({
enabled: false,
clickndrag: false,
checkboxes: false
}, allsettings.select);
const template = '<span class="selector"><img src="' + resource.image('selected') + '" alt="selected"/></span>';
let x = 0;
let y = 0;
let l = 0;
let t = 0;
let w = 0;
let h = 0;
let isDragSelect;
let isCtrlPressed;
const shrink = 1 / 3;
const $document = jq(doc);
const $html = jq('html');
const $selectionRect = jq('<div id="selection-rect"/>');
function publish() {
const items = lo.map(jq('#items .item.selected'), itemElement => {
return jq(itemElement).data('item');
});
event.pub('selection', items);
}
function elementRect($element) {
if (!$element.is(':visible')) {
return null;
}
function elementRect($element) {
if (!$element.is(':visible')) {
return null;
}
const offset = $element.offset();
const elL = offset.left;
const elT = offset.top;
const elW = $element.outerWidth();
const elH = $element.outerHeight();
return {l: elL, t: elT, w: elW, h: elH, r: elL + elW, b: elT + elH};
}
var offset = $element.offset();
var elL = offset.left;
var elT = offset.top;
var elW = $element.outerWidth();
var elH = $element.outerHeight();
return {l: elL, t: elT, w: elW, h: elH, r: elL + elW, b: elT + elH};
function doOverlap(rect1, rect2) {
if (!rect1 || !rect2) {
return false;
}
function doOverlap(rect1, rect2) {
if (!rect1 || !rect2) {
return false;
}
const left = Math.max(rect1.l, rect2.l);
const right = Math.min(rect1.r, rect2.r);
const top = Math.max(rect1.t, rect2.t);
const bottom = Math.min(rect1.b, rect2.b);
const width = right - left;
const height = bottom - top;
var left = Math.max(rect1.l, rect2.l);
var right = Math.min(rect1.r, rect2.r);
var top = Math.max(rect1.t, rect2.t);
var bottom = Math.min(rect1.b, rect2.b);
var width = right - left;
var height = bottom - top;
return width >= 0 && height >= 0;
}
return width >= 0 && height >= 0;
function selectionUpdate(ev) {
l = Math.min(x, ev.pageX);
t = Math.min(y, ev.pageY);
w = Math.abs(x - ev.pageX);
h = Math.abs(y - ev.pageY);
if (!isDragSelect && w < 4 && h < 4) {
return;
}
function selectionUpdate(ev) {
l = Math.min(x, ev.pageX);
t = Math.min(y, ev.pageY);
w = Math.abs(x - ev.pageX);
h = Math.abs(y - ev.pageY);
if (!isDragSelect && w < 4 && h < 4) {
return;
}
if (!isDragSelect && !isCtrlPressed) {
$('#items .item').removeClass('selected');
publish();
}
isDragSelect = true;
$html.addClass('drag-select');
ev.preventDefault();
$selectionRect
.stop(true, true)
.css({left: l, top: t, width: w, height: h, opacity: 1})
.show();
var selRect = elementRect($selectionRect);
$('#items .item').removeClass('selecting').each(function () {
var $item = $(this);
var inter = doOverlap(selRect, elementRect($item.find('a')));
if (inter && !$item.hasClass('folder-parent')) {
$item.addClass('selecting');
}
});
}
function selectionEnd(ev) {
$document.off('mousemove', selectionUpdate);
if (!isDragSelect) {
return;
}
ev.preventDefault();
$('#items .item.selecting.selected').removeClass('selecting').removeClass('selected');
$('#items .item.selecting').removeClass('selecting').addClass('selected');
if (!isDragSelect && !isCtrlPressed) {
jq('#items .item').removeClass('selected');
publish();
}
$html.removeClass('drag-select');
$selectionRect
.stop(true, true)
.animate({
left: l + w * 0.5 * shrink,
top: t + h * 0.5 * shrink,
width: w * (1 - shrink),
height: h * (1 - shrink),
opacity: 0
},
300,
function () {
$selectionRect.hide();
isDragSelect = true;
$html.addClass('drag-select');
ev.preventDefault();
$selectionRect
.stop(true, true)
.css({left: l, top: t, width: w, height: h, opacity: 1})
.show();
const selRect = elementRect($selectionRect);
jq('#items .item').removeClass('selecting').each((idx, el) => {
const $item = jq(el);
const inter = doOverlap(selRect, elementRect($item.find('a')));
if (inter && !$item.hasClass('folder-parent')) {
$item.addClass('selecting');
}
});
}
function selectionEnd(ev) {
$document.off('mousemove', selectionUpdate);
if (!isDragSelect) {
return;
}
ev.preventDefault();
jq('#items .item.selecting.selected').removeClass('selecting').removeClass('selected');
jq('#items .item.selecting').removeClass('selecting').addClass('selected');
publish();
$html.removeClass('drag-select');
$selectionRect
.stop(true, true)
.animate({
left: l + w * 0.5 * shrink,
top: t + h * 0.5 * shrink,
width: w * (1 - shrink),
height: h * (1 - shrink),
opacity: 0
},
300,
() => {
$selectionRect.hide();
});
}
function selectionStart(ev) {
// only on left button and don't block scrollbar
if (ev.button !== 0 || ev.offsetX >= jq('#content').width() - 14) {
return;
}
isDragSelect = false;
isCtrlPressed = ev.ctrlKey || ev.metaKey;
x = ev.pageX;
y = ev.pageY;
$document
.on('mousemove', selectionUpdate)
.one('mouseup', selectionEnd);
}
function onSelectorClick(ev) {
ev.stopImmediatePropagation();
ev.preventDefault();
jq(ev.target).closest('.item').toggleClass('selected');
publish();
}
function addCheckbox(item) {
if (item.$view && !item.isCurrentParentFolder()) {
jq(template)
.on('click', onSelectorClick)
.appendTo(item.$view.find('a'));
}
}
function onViewChanged(added, removed) {
if (settings.checkboxes) {
lo.each(added, addCheckbox);
}
lo.each(removed, item => {
if (item.$view) {
item.$view.removeClass('selected');
}
});
publish();
}
function init() {
if (!settings.enabled || !settings.clickndrag && !settings.checkboxes) {
return;
}
event.sub('view.changed', onViewChanged);
if (settings.clickndrag) {
$selectionRect.hide().appendTo('body');
jq('#content')
.on('mousedown', selectionStart)
.on('drag dragstart', ev => {
ev.stopImmediatePropagation();
ev.preventDefault();
})
.on('click', () => {
jq('#items .item').removeClass('selected');
publish();
});
}
function selectionStart(ev) {
// only on left button and don't block scrollbar
if (ev.button !== 0 || ev.offsetX >= $('#content').width() - 14) {
return;
}
isDragSelect = false;
isCtrlPressed = ev.ctrlKey || ev.metaKey;
x = ev.pageX;
y = ev.pageY;
$document
.on('mousemove', selectionUpdate)
.one('mouseup', selectionEnd);
}
function onSelectorClick(ev) {
ev.stopImmediatePropagation();
ev.preventDefault();
$(ev.target).closest('.item').toggleClass('selected');
publish();
}
function addCheckbox(item) {
if (item.$view && !item.isCurrentParentFolder()) {
$(template)
.on('click', onSelectorClick)
.appendTo(item.$view.find('a'));
}
}
function onViewChanged(added, removed) {
if (settings.checkboxes) {
_.each(added, addCheckbox);
}
_.each(removed, function (item) {
if (item.$view) {
item.$view.removeClass('selected');
}
});
publish();
}
function init() {
if (!settings.enabled || !settings.clickndrag && !settings.checkboxes) {
return;
}
event.sub('view.changed', onViewChanged);
if (settings.clickndrag) {
$selectionRect.hide().appendTo('body');
$('#content')
.on('mousedown', selectionStart)
.on('drag dragstart', function (ev) {
ev.stopImmediatePropagation();
ev.preventDefault();
})
.on('click', function () {
$('#items .item').removeClass('selected');
publish();
});
}
}
}
init();
});
init();

View file

@ -1,146 +1,151 @@
modulejs.define('ext/sort', ['_', '$', 'core/event', 'core/resource', 'core/settings', 'core/store', 'core/util'], function (_, $, event, resource, allsettings, store, util) {
var settings = _.extend({
enabled: false,
column: 0,
reverse: false,
ignorecase: true,
natural: false,
folders: 0
}, allsettings.sort);
var storekey = 'ext/sort';
var template = '<img src="' + resource.image('sort') + '" class="sort" alt="sort order" />';
const {jQuery: jq, _: lo} = require('../win');
const event = require('../core/event');
const resource = require('../core/resource');
const allsettings = require('../core/settings');
const store = require('../core/store');
const util = require('../core/util');
const settings = lo.extend({
enabled: false,
column: 0,
reverse: false,
ignorecase: true,
natural: false,
folders: 0
}, allsettings.sort);
const storekey = 'ext/sort';
const template = '<img src="' + resource.image('sort') + '" class="sort" alt="sort order" />';
function getType(item) {
var $item = $(item);
function getType(item) {
const $item = jq(item);
if ($item.hasClass('folder-parent')) {
return 0;
if ($item.hasClass('folder-parent')) {
return 0;
}
if ($item.hasClass('folder')) {
if (settings.folders === 1) {
return 2;
} else if (settings.folders === 2) {
return 3;
}
if ($item.hasClass('folder')) {
if (settings.folders === 1) {
return 2;
} else if (settings.folders === 2) {
return 3;
return 1;
}
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 = {
0: getName,
1: getTime,
2: getSize
};
const columnClasses = {
0: 'label',
1: 'date',
2: 'size'
};
function cmpFn(getValue, reverse, ignorecase, natural) {
return (item1, item2) => {
let res;
let val1;
let val2;
res = getType(item1) - getType(item2);
if (res !== 0) {
return res;
}
val1 = getValue(item1);
val2 = getValue(item2);
if (isNaN(val1) || isNaN(val2)) {
val1 = String(val1);
val2 = String(val2);
if (ignorecase) {
val1 = val1.toLowerCase();
val2 = val2.toLowerCase();
}
return 1;
}
return 2;
}
function getName(item) {
return $(item).find('.label').text();
}
function getTime(item) {
return $(item).find('.date').data('time');
}
function getSize(item) {
return $(item).find('.size').data('bytes');
}
var columnGetters = {
0: getName,
1: getTime,
2: getSize
};
var columnClasses = {
0: 'label',
1: 'date',
2: 'size'
res = natural ? util.naturalCmpFn(val1, val2) : util.regularCmpFn(val1, val2);
return reverse ? -res : res;
};
}
function sortItems(column, reverse) {
const $headers = jq('#items li.header a');
const $header = jq('#items li.header a.' + columnClasses[column]);
const fn = cmpFn(columnGetters[column], reverse, settings.ignorecase, column === 0 && settings.natural);
const $current = jq('#items .item');
const $sorted = jq('#items .item').sort(fn);
function cmpFn(getValue, reverse, ignorecase, natural) {
return function (item1, item2) {
var res;
var val1;
var val2;
store.put(storekey, {column, reverse});
res = getType(item1) - getType(item2);
if (res !== 0) {
return res;
}
$headers.removeClass('ascending descending');
$header.addClass(reverse ? 'descending' : 'ascending');
val1 = getValue(item1);
val2 = getValue(item2);
if (isNaN(val1) || isNaN(val2)) {
val1 = String(val1);
val2 = String(val2);
if (ignorecase) {
val1 = val1.toLowerCase();
val2 = val2.toLowerCase();
}
}
res = natural ? util.naturalCmpFn(val1, val2) : util.regularCmpFn(val1, val2);
return reverse ? -res : res;
};
}
function sortItems(column, reverse) {
var $headers = $('#items li.header a');
var $header = $('#items li.header a.' + columnClasses[column]);
var fn = cmpFn(columnGetters[column], reverse, settings.ignorecase, column === 0 && settings.natural);
var $current = $('#items .item');
var $sorted = $('#items .item').sort(fn);
store.put(storekey, {column: column, reverse: reverse});
$headers.removeClass('ascending descending');
$header.addClass(reverse ? 'descending' : 'ascending');
for (var i = 0, l = $current.length; i < l; i += 1) {
if ($current[i] !== $sorted[i]) {
$sorted.detach().sort(fn).appendTo('#items');
break;
}
for (let i = 0, l = $current.length; i < l; i += 1) {
if ($current[i] !== $sorted[i]) {
$sorted.detach().sort(fn).appendTo('#items');
break;
}
}
}
function onContentChanged() {
var order = store.get(storekey);
var column = order && order.column || settings.column;
var reverse = order && order.reverse || settings.reverse;
function onContentChanged() {
const order = store.get(storekey);
const column = order && order.column || settings.column;
const reverse = order && order.reverse || settings.reverse;
sortItems(column, reverse);
sortItems(column, reverse);
}
function init() {
if (!settings.enabled) {
return;
}
function init() {
if (!settings.enabled) {
return;
}
const $header = jq('#items li.header');
var $header = $('#items li.header');
$header.find('a.label')
.append(template)
.click(ev => {
sortItems(0, jq(ev.currentTarget).hasClass('ascending'));
ev.preventDefault();
});
$header.find('a.label')
.append(template)
.click(function (ev) {
sortItems(0, $(this).hasClass('ascending'));
ev.preventDefault();
});
$header.find('a.date')
.prepend(template)
.click(ev => {
sortItems(1, jq(ev.currentTarget).hasClass('ascending'));
ev.preventDefault();
});
$header.find('a.date')
.prepend(template)
.click(function (ev) {
sortItems(1, $(this).hasClass('ascending'));
ev.preventDefault();
});
$header.find('a.size')
.prepend(template)
.click(ev => {
sortItems(2, jq(ev.currentTarget).hasClass('ascending'));
ev.preventDefault();
});
$header.find('a.size')
.prepend(template)
.click(function (ev) {
sortItems(2, $(this).hasClass('ascending'));
ev.preventDefault();
});
event.sub('view.changed', onContentChanged);
}
event.sub('view.changed', onContentChanged);
}
init();
});
init();

View file

@ -1,108 +1,111 @@
modulejs.define('ext/thumbnails', ['_', 'core/event', 'core/server', 'core/settings'], function (_, event, server, allsettings) {
var settings = _.extend({
enabled: false,
img: ['img-bmp', 'img-gif', 'img-ico', 'img-jpg', 'img-png'],
mov: ['vid-avi', 'vid-flv', 'vid-mkv', 'vid-mov', 'vid-mp4', 'vid-mpg', 'vid-webm'],
doc: ['x-pdf', 'x-ps'],
delay: 1,
size: 100,
exif: false
}, allsettings.thumbnails);
var landscapeRatio = 4 / 3;
const {_: lo} = require('../win');
const event = require('../core/event');
const server = require('../core/server');
const allsettings = require('../core/settings');
const settings = lo.extend({
enabled: false,
img: ['img-bmp', 'img-gif', 'img-ico', 'img-jpg', 'img-png'],
mov: ['vid-avi', 'vid-flv', 'vid-mkv', 'vid-mov', 'vid-mp4', 'vid-mpg', 'vid-webm'],
doc: ['x-pdf', 'x-ps'],
delay: 1,
size: 100,
exif: false
}, allsettings.thumbnails);
const landscapeRatio = 4 / 3;
function queueItem(queue, item) {
var type = null;
function queueItem(queue, item) {
let type = null;
if (_.includes(settings.img, item.type)) {
type = 'img';
} else if (_.includes(settings.mov, item.type)) {
type = 'mov';
} else if (_.includes(settings.doc, item.type)) {
type = 'doc';
} else {
return;
}
if (lo.includes(settings.img, item.type)) {
type = 'img';
} else if (lo.includes(settings.mov, item.type)) {
type = 'mov';
} else if (lo.includes(settings.doc, item.type)) {
type = 'doc';
} else {
return;
}
if (item.thumbSquare) {
item.$view.find('.icon.square img').addClass('thumb').attr('src', item.thumbSquare);
} else {
queue.push({
type: type,
href: item.absHref,
ratio: 1,
callback: function (src) {
if (src && item.$view) {
item.thumbSquare = src;
item.$view.find('.icon.square img').addClass('thumb').attr('src', src);
}
if (item.thumbSquare) {
item.$view.find('.icon.square img').addClass('thumb').attr('src', item.thumbSquare);
} else {
queue.push({
type,
href: item.absHref,
ratio: 1,
callback: src => {
if (src && item.$view) {
item.thumbSquare = src;
item.$view.find('.icon.square img').addClass('thumb').attr('src', src);
}
});
}
}
});
}
if (item.thumbRational) {
item.$view.find('.icon.landscape img').addClass('thumb').attr('src', item.thumbRational);
} else {
queue.push({
type: type,
href: item.absHref,
ratio: landscapeRatio,
callback: function (src) {
if (src && item.$view) {
item.thumbRational = src;
item.$view.find('.icon.landscape img').addClass('thumb').attr('src', src);
}
if (item.thumbRational) {
item.$view.find('.icon.landscape img').addClass('thumb').attr('src', item.thumbRational);
} else {
queue.push({
type,
href: item.absHref,
ratio: landscapeRatio,
callback: src => {
if (src && item.$view) {
item.thumbRational = src;
item.$view.find('.icon.landscape img').addClass('thumb').attr('src', src);
}
});
}
}
function requestQueue(queue) {
var thumbs = _.map(queue, function (req) {
return {
type: req.type,
href: req.href,
width: Math.round(settings.size * req.ratio),
height: settings.size
};
});
server.request({
action: 'get',
thumbs: thumbs
}, function (json) {
_.each(queue, function (req, idx) {
req.callback(json && json.thumbs ? json.thumbs[idx] : null);
});
}
});
}
}
function handleItems(items) {
var queue = [];
function requestQueue(queue) {
const thumbs = lo.map(queue, req => {
return {
type: req.type,
href: req.href,
width: Math.round(settings.size * req.ratio),
height: settings.size
};
});
_.each(items, function (item) {
queueItem(queue, item);
server.request({
action: 'get',
thumbs
}).then(json => {
lo.each(queue, (req, idx) => {
req.callback(json && json.thumbs ? json.thumbs[idx] : null);
});
});
}
if (queue.length) {
requestQueue(queue);
}
function handleItems(items) {
const queue = [];
lo.each(items, item => {
queueItem(queue, item);
});
if (queue.length) {
requestQueue(queue);
}
}
function onViewChanged(added) {
setTimeout(() => {
handleItems(added);
}, settings.delay);
}
function init() {
if (!settings.enabled) {
return;
}
function onViewChanged(added) {
setTimeout(function () {
handleItems(added);
}, settings.delay);
}
function init() {
if (!settings.enabled) {
return;
}
event.sub('view.changed', onViewChanged);
}
event.sub('view.changed', onViewChanged);
}
init();
});
init();

View file

@ -1,26 +1,29 @@
modulejs.define('ext/title', ['_', 'core/event', 'core/settings'], function (_, event, allsettings) {
var settings = _.extend({
enabled: false
}, allsettings.title);
const {document: doc, _: lo} = require('../win');
const event = require('../core/event');
const allsettings = require('../core/settings');
function onLocationChanged(item) {
var labels = _.map(item.getCrumb(), 'label');
var title = labels.join(' > ');
if (labels.length > 1) {
title = labels[labels.length - 1] + ' - ' + title;
}
const settings = lo.extend({
enabled: false
}, allsettings.title);
document.title = title;
function onLocationChanged(item) {
const labels = lo.map(item.getCrumb(), 'label');
let title = labels.join(' > ');
if (labels.length > 1) {
title = labels[labels.length - 1] + ' - ' + title;
}
function init() {
if (!settings.enabled) {
return;
}
doc.title = title;
}
event.sub('location.changed', onLocationChanged);
function init() {
if (!settings.enabled) {
return;
}
init();
});
event.sub('location.changed', onLocationChanged);
}
init();

View file

@ -1,201 +1,208 @@
modulejs.define('ext/tree', ['_', '$', 'core/event', 'core/location', 'core/resource', 'core/settings', 'core/store', 'core/util'], function (_, $, event, location, resource, allsettings, store, util) {
var settings = _.extend({
enabled: false,
show: true,
maxSubfolders: 50,
naturalSort: false,
ignorecase: true
}, allsettings.tree);
var template =
'<div class="item">' +
'<span class="indicator none">' +
'<img src="' + resource.image('tree-indicator') + '"/>' +
'</span>' +
'<a>' +
'<span class="icon"><img/></span>' +
'<span class="label"/>' +
'</a>' +
'</span>';
var settingsTemplate =
'<div class="block">' +
'<h1 class="l10n-tree">Tree</h1>' +
'<div id="view-tree" class="button view">' +
'<img src="' + resource.image('tree-toggle') + '" alt="view-tree"/>' +
'</div>' +
'</div>';
var storekey = 'ext/tree';
const {jQuery: jq, _: lo} = require('../win');
const event = require('../core/event');
const location = require('../core/location');
const resource = require('../core/resource');
const allsettings = require('../core/settings');
const store = require('../core/store');
const util = require('../core/util');
function cmpFn(item1, item2) {
var val1 = item1.label;
var val2 = item2.label;
const settings = lo.extend({
enabled: false,
show: true,
maxSubfolders: 50,
naturalSort: false,
ignorecase: true
}, allsettings.tree);
const template =
`<div class="item">
<span class="indicator none">
<img src="${resource.image('tree-indicator')}"/>
</span>
<a>
<span class="icon"><img/></span>
<span class="label"/>
</a>
</span>`;
const settingsTemplate =
`<div class="block">
<h1 class="l10n-tree">Tree</h1>
<div id="view-tree" class="button view">
<img src="${resource.image('tree-toggle')}" alt="view-tree"/>
</div>
</div>`;
const storekey = 'ext/tree';
if (settings.ignorecase) {
val1 = val1.toLowerCase();
val2 = val2.toLowerCase();
}
return settings.natural ? util.naturalCmpFn(val1, val2) : util.regularCmpFn(val1, val2);
function cmpFn(item1, item2) {
let val1 = item1.label;
let val2 = item2.label;
if (settings.ignorecase) {
val1 = val1.toLowerCase();
val2 = val2.toLowerCase();
}
function update(item) {
var $html = $(template);
var $indicator = $html.find('.indicator');
var $a = $html.find('a');
var $img = $html.find('.icon img');
var $label = $html.find('.label');
return settings.natural ? util.naturalCmpFn(val1, val2) : util.regularCmpFn(val1, val2);
}
$html
.addClass(item.isFolder() ? 'folder' : 'file')
.data('item', item);
function update(item) {
const $html = jq(template);
const $indicator = $html.find('.indicator');
const $a = $html.find('a');
const $img = $html.find('.icon img');
const $label = $html.find('.label');
location.setLink($a, item);
$img.attr('src', resource.icon('folder'));
$label.text(item.label);
$html
.addClass(item.isFolder() ? 'folder' : 'file')
.data('item', item);
if (item.isFolder()) {
var subfolders = item.getSubfolders();
location.setLink($a, item);
$img.attr('src', resource.icon('folder'));
$label.text(item.label);
// indicator
if (item.isManaged && !item.isContentFetched || subfolders.length) {
$indicator.removeClass('none');
if (item.isFolder()) {
const subfolders = item.getSubfolders();
if (item.isManaged && !item.isContentFetched) {
$indicator.addClass('unknown');
} else if (item.isContentVisible) {
$indicator.addClass('open');
} else {
$indicator.addClass('close');
}
}
// indicator
if (item.isManaged && !item.isContentFetched || subfolders.length) {
$indicator.removeClass('none');
// is it the current folder?
if (item.isCurrentFolder()) {
$html.addClass('active');
}
// does it have subfolders?
if (subfolders.length) {
subfolders.sort(cmpFn);
var $ul = $('<ul class="content"/>').appendTo($html);
var counter = 0;
_.each(subfolders, function (e) {
counter += 1;
if (counter <= settings.maxSubfolders) {
$('<li/>').append(update(e)).appendTo($ul);
}
});
if (subfolders.length > settings.maxSubfolders) {
$('<li class="summary">… ' + (subfolders.length - settings.maxSubfolders) + ' more subfolders</li>').appendTo($ul);
}
if (!item.isContentVisible) {
$ul.hide();
}
}
// reflect folder status
if (!item.isManaged) {
$img.attr('src', resource.icon('folder-page'));
}
}
if (item.$tree) {
item.$tree.replaceWith($html);
}
item.$tree = $html;
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']();
}
return function () {
var $indicator = $(this);
var $item = $indicator.closest('.item');
var item = $item.data('item');
var $content = $item.find('> ul.content');
if ($indicator.hasClass('unknown')) {
item.fetchContent(function () {
item.isContentVisible = false;
$item = update(item);
$indicator = $item.find('> .indicator');
$content = $item.find('> ul.content');
if (!$indicator.hasClass('none')) {
slide(item, $indicator, $content, true);
}
});
} else if ($indicator.hasClass('open')) {
slide(item, $indicator, $content, false);
} else if ($indicator.hasClass('close')) {
slide(item, $indicator, $content, true);
}
};
}
function fetchTree(item, callback) {
item.isContentVisible = true;
item.fetchContent(function () {
if (item.parent) {
fetchTree(item.parent, callback);
if (item.isManaged && !item.isContentFetched) {
$indicator.addClass('unknown');
} else if (item.isContentVisible) {
$indicator.addClass('open');
} else {
callback(item);
$indicator.addClass('close');
}
});
}
function updateSettings() {
if (store.get(storekey)) {
$('#view-tree').addClass('active');
$('#tree').show();
} else {
$('#view-tree').removeClass('active');
$('#tree').hide();
}
}
function onLocationChanged(item) {
fetchTree(item, function (root) {
$('#tree').append(update(root));
updateSettings();
});
}
function init() {
if (!settings.enabled) {
return;
}
$('<div id="tree"/>')
.appendTo('#mainrow')
.on('click', '.indicator', createOnIndicatorClick());
// is it the current folder?
if (item.isCurrentFolder()) {
$html.addClass('active');
}
$(settingsTemplate)
.appendTo('#sidebar')
.find('#view-tree')
.on('click', function (ev) {
store.put(storekey, !store.get(storekey));
updateSettings();
ev.preventDefault();
// does it have subfolders?
if (subfolders.length) {
subfolders.sort(cmpFn);
const $ul = jq('<ul class="content"/>').appendTo($html);
let counter = 0;
lo.each(subfolders, e => {
counter += 1;
if (counter <= settings.maxSubfolders) {
jq('<li/>').append(update(e)).appendTo($ul);
}
});
// ensure stored value is boolean, otherwise set default
if (typeof store.get(storekey) !== 'boolean') {
store.put(storekey, settings.show);
if (subfolders.length > settings.maxSubfolders) {
jq('<li class="summary">… ' + (subfolders.length - settings.maxSubfolders) + ' more subfolders</li>').appendTo($ul);
}
if (!item.isContentVisible) {
$ul.hide();
}
}
updateSettings();
event.sub('location.changed', onLocationChanged);
// reflect folder status
if (!item.isManaged) {
$img.attr('src', resource.icon('folder-page'));
}
}
if (item.$tree) {
item.$tree.replaceWith($html);
}
item.$tree = $html;
init();
});
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']();
}
return ev => {
let $indicator = jq(ev.currentTarget);
let $item = $indicator.closest('.item');
const item = $item.data('item');
let $content = $item.find('> ul.content');
if ($indicator.hasClass('unknown')) {
item.fetchContent(() => {
item.isContentVisible = false;
$item = update(item);
$indicator = $item.find('> .indicator');
$content = $item.find('> ul.content');
if (!$indicator.hasClass('none')) {
slide(item, $indicator, $content, true);
}
});
} else if ($indicator.hasClass('open')) {
slide(item, $indicator, $content, false);
} else if ($indicator.hasClass('close')) {
slide(item, $indicator, $content, true);
}
};
}
function fetchTree(item, callback) {
item.isContentVisible = true;
item.fetchContent(() => {
if (item.parent) {
fetchTree(item.parent, callback);
} else {
callback(item);
}
});
}
function updateSettings() {
if (store.get(storekey)) {
jq('#view-tree').addClass('active');
jq('#tree').show();
} else {
jq('#view-tree').removeClass('active');
jq('#tree').hide();
}
}
function onLocationChanged(item) {
fetchTree(item, root => {
jq('#tree').append(update(root));
updateSettings();
});
}
function init() {
if (!settings.enabled) {
return;
}
jq('<div id="tree"/>')
.appendTo('#mainrow')
.on('click', '.indicator', createOnIndicatorClick());
jq(settingsTemplate)
.appendTo('#sidebar')
.find('#view-tree')
.on('click', ev => {
store.put(storekey, !store.get(storekey));
updateSettings();
ev.preventDefault();
});
// ensure stored value is boolean, otherwise set default
if (typeof store.get(storekey) !== 'boolean') {
store.put(storekey, settings.show);
}
updateSettings();
event.sub('location.changed', onLocationChanged);
}
init();