Begin to move all src javascript to es6. Add search/filter ignore case option.
This commit is contained in:
parent
f37e8e7b89
commit
7ec2bdf16a
58 changed files with 3546 additions and 3420 deletions
27
.eslintrc
27
.eslintrc
|
@ -5,29 +5,8 @@
|
|||
es6: true
|
||||
node: true
|
||||
|
||||
ecmaFeatures:
|
||||
arrowFunctions: true
|
||||
binaryLiterals: true
|
||||
blockBindings: true
|
||||
classes: false
|
||||
defaultParams: true
|
||||
destructuring: true
|
||||
forOf: true
|
||||
generators: true
|
||||
globalReturn: true
|
||||
jsx: false
|
||||
modules: true
|
||||
objectLiteralComputedProperties: true
|
||||
objectLiteralDuplicateProperties: true
|
||||
objectLiteralShorthandMethods: true
|
||||
objectLiteralShorthandProperties: true
|
||||
octalLiterals: true
|
||||
regexUFlag: true
|
||||
regexYFlag: true
|
||||
spread: true
|
||||
superInFunctions: false
|
||||
templateStrings: true
|
||||
unicodeCodePointEscapes: true
|
||||
parserOptions:
|
||||
ecmaVersion: 6
|
||||
|
||||
rules:
|
||||
array-bracket-spacing: [2, never]
|
||||
|
@ -179,7 +158,7 @@
|
|||
prefer-const: 1
|
||||
prefer-reflect: 1
|
||||
prefer-spread: 2
|
||||
prefer-template: 0 ###
|
||||
prefer-template: 0
|
||||
quote-props: [2, as-needed]
|
||||
quotes: [2, single, avoid-escape]
|
||||
radix: 2
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# Changelog
|
||||
|
||||
* add options to filter/search ignore case
|
||||
* replace PHP `getenv` calls with `$_SERVER` lookups
|
||||
* adds `view.fallbackMode` option to generally serve only fallback mode
|
||||
* serves fallback mode for text browsers (`curl`, `links`, `lynx`, `w3m`)
|
||||
|
@ -15,7 +16,7 @@
|
|||
* updates `jQuery` to 2.2.4
|
||||
* updates `jquery-qrcode` to 0.14.0
|
||||
* updates `lodash` to 4.13.1 (removes `contains`)
|
||||
* updates `modulejs` to 1.14.0
|
||||
* removes `modulejs`
|
||||
|
||||
|
||||
## v0.28.0 - *2015-12-19*
|
||||
|
|
23
ghu.js
23
ghu.js
|
@ -1,7 +1,7 @@
|
|||
const {resolve, join} = require('path');
|
||||
const {
|
||||
ghu, autoprefixer, cssmin, each, ife, includeit, jszip, less, mapfn,
|
||||
newerThan, pug, read, remove, run, uglify, watch, wrap, write
|
||||
newerThan, pug, read, remove, run, uglify, watch, webpack, wrap, write
|
||||
} = require('ghu');
|
||||
|
||||
const ROOT = resolve(__dirname);
|
||||
|
@ -49,8 +49,27 @@ ghu.task('lint', 'lint all JavaScript files with eslint', () => {
|
|||
});
|
||||
|
||||
ghu.task('build:scripts', runtime => {
|
||||
return read(`${SRC}/_h5ai/public/js/*.js`)
|
||||
const webpackConfig = {
|
||||
output: {},
|
||||
module: {
|
||||
loaders: [
|
||||
{
|
||||
include: [SRC],
|
||||
loader: 'babel',
|
||||
query: {
|
||||
presets: ['es2015'],
|
||||
cacheDirectory: true
|
||||
}
|
||||
}
|
||||
],
|
||||
presets: ['es2015']
|
||||
}
|
||||
};
|
||||
|
||||
return read(`${SRC}/_h5ai/public/js/scripts.js`)
|
||||
.then(newerThan(mapper, `${SRC}/_h5ai/public/js/**`))
|
||||
.then(webpack(webpackConfig, {showStats: true}))
|
||||
.then(wrap('\n\n// @include "vendor/*"\n\n'))
|
||||
.then(includeit())
|
||||
.then(ife(() => runtime.args.production, uglify()))
|
||||
.then(wrap(runtime.commentJs))
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
"build": "node ghu release"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-loader": "6.2.4",
|
||||
"babel-preset-es2015": "6.9.0",
|
||||
"eslint": "2.11.0",
|
||||
"ghu": "0.6.0"
|
||||
},
|
||||
|
|
|
@ -1,43 +1,5 @@
|
|||
---
|
||||
env:
|
||||
es6: false
|
||||
node: false
|
||||
browser: true
|
||||
mocha: false
|
||||
|
||||
globals:
|
||||
modulejs: false
|
||||
|
||||
ecmaFeatures:
|
||||
arrowFunctions: false
|
||||
binaryLiterals: false
|
||||
blockBindings: false
|
||||
classes: false
|
||||
defaultParams: false
|
||||
destructuring: false
|
||||
forOf: false
|
||||
generators: false
|
||||
globalReturn: false
|
||||
jsx: false
|
||||
modules: false
|
||||
objectLiteralComputedProperties: false
|
||||
objectLiteralDuplicateProperties: false
|
||||
objectLiteralShorthandMethods: false
|
||||
objectLiteralShorthandProperties: false
|
||||
octalLiterals: false
|
||||
regexUFlag: false
|
||||
regexYFlag: false
|
||||
spread: false
|
||||
superInFunctions: false
|
||||
templateStrings: false
|
||||
unicodeCodePointEscapes: false
|
||||
|
||||
rules:
|
||||
consistent-this: 0
|
||||
func-names: 0
|
||||
max-params: [1, 10]
|
||||
no-invalid-this: 0
|
||||
no-var: 0
|
||||
object-shorthand: 0
|
||||
prefer-arrow-callback: 0
|
||||
no-console: 1
|
||||
prefer-reflect: 0
|
||||
|
|
|
@ -144,11 +144,13 @@
|
|||
|
||||
- advanced: boolean, use advanced pattern parsing
|
||||
- debounceTime: number, debounce wait time in milliseconds
|
||||
- ignorecase: boolean, ignore case
|
||||
*/
|
||||
"filter": {
|
||||
"enabled": false,
|
||||
"enabled": true,
|
||||
"advanced": true,
|
||||
"debounceTime": 100
|
||||
"debounceTime": 100,
|
||||
"ignorecase": true
|
||||
},
|
||||
|
||||
/*
|
||||
|
@ -311,11 +313,13 @@
|
|||
|
||||
- advanced: boolean, use advanced pattern parsing
|
||||
- debounceTime: number, debounce wait time in milliseconds
|
||||
- ignorecase: boolean, ignore case
|
||||
*/
|
||||
"search": {
|
||||
"enabled": true,
|
||||
"advanced": true,
|
||||
"debounceTime": 300
|
||||
"debounceTime": 300,
|
||||
"ignorecase": true
|
||||
},
|
||||
|
||||
/*
|
||||
|
|
|
@ -45,7 +45,6 @@ class Api {
|
|||
|
||||
foreach (['langs', 'options', 'types'] as $name) {
|
||||
if ($this->request->query_boolean($name, false)) {
|
||||
|
||||
$methodname = 'get_' . $name;
|
||||
$response[$name] = $this->context->$methodname();
|
||||
}
|
||||
|
@ -84,8 +83,9 @@ class Api {
|
|||
Util::json_fail(Util::ERR_DISABLED, 'search disabled', !$this->context->query_option('search.enabled', false));
|
||||
$href = $this->request->query('search.href');
|
||||
$pattern = $this->request->query('search.pattern');
|
||||
$ignorecase = $this->request->query_boolean('search.ignorecase', false);
|
||||
$search = new Search($this->context);
|
||||
$response['search'] = $search->get_items($href, $pattern);
|
||||
$response['search'] = $search->get_items($href, $pattern, $ignorecase);
|
||||
}
|
||||
|
||||
if ($this->request->query('thumbs', false)) {
|
||||
|
|
|
@ -7,10 +7,13 @@ class Search {
|
|||
$this->context = $context;
|
||||
}
|
||||
|
||||
public function get_paths($root, $pattern = null) {
|
||||
public function get_paths($root, $pattern = null, $ignorecase = false) {
|
||||
$paths = [];
|
||||
if ($pattern && $this->context->is_managed_path($root)) {
|
||||
$re = Util::wrap_pattern($pattern);
|
||||
if ($ignorecase) {
|
||||
$re .= 'i';
|
||||
}
|
||||
$names = $this->context->read_dir($root);
|
||||
foreach ($names as $name) {
|
||||
$path = $root . '/' . $name;
|
||||
|
@ -18,17 +21,17 @@ class Search {
|
|||
$paths[] = $path;
|
||||
}
|
||||
if (@is_dir($path)) {
|
||||
$paths = array_merge($paths, $this->get_paths($path, $pattern));
|
||||
$paths = array_merge($paths, $this->get_paths($path, $pattern, $ignorecase));
|
||||
}
|
||||
}
|
||||
}
|
||||
return $paths;
|
||||
}
|
||||
|
||||
public function get_items($href, $pattern = null) {
|
||||
public function get_items($href, $pattern = null, $ignorecase = false) {
|
||||
$cache = [];
|
||||
$root = $this->context->to_path($href);
|
||||
$paths = $this->get_paths($root, $pattern);
|
||||
$paths = $this->get_paths($root, $pattern, $ignorecase);
|
||||
$items = array_map(function ($path) {
|
||||
return Item::get($this->context, $path, $cache)->to_json_object();
|
||||
}, $paths);
|
||||
|
|
|
@ -1,25 +0,0 @@
|
|||
modulejs.define('boot', ['$', 'core/server'], function ($, server) {
|
||||
var module = $('script[data-module]').data('module');
|
||||
var data = {
|
||||
action: 'get',
|
||||
setup: true,
|
||||
options: true,
|
||||
types: true
|
||||
};
|
||||
|
||||
if (module === 'index') {
|
||||
data.theme = true;
|
||||
data.langs = true;
|
||||
} else if (module === 'info') {
|
||||
data.refresh = true;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
server.request(data, function (config) {
|
||||
modulejs.define('config', config);
|
||||
$(function () {
|
||||
modulejs.require('main/' + module);
|
||||
});
|
||||
});
|
||||
});
|
10
src/_h5ai/public/js/lib/config.js
Normal file
10
src/_h5ai/public/js/lib/config.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
const {request} = require('./core/server');
|
||||
|
||||
const config = module.exports = {
|
||||
_update: data => {
|
||||
return request(data).then(newConfig => {
|
||||
Object.assign(config, newConfig);
|
||||
return config;
|
||||
});
|
||||
}
|
||||
};
|
|
@ -1,36 +1,33 @@
|
|||
modulejs.define('core/event', ['_'], function (_) {
|
||||
var slice = Array.prototype.slice;
|
||||
var subscriptions = {};
|
||||
const {_: lo} = require('../win');
|
||||
|
||||
function sub(topic, callback) {
|
||||
if (_.isString(topic) && _.isFunction(callback)) {
|
||||
if (!subscriptions[topic]) {
|
||||
subscriptions[topic] = [];
|
||||
}
|
||||
subscriptions[topic].push(callback);
|
||||
const subscriptions = {};
|
||||
|
||||
function sub(topic, listener) {
|
||||
if (lo.isString(topic) && lo.isFunction(listener)) {
|
||||
if (!subscriptions[topic]) {
|
||||
subscriptions[topic] = [];
|
||||
}
|
||||
subscriptions[topic].push(listener);
|
||||
}
|
||||
}
|
||||
|
||||
function unsub(topic, callback) {
|
||||
if (_.isString(topic) && _.isFunction(callback) && subscriptions[topic]) {
|
||||
subscriptions[topic] = _.without(subscriptions[topic], callback);
|
||||
}
|
||||
function unsub(topic, listener) {
|
||||
if (lo.isString(topic) && lo.isFunction(listener) && subscriptions[topic]) {
|
||||
subscriptions[topic] = lo.without(subscriptions[topic], listener);
|
||||
}
|
||||
}
|
||||
|
||||
function pub(topic) {
|
||||
var args = slice.call(arguments, 1);
|
||||
|
||||
if (_.isString(topic) && subscriptions[topic]) {
|
||||
_.each(subscriptions[topic], function (callback) {
|
||||
callback.apply(topic, args);
|
||||
});
|
||||
}
|
||||
function pub(topic, ...args) {
|
||||
// console.log(topic, args);
|
||||
if (lo.isString(topic) && subscriptions[topic]) {
|
||||
lo.each(subscriptions[topic], listener => {
|
||||
listener.apply(topic, args);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
sub: sub,
|
||||
unsub: unsub,
|
||||
pub: pub
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
sub,
|
||||
unsub,
|
||||
pub
|
||||
};
|
||||
|
|
|
@ -1,95 +1,96 @@
|
|||
modulejs.define('core/format', ['_'], function (_) {
|
||||
var decimalMetric = {
|
||||
t: 1000.0,
|
||||
k: 1000.0,
|
||||
u: ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||
const {_: lo} = require('../win');
|
||||
|
||||
const decimalMetric = {
|
||||
t: 1000.0,
|
||||
k: 1000.0,
|
||||
u: ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||
};
|
||||
const binaryMetric = {
|
||||
t: 1024.0,
|
||||
k: 1024.0,
|
||||
u: ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
|
||||
};
|
||||
let defaultMetric = decimalMetric;
|
||||
|
||||
const datePatterns = [
|
||||
[/YYYY/, 'Y', 4],
|
||||
[/YY/, 'Y', 2],
|
||||
[/Y/, 'Y', 0],
|
||||
[/MM/, 'M', 2],
|
||||
[/M/, 'M', 0],
|
||||
[/DD/, 'D', 2],
|
||||
[/D/, 'D', 0],
|
||||
[/HH/, 'H', 2],
|
||||
[/H/, 'H', 0],
|
||||
[/mm/, 'm', 2],
|
||||
[/m/, 'm', 0],
|
||||
[/ss/, 's', 2],
|
||||
[/s/, 's', 0]
|
||||
];
|
||||
let defaultDateFormat = 'YYYY-MM-DD HH:mm';
|
||||
|
||||
|
||||
function setDefaultMetric(useBinaryMetric) {
|
||||
defaultMetric = useBinaryMetric ? binaryMetric : decimalMetric;
|
||||
}
|
||||
|
||||
function formatSize(size, metric) {
|
||||
metric = metric || defaultMetric;
|
||||
|
||||
if (!lo.isNumber(size) || size < 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
let i = 0;
|
||||
const maxI = metric.u.length - 1;
|
||||
|
||||
while (size >= metric.t && i < maxI) {
|
||||
size /= metric.k;
|
||||
i += 1;
|
||||
}
|
||||
return (i <= 1 ? Math.round(size) : size.toFixed(1)).toString() + ' ' + metric.u[i];
|
||||
}
|
||||
|
||||
function setDefaultDateFormat(dateFormat) {
|
||||
defaultDateFormat = dateFormat;
|
||||
}
|
||||
|
||||
function formatNumber(number, padding) {
|
||||
let str = String(number);
|
||||
if (padding) {
|
||||
str = ('000' + str).substr(-padding);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function formatDate(millis, format) {
|
||||
if (!millis || !lo.isNumber(millis)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
format = format || defaultDateFormat;
|
||||
|
||||
const date = new Date(millis);
|
||||
const d = {
|
||||
Y: date.getFullYear(),
|
||||
M: date.getMonth() + 1,
|
||||
D: date.getDate(),
|
||||
H: date.getHours(),
|
||||
m: date.getMinutes(),
|
||||
s: date.getSeconds()
|
||||
};
|
||||
var binaryMetric = {
|
||||
t: 1024.0,
|
||||
k: 1024.0,
|
||||
u: ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB']
|
||||
};
|
||||
var defaultMetric = decimalMetric;
|
||||
var datePatterns = [
|
||||
[/YYYY/, 'Y', 4],
|
||||
[/YY/, 'Y', 2],
|
||||
[/Y/, 'Y', 0],
|
||||
[/MM/, 'M', 2],
|
||||
[/M/, 'M', 0],
|
||||
[/DD/, 'D', 2],
|
||||
[/D/, 'D', 0],
|
||||
[/HH/, 'H', 2],
|
||||
[/H/, 'H', 0],
|
||||
[/mm/, 'm', 2],
|
||||
[/m/, 'm', 0],
|
||||
[/ss/, 's', 2],
|
||||
[/s/, 's', 0]
|
||||
];
|
||||
var defaultDateFormat = 'YYYY-MM-DD HH:mm';
|
||||
|
||||
datePatterns.forEach(pattern => {
|
||||
format = format.replace(pattern[0], formatNumber(d[pattern[1]], pattern[2]));
|
||||
});
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
|
||||
function setDefaultMetric(useBinaryMetric) {
|
||||
defaultMetric = useBinaryMetric ? binaryMetric : decimalMetric;
|
||||
}
|
||||
|
||||
function formatSize(size, metric) {
|
||||
metric = metric || defaultMetric;
|
||||
|
||||
if (!_.isNumber(size) || size < 0) {
|
||||
return '';
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
var maxI = metric.u.length - 1;
|
||||
|
||||
while (size >= metric.t && i < maxI) {
|
||||
size /= metric.k;
|
||||
i += 1;
|
||||
}
|
||||
return (i <= 1 ? Math.round(size) : size.toFixed(1)).toString() + ' ' + metric.u[i];
|
||||
}
|
||||
|
||||
function setDefaultDateFormat(dateFormat) {
|
||||
defaultDateFormat = dateFormat;
|
||||
}
|
||||
|
||||
function formatNumber(number, padding) {
|
||||
var str = String(number);
|
||||
if (padding) {
|
||||
str = ('000' + str).substr(-padding);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
function formatDate(millis, format) {
|
||||
if (!millis || !_.isNumber(millis)) {
|
||||
return '';
|
||||
}
|
||||
|
||||
format = format || defaultDateFormat;
|
||||
|
||||
var date = new Date(millis);
|
||||
var d = {
|
||||
Y: date.getFullYear(),
|
||||
M: date.getMonth() + 1,
|
||||
D: date.getDate(),
|
||||
H: date.getHours(),
|
||||
m: date.getMinutes(),
|
||||
s: date.getSeconds()
|
||||
};
|
||||
|
||||
datePatterns.forEach(function (pattern) {
|
||||
format = format.replace(pattern[0], formatNumber(d[pattern[1]], pattern[2]));
|
||||
});
|
||||
|
||||
return format;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
setDefaultMetric: setDefaultMetric,
|
||||
formatSize: formatSize,
|
||||
setDefaultDateFormat: setDefaultDateFormat,
|
||||
formatDate: formatDate
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
setDefaultMetric,
|
||||
formatSize,
|
||||
setDefaultDateFormat,
|
||||
formatDate
|
||||
};
|
||||
|
|
|
@ -1,3 +1,2 @@
|
|||
modulejs.define('core/langs', ['_', 'config'], function (_, config) {
|
||||
return _.extend({}, config.langs);
|
||||
});
|
||||
const config = require('../config');
|
||||
module.exports = Object.assign({}, config.langs);
|
||||
|
|
|
@ -1,181 +1,191 @@
|
|||
modulejs.define('core/location', ['_', 'core/event', 'core/modernizr', 'core/settings', 'view/notification'], function (_, event, modernizr, allsettings, notification) {
|
||||
var settings = _.extend({
|
||||
fastBrowsing: true,
|
||||
unmanagedInNewWindow: true
|
||||
}, allsettings.view);
|
||||
var doc = document;
|
||||
var history = settings.fastBrowsing && modernizr.history ? window.history : null;
|
||||
var reUriToPathname = /^.*:\/\/[^\/]*|[^\/]*$/g;
|
||||
var absHref = null;
|
||||
var reForceEncoding = [
|
||||
[/\/+/g, '/'],
|
||||
[/ /g, '%20'],
|
||||
[/!/g, '%21'],
|
||||
[/#/g, '%23'],
|
||||
[/\$/g, '%24'],
|
||||
[/&/g, '%26'],
|
||||
[/'/g, '%27'],
|
||||
[/\(/g, '%28'],
|
||||
[/\)/g, '%29'],
|
||||
[/\*/g, '%2A'],
|
||||
[/\+/g, '%2B'],
|
||||
[/\,/g, '%2C'],
|
||||
[/:/g, '%3A'],
|
||||
[/;/g, '%3B'],
|
||||
[/\=/g, '%3D'],
|
||||
[/\?/g, '%3F'],
|
||||
[/@/g, '%40'],
|
||||
[/\[/g, '%5B'],
|
||||
[/\]/g, '%5D']
|
||||
];
|
||||
const {window: win, document: doc, _: lo} = require('../win');
|
||||
const {request} = require('./server');
|
||||
const allsettings = require('./settings');
|
||||
const modernizr = require('./modernizr');
|
||||
const event = require('./event');
|
||||
|
||||
function forceEncoding(href) {
|
||||
return reForceEncoding.reduce(function (nuHref, data) {
|
||||
return nuHref.replace(data[0], data[1]);
|
||||
}, href);
|
||||
const notification = require('../view/notification');
|
||||
|
||||
|
||||
const settings = lo.extend({
|
||||
fastBrowsing: true,
|
||||
unmanagedInNewWindow: true
|
||||
}, allsettings.view);
|
||||
const history = settings.fastBrowsing && modernizr.history ? win.history : null;
|
||||
const reUriToPathname = /^.*:\/\/[^\/]*|[^\/]*$/g;
|
||||
const reForceEncoding = [
|
||||
[/\/+/g, '/'],
|
||||
[/ /g, '%20'],
|
||||
[/!/g, '%21'],
|
||||
[/#/g, '%23'],
|
||||
[/\$/g, '%24'],
|
||||
[/&/g, '%26'],
|
||||
[/'/g, '%27'],
|
||||
[/\(/g, '%28'],
|
||||
[/\)/g, '%29'],
|
||||
[/\*/g, '%2A'],
|
||||
[/\+/g, '%2B'],
|
||||
[/\,/g, '%2C'],
|
||||
[/:/g, '%3A'],
|
||||
[/;/g, '%3B'],
|
||||
[/\=/g, '%3D'],
|
||||
[/\?/g, '%3F'],
|
||||
[/@/g, '%40'],
|
||||
[/\[/g, '%5B'],
|
||||
[/\]/g, '%5D']
|
||||
];
|
||||
|
||||
|
||||
let absHref = null;
|
||||
|
||||
|
||||
function forceEncoding(href) {
|
||||
return reForceEncoding.reduce((nuHref, data) => {
|
||||
return nuHref.replace(data[0], data[1]);
|
||||
}, href);
|
||||
}
|
||||
|
||||
function uriToPathname(uri) {
|
||||
return uri.replace(reUriToPathname, '');
|
||||
}
|
||||
|
||||
const hrefsAreDecoded = (() => {
|
||||
const testpathname = '/a b';
|
||||
const a = doc.createElement('a');
|
||||
|
||||
a.href = testpathname;
|
||||
return uriToPathname(a.href) === testpathname;
|
||||
})();
|
||||
|
||||
function encodedHref(href) {
|
||||
const a = doc.createElement('a');
|
||||
let location;
|
||||
|
||||
a.href = href;
|
||||
location = uriToPathname(a.href);
|
||||
|
||||
if (hrefsAreDecoded) {
|
||||
location = encodeURIComponent(location).replace(/%2F/ig, '/');
|
||||
}
|
||||
|
||||
function uriToPathname(uri) {
|
||||
return uri.replace(reUriToPathname, '');
|
||||
}
|
||||
return forceEncoding(location);
|
||||
}
|
||||
|
||||
var hrefsAreDecoded = (function () {
|
||||
var testpathname = '/a b';
|
||||
var a = doc.createElement('a');
|
||||
function getDomain() {
|
||||
return doc.domain;
|
||||
}
|
||||
|
||||
a.href = testpathname;
|
||||
return uriToPathname(a.href) === testpathname;
|
||||
}());
|
||||
function getAbsHref() {
|
||||
return absHref;
|
||||
}
|
||||
|
||||
function encodedHref(href) {
|
||||
var a = doc.createElement('a');
|
||||
var location;
|
||||
function getItem() {
|
||||
const Item = require('../model/item');
|
||||
return Item.get(absHref);
|
||||
}
|
||||
|
||||
a.href = href;
|
||||
location = uriToPathname(a.href);
|
||||
function load(callback) {
|
||||
request({action: 'get', items: {href: absHref, what: 1}}).then(json => {
|
||||
const Item = require('../model/item');
|
||||
const item = Item.get(absHref);
|
||||
|
||||
if (hrefsAreDecoded) {
|
||||
location = encodeURIComponent(location).replace(/%2F/ig, '/');
|
||||
}
|
||||
if (json) {
|
||||
const found = {};
|
||||
|
||||
return forceEncoding(location);
|
||||
}
|
||||
lo.each(json.items, jsonItem => {
|
||||
const e = Item.get(jsonItem);
|
||||
found[e.absHref] = true;
|
||||
});
|
||||
|
||||
function getDomain() {
|
||||
return doc.domain;
|
||||
}
|
||||
|
||||
function getAbsHref() {
|
||||
return absHref;
|
||||
}
|
||||
|
||||
function getItem() {
|
||||
return modulejs.require('model/item').get(absHref);
|
||||
}
|
||||
|
||||
function load(callback) {
|
||||
modulejs.require('core/server').request({action: 'get', items: {href: absHref, what: 1}}, function (json) {
|
||||
var Item = modulejs.require('model/item');
|
||||
var item = Item.get(absHref);
|
||||
|
||||
if (json) {
|
||||
var found = {};
|
||||
|
||||
_.each(json.items, function (jsonItem) {
|
||||
var e = Item.get(jsonItem);
|
||||
found[e.absHref] = true;
|
||||
});
|
||||
|
||||
_.each(item.content, function (e) {
|
||||
if (!found[e.absHref]) {
|
||||
Item.remove(e.absHref);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (_.isFunction(callback)) {
|
||||
callback(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
var item = getItem();
|
||||
var oldItems = _.values(item.content);
|
||||
|
||||
event.pub('location.beforeRefresh');
|
||||
|
||||
load(function () {
|
||||
var newItems = _.values(item.content);
|
||||
var added = _.difference(newItems, oldItems);
|
||||
var removed = _.difference(oldItems, newItems);
|
||||
|
||||
event.pub('location.refreshed', item, added, removed);
|
||||
});
|
||||
}
|
||||
|
||||
function setLocation(newAbsHref, keepBrowserUrl) {
|
||||
event.pub('location.beforeChange');
|
||||
|
||||
newAbsHref = encodedHref(newAbsHref);
|
||||
|
||||
if (absHref !== newAbsHref) {
|
||||
absHref = newAbsHref;
|
||||
|
||||
if (history) {
|
||||
if (keepBrowserUrl) {
|
||||
history.replaceState({absHref: absHref}, '', absHref);
|
||||
} else {
|
||||
history.pushState({absHref: absHref}, '', absHref);
|
||||
lo.each(item.content, e => {
|
||||
if (!found[e.absHref]) {
|
||||
Item.remove(e.absHref);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (lo.isFunction(callback)) {
|
||||
callback(item);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
const item = getItem();
|
||||
const oldItems = lo.values(item.content);
|
||||
|
||||
event.pub('location.beforeRefresh');
|
||||
|
||||
load(() => {
|
||||
const newItems = lo.values(item.content);
|
||||
const added = lo.difference(newItems, oldItems);
|
||||
const removed = lo.difference(oldItems, newItems);
|
||||
|
||||
event.pub('location.refreshed', item, added, removed);
|
||||
});
|
||||
}
|
||||
|
||||
function setLocation(newAbsHref, keepBrowserUrl) {
|
||||
event.pub('location.beforeChange');
|
||||
|
||||
newAbsHref = encodedHref(newAbsHref);
|
||||
|
||||
if (absHref !== newAbsHref) {
|
||||
absHref = newAbsHref;
|
||||
|
||||
if (history) {
|
||||
if (keepBrowserUrl) {
|
||||
history.replaceState({absHref}, '', absHref);
|
||||
} else {
|
||||
history.pushState({absHref}, '', absHref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var item = getItem();
|
||||
if (item.isLoaded) {
|
||||
const item = getItem();
|
||||
if (item.isLoaded) {
|
||||
event.pub('location.changed', item);
|
||||
refresh();
|
||||
} else {
|
||||
notification.set('loading...');
|
||||
load(() => {
|
||||
item.isLoaded = true;
|
||||
notification.set();
|
||||
event.pub('location.changed', item);
|
||||
refresh();
|
||||
} else {
|
||||
notification.set('loading...');
|
||||
load(function () {
|
||||
item.isLoaded = true;
|
||||
notification.set();
|
||||
event.pub('location.changed', item);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function setLink($el, item) {
|
||||
$el.attr('href', item.absHref);
|
||||
|
||||
if (history && item.isFolder() && item.isManaged) {
|
||||
$el.on('click', () => {
|
||||
setLocation(item.absHref);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
function setLink($el, item) {
|
||||
$el.attr('href', item.absHref);
|
||||
|
||||
if (history && item.isFolder() && item.isManaged) {
|
||||
$el.on('click', function () {
|
||||
setLocation(item.absHref);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
if (settings.unmanagedInNewWindow && !item.isManaged) {
|
||||
$el.attr('target', '_blank');
|
||||
}
|
||||
if (settings.unmanagedInNewWindow && !item.isManaged) {
|
||||
$el.attr('target', '_blank');
|
||||
}
|
||||
}
|
||||
|
||||
function onPopState(ev) {
|
||||
if (ev.state && ev.state.absHref) {
|
||||
setLocation(ev.state.absHref, true);
|
||||
}
|
||||
function onPopState(ev) {
|
||||
if (ev.state && ev.state.absHref) {
|
||||
setLocation(ev.state.absHref, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
window.onpopstate = history ? onPopState : null;
|
||||
win.onpopstate = history ? onPopState : null;
|
||||
|
||||
|
||||
return {
|
||||
forceEncoding: forceEncoding,
|
||||
getDomain: getDomain,
|
||||
getAbsHref: getAbsHref,
|
||||
getItem: getItem,
|
||||
setLocation: setLocation,
|
||||
refresh: refresh,
|
||||
setLink: setLink
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
forceEncoding,
|
||||
getDomain,
|
||||
getAbsHref,
|
||||
getItem,
|
||||
setLocation,
|
||||
refresh,
|
||||
setLink
|
||||
};
|
||||
|
|
|
@ -1,25 +1,25 @@
|
|||
modulejs.define('core/modernizr', function () {
|
||||
var hasCanvas = (function () {
|
||||
var elem = document.createElement('canvas');
|
||||
return Boolean(elem.getContext && elem.getContext('2d'));
|
||||
}());
|
||||
const win = require('../win');
|
||||
|
||||
var hasHistory = Boolean(window.history && history.pushState);
|
||||
const hasCanvas = (() => {
|
||||
const elem = win.document.createElement('canvas');
|
||||
return !!(elem.getContext && elem.getContext('2d'));
|
||||
})();
|
||||
|
||||
var hasLocalStorage = (function () {
|
||||
var key = '#test#';
|
||||
try {
|
||||
localStorage.setItem(key, key);
|
||||
localStorage.removeItem(key);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}());
|
||||
const hasHistory = !!(win.history && win.history.pushState);
|
||||
|
||||
return {
|
||||
canvas: hasCanvas,
|
||||
history: hasHistory,
|
||||
localstorage: hasLocalStorage
|
||||
};
|
||||
});
|
||||
const hasLocalStorage = (() => {
|
||||
const key = '#test#';
|
||||
try {
|
||||
win.localStorage.setItem(key, key);
|
||||
win.localStorage.removeItem(key);
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
})();
|
||||
|
||||
module.exports = {
|
||||
canvas: hasCanvas,
|
||||
history: hasHistory,
|
||||
localstorage: hasLocalStorage
|
||||
};
|
||||
|
|
|
@ -1,37 +1,39 @@
|
|||
modulejs.define('core/resource', ['_', 'config', 'core/settings'], function (_, config, settings) {
|
||||
var imagesHref = settings.publicHref + 'images/';
|
||||
var uiHref = imagesHref + 'ui/';
|
||||
var themesHref = imagesHref + 'themes/';
|
||||
var defaultThemeHref = themesHref + 'default/';
|
||||
var defaultIcons = ['file', 'folder', 'folder-page', 'folder-parent', 'ar', 'aud', 'bin', 'img', 'txt', 'vid', 'x'];
|
||||
const {_: lo} = require('../win');
|
||||
const config = require('../config');
|
||||
const settings = require('./settings');
|
||||
|
||||
const imagesHref = settings.publicHref + 'images/';
|
||||
const uiHref = imagesHref + 'ui/';
|
||||
const themesHref = imagesHref + 'themes/';
|
||||
const defaultThemeHref = themesHref + 'default/';
|
||||
const defaultIcons = ['file', 'folder', 'folder-page', 'folder-parent', 'ar', 'aud', 'bin', 'img', 'txt', 'vid', 'x'];
|
||||
|
||||
|
||||
function image(id) {
|
||||
return uiHref + id + '.svg';
|
||||
function image(id) {
|
||||
return uiHref + id + '.svg';
|
||||
}
|
||||
|
||||
function icon(id) {
|
||||
const baseId = (id || '').split('-')[0];
|
||||
const href = config.theme[id] || config.theme[baseId];
|
||||
|
||||
if (href) {
|
||||
return themesHref + href;
|
||||
}
|
||||
|
||||
function icon(id) {
|
||||
var baseId = (id || '').split('-')[0];
|
||||
var href = config.theme[id] || config.theme[baseId];
|
||||
|
||||
if (href) {
|
||||
return themesHref + href;
|
||||
}
|
||||
|
||||
if (_.includes(defaultIcons, id)) {
|
||||
return defaultThemeHref + id + '.svg';
|
||||
}
|
||||
|
||||
if (_.includes(defaultIcons, baseId)) {
|
||||
return defaultThemeHref + baseId + '.svg';
|
||||
}
|
||||
|
||||
return defaultThemeHref + 'file.svg';
|
||||
if (lo.includes(defaultIcons, id)) {
|
||||
return defaultThemeHref + id + '.svg';
|
||||
}
|
||||
|
||||
if (lo.includes(defaultIcons, baseId)) {
|
||||
return defaultThemeHref + baseId + '.svg';
|
||||
}
|
||||
|
||||
return {
|
||||
image: image,
|
||||
icon: icon
|
||||
};
|
||||
});
|
||||
return defaultThemeHref + 'file.svg';
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
image,
|
||||
icon
|
||||
};
|
||||
|
|
|
@ -1,35 +1,32 @@
|
|||
modulejs.define('core/server', ['_', '$'], function (_, $) {
|
||||
function request(data, callback) {
|
||||
$.ajax({
|
||||
const {jQuery: jq, _: lo} = require('../win');
|
||||
|
||||
function request(data) {
|
||||
return new Promise(resolve => {
|
||||
jq.ajax({
|
||||
url: '?',
|
||||
data: data,
|
||||
data,
|
||||
type: 'post',
|
||||
dataType: 'json'
|
||||
})
|
||||
.done(function (json) {
|
||||
callback(json);
|
||||
})
|
||||
.fail(function () {
|
||||
callback();
|
||||
});
|
||||
}
|
||||
.done(json => resolve(json))
|
||||
.fail(() => resolve());
|
||||
});
|
||||
}
|
||||
|
||||
function formRequest(data) {
|
||||
var $form = $('<form method="post" action="?" style="display:none;"/>');
|
||||
function formRequest(data) {
|
||||
const $form = jq('<form method="post" action="?" style="display:none;"/>');
|
||||
|
||||
_.each(data, function (val, key) {
|
||||
$('<input type="hidden"/>')
|
||||
.attr('name', key)
|
||||
.attr('value', val)
|
||||
.appendTo($form);
|
||||
});
|
||||
lo.each(data, (val, key) => {
|
||||
jq('<input type="hidden"/>')
|
||||
.attr('name', key)
|
||||
.attr('value', val)
|
||||
.appendTo($form);
|
||||
});
|
||||
|
||||
$form.appendTo('body').submit().remove();
|
||||
}
|
||||
$form.appendTo('body').submit().remove();
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
request: request,
|
||||
formRequest: formRequest
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
request,
|
||||
formRequest
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
modulejs.define('core/settings', ['_', 'config'], function (_, config) {
|
||||
return _.extend({}, config.options, {
|
||||
publicHref: config.setup.PUBLIC_HREF,
|
||||
rootHref: config.setup.ROOT_HREF
|
||||
});
|
||||
const config = require('../config');
|
||||
|
||||
module.exports = Object.assign({}, config.options, {
|
||||
publicHref: config.setup.PUBLIC_HREF,
|
||||
rootHref: config.setup.ROOT_HREF
|
||||
});
|
||||
|
|
|
@ -1,32 +1,33 @@
|
|||
modulejs.define('core/store', ['core/modernizr'], function (modernizr) {
|
||||
var store = modernizr.localstorage ? window.localStorage : {};
|
||||
var storekey = '_h5ai';
|
||||
const win = require('../win');
|
||||
const modernizr = require('./modernizr');
|
||||
|
||||
const store = modernizr.localstorage ? win.localStorage : {};
|
||||
const storekey = '_h5ai';
|
||||
|
||||
|
||||
function load() {
|
||||
try {
|
||||
return JSON.parse(store[storekey]);
|
||||
} catch (e) {/* skip */}
|
||||
return {};
|
||||
}
|
||||
function load() {
|
||||
try {
|
||||
return JSON.parse(store[storekey]);
|
||||
} catch (e) {/* skip */}
|
||||
return {};
|
||||
}
|
||||
|
||||
function save(obj) {
|
||||
store[storekey] = JSON.stringify(obj);
|
||||
}
|
||||
function save(obj) {
|
||||
store[storekey] = JSON.stringify(obj);
|
||||
}
|
||||
|
||||
function put(key, value) {
|
||||
var obj = load();
|
||||
obj[key] = value;
|
||||
save(obj);
|
||||
}
|
||||
function put(key, value) {
|
||||
const obj = load();
|
||||
obj[key] = value;
|
||||
save(obj);
|
||||
}
|
||||
|
||||
function get(key) {
|
||||
return load()[key];
|
||||
}
|
||||
function get(key) {
|
||||
return load()[key];
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
put: put,
|
||||
get: get
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
put,
|
||||
get
|
||||
};
|
||||
|
|
|
@ -1,43 +1,44 @@
|
|||
modulejs.define('core/types', ['_', 'config'], function (_, config) {
|
||||
var reEndsWithSlash = /\/$/;
|
||||
var regexps = {};
|
||||
const {_: lo} = require('../win');
|
||||
const config = require('../config');
|
||||
|
||||
const reEndsWithSlash = /\/$/;
|
||||
const regexps = {};
|
||||
|
||||
|
||||
function escapeRegExp(sequence) {
|
||||
return sequence.replace(/[\-\[\]\/\{\}\(\)\+\?\.\\\^\$]/g, '\\$&');
|
||||
// return sequence.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
|
||||
function escapeRegExp(sequence) {
|
||||
return sequence.replace(/[\-\[\]\/\{\}\(\)\+\?\.\\\^\$]/g, '\\$&');
|
||||
// return sequence.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
|
||||
}
|
||||
|
||||
function parse(types) {
|
||||
lo.each(types, (patterns, type) => {
|
||||
const pattern = '^(' + lo.map(patterns, p => '(' + escapeRegExp(p).replace(/\*/g, '.*') + ')').join('|') + ')$';
|
||||
regexps[type] = new RegExp(pattern, 'i');
|
||||
});
|
||||
}
|
||||
|
||||
function getType(sequence) {
|
||||
if (reEndsWithSlash.test(sequence)) {
|
||||
return 'folder';
|
||||
}
|
||||
|
||||
function parse(types) {
|
||||
_.each(types, function (patterns, type) {
|
||||
var pattern = '^(' + _.map(patterns, function (p) { return '(' + escapeRegExp(p).replace(/\*/g, '.*') + ')'; }).join('|') + ')$';
|
||||
regexps[type] = new RegExp(pattern, 'i');
|
||||
});
|
||||
}
|
||||
const slashidx = sequence.lastIndexOf('/');
|
||||
const name = slashidx >= 0 ? sequence.substr(slashidx + 1) : sequence;
|
||||
let result;
|
||||
|
||||
function getType(sequence) {
|
||||
if (reEndsWithSlash.test(sequence)) {
|
||||
return 'folder';
|
||||
lo.each(regexps, (regexp, type) => { // eslint-disable-line consistent-return
|
||||
if (regexps[type].test(name)) {
|
||||
result = type;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
var slashidx = sequence.lastIndexOf('/');
|
||||
var name = slashidx >= 0 ? sequence.substr(slashidx + 1) : sequence;
|
||||
var result;
|
||||
|
||||
_.each(regexps, function (regexp, type) { // eslint-disable-line consistent-return
|
||||
if (regexps[type].test(name)) {
|
||||
result = type;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
return result ? result : 'file';
|
||||
}
|
||||
return result ? result : 'file';
|
||||
}
|
||||
|
||||
|
||||
parse(_.extend({}, config.types));
|
||||
parse(Object.assign({}, config.types));
|
||||
|
||||
return {
|
||||
getType: getType
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
getType
|
||||
};
|
||||
|
|
|
@ -1,93 +1,93 @@
|
|||
modulejs.define('core/util', ['_'], function (_) {
|
||||
function regularCmpFn(val1, val2) {
|
||||
if (val1 < val2) {
|
||||
const {_: lo} = require('../win');
|
||||
|
||||
function regularCmpFn(val1, val2) {
|
||||
if (val1 < val2) {
|
||||
return -1;
|
||||
}
|
||||
if (val1 > val2) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Natural Sort algorithm for Javascript - Version 0.7 - Released under MIT license
|
||||
// Author: Jim Palmer (based on chunking idea from Dave Koelle)
|
||||
//
|
||||
// Modified to make it work with h5ai
|
||||
function naturalCmpFn(val1, val2) {
|
||||
const re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi;
|
||||
const sre = /(^[ ]*|[ ]*$)/g;
|
||||
const dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/;
|
||||
const hre = /^0x[0-9a-f]+$/i;
|
||||
const ore = /^0/;
|
||||
// convert all to strings strip whitespace
|
||||
const x = String(val1).replace(sre, '');
|
||||
const y = String(val2).replace(sre, '');
|
||||
// chunk/tokenize
|
||||
const xN = x.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0');
|
||||
const yN = y.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0');
|
||||
// numeric, hex or date detection
|
||||
const xD = parseInt(x.match(hre), 10) || xN.length !== 1 && x.match(dre) && Date.parse(x);
|
||||
const yD = parseInt(y.match(hre), 10) || xD && y.match(dre) && Date.parse(y) || null;
|
||||
let oFxNcL;
|
||||
let oFyNcL;
|
||||
// first try and sort Hex codes or Dates
|
||||
if (yD) {
|
||||
if (xD < yD) {
|
||||
return -1;
|
||||
}
|
||||
if (val1 > val2) {
|
||||
} else if (xD > yD) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// natural sorting through split numeric strings and default strings
|
||||
for (let cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc += 1) {
|
||||
// find floats not starting with '0', string or 0 if not defined (Clint Priest)
|
||||
oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0;
|
||||
oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0;
|
||||
// handle numeric vs string comparison - number < string - (Kyle Adams)
|
||||
if (isNaN(oFxNcL) !== isNaN(oFyNcL)) {
|
||||
return isNaN(oFxNcL) ? 1 : -1;
|
||||
} else if (typeof oFxNcL !== typeof oFyNcL) {
|
||||
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
|
||||
oFxNcL = String(oFxNcL);
|
||||
oFxNcL = String(oFxNcL);
|
||||
}
|
||||
if (oFxNcL < oFyNcL) {
|
||||
return -1;
|
||||
}
|
||||
if (oFxNcL > oFyNcL) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function escapePattern(sequence) {
|
||||
return sequence.replace(/[\-\[\]{}()*+?.,\\$\^|#\s]/g, '\\$&');
|
||||
}
|
||||
|
||||
function parsePattern(sequence, advanced) {
|
||||
if (!advanced) {
|
||||
return escapePattern(sequence);
|
||||
}
|
||||
|
||||
// Natural Sort algorithm for Javascript - Version 0.7 - Released under MIT license
|
||||
// Author: Jim Palmer (based on chunking idea from Dave Koelle)
|
||||
//
|
||||
// Modified to make it work with h5ai
|
||||
function naturalCmpFn(val1, val2) {
|
||||
var re = /(^-?[0-9]+(\.?[0-9]*)[df]?e?[0-9]?$|^0x[0-9a-f]+$|[0-9]+)/gi;
|
||||
var sre = /(^[ ]*|[ ]*$)/g;
|
||||
var dre = /(^([\w ]+,?[\w ]+)?[\w ]+,?[\w ]+\d+:\d+(:\d+)?[\w ]?|^\d{1,4}[\/\-]\d{1,4}[\/\-]\d{1,4}|^\w+, \w+ \d+, \d{4})/;
|
||||
var hre = /^0x[0-9a-f]+$/i;
|
||||
var ore = /^0/;
|
||||
// convert all to strings strip whitespace
|
||||
var x = String(val1).replace(sre, '');
|
||||
var y = String(val2).replace(sre, '');
|
||||
// chunk/tokenize
|
||||
var xN = x.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0');
|
||||
var yN = y.replace(re, '\0$1\0').replace(/\0$/, '').replace(/^\0/, '').split('\0');
|
||||
// numeric, hex or date detection
|
||||
var xD = parseInt(x.match(hre), 10) || xN.length !== 1 && x.match(dre) && Date.parse(x);
|
||||
var yD = parseInt(y.match(hre), 10) || xD && y.match(dre) && Date.parse(y) || null;
|
||||
var oFxNcL;
|
||||
var oFyNcL;
|
||||
// first try and sort Hex codes or Dates
|
||||
if (yD) {
|
||||
if (xD < yD) {
|
||||
return -1;
|
||||
} else if (xD > yD) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
// natural sorting through split numeric strings and default strings
|
||||
for (var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc += 1) {
|
||||
// find floats not starting with '0', string or 0 if not defined (Clint Priest)
|
||||
oFxNcL = !(xN[cLoc] || '').match(ore) && parseFloat(xN[cLoc]) || xN[cLoc] || 0;
|
||||
oFyNcL = !(yN[cLoc] || '').match(ore) && parseFloat(yN[cLoc]) || yN[cLoc] || 0;
|
||||
// handle numeric vs string comparison - number < string - (Kyle Adams)
|
||||
if (isNaN(oFxNcL) !== isNaN(oFyNcL)) {
|
||||
return isNaN(oFxNcL) ? 1 : -1;
|
||||
} else if (typeof oFxNcL !== typeof oFyNcL) {
|
||||
// rely on string comparison if different types - i.e. '02' < 2 != '02' < '2'
|
||||
oFxNcL = String(oFxNcL);
|
||||
oFxNcL = String(oFxNcL);
|
||||
}
|
||||
if (oFxNcL < oFyNcL) {
|
||||
return -1;
|
||||
}
|
||||
if (oFxNcL > oFyNcL) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
if (sequence.substr(0, 3) === 're:') {
|
||||
return sequence.substr(3);
|
||||
}
|
||||
|
||||
function escapePattern(sequence) {
|
||||
return sequence.replace(/[\-\[\]{}()*+?.,\\$\^|#\s]/g, '\\$&');
|
||||
}
|
||||
sequence = lo.map(lo.trim(sequence).split(/\s+/), part => {
|
||||
return lo.map(part.split(''), character => {
|
||||
return escapePattern(character);
|
||||
}).join('.*?');
|
||||
}).join('|');
|
||||
|
||||
function parsePattern(sequence, advanced) {
|
||||
if (!advanced) {
|
||||
return escapePattern(sequence);
|
||||
}
|
||||
|
||||
if (sequence.substr(0, 3) === 're:') {
|
||||
return sequence.substr(3);
|
||||
}
|
||||
|
||||
sequence = _.map(_.trim(sequence).split(/\s+/), function (part) {
|
||||
return _.map(part.split(''), function (character) {
|
||||
return escapePattern(character);
|
||||
}).join('.*?');
|
||||
}).join('|');
|
||||
|
||||
return sequence;
|
||||
}
|
||||
return sequence;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
regularCmpFn: regularCmpFn,
|
||||
naturalCmpFn: naturalCmpFn,
|
||||
escapePattern: escapePattern,
|
||||
parsePattern: parsePattern
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
regularCmpFn,
|
||||
naturalCmpFn,
|
||||
escapePattern,
|
||||
parsePattern
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
53
src/_h5ai/public/js/lib/ext/piwik-analytics.js
Executable file → Normal 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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
};
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
23
src/_h5ai/public/js/lib/init.js
Normal file
23
src/_h5ai/public/js/lib/init.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
const {jQuery: jq} = require('./win');
|
||||
const config = require('./config');
|
||||
|
||||
const name = jq('script[data-module]').data('module');
|
||||
const request = {
|
||||
action: 'get',
|
||||
setup: true,
|
||||
options: true,
|
||||
types: true
|
||||
};
|
||||
|
||||
if (name === 'index') {
|
||||
request.theme = true;
|
||||
request.langs = true;
|
||||
} else if (name === 'info') {
|
||||
request.refresh = true;
|
||||
} else {
|
||||
throw new Error(`no-main-module: '${name}'`);
|
||||
}
|
||||
|
||||
config._update(request).then(() => {
|
||||
jq(() => require(`./main/${name}`));
|
||||
});
|
|
@ -1,11 +1,28 @@
|
|||
modulejs.define('main/index', ['_', 'core/location'], function (_, location) {
|
||||
modulejs.require('view/viewmode');
|
||||
const {document: doc} = require('../win');
|
||||
const location = require('../core/location');
|
||||
|
||||
_.each(modulejs.state(), function (state, id) {
|
||||
if (id.indexOf('ext/') === 0) {
|
||||
modulejs.require(id);
|
||||
}
|
||||
});
|
||||
require('../view/viewmode');
|
||||
require('../ext/autorefresh');
|
||||
require('../ext/contextmenu');
|
||||
require('../ext/crumb');
|
||||
require('../ext/custom');
|
||||
require('../ext/download');
|
||||
require('../ext/filter');
|
||||
require('../ext/google-analytics');
|
||||
require('../ext/info');
|
||||
require('../ext/l10n');
|
||||
require('../ext/peer5');
|
||||
require('../ext/piwik-analytics');
|
||||
require('../ext/preview');
|
||||
require('../ext/preview-aud');
|
||||
require('../ext/preview-img');
|
||||
require('../ext/preview-txt');
|
||||
require('../ext/preview-vid');
|
||||
require('../ext/search');
|
||||
require('../ext/select');
|
||||
require('../ext/sort');
|
||||
require('../ext/thumbnails');
|
||||
require('../ext/title');
|
||||
require('../ext/tree');
|
||||
|
||||
location.setLocation(document.location.href, true);
|
||||
});
|
||||
location.setLocation(doc.location.href, true);
|
||||
|
|
|
@ -1,178 +1,182 @@
|
|||
modulejs.define('main/info', ['$', 'config', 'core/resource', 'core/server'], function ($, config, resource, server) {
|
||||
var tplTests =
|
||||
'<ul id="tests">';
|
||||
var tplTest =
|
||||
'<li class="test">' +
|
||||
'<span class="label"></span>' +
|
||||
'<span class="result"></span>' +
|
||||
'<div class="info"></div>' +
|
||||
'</li>';
|
||||
var tplLogin =
|
||||
'<div id="login-wrapper">' +
|
||||
'<input id="pass" type="password" placeholder="password"/>' +
|
||||
'<span id="login">login</span>' +
|
||||
'<span id="logout">logout</span>' +
|
||||
'<div id="hint">' +
|
||||
'The preset password is the empty string, just click login. ' +
|
||||
'Change it in \'_h5ai/private/conf/options.json\'.' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
var tplSupport =
|
||||
'<div id="support">' +
|
||||
'Show your support with a donation!' +
|
||||
'<div class="paypal">' +
|
||||
'<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">' +
|
||||
'<input type="hidden" name="cmd" value="_s-xclick" />' +
|
||||
'<input type="hidden" name="hosted_button_id" value="8WSPKWT7YBTSQ" />' +
|
||||
'<input type="image" src="' + resource.image('paypal') + '" name="submit" alt="PayPal" />' +
|
||||
'</form>' +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
var setup = config.setup;
|
||||
const {window: win, jQuery: jq} = require('../win');
|
||||
const config = require('../config');
|
||||
const resource = require('../core/resource');
|
||||
const server = require('../core/server');
|
||||
|
||||
|
||||
function addTest(label, info, passed, result) {
|
||||
var $test = $(tplTest).appendTo('#tests');
|
||||
$test.find('.label').text(label);
|
||||
$test.find('.result')
|
||||
.addClass(passed ? 'passed' : 'failed')
|
||||
.text(result ? result : passed ? 'yes' : 'no');
|
||||
$test.find('.info').html(info);
|
||||
const tplTests =
|
||||
'<ul id="tests">';
|
||||
const tplTest =
|
||||
`<li class="test">
|
||||
<span class="label"></span>
|
||||
<span class="result"></span>
|
||||
<div class="info"></div>
|
||||
</li>`;
|
||||
const tplLogin =
|
||||
`<div id="login-wrapper">
|
||||
<input id="pass" type="password" placeholder="password"/>
|
||||
<span id="login">login</span>
|
||||
<span id="logout">logout</span>
|
||||
<div id="hint">
|
||||
The preset password is the empty string, just click login.
|
||||
Change it in '_h5ai/private/conf/options.json'.
|
||||
</div>
|
||||
</div>`;
|
||||
const tplSupport =
|
||||
`<div id="support">
|
||||
Show your support with a donation!
|
||||
<div class="paypal">
|
||||
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_blank">
|
||||
<input type="hidden" name="cmd" value="_s-xclick" />
|
||||
<input type="hidden" name="hosted_button_id" value="8WSPKWT7YBTSQ" />
|
||||
<input type="image" src="${resource.image('paypal')}" name="submit" alt="PayPal" />
|
||||
</form>
|
||||
</div>
|
||||
</div>`;
|
||||
const setup = config.setup;
|
||||
|
||||
|
||||
function addTest(label, info, passed, result) {
|
||||
const $test = jq(tplTest).appendTo('#tests');
|
||||
$test.find('.label').text(label);
|
||||
$test.find('.result')
|
||||
.addClass(passed ? 'passed' : 'failed')
|
||||
.text(result ? result : passed ? 'yes' : 'no');
|
||||
$test.find('.info').html(info);
|
||||
}
|
||||
|
||||
function addTests() {
|
||||
if (!setup.AS_ADMIN) {
|
||||
return;
|
||||
}
|
||||
|
||||
function addTests() {
|
||||
if (!setup.AS_ADMIN) {
|
||||
return;
|
||||
}
|
||||
jq(tplTests).appendTo('#content');
|
||||
|
||||
$(tplTests).appendTo('#content');
|
||||
addTest(
|
||||
'h5ai version', 'Only green if this is an official h5ai release',
|
||||
(/^\d+\.\d+\.\d+$/).test(setup.VERSION), setup.VERSION
|
||||
);
|
||||
|
||||
addTest(
|
||||
'h5ai version', 'Only green if this is an official h5ai release',
|
||||
(/^\d+\.\d+\.\d+$/).test(setup.VERSION), setup.VERSION
|
||||
);
|
||||
addTest(
|
||||
'Index file found', 'Add <code>' + setup.INDEX_HREF + '</code> to your index file list',
|
||||
setup.INDEX_HREF
|
||||
);
|
||||
|
||||
addTest(
|
||||
'Index file found', 'Add <code>' + setup.INDEX_HREF + '</code> to your index file list',
|
||||
setup.INDEX_HREF
|
||||
);
|
||||
addTest(
|
||||
'Options parsable', 'File <code>options.json</code> is readable and syntax is correct',
|
||||
config.options !== null
|
||||
);
|
||||
|
||||
addTest(
|
||||
'Options parsable', 'File <code>options.json</code> is readable and syntax is correct',
|
||||
config.options !== null
|
||||
);
|
||||
addTest(
|
||||
'Types parsable', 'File <code>types.json</code> is readable and syntax is correct',
|
||||
config.types !== null
|
||||
);
|
||||
|
||||
addTest(
|
||||
'Types parsable', 'File <code>types.json</code> is readable and syntax is correct',
|
||||
config.types !== null
|
||||
);
|
||||
addTest(
|
||||
'Server software', 'Server is one of apache, lighttpd, nginx or cherokee',
|
||||
setup.HAS_SERVER, setup.SERVER_NAME + ' ' + setup.SERVER_VERSION
|
||||
);
|
||||
|
||||
addTest(
|
||||
'Server software', 'Server is one of apache, lighttpd, nginx or cherokee',
|
||||
setup.HAS_SERVER, setup.SERVER_NAME + ' ' + setup.SERVER_VERSION
|
||||
);
|
||||
addTest(
|
||||
'PHP version', 'PHP version >= ' + setup.MIN_PHP_VERSION,
|
||||
true, setup.PHP_VERSION
|
||||
);
|
||||
|
||||
addTest(
|
||||
'PHP version', 'PHP version >= ' + setup.MIN_PHP_VERSION,
|
||||
true, setup.PHP_VERSION
|
||||
);
|
||||
addTest(
|
||||
'Public Cache directory', 'Web server has write access',
|
||||
setup.HAS_WRITABLE_CACHE_PUB
|
||||
);
|
||||
|
||||
addTest(
|
||||
'Public Cache directory', 'Web server has write access',
|
||||
setup.HAS_WRITABLE_CACHE_PUB
|
||||
);
|
||||
addTest(
|
||||
'Private Cache directory', 'Web server has write access',
|
||||
setup.HAS_WRITABLE_CACHE_PRV
|
||||
);
|
||||
|
||||
addTest(
|
||||
'Private Cache directory', 'Web server has write access',
|
||||
setup.HAS_WRITABLE_CACHE_PRV
|
||||
);
|
||||
addTest(
|
||||
'Image thumbs', 'PHP GD extension with JPEG support available',
|
||||
setup.HAS_PHP_JPEG
|
||||
);
|
||||
|
||||
addTest(
|
||||
'Image thumbs', 'PHP GD extension with JPEG support available',
|
||||
setup.HAS_PHP_JPEG
|
||||
);
|
||||
addTest(
|
||||
'Use EXIF thumbs', 'PHP EXIF extension available',
|
||||
setup.HAS_PHP_EXIF
|
||||
);
|
||||
|
||||
addTest(
|
||||
'Use EXIF thumbs', 'PHP EXIF extension available',
|
||||
setup.HAS_PHP_EXIF
|
||||
);
|
||||
addTest(
|
||||
'Movie thumbs', 'Command line program <code>avconv</code> or <code>ffmpeg</code> available',
|
||||
setup.HAS_CMD_AVCONV || setup.HAS_CMD_FFMPEG
|
||||
);
|
||||
|
||||
addTest(
|
||||
'Movie thumbs', 'Command line program <code>avconv</code> or <code>ffmpeg</code> available',
|
||||
setup.HAS_CMD_AVCONV || setup.HAS_CMD_FFMPEG
|
||||
);
|
||||
addTest(
|
||||
'PDF thumbs', 'Command line program <code>convert</code> or <code>gm</code> available',
|
||||
setup.HAS_CMD_CONVERT || setup.HAS_CMD_GM
|
||||
);
|
||||
|
||||
addTest(
|
||||
'PDF thumbs', 'Command line program <code>convert</code> or <code>gm</code> available',
|
||||
setup.HAS_CMD_CONVERT || setup.HAS_CMD_GM
|
||||
);
|
||||
addTest(
|
||||
'Shell tar', 'Command line program <code>tar</code> available',
|
||||
setup.HAS_CMD_TAR
|
||||
);
|
||||
|
||||
addTest(
|
||||
'Shell tar', 'Command line program <code>tar</code> available',
|
||||
setup.HAS_CMD_TAR
|
||||
);
|
||||
addTest(
|
||||
'Shell zip', 'Command line program <code>zip</code> available',
|
||||
setup.HAS_CMD_ZIP
|
||||
);
|
||||
|
||||
addTest(
|
||||
'Shell zip', 'Command line program <code>zip</code> available',
|
||||
setup.HAS_CMD_ZIP
|
||||
);
|
||||
addTest(
|
||||
'Shell du', 'Command line program <code>du</code> available',
|
||||
setup.HAS_CMD_DU
|
||||
);
|
||||
}
|
||||
|
||||
addTest(
|
||||
'Shell du', 'Command line program <code>du</code> available',
|
||||
setup.HAS_CMD_DU
|
||||
);
|
||||
function reload() {
|
||||
win.location.reload();
|
||||
}
|
||||
|
||||
function onLogin() {
|
||||
server.request({
|
||||
action: 'login',
|
||||
pass: jq('#pass').val()
|
||||
}).then(reload);
|
||||
}
|
||||
|
||||
function onLogout() {
|
||||
server.request({
|
||||
action: 'logout'
|
||||
}).then(reload);
|
||||
}
|
||||
|
||||
function onKeydown(event) {
|
||||
if (event.which === 13) {
|
||||
onLogin();
|
||||
}
|
||||
}
|
||||
|
||||
function reload() {
|
||||
window.location.reload();
|
||||
function addSupport() {
|
||||
jq(tplSupport).appendTo('#content');
|
||||
}
|
||||
|
||||
function addLogin() {
|
||||
jq(tplLogin).appendTo('#content');
|
||||
|
||||
if (setup.AS_ADMIN) {
|
||||
jq('#pass').remove();
|
||||
jq('#login').remove();
|
||||
jq('#logout').on('click', onLogout);
|
||||
} else {
|
||||
jq('#pass').on('keydown', onKeydown).focus();
|
||||
jq('#login').on('click', onLogin);
|
||||
jq('#logout').remove();
|
||||
}
|
||||
|
||||
function onLogin() {
|
||||
server.request({
|
||||
action: 'login',
|
||||
pass: $('#pass').val()
|
||||
}, reload);
|
||||
if (config.options.hasCustomPasshash) {
|
||||
jq('#hint').remove();
|
||||
}
|
||||
}
|
||||
|
||||
function onLogout() {
|
||||
server.request({
|
||||
action: 'logout'
|
||||
}, reload);
|
||||
}
|
||||
|
||||
function onKeydown(event) {
|
||||
if (event.which === 13) {
|
||||
onLogin();
|
||||
}
|
||||
}
|
||||
|
||||
function addSupport() {
|
||||
$(tplSupport).appendTo('#content');
|
||||
}
|
||||
|
||||
function addLogin() {
|
||||
$(tplLogin).appendTo('#content');
|
||||
|
||||
if (setup.AS_ADMIN) {
|
||||
$('#pass').remove();
|
||||
$('#login').remove();
|
||||
$('#logout').on('click', onLogout);
|
||||
} else {
|
||||
$('#pass').on('keydown', onKeydown).focus();
|
||||
$('#login').on('click', onLogin);
|
||||
$('#logout').remove();
|
||||
}
|
||||
if (config.options.hasCustomPasshash) {
|
||||
$('#hint').remove();
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
addSupport();
|
||||
addLogin();
|
||||
addTests();
|
||||
}
|
||||
function init() {
|
||||
addSupport();
|
||||
addLogin();
|
||||
addTests();
|
||||
}
|
||||
|
||||
|
||||
init();
|
||||
});
|
||||
init();
|
||||
|
|
|
@ -1,226 +1,230 @@
|
|||
modulejs.define('model/item', ['_', 'core/event', 'core/location', 'core/server', 'core/settings', 'core/types'], function (_, event, location, server, settings, types) {
|
||||
var reEndsWithSlash = /\/$/;
|
||||
var reSplitPath = /^(.*\/)([^\/]+\/?)$/;
|
||||
var cache = {};
|
||||
const {_: lo} = require('../win');
|
||||
const location = require('../core/location');
|
||||
const server = require('../core/server');
|
||||
const settings = require('../core/settings');
|
||||
const types = require('../core/types');
|
||||
|
||||
|
||||
function startsWith(sequence, part) {
|
||||
if (!sequence || !sequence.indexOf) {
|
||||
return false;
|
||||
}
|
||||
const reEndsWithSlash = /\/$/;
|
||||
const reSplitPath = /^(.*\/)([^\/]+\/?)$/;
|
||||
const cache = {};
|
||||
|
||||
return sequence.indexOf(part) === 0;
|
||||
|
||||
function startsWith(sequence, part) {
|
||||
if (!sequence || !sequence.indexOf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function createLabel(sequence) {
|
||||
sequence = sequence.replace(reEndsWithSlash, '');
|
||||
try {
|
||||
sequence = decodeURIComponent(sequence);
|
||||
} catch (e) {/* skip */}
|
||||
return sequence;
|
||||
return sequence.indexOf(part) === 0;
|
||||
}
|
||||
|
||||
function createLabel(sequence) {
|
||||
sequence = sequence.replace(reEndsWithSlash, '');
|
||||
try {
|
||||
sequence = decodeURIComponent(sequence);
|
||||
} catch (e) {/* skip */}
|
||||
return sequence;
|
||||
}
|
||||
|
||||
function splitPath(sequence) { // eslint-disable-line consistent-return
|
||||
if (sequence === '/') {
|
||||
return {
|
||||
parent: null,
|
||||
name: '/'
|
||||
};
|
||||
}
|
||||
|
||||
function splitPath(sequence) { // eslint-disable-line consistent-return
|
||||
if (sequence === '/') {
|
||||
return {
|
||||
parent: null,
|
||||
name: '/'
|
||||
};
|
||||
const match = reSplitPath.exec(sequence);
|
||||
if (match) {
|
||||
const split = {
|
||||
parent: match[1],
|
||||
name: match[2]
|
||||
};
|
||||
|
||||
if (split.parent && !startsWith(split.parent, settings.rootHref)) {
|
||||
split.parent = null;
|
||||
}
|
||||
return split;
|
||||
}
|
||||
}
|
||||
|
||||
var match = reSplitPath.exec(sequence);
|
||||
if (match) {
|
||||
var split = {
|
||||
parent: match[1],
|
||||
name: match[2]
|
||||
};
|
||||
function getItem(options) {
|
||||
if (lo.isString(options)) {
|
||||
options = {href: options};
|
||||
} else if (!options || !lo.isString(options.href)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (split.parent && !startsWith(split.parent, settings.rootHref)) {
|
||||
split.parent = null;
|
||||
const href = location.forceEncoding(options.href);
|
||||
|
||||
if (!startsWith(href, settings.rootHref)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const item = cache[href] || new Item(href); // eslint-disable-line no-use-before-define
|
||||
|
||||
if (lo.isNumber(options.time)) {
|
||||
item.time = options.time;
|
||||
}
|
||||
if (lo.isNumber(options.size)) {
|
||||
item.size = options.size;
|
||||
}
|
||||
if (options.managed) {
|
||||
item.isManaged = true;
|
||||
}
|
||||
if (options.fetched) {
|
||||
item.isContentFetched = true;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
function removeItem(absHref) {
|
||||
absHref = location.forceEncoding(absHref);
|
||||
|
||||
const item = cache[absHref];
|
||||
|
||||
if (item) {
|
||||
delete cache[absHref];
|
||||
if (item.parent) {
|
||||
delete item.parent.content[item.absHref];
|
||||
}
|
||||
lo.each(item.content, child => {
|
||||
removeItem(child.absHref);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function fetchContent(absHref, callback) {
|
||||
const item = getItem(absHref);
|
||||
|
||||
if (!lo.isFunction(callback)) {
|
||||
callback = () => undefined;
|
||||
}
|
||||
|
||||
if (item.isContentFetched) {
|
||||
callback(item);
|
||||
} else {
|
||||
server.request({action: 'get', items: {href: item.absHref, what: 1}}).then(response => {
|
||||
if (response.items) {
|
||||
lo.each(response.items, jsonItem => {
|
||||
getItem(jsonItem);
|
||||
});
|
||||
}
|
||||
return split;
|
||||
}
|
||||
}
|
||||
|
||||
function getItem(options) {
|
||||
if (_.isString(options)) {
|
||||
options = {href: options};
|
||||
} else if (!options || !_.isString(options.href)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var href = location.forceEncoding(options.href);
|
||||
|
||||
if (!startsWith(href, settings.rootHref)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
var item = cache[href] || new Item(href); // eslint-disable-line no-use-before-define
|
||||
|
||||
if (_.isNumber(options.time)) {
|
||||
item.time = options.time;
|
||||
}
|
||||
if (_.isNumber(options.size)) {
|
||||
item.size = options.size;
|
||||
}
|
||||
if (options.managed) {
|
||||
item.isManaged = true;
|
||||
}
|
||||
if (options.fetched) {
|
||||
item.isContentFetched = true;
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
|
||||
function removeItem(absHref) {
|
||||
absHref = location.forceEncoding(absHref);
|
||||
|
||||
var item = cache[absHref];
|
||||
|
||||
if (item) {
|
||||
delete cache[absHref];
|
||||
if (item.parent) {
|
||||
delete item.parent.content[item.absHref];
|
||||
}
|
||||
_.each(item.content, function (child) {
|
||||
removeItem(child.absHref);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function fetchContent(absHref, callback) {
|
||||
var item = getItem(absHref);
|
||||
|
||||
if (!_.isFunction(callback)) {
|
||||
callback = function () {};
|
||||
}
|
||||
|
||||
if (item.isContentFetched) {
|
||||
callback(item);
|
||||
} else {
|
||||
server.request({action: 'get', items: {href: item.absHref, what: 1}}, function (response) {
|
||||
if (response.items) {
|
||||
_.each(response.items, function (jsonItem) {
|
||||
getItem(jsonItem);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
callback(item);
|
||||
});
|
||||
|
||||
function Item(absHref) {
|
||||
const split = splitPath(absHref);
|
||||
|
||||
cache[absHref] = this;
|
||||
|
||||
this.absHref = absHref;
|
||||
this.type = types.getType(absHref);
|
||||
this.label = createLabel(absHref === '/' ? location.getDomain() : split.name);
|
||||
this.time = null;
|
||||
this.size = null;
|
||||
this.parent = null;
|
||||
this.isManaged = null;
|
||||
this.content = {};
|
||||
|
||||
if (split.parent) {
|
||||
this.parent = getItem(split.parent);
|
||||
this.parent.content[this.absHref] = this;
|
||||
if (lo.keys(this.parent.content).length > 1) {
|
||||
this.parent.isContentFetched = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
lo.extend(Item.prototype, {
|
||||
isFolder() {
|
||||
return reEndsWithSlash.test(this.absHref);
|
||||
},
|
||||
|
||||
function Item(absHref) {
|
||||
var split = splitPath(absHref);
|
||||
isCurrentFolder() {
|
||||
return this.absHref === location.getAbsHref();
|
||||
},
|
||||
|
||||
cache[absHref] = this;
|
||||
isInCurrentFolder() {
|
||||
return Boolean(this.parent) && this.parent.isCurrentFolder();
|
||||
},
|
||||
|
||||
this.absHref = absHref;
|
||||
this.type = types.getType(absHref);
|
||||
this.label = createLabel(absHref === '/' ? location.getDomain() : split.name);
|
||||
this.time = null;
|
||||
this.size = null;
|
||||
this.parent = null;
|
||||
this.isManaged = null;
|
||||
this.content = {};
|
||||
isCurrentParentFolder() {
|
||||
const item = getItem(location.getAbsHref());
|
||||
return Boolean(item) && this === item.parent;
|
||||
},
|
||||
|
||||
if (split.parent) {
|
||||
this.parent = getItem(split.parent);
|
||||
this.parent.content[this.absHref] = this;
|
||||
if (_.keys(this.parent.content).length > 1) {
|
||||
this.parent.isContentFetched = true;
|
||||
}
|
||||
isDomain() {
|
||||
return this.absHref === '/';
|
||||
},
|
||||
|
||||
isRoot() {
|
||||
return this.absHref === settings.rootHref;
|
||||
},
|
||||
|
||||
isEmpty() {
|
||||
return lo.keys(this.content).length === 0;
|
||||
},
|
||||
|
||||
fetchContent(callback) {
|
||||
return fetchContent(this.absHref, callback);
|
||||
},
|
||||
|
||||
getCrumb() {
|
||||
let item = this; // eslint-disable-line consistent-this
|
||||
const crumb = [item];
|
||||
|
||||
while (item.parent) {
|
||||
item = item.parent;
|
||||
crumb.unshift(item);
|
||||
}
|
||||
|
||||
return crumb;
|
||||
},
|
||||
|
||||
getSubfolders() {
|
||||
return lo.sortBy(lo.filter(this.content, item => {
|
||||
return item.isFolder();
|
||||
}), item => {
|
||||
return item.label.toLowerCase();
|
||||
});
|
||||
},
|
||||
|
||||
getStats() {
|
||||
let folders = 0;
|
||||
let files = 0;
|
||||
|
||||
lo.each(this.content, item => {
|
||||
if (item.isFolder()) {
|
||||
folders += 1;
|
||||
} else {
|
||||
files += 1;
|
||||
}
|
||||
});
|
||||
|
||||
let depth = 0;
|
||||
let item = this; // eslint-disable-line consistent-this
|
||||
|
||||
while (item.parent) {
|
||||
depth += 1;
|
||||
item = item.parent;
|
||||
}
|
||||
|
||||
return {
|
||||
folders,
|
||||
files,
|
||||
depth
|
||||
};
|
||||
}
|
||||
|
||||
_.extend(Item.prototype, {
|
||||
|
||||
isFolder: function () {
|
||||
return reEndsWithSlash.test(this.absHref);
|
||||
},
|
||||
|
||||
isCurrentFolder: function () {
|
||||
return this.absHref === location.getAbsHref();
|
||||
},
|
||||
|
||||
isInCurrentFolder: function () {
|
||||
return Boolean(this.parent) && this.parent.isCurrentFolder();
|
||||
},
|
||||
|
||||
isCurrentParentFolder: function () {
|
||||
var item = getItem(location.getAbsHref());
|
||||
return Boolean(item) && this === item.parent;
|
||||
},
|
||||
|
||||
isDomain: function () {
|
||||
return this.absHref === '/';
|
||||
},
|
||||
|
||||
isRoot: function () {
|
||||
return this.absHref === settings.rootHref;
|
||||
},
|
||||
|
||||
isEmpty: function () {
|
||||
return _.keys(this.content).length === 0;
|
||||
},
|
||||
|
||||
fetchContent: function (callback) {
|
||||
return fetchContent(this.absHref, callback);
|
||||
},
|
||||
|
||||
getCrumb: function () {
|
||||
var item = this; // eslint-disable-line consistent-this
|
||||
var crumb = [item];
|
||||
|
||||
while (item.parent) {
|
||||
item = item.parent;
|
||||
crumb.unshift(item);
|
||||
}
|
||||
|
||||
return crumb;
|
||||
},
|
||||
|
||||
getSubfolders: function () {
|
||||
return _.sortBy(_.filter(this.content, function (item) {
|
||||
return item.isFolder();
|
||||
}), function (item) {
|
||||
return item.label.toLowerCase();
|
||||
});
|
||||
},
|
||||
|
||||
getStats: function () {
|
||||
var folders = 0;
|
||||
var files = 0;
|
||||
|
||||
_.each(this.content, function (item) {
|
||||
if (item.isFolder()) {
|
||||
folders += 1;
|
||||
} else {
|
||||
files += 1;
|
||||
}
|
||||
});
|
||||
|
||||
var depth = 0;
|
||||
var item = this; // eslint-disable-line consistent-this
|
||||
|
||||
while (item.parent) {
|
||||
depth += 1;
|
||||
item = item.parent;
|
||||
}
|
||||
|
||||
return {
|
||||
folders: folders,
|
||||
files: files,
|
||||
depth: depth
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
get: getItem,
|
||||
remove: removeItem
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
module.exports = {
|
||||
get: getItem,
|
||||
remove: removeItem
|
||||
};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
modulejs.define('view/content', ['$', 'view/mainrow'], function ($, mainrow) {
|
||||
var $el = $('<div id="content"/>').appendTo(mainrow.$el);
|
||||
const {jQuery: jq} = require('../win');
|
||||
const mainrow = require('./mainrow');
|
||||
|
||||
return {
|
||||
$el: $el
|
||||
};
|
||||
});
|
||||
const $el = jq('<div id="content"/>').appendTo(mainrow.$el);
|
||||
|
||||
module.exports = {
|
||||
$el
|
||||
};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
modulejs.define('view/mainrow', ['$', 'view/root'], function ($, root) {
|
||||
var $el = $('<div id="mainrow"/>').appendTo(root.$el);
|
||||
const {jQuery: jq} = require('../win');
|
||||
const root = require('./root');
|
||||
|
||||
return {
|
||||
$el: $el
|
||||
};
|
||||
});
|
||||
const $el = jq('<div id="mainrow"/>').appendTo(root.$el);
|
||||
|
||||
module.exports = {
|
||||
$el
|
||||
};
|
||||
|
|
|
@ -1,16 +1,17 @@
|
|||
modulejs.define('view/notification', ['$', 'view/root'], function ($, root) {
|
||||
var $el = $('<div id="notification"/>').hide().appendTo(root.$el);
|
||||
const {jQuery: jq} = require('../win');
|
||||
const root = require('./root');
|
||||
|
||||
function set(content) {
|
||||
if (content) {
|
||||
$el.stop(true, true).html(content).fadeIn(400);
|
||||
} else {
|
||||
$el.stop(true, true).fadeOut(400);
|
||||
}
|
||||
const $el = jq('<div id="notification"/>').hide().appendTo(root.$el);
|
||||
|
||||
function set(content) {
|
||||
if (content) {
|
||||
$el.stop(true, true).html(content).fadeIn(400);
|
||||
} else {
|
||||
$el.stop(true, true).fadeOut(400);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
$el: $el,
|
||||
set: set
|
||||
};
|
||||
});
|
||||
module.exports = {
|
||||
$el,
|
||||
set
|
||||
};
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
modulejs.define('view/root', ['$'], function ($) {
|
||||
var $el = $('body').attr('id', 'root');
|
||||
const {jQuery: jq} = require('../win');
|
||||
|
||||
$('#fallback, #fallback-hints').remove();
|
||||
const $el = jq('body').attr('id', 'root');
|
||||
|
||||
return {
|
||||
$el: $el
|
||||
};
|
||||
});
|
||||
jq('#fallback, #fallback-hints').remove();
|
||||
|
||||
module.exports = {
|
||||
$el
|
||||
};
|
||||
|
|
|
@ -1,40 +1,45 @@
|
|||
modulejs.define('view/sidebar', ['$', 'core/resource', 'core/store', 'view/mainrow', 'view/topbar'], function ($, resource, store, mainrow, topbar) {
|
||||
var storekey = 'sidebarIsVisible';
|
||||
var tplSidebar = '<div id="sidebar"/>';
|
||||
var tplToggle =
|
||||
'<div id="sidebar-toggle" class="tool">' +
|
||||
'<img alt="sidebar"/>' +
|
||||
'</div>';
|
||||
var $sidebar = $(tplSidebar);
|
||||
var $toggle = $(tplToggle);
|
||||
var $img = $toggle.find('img');
|
||||
const {jQuery: jq} = require('../win');
|
||||
const resource = require('../core/resource');
|
||||
const store = require('../core/store');
|
||||
const mainrow = require('./mainrow');
|
||||
const topbar = require('./topbar');
|
||||
|
||||
|
||||
function update(toggle) {
|
||||
var isVisible = store.get(storekey);
|
||||
const storekey = 'sidebarIsVisible';
|
||||
const tplSidebar = '<div id="sidebar"/>';
|
||||
const tplToggle =
|
||||
`<div id="sidebar-toggle" class="tool">
|
||||
<img alt="sidebar"/>
|
||||
</div>`;
|
||||
const $sidebar = jq(tplSidebar);
|
||||
const $toggle = jq(tplToggle);
|
||||
const $img = $toggle.find('img');
|
||||
|
||||
if (toggle) {
|
||||
isVisible = !isVisible;
|
||||
store.put(storekey, isVisible);
|
||||
}
|
||||
|
||||
if (isVisible) {
|
||||
$toggle.addClass('active');
|
||||
$img.attr('src', resource.image('back'));
|
||||
$sidebar.show();
|
||||
} else {
|
||||
$toggle.removeClass('active');
|
||||
$img.attr('src', resource.image('sidebar'));
|
||||
$sidebar.hide();
|
||||
}
|
||||
function update(toggle) {
|
||||
let isVisible = store.get(storekey);
|
||||
|
||||
if (toggle) {
|
||||
isVisible = !isVisible;
|
||||
store.put(storekey, isVisible);
|
||||
}
|
||||
|
||||
if (isVisible) {
|
||||
$toggle.addClass('active');
|
||||
$img.attr('src', resource.image('back'));
|
||||
$sidebar.show();
|
||||
} else {
|
||||
$toggle.removeClass('active');
|
||||
$img.attr('src', resource.image('sidebar'));
|
||||
$sidebar.hide();
|
||||
}
|
||||
}
|
||||
|
||||
$sidebar.appendTo(mainrow.$el);
|
||||
$toggle.appendTo(topbar.$toolbar).on('click', function () { update(true); });
|
||||
update(false);
|
||||
|
||||
return {
|
||||
$el: $sidebar
|
||||
};
|
||||
});
|
||||
$sidebar.appendTo(mainrow.$el);
|
||||
$toggle.appendTo(topbar.$toolbar).on('click', () => update(true));
|
||||
update();
|
||||
|
||||
module.exports = {
|
||||
$el: $sidebar
|
||||
};
|
||||
|
|
|
@ -1,18 +1,19 @@
|
|||
modulejs.define('view/topbar', ['$', 'view/root'], function ($, root) {
|
||||
var tplTopbar =
|
||||
'<div id="topbar">' +
|
||||
'<div id="toolbar"/>' +
|
||||
'<div id="flowbar"/>' +
|
||||
'<a id="backlink" href="https://larsjung.de/h5ai/" title="powered by h5ai - https://larsjung.de/h5ai/">' +
|
||||
'<div>powered</div>' +
|
||||
'<div>by h5ai</div>' +
|
||||
'</a>' +
|
||||
'</div>';
|
||||
var $el = $(tplTopbar).appendTo(root.$el);
|
||||
const {jQuery: jq} = require('../win');
|
||||
const root = require('./root');
|
||||
|
||||
return {
|
||||
$el: $el,
|
||||
$toolbar: $el.find('#toolbar'),
|
||||
$flowbar: $el.find('#flowbar')
|
||||
};
|
||||
});
|
||||
const tplTopbar =
|
||||
`<div id="topbar">
|
||||
<div id="toolbar"/>
|
||||
<div id="flowbar"/>
|
||||
<a id="backlink" href="https://larsjung.de/h5ai/" title="powered by h5ai - https://larsjung.de/h5ai/">
|
||||
<div>powered</div>
|
||||
<div>by h5ai</div>
|
||||
</a>
|
||||
</div>`;
|
||||
const $el = jq(tplTopbar).appendTo(root.$el);
|
||||
|
||||
module.exports = {
|
||||
$el,
|
||||
$toolbar: $el.find('#toolbar'),
|
||||
$flowbar: $el.find('#flowbar')
|
||||
};
|
||||
|
|
|
@ -1,292 +1,299 @@
|
|||
modulejs.define('view/view', ['_', '$', 'core/event', 'core/format', 'core/location', 'core/resource', 'core/settings', 'core/store', 'view/content'], function (_, $, event, format, location, resource, allsettings, store, content) {
|
||||
var modes = ['details', 'grid', 'icons'];
|
||||
var sizes = [20, 40, 60, 80, 100, 150, 200, 250, 300, 350, 400];
|
||||
var settings = _.extend({
|
||||
binaryPrefix: false,
|
||||
hideFolders: false,
|
||||
hideParentFolder: false,
|
||||
modes: modes,
|
||||
setParentFolderLabels: false,
|
||||
sizes: sizes
|
||||
}, allsettings.view);
|
||||
var sortedSizes = settings.sizes.sort(function (a, b) { return a - b; });
|
||||
var checkedModes = _.intersection(settings.modes, modes);
|
||||
var storekey = 'view';
|
||||
var tplView =
|
||||
'<div id="view">' +
|
||||
'<ul id="items" class="clearfix">' +
|
||||
'<li class="header">' +
|
||||
'<a class="icon"/>' +
|
||||
'<a class="label" href="#"><span class="l10n-name"/></a>' +
|
||||
'<a class="date" href="#"><span class="l10n-lastModified"/></a>' +
|
||||
'<a class="size" href="#"><span class="l10n-size"/></a>' +
|
||||
'</li>' +
|
||||
'</ul>' +
|
||||
'<div id="view-hint"/>' +
|
||||
'</div>';
|
||||
var tplItem =
|
||||
'<li class="item">' +
|
||||
'<a>' +
|
||||
'<span class="icon square"><img/></span>' +
|
||||
'<span class="icon landscape"><img/></span>' +
|
||||
'<span class="label"/>' +
|
||||
'<span class="date"/>' +
|
||||
'<span class="size"/>' +
|
||||
'</a>' +
|
||||
'</li>';
|
||||
var $view = $(tplView);
|
||||
var $items = $view.find('#items');
|
||||
var $hint = $view.find('#view-hint');
|
||||
const {jQuery: jq, _: lo} = require('../win');
|
||||
const event = require('../core/event');
|
||||
const format = require('../core/format');
|
||||
const location = require('../core/location');
|
||||
const resource = require('../core/resource');
|
||||
const store = require('../core/store');
|
||||
const allsettings = require('../core/settings');
|
||||
const content = require('./content');
|
||||
|
||||
const modes = ['details', 'grid', 'icons'];
|
||||
const sizes = [20, 40, 60, 80, 100, 150, 200, 250, 300, 350, 400];
|
||||
const settings = lo.extend({
|
||||
binaryPrefix: false,
|
||||
hideFolders: false,
|
||||
hideParentFolder: false,
|
||||
modes,
|
||||
setParentFolderLabels: false,
|
||||
sizes
|
||||
}, allsettings.view);
|
||||
const sortedSizes = settings.sizes.sort((a, b) => a - b);
|
||||
const checkedModes = lo.intersection(settings.modes, modes);
|
||||
const storekey = 'view';
|
||||
const tplView =
|
||||
`<div id="view">
|
||||
<ul id="items" class="clearfix">
|
||||
<li class="header">
|
||||
<a class="icon"/>
|
||||
<a class="label" href="#"><span class="l10n-name"/></a>
|
||||
<a class="date" href="#"><span class="l10n-lastModified"/></a>
|
||||
<a class="size" href="#"><span class="l10n-size"/></a>
|
||||
</li>
|
||||
</ul>
|
||||
<div id="view-hint"/>
|
||||
</div>`;
|
||||
const tplItem =
|
||||
`<li class="item">
|
||||
<a>
|
||||
<span class="icon square"><img/></span>
|
||||
<span class="icon landscape"><img/></span>
|
||||
<span class="label"/>
|
||||
<span class="date"/>
|
||||
<span class="size"/>
|
||||
</a>
|
||||
</li>`;
|
||||
const $view = jq(tplView);
|
||||
const $items = $view.find('#items');
|
||||
const $hint = $view.find('#view-hint');
|
||||
|
||||
|
||||
function cropSize(size, min, max) {
|
||||
return Math.min(max, Math.max(min, size));
|
||||
}
|
||||
function cropSize(size, min, max) {
|
||||
return Math.min(max, Math.max(min, size));
|
||||
}
|
||||
|
||||
function createStyles(size) {
|
||||
var dsize = cropSize(size, 20, 80);
|
||||
var gsize = cropSize(size, 40, 160);
|
||||
var isize = cropSize(size, 80, 1000);
|
||||
var ilsize = Math.round(isize * 4 / 3);
|
||||
var rules = [
|
||||
'#view.view-details.view-size-' + size + ' .item .label { line-height: ' + (dsize + 14) + 'px !important; }',
|
||||
'#view.view-details.view-size-' + size + ' .item .date { line-height: ' + (dsize + 14) + 'px !important; }',
|
||||
'#view.view-details.view-size-' + size + ' .item .size { line-height: ' + (dsize + 14) + 'px !important; }',
|
||||
'#view.view-details.view-size-' + size + ' .square { width: ' + dsize + 'px !important; height: ' + dsize + 'px !important; }',
|
||||
'#view.view-details.view-size-' + size + ' .square img { width: ' + dsize + 'px !important; height: ' + dsize + 'px !important; }',
|
||||
'#view.view-details.view-size-' + size + ' .label { margin-left: ' + (dsize + 32) + 'px !important; }',
|
||||
function createStyles(size) {
|
||||
const dsize = cropSize(size, 20, 80);
|
||||
const gsize = cropSize(size, 40, 160);
|
||||
const isize = cropSize(size, 80, 1000);
|
||||
const ilsize = Math.round(isize * 4 / 3);
|
||||
const rules = [
|
||||
`#view.view-details.view-size-${size} .item .label {line-height: ${dsize + 14}px !important;}`,
|
||||
`#view.view-details.view-size-${size} .item .date {line-height: ${dsize + 14}px !important;}`,
|
||||
`#view.view-details.view-size-${size} .item .size {line-height: ${dsize + 14}px !important;}`,
|
||||
`#view.view-details.view-size-${size} .square {width: ${dsize}px !important; height: ${dsize}px !important;}`,
|
||||
`#view.view-details.view-size-${size} .square img {width: ${dsize}px !important; height: ${dsize}px !important;}`,
|
||||
`#view.view-details.view-size-${size} .label {margin-left: ${dsize + 32}px !important;}`,
|
||||
|
||||
'#view.view-grid.view-size-' + size + ' .item .label { line-height: ' + gsize + 'px !important; }',
|
||||
'#view.view-grid.view-size-' + size + ' .square { width: ' + gsize + 'px !important; height: ' + gsize + 'px !important; }',
|
||||
'#view.view-grid.view-size-' + size + ' .square img { width: ' + gsize + 'px !important; height: ' + gsize + 'px !important; }',
|
||||
`#view.view-grid.view-size-${size} .item .label {line-height: ${gsize}px !important;}`,
|
||||
`#view.view-grid.view-size-${size} .square {width: ${gsize}px !important; height: ${gsize}px !important;}`,
|
||||
`#view.view-grid.view-size-${size} .square img {width: ${gsize}px !important; height: ${gsize}px !important;}`,
|
||||
|
||||
'#view.view-icons.view-size-' + size + ' .item { width: ' + ilsize + 'px !important; }',
|
||||
'#view.view-icons.view-size-' + size + ' .landscape { width: ' + ilsize + 'px !important; height: ' + isize + 'px !important; }',
|
||||
'#view.view-icons.view-size-' + size + ' .landscape img { width: ' + isize + 'px !important; height: ' + isize + 'px !important; }',
|
||||
'#view.view-icons.view-size-' + size + ' .landscape .thumb { width: ' + ilsize + 'px !important; }'
|
||||
];
|
||||
`#view.view-icons.view-size-${size} .item {width: ${ilsize}px !important;}`,
|
||||
`#view.view-icons.view-size-${size} .landscape {width: ${ilsize}px !important; height: ${isize}px !important;}`,
|
||||
`#view.view-icons.view-size-${size} .landscape img {width: ${isize}px !important; height: ${isize}px !important;}`,
|
||||
`#view.view-icons.view-size-${size} .landscape .thumb {width: ${ilsize}px !important;}`
|
||||
];
|
||||
|
||||
return rules.join('\n');
|
||||
}
|
||||
return rules.join('\n');
|
||||
}
|
||||
|
||||
function addCssStyles() {
|
||||
var styles = _.map(sortedSizes, function (size) { return createStyles(size); });
|
||||
styles.push('#view .icon img { max-width: ' + settings.maxIconSize + 'px; max-height: ' + settings.maxIconSize + 'px; }');
|
||||
$('<style/>').text(styles.join('\n')).appendTo('head');
|
||||
}
|
||||
function addCssStyles() {
|
||||
const styles = lo.map(sortedSizes, size => createStyles(size));
|
||||
styles.push(`#view .icon img {max-width: ${settings.maxIconSize}px; max-height: ${settings.maxIconSize}px;}`);
|
||||
jq('<style/>').text(styles.join('\n')).appendTo('head');
|
||||
}
|
||||
|
||||
function set(mode, size) {
|
||||
var stored = store.get(storekey);
|
||||
function set(mode, size) {
|
||||
const stored = store.get(storekey);
|
||||
|
||||
mode = mode || stored && stored.mode;
|
||||
size = size || stored && stored.size;
|
||||
mode = _.includes(settings.modes, mode) ? mode : settings.modes[0];
|
||||
size = _.includes(settings.sizes, size) ? size : settings.sizes[0];
|
||||
store.put(storekey, {mode: mode, size: size});
|
||||
mode = mode || stored && stored.mode;
|
||||
size = size || stored && stored.size;
|
||||
mode = lo.includes(settings.modes, mode) ? mode : settings.modes[0];
|
||||
size = lo.includes(settings.sizes, size) ? size : settings.sizes[0];
|
||||
store.put(storekey, {mode, size});
|
||||
|
||||
_.each(checkedModes, function (m) {
|
||||
if (m === mode) {
|
||||
$view.addClass('view-' + m);
|
||||
} else {
|
||||
$view.removeClass('view-' + m);
|
||||
}
|
||||
});
|
||||
|
||||
_.each(sortedSizes, function (s) {
|
||||
if (s === size) {
|
||||
$view.addClass('view-size-' + s);
|
||||
} else {
|
||||
$view.removeClass('view-size-' + s);
|
||||
}
|
||||
});
|
||||
|
||||
event.pub('view.mode.changed', mode, size);
|
||||
}
|
||||
|
||||
function getModes() {
|
||||
return checkedModes;
|
||||
}
|
||||
|
||||
function getSizes() {
|
||||
return sortedSizes;
|
||||
}
|
||||
|
||||
function getMode() {
|
||||
return store.get(storekey).mode;
|
||||
}
|
||||
|
||||
function setMode(mode) {
|
||||
set(mode, null);
|
||||
}
|
||||
|
||||
function getSize() {
|
||||
return store.get(storekey).size;
|
||||
}
|
||||
|
||||
function setSize(size) {
|
||||
set(null, size);
|
||||
}
|
||||
|
||||
function createHtml(item) {
|
||||
var $html = $(tplItem);
|
||||
var $a = $html.find('a');
|
||||
var $iconImg = $html.find('.icon img');
|
||||
var $label = $html.find('.label');
|
||||
var $date = $html.find('.date');
|
||||
var $size = $html.find('.size');
|
||||
|
||||
$html
|
||||
.addClass(item.isFolder() ? 'folder' : 'file')
|
||||
.data('item', item);
|
||||
|
||||
location.setLink($a, item);
|
||||
|
||||
$label.text(item.label).attr('title', item.label);
|
||||
$date.data('time', item.time).text(format.formatDate(item.time));
|
||||
$size.data('bytes', item.size).text(format.formatSize(item.size));
|
||||
item.icon = resource.icon(item.type);
|
||||
|
||||
if (item.isFolder() && !item.isManaged) {
|
||||
$html.addClass('page');
|
||||
item.icon = resource.icon('folder-page');
|
||||
}
|
||||
|
||||
if (item.isCurrentParentFolder()) {
|
||||
item.icon = resource.icon('folder-parent');
|
||||
if (!settings.setParentFolderLabels) {
|
||||
$label.addClass('l10n-parentDirectory');
|
||||
}
|
||||
$html.addClass('folder-parent');
|
||||
}
|
||||
$iconImg.attr('src', item.icon).attr('alt', item.type);
|
||||
|
||||
item.$view = $html;
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
function onMouseenter() {
|
||||
var item = $(this).closest('.item').data('item');
|
||||
event.pub('item.mouseenter', item);
|
||||
}
|
||||
|
||||
function onMouseleave() {
|
||||
var item = $(this).closest('.item').data('item');
|
||||
event.pub('item.mouseleave', item);
|
||||
}
|
||||
|
||||
function checkHint() {
|
||||
var hasNoItems = $items.find('.item').not('.folder-parent').length === 0;
|
||||
|
||||
if (hasNoItems) {
|
||||
$hint.show();
|
||||
lo.each(checkedModes, m => {
|
||||
if (m === mode) {
|
||||
$view.addClass('view-' + m);
|
||||
} else {
|
||||
$hint.hide();
|
||||
$view.removeClass('view-' + m);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function setItems(items) {
|
||||
var removed = _.map($items.find('.item'), function (item) {
|
||||
return $(item).data('item');
|
||||
});
|
||||
|
||||
$items.find('.item').remove();
|
||||
|
||||
_.each(items, function (e) {
|
||||
$items.append(createHtml(e));
|
||||
});
|
||||
|
||||
content.$el.scrollLeft(0).scrollTop(0);
|
||||
checkHint();
|
||||
event.pub('view.changed', items, removed);
|
||||
}
|
||||
|
||||
function changeItems(add, remove) {
|
||||
_.each(add, function (item) {
|
||||
createHtml(item).hide().appendTo($items).fadeIn(400);
|
||||
});
|
||||
|
||||
_.each(remove, function (item) {
|
||||
item.$view.fadeOut(400, function () {
|
||||
item.$view.remove();
|
||||
});
|
||||
});
|
||||
|
||||
checkHint();
|
||||
event.pub('view.changed', add, remove);
|
||||
}
|
||||
|
||||
function setHint(l10nKey) {
|
||||
$hint.removeClass().addClass('l10n-' + l10nKey);
|
||||
checkHint();
|
||||
}
|
||||
|
||||
function onLocationChanged(item) {
|
||||
if (!item) {
|
||||
item = location.getItem();
|
||||
lo.each(sortedSizes, s => {
|
||||
if (s === size) {
|
||||
$view.addClass('view-size-' + s);
|
||||
} else {
|
||||
$view.removeClass('view-size-' + s);
|
||||
}
|
||||
});
|
||||
|
||||
var items = [];
|
||||
event.pub('view.mode.changed', mode, size);
|
||||
}
|
||||
|
||||
if (item.parent && !settings.hideParentFolder) {
|
||||
items.push(item.parent);
|
||||
function getModes() {
|
||||
return checkedModes;
|
||||
}
|
||||
|
||||
function getSizes() {
|
||||
return sortedSizes;
|
||||
}
|
||||
|
||||
function getMode() {
|
||||
return store.get(storekey).mode;
|
||||
}
|
||||
|
||||
function setMode(mode) {
|
||||
set(mode, null);
|
||||
}
|
||||
|
||||
function getSize() {
|
||||
return store.get(storekey).size;
|
||||
}
|
||||
|
||||
function setSize(size) {
|
||||
set(null, size);
|
||||
}
|
||||
|
||||
function createHtml(item) {
|
||||
const $html = jq(tplItem);
|
||||
const $a = $html.find('a');
|
||||
const $iconImg = $html.find('.icon img');
|
||||
const $label = $html.find('.label');
|
||||
const $date = $html.find('.date');
|
||||
const $size = $html.find('.size');
|
||||
|
||||
$html
|
||||
.addClass(item.isFolder() ? 'folder' : 'file')
|
||||
.data('item', item);
|
||||
|
||||
location.setLink($a, item);
|
||||
|
||||
$label.text(item.label).attr('title', item.label);
|
||||
$date.data('time', item.time).text(format.formatDate(item.time));
|
||||
$size.data('bytes', item.size).text(format.formatSize(item.size));
|
||||
item.icon = resource.icon(item.type);
|
||||
|
||||
if (item.isFolder() && !item.isManaged) {
|
||||
$html.addClass('page');
|
||||
item.icon = resource.icon('folder-page');
|
||||
}
|
||||
|
||||
if (item.isCurrentParentFolder()) {
|
||||
item.icon = resource.icon('folder-parent');
|
||||
if (!settings.setParentFolderLabels) {
|
||||
$label.addClass('l10n-parentDirectory');
|
||||
}
|
||||
|
||||
_.each(item.content, function (child) {
|
||||
if (!(child.isFolder() && settings.hideFolders)) {
|
||||
items.push(child);
|
||||
}
|
||||
});
|
||||
|
||||
setHint('empty');
|
||||
setItems(items);
|
||||
$html.addClass('folder-parent');
|
||||
}
|
||||
$iconImg.attr('src', item.icon).attr('alt', item.type);
|
||||
|
||||
function onLocationRefreshed(item, added, removed) {
|
||||
var add = [];
|
||||
item.$view = $html;
|
||||
|
||||
_.each(added, function (child) {
|
||||
if (!(child.isFolder() && settings.hideFolders)) {
|
||||
add.push(child);
|
||||
}
|
||||
});
|
||||
return $html;
|
||||
}
|
||||
|
||||
setHint('empty');
|
||||
changeItems(add, removed);
|
||||
}
|
||||
function onMouseenter(ev) {
|
||||
const item = jq(ev.currentTarget).closest('.item').data('item');
|
||||
event.pub('item.mouseenter', item);
|
||||
}
|
||||
|
||||
function init() {
|
||||
addCssStyles();
|
||||
set();
|
||||
function onMouseleave(ev) {
|
||||
const item = jq(ev.currentTarget).closest('.item').data('item');
|
||||
event.pub('item.mouseleave', item);
|
||||
}
|
||||
|
||||
$view.appendTo(content.$el);
|
||||
function checkHint() {
|
||||
const hasNoItems = $items.find('.item').not('.folder-parent').length === 0;
|
||||
|
||||
if (hasNoItems) {
|
||||
$hint.show();
|
||||
} else {
|
||||
$hint.hide();
|
||||
}
|
||||
}
|
||||
|
||||
format.setDefaultMetric(settings.binaryPrefix);
|
||||
function setItems(items) {
|
||||
const removed = lo.map($items.find('.item'), item => {
|
||||
return jq(item).data('item');
|
||||
});
|
||||
|
||||
$items
|
||||
.on('mouseenter', '.item a', onMouseenter)
|
||||
.on('mouseleave', '.item a', onMouseleave);
|
||||
$items.find('.item').remove();
|
||||
|
||||
event.sub('location.changed', onLocationChanged);
|
||||
event.sub('location.refreshed', onLocationRefreshed);
|
||||
lo.each(items, e => {
|
||||
$items.append(createHtml(e));
|
||||
});
|
||||
|
||||
content.$el.scrollLeft(0).scrollTop(0);
|
||||
checkHint();
|
||||
event.pub('view.changed', items, removed);
|
||||
}
|
||||
|
||||
function changeItems(add, remove) {
|
||||
lo.each(add, item => {
|
||||
createHtml(item).hide().appendTo($items).fadeIn(400);
|
||||
});
|
||||
|
||||
lo.each(remove, item => {
|
||||
item.$view.fadeOut(400, () => {
|
||||
item.$view.remove();
|
||||
});
|
||||
});
|
||||
|
||||
checkHint();
|
||||
event.pub('view.changed', add, remove);
|
||||
}
|
||||
|
||||
function setHint(l10nKey) {
|
||||
$hint.removeClass().addClass('l10n-' + l10nKey);
|
||||
checkHint();
|
||||
}
|
||||
|
||||
function onLocationChanged(item) {
|
||||
if (!item) {
|
||||
item = location.getItem();
|
||||
}
|
||||
|
||||
const items = [];
|
||||
|
||||
init();
|
||||
if (item.parent && !settings.hideParentFolder) {
|
||||
items.push(item.parent);
|
||||
}
|
||||
|
||||
return {
|
||||
$el: $view,
|
||||
$items: $items,
|
||||
setItems: setItems,
|
||||
changeItems: changeItems,
|
||||
setLocation: onLocationChanged,
|
||||
setHint: setHint,
|
||||
getModes: getModes,
|
||||
getMode: getMode,
|
||||
setMode: setMode,
|
||||
getSizes: getSizes,
|
||||
getSize: getSize,
|
||||
setSize: setSize
|
||||
};
|
||||
});
|
||||
lo.each(item.content, child => {
|
||||
if (!(child.isFolder() && settings.hideFolders)) {
|
||||
items.push(child);
|
||||
}
|
||||
});
|
||||
|
||||
setHint('empty');
|
||||
setItems(items);
|
||||
}
|
||||
|
||||
function onLocationRefreshed(item, added, removed) {
|
||||
const add = [];
|
||||
|
||||
lo.each(added, child => {
|
||||
if (!(child.isFolder() && settings.hideFolders)) {
|
||||
add.push(child);
|
||||
}
|
||||
});
|
||||
|
||||
setHint('empty');
|
||||
changeItems(add, removed);
|
||||
}
|
||||
|
||||
function init() {
|
||||
addCssStyles();
|
||||
set();
|
||||
|
||||
$view.appendTo(content.$el);
|
||||
$hint.hide();
|
||||
|
||||
format.setDefaultMetric(settings.binaryPrefix);
|
||||
|
||||
$items
|
||||
.on('mouseenter', '.item a', onMouseenter)
|
||||
.on('mouseleave', '.item a', onMouseleave);
|
||||
|
||||
event.sub('location.changed', onLocationChanged);
|
||||
event.sub('location.refreshed', onLocationRefreshed);
|
||||
}
|
||||
|
||||
|
||||
init();
|
||||
|
||||
module.exports = {
|
||||
$el: $view,
|
||||
$items,
|
||||
setItems,
|
||||
changeItems,
|
||||
setLocation: onLocationChanged,
|
||||
setHint,
|
||||
getModes,
|
||||
getMode,
|
||||
setMode,
|
||||
getSizes,
|
||||
getSize,
|
||||
setSize
|
||||
};
|
||||
|
|
|
@ -1,91 +1,98 @@
|
|||
modulejs.define('view/viewmode', ['_', '$', 'core/event', 'core/resource', 'core/settings', 'view/sidebar', 'view/topbar', 'view/view'], function (_, $, event, resource, allsettings, sidebar, topbar, view) {
|
||||
var settings = _.extend({
|
||||
modeToggle: false
|
||||
}, allsettings.view);
|
||||
var tplSettings =
|
||||
'<div id="viewmode-settings" class="block"><h1 class="l10n-view">View</h1></div>';
|
||||
var tplMode =
|
||||
'<div id="viewmode-[MODE]" class="button mode">' +
|
||||
'<img src="' + resource.image('view-[MODE]') + '" alt="viewmode-[MODE]"/>' +
|
||||
'</div>';
|
||||
var tplSize =
|
||||
'<input id="viewmode-size" type="range" min="0" max="0" value="0">';
|
||||
var tplToggle =
|
||||
'<div id="viewmode-toggle" class="tool">' +
|
||||
'<img alt="viewmode"/>' +
|
||||
'</div>';
|
||||
var modes;
|
||||
var sizes;
|
||||
const {jQuery: jq, _: lo} = require('../win');
|
||||
const event = require('../core/event');
|
||||
const resource = require('../core/resource');
|
||||
const allsettings = require('../core/settings');
|
||||
const sidebar = require('./sidebar');
|
||||
const topbar = require('./topbar');
|
||||
const view = require('./view');
|
||||
|
||||
|
||||
function onChanged(mode, size) {
|
||||
$('#viewmode-settings .mode').removeClass('active');
|
||||
$('#viewmode-' + mode).addClass('active');
|
||||
$('#viewmode-size').val(_.indexOf(sizes, size));
|
||||
const settings = lo.extend({
|
||||
modeToggle: false
|
||||
}, allsettings.view);
|
||||
const tplSettings =
|
||||
'<div id="viewmode-settings" class="block"><h1 class="l10n-view">View</h1></div>';
|
||||
const tplMode =
|
||||
`<div id="viewmode-[MODE]" class="button mode">
|
||||
<img src="${resource.image('view-[MODE]')}" alt="viewmode-[MODE]"/>
|
||||
</div>`;
|
||||
const tplSize =
|
||||
'<input id="viewmode-size" type="range" min="0" max="0" value="0">';
|
||||
const tplToggle =
|
||||
`<div id="viewmode-toggle" class="tool">
|
||||
<img alt="viewmode"/>
|
||||
</div>`;
|
||||
let modes;
|
||||
let sizes;
|
||||
|
||||
if (settings.modeToggle === 'next') {
|
||||
mode = modes[(modes.indexOf(mode) + 1) % modes.length];
|
||||
}
|
||||
$('#viewmode-toggle img').attr('src', resource.image('view-' + mode));
|
||||
|
||||
function onChanged(mode, size) {
|
||||
jq('#viewmode-settings .mode').removeClass('active');
|
||||
jq('#viewmode-' + mode).addClass('active');
|
||||
jq('#viewmode-size').val(lo.indexOf(sizes, size));
|
||||
|
||||
if (settings.modeToggle === 'next') {
|
||||
mode = modes[(modes.indexOf(mode) + 1) % modes.length];
|
||||
}
|
||||
jq('#viewmode-toggle img').attr('src', resource.image('view-' + mode));
|
||||
}
|
||||
|
||||
function addSettings() {
|
||||
if (modes.length < 2 && sizes.length < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
function addSettings() {
|
||||
if (modes.length < 2 && sizes.length < 2) {
|
||||
return;
|
||||
}
|
||||
const $viewBlock = jq(tplSettings);
|
||||
|
||||
var $viewBlock = $(tplSettings);
|
||||
|
||||
if (modes.length > 1) {
|
||||
_.each(modes, function (mode) {
|
||||
$(tplMode.replace(/\[MODE\]/g, mode))
|
||||
.on('click', function () {
|
||||
view.setMode(mode);
|
||||
})
|
||||
.appendTo($viewBlock);
|
||||
});
|
||||
}
|
||||
|
||||
if (sizes.length > 1) {
|
||||
var max = sizes.length - 1;
|
||||
$(tplSize)
|
||||
.prop('max', max).attr('max', max)
|
||||
.on('input change', function (ev) {
|
||||
view.setSize(sizes[ev.target.valueAsNumber]);
|
||||
if (modes.length > 1) {
|
||||
lo.each(modes, mode => {
|
||||
jq(tplMode.replace(/\[MODE\]/g, mode))
|
||||
.on('click', () => {
|
||||
view.setMode(mode);
|
||||
})
|
||||
.appendTo($viewBlock);
|
||||
}
|
||||
|
||||
$viewBlock.appendTo(sidebar.$el);
|
||||
});
|
||||
}
|
||||
|
||||
function onToggle() {
|
||||
var mode = view.getMode();
|
||||
var nextIdx = (modes.indexOf(mode) + 1) % modes.length;
|
||||
var nextMode = modes[nextIdx];
|
||||
|
||||
view.setMode(nextMode);
|
||||
if (sizes.length > 1) {
|
||||
const max = sizes.length - 1;
|
||||
jq(tplSize)
|
||||
.prop('max', max).attr('max', max)
|
||||
.on('input change', ev => {
|
||||
view.setSize(sizes[ev.target.valueAsNumber]);
|
||||
})
|
||||
.appendTo($viewBlock);
|
||||
}
|
||||
|
||||
function addToggle() {
|
||||
if (settings.modeToggle && modes.length > 1) {
|
||||
$(tplToggle)
|
||||
.on('click', onToggle)
|
||||
.appendTo(topbar.$toolbar);
|
||||
}
|
||||
$viewBlock.appendTo(sidebar.$el);
|
||||
}
|
||||
|
||||
function onToggle() {
|
||||
const mode = view.getMode();
|
||||
const nextIdx = (modes.indexOf(mode) + 1) % modes.length;
|
||||
const nextMode = modes[nextIdx];
|
||||
|
||||
view.setMode(nextMode);
|
||||
}
|
||||
|
||||
function addToggle() {
|
||||
if (settings.modeToggle && modes.length > 1) {
|
||||
jq(tplToggle)
|
||||
.on('click', onToggle)
|
||||
.appendTo(topbar.$toolbar);
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
modes = view.getModes();
|
||||
sizes = view.getSizes();
|
||||
function init() {
|
||||
modes = view.getModes();
|
||||
sizes = view.getSizes();
|
||||
|
||||
addSettings();
|
||||
addToggle();
|
||||
onChanged(view.getMode(), view.getSize());
|
||||
addSettings();
|
||||
addToggle();
|
||||
onChanged(view.getMode(), view.getSize());
|
||||
|
||||
event.sub('view.mode.changed', onChanged);
|
||||
}
|
||||
event.sub('view.mode.changed', onChanged);
|
||||
}
|
||||
|
||||
|
||||
init();
|
||||
});
|
||||
init();
|
||||
|
|
23
src/_h5ai/public/js/lib/win.js
Normal file
23
src/_h5ai/public/js/lib/win.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
const win = window; // eslint-disable-line no-undef
|
||||
|
||||
if (typeof win !== 'object' || win.window !== win || !win.document) {
|
||||
throw new Error('no-window');
|
||||
}
|
||||
|
||||
const noBrowser = 'no-browser';
|
||||
const doc = win.document;
|
||||
const docEl = doc.documentElement;
|
||||
docEl.className = '';
|
||||
|
||||
function assert(expr, hint) {
|
||||
if (!expr) {
|
||||
docEl.className = noBrowser;
|
||||
throw new Error(`${noBrowser}: ${hint}`);
|
||||
}
|
||||
}
|
||||
|
||||
assert(!doc.getElementById(noBrowser), 'ie<10');
|
||||
assert(typeof Object.assign === 'function', 'assign');
|
||||
assert(typeof Promise === 'function', 'promise');
|
||||
|
||||
module.exports = win;
|
|
@ -1,30 +1 @@
|
|||
(function () {
|
||||
var doc = document;
|
||||
var el = doc.documentElement;
|
||||
var id = 'no-browser';
|
||||
el.className = '';
|
||||
if (doc.getElementById(id)) {
|
||||
el.className = id;
|
||||
throw id;
|
||||
}
|
||||
}());
|
||||
|
||||
// @include 'vendor/jquery-*.js'
|
||||
// @include 'vendor/lodash-*.js'
|
||||
// @include 'vendor/marked-*.js'
|
||||
// @include 'vendor/modulejs-*.js'
|
||||
// @include 'vendor/prism-*.js'
|
||||
|
||||
(function () {
|
||||
'use strict'; // eslint-disable-line strict
|
||||
|
||||
var win = window;
|
||||
modulejs.define('_', function () { return win._; });
|
||||
modulejs.define('$', function () { return win.jQuery; });
|
||||
modulejs.define('marked', function () { return win.marked; });
|
||||
modulejs.define('prism', function () { return win.Prism; });
|
||||
|
||||
// @include 'lib/**/*.js'
|
||||
|
||||
modulejs.require('boot');
|
||||
}());
|
||||
require('./lib/init');
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
/*! modulejs v1.14.0 - https://larsjung.de/modulejs/ */
|
||||
!function(n,r){"object"==typeof exports&&"object"==typeof module?module.exports=r():"function"==typeof define&&define.amd?define([],r):"object"==typeof exports?exports.modulejs=r():n.modulejs=r()}(this,function(){return function(n){function r(t){if(e[t])return e[t].exports;var i=e[t]={exports:{},id:t,loaded:!1};return n[t].call(i.exports,i,i.exports,r),i.loaded=!0,i.exports}var e={};return r.m=n,r.c=e,r.p="",r(0)}([function(n,r){"use strict";var e=Object.prototype,t=function(n){return function(r){return e.toString.call(r)==="[object "+n+"]"}},i=t("Array"),o=t("Function"),u=t("String"),s=function(n,r){return void 0!==n&&null!==n&&e.hasOwnProperty.call(n,r)},f=function(n,r){if(n&&n.length)for(var e=0,t=n.length;t>e;e+=1)r(n[e],e,n);else for(var i in n)s(n,i)&&r(n[i],i,n)},c=function(n,r){if(n&&n.length)for(var e=0,t=n.length;t>e;e+=1)if(n[e]===r)return!0;return!1},a=function(n){var r=[];return f(n,function(n){c(r,n)||r.push(n)}),r},d=function(n,r){if(!n)throw new Error("[modulejs] "+r)},p=function l(){var n={},r={},e=function y(e,t,i){d(u(e),"id must be string: "+e);var o=t===!0,p=(o?void 0:t)||r;if(!o&&s(p,e))return p[e];var l=n[e];d(l,"id not defined: "+e),i=(i||[]).slice(),i.push(e);var v=[];if(f(l.deps,function(n){d(!c(i,n),"circular dependencies: "+n+" in "+i),o?(v=v.concat(y(n,t,i)),v.push(n)):v.push(y(n,t,i))}),o)return a(v);var h=l.fn.apply(void 0,v);return p[e]=h,h},t=function(r,e,t){if(void 0===t){var f=[[],e];e=f[0],t=f[1]}d(u(r),"id must be string: "+r),d(!s(n,r),"id already defined: "+r),d(i(e),"deps must be array: "+r),n[r]={id:r,deps:e,fn:o(t)?t:function(){return t}}},p=function(n,r){return e(n,r)},v=function(){var t={};return f(n,function(n,i){t[i]={deps:n.deps.slice(),reqs:e(i,!0),init:s(r,i)}}),f(n,function(r,e){var i=[];f(n,function(n,r){c(t[r].reqs,e)&&i.push(r)}),t[e].reqd=i}),t},h=function(n){var r="\n";return f(v(),function(e,t){var i=n?e.reqd:e.reqs;r+=(e.init?"* ":" ")+t+" -> [ "+i.join(", ")+" ]\n"}),r};return{create:l,define:t,log:h,require:p,state:v,_private:{assert:d,contains:c,definitions:n,each:f,has:s,instances:r,isArray:i,isFunction:o,isString:u,resolve:e,uniq:a}}};n.exports=p()}])});
|
Loading…
Add table
Reference in a new issue