mirror of
https://github.com/lrsjng/h5ai.git
synced 2025-06-01 07:48:20 -04:00
Refactored and lots of modification. See README.md.
This commit is contained in:
parent
859a680e19
commit
71ed41fa69
85 changed files with 3191 additions and 2969 deletions
84
src/_h5ai/js/inc/ext/crumb.js
Normal file
84
src/_h5ai/js/inc/ext/crumb.js
Normal file
|
@ -0,0 +1,84 @@
|
|||
|
||||
module.define('ext/crumb', [jQuery, 'core/settings', 'core/resource', 'core/entry'], function ($, allsettings, resource, entry) {
|
||||
|
||||
var defaults = {
|
||||
enabled: true
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.crumb),
|
||||
|
||||
template = '<li class="crumb">' +
|
||||
'<a>' +
|
||||
'<img src="' + resource.image('crumb') + '" alt=">" />' +
|
||||
'<span />' +
|
||||
'</a>' +
|
||||
'</li>',
|
||||
pageHintTemplate = '<img class="hint" src="' + resource.image('page') + '" alt="has index page" />',
|
||||
statusHintTemplate = '<span class="hint"></span>',
|
||||
|
||||
// updates the crumb for this single entry
|
||||
update = function (entry) {
|
||||
|
||||
if (entry.$crumb && entry.$crumb.data('status') === entry.status) {
|
||||
return entry.$crumb;
|
||||
}
|
||||
|
||||
var $html = $(template),
|
||||
$a = $html.find('a');
|
||||
|
||||
$html
|
||||
.addClass(entry.isFolder() ? 'folder' : 'file')
|
||||
.data('status', entry.status);
|
||||
|
||||
$a
|
||||
.attr('href', entry.absHref)
|
||||
.find('span').text(entry.label).end();
|
||||
|
||||
if (entry.isDomain()) {
|
||||
$html.addClass('domain');
|
||||
$a.find('img').attr('src', resource.image('home'));
|
||||
}
|
||||
|
||||
if (entry.isCurrentFolder()) {
|
||||
$html.addClass('current');
|
||||
}
|
||||
|
||||
if (_.isNumber(entry.status)) {
|
||||
if (entry.status === 200) {
|
||||
$a.append($(pageHintTemplate));
|
||||
} else {
|
||||
$a.append($(statusHintTemplate).text('(' + entry.status + ')'));
|
||||
}
|
||||
}
|
||||
|
||||
if (entry.$crumb) {
|
||||
entry.$crumb.replaceWith($html);
|
||||
}
|
||||
entry.$crumb = $html;
|
||||
|
||||
return $html;
|
||||
},
|
||||
|
||||
// creates the complete crumb from entry down to the root
|
||||
init = function (entry) {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var crumb = entry.getCrumb(),
|
||||
$ul = $('#navbar');
|
||||
|
||||
_.each(crumb, function (e) {
|
||||
|
||||
$ul.append(update(e));
|
||||
|
||||
e.fetchStatus(function (e) {
|
||||
|
||||
update(e);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
init(entry);
|
||||
});
|
42
src/_h5ai/js/inc/ext/custom.js
Normal file
42
src/_h5ai/js/inc/ext/custom.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
|
||||
module.define('ext/custom', [jQuery, 'core/settings'], function ($, allsettings) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false,
|
||||
header: '_h5ai.header.html',
|
||||
footer: '_h5ai.footer.html'
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.custom),
|
||||
|
||||
init = function () {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_.isString(settings.header)) {
|
||||
$.ajax({
|
||||
url: settings.header,
|
||||
dataType: 'html',
|
||||
success: function (data) {
|
||||
|
||||
$('<div id="content-header">' + data + '</div>').prependTo('#content');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (_.isString(settings.footer)) {
|
||||
$.ajax({
|
||||
url: settings.footer,
|
||||
dataType: 'html',
|
||||
success: function (data) {
|
||||
|
||||
$('<div id="content-footer">' + data + '</div>').appendTo('#content');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
123
src/_h5ai/js/inc/ext/filter.js
Normal file
123
src/_h5ai/js/inc/ext/filter.js
Normal file
|
@ -0,0 +1,123 @@
|
|||
|
||||
module.define('ext/filter', [jQuery, 'core/settings', 'core/resource'], function ($, allsettings, resource) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.filter),
|
||||
|
||||
template = '<li id="filter">' +
|
||||
'<span class="element">' +
|
||||
'<img src="' + resource.image('filter') + '" alt="filter" />' +
|
||||
'<input type="text" value="" placeholder="filter" />' +
|
||||
'</span>' +
|
||||
'</li>',
|
||||
noMatchTemplate = '<div class="no-match l10n-noMatch">no match</div>',
|
||||
|
||||
$filter, $input, $noMatch,
|
||||
|
||||
filter = function (re) {
|
||||
|
||||
var match = [],
|
||||
noMatch = [],
|
||||
duration = 200;
|
||||
|
||||
if (re) {
|
||||
$('#extended .entry').each(function () {
|
||||
|
||||
var label = $(this).find('.label').text();
|
||||
|
||||
if (label.match(re)) {
|
||||
match.push(this);
|
||||
} else {
|
||||
noMatch.push(this);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
match = $('#extended .entry');
|
||||
}
|
||||
|
||||
if ($(match).length) {
|
||||
$noMatch.hide();
|
||||
} else {
|
||||
setTimeout(function () { $noMatch.show(); }, duration);
|
||||
}
|
||||
$(match).fadeIn(duration);
|
||||
$(noMatch).fadeOut(duration);
|
||||
},
|
||||
|
||||
checkState = function (focus) {
|
||||
|
||||
var val = $input.val();
|
||||
|
||||
if (val || focus) {
|
||||
$filter.addClass('current');
|
||||
} else {
|
||||
$filter.removeClass('current');
|
||||
}
|
||||
},
|
||||
|
||||
escapeRegExp = function (sequence) {
|
||||
|
||||
return sequence.replace(/[\-\[\]{}()*+?.,\\$\^|#\s]/g, '\\$&');
|
||||
// return sequence.replace(/[|()\[{.+*?^$\\]/g,"\\$0");
|
||||
},
|
||||
|
||||
parseFilterSequence = function (sequence) {
|
||||
|
||||
if (sequence.substr(0, 3) === 're:') {
|
||||
return new RegExp(sequence.substr(3));
|
||||
}
|
||||
|
||||
sequence = $.map($.trim(sequence).split(/\s+/), function (part) {
|
||||
|
||||
return escapeRegExp(part);
|
||||
}).join('|');
|
||||
|
||||
return new RegExp(sequence);
|
||||
},
|
||||
|
||||
update = function () {
|
||||
|
||||
var val = $input.val();
|
||||
|
||||
if (val) {
|
||||
filter(parseFilterSequence(val));
|
||||
} else {
|
||||
filter();
|
||||
}
|
||||
checkState($input.is(':focus'));
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$filter = $(template);
|
||||
$input = $filter.find('input');
|
||||
$noMatch = $(noMatchTemplate).appendTo($('#extended'));
|
||||
|
||||
$filter
|
||||
.on('click', function () {
|
||||
|
||||
$input.focus();
|
||||
})
|
||||
.appendTo($('#navbar'));
|
||||
|
||||
$input
|
||||
.on('focus', function () {
|
||||
|
||||
checkState(true);
|
||||
})
|
||||
.on('blur', function () {
|
||||
|
||||
checkState(false);
|
||||
})
|
||||
.on('keyup', update);
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
14
src/_h5ai/js/inc/ext/folderstatus.js
Normal file
14
src/_h5ai/js/inc/ext/folderstatus.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
|
||||
module.define('ext/folderstatus', [jQuery, 'core/settings'], function ($, allsettings) {
|
||||
|
||||
var defaults = {
|
||||
enabled: true,
|
||||
folders: {}
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.folderstatus),
|
||||
|
||||
folders = settings.enabled ? settings.folders : defaults.folders;
|
||||
|
||||
return folders;
|
||||
});
|
118
src/_h5ai/js/inc/ext/l10n.js
Normal file
118
src/_h5ai/js/inc/ext/l10n.js
Normal file
|
@ -0,0 +1,118 @@
|
|||
|
||||
module.define('ext/l10n', [jQuery, 'core/settings', 'core/langs', 'core/format', 'core/store'], function ($, allsettings, langs, format, store) {
|
||||
|
||||
var defaults = {
|
||||
enabled: true,
|
||||
lang: "en",
|
||||
useBrowserLang: true,
|
||||
defaultDateFormat: 'YYYY-MM-DD HH:mm'
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.l10n),
|
||||
|
||||
template = '<span id="langSelector">' +
|
||||
'<span class="lang">en</span> - <span class="l10n-lang">english</span>' +
|
||||
'<span class="langOptions"> <ul /> </span>' +
|
||||
'</span>',
|
||||
langOptionTemplate = '<li class="langOption" />',
|
||||
|
||||
storekey = 'h5ai.language',
|
||||
|
||||
currentLang = null,
|
||||
|
||||
localize = function (langs, lang, useBrowserLang) {
|
||||
|
||||
var storedLang = store.get(storekey),
|
||||
browserLang, key;
|
||||
|
||||
if (langs[storedLang]) {
|
||||
lang = storedLang;
|
||||
} else if (useBrowserLang) {
|
||||
browserLang = navigator.language || navigator.browserLanguage;
|
||||
if (browserLang) {
|
||||
if (langs[browserLang]) {
|
||||
lang = browserLang;
|
||||
} else if (browserLang.length > 2 && langs[browserLang.substr(0, 2)]) {
|
||||
lang = browserLang.substr(0, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!langs[lang]) {
|
||||
lang = 'en';
|
||||
}
|
||||
|
||||
currentLang = langs[lang];
|
||||
if (currentLang) {
|
||||
$.each(currentLang, function (key, value) {
|
||||
$('.l10n-' + key).text(value);
|
||||
});
|
||||
$('.lang').text(lang);
|
||||
$('.langOption').removeClass('current');
|
||||
$('.langOption.' + lang).addClass('current');
|
||||
}
|
||||
|
||||
format.setDefaultDateFormat(currentLang.dateFormat || settings.defaultDateFormat);
|
||||
|
||||
$('#extended .entry .date').each(function () {
|
||||
|
||||
var $this = $(this);
|
||||
|
||||
$this.text(format.formatDate($this.data('time')));
|
||||
});
|
||||
},
|
||||
|
||||
initLangSelector = function (langs) {
|
||||
|
||||
var $langSelector = $(template).appendTo('#bottombar .right'),
|
||||
$langOptions = $langSelector.find('.langOptions'),
|
||||
$ul = $langOptions.find('ul'),
|
||||
sortedLangsKeys = [];
|
||||
|
||||
$.each(langs, function (lang) {
|
||||
sortedLangsKeys.push(lang);
|
||||
});
|
||||
sortedLangsKeys.sort();
|
||||
|
||||
$.each(sortedLangsKeys, function (idx, lang) {
|
||||
$(langOptionTemplate)
|
||||
.addClass(lang)
|
||||
.text(lang + ' - ' + langs[lang].lang)
|
||||
.appendTo($ul)
|
||||
.click(function () {
|
||||
store.put(storekey, lang);
|
||||
localize(langs, lang, false);
|
||||
});
|
||||
});
|
||||
$langOptions
|
||||
.append($ul)
|
||||
.scrollpanel();
|
||||
|
||||
$langSelector.hover(
|
||||
function () {
|
||||
$langOptions
|
||||
.css('top', '-' + $langOptions.outerHeight() + 'px')
|
||||
.stop(true, true)
|
||||
.fadeIn();
|
||||
$langOptions.get(0).updateScrollbar();
|
||||
},
|
||||
function () {
|
||||
$langOptions
|
||||
.stop(true, true)
|
||||
.fadeOut();
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
initLangSelector(langs);
|
||||
localize(langs, settings.lang, settings.useBrowserLang);
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
44
src/_h5ai/js/inc/ext/link-hover-states.js
Normal file
44
src/_h5ai/js/inc/ext/link-hover-states.js
Normal file
|
@ -0,0 +1,44 @@
|
|||
|
||||
module.define('ext/link-hover-states', [jQuery, 'core/settings'], function ($, allsettings) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings['link-hover-states']),
|
||||
|
||||
selector = "a[href^='/']",
|
||||
|
||||
selectLinks = function (href) {
|
||||
|
||||
return $(_.filter($(selector), function (el) {
|
||||
|
||||
return $(el).attr('href') === href;
|
||||
}));
|
||||
},
|
||||
|
||||
onMouseEnter = function () {
|
||||
|
||||
var href = $(this).attr('href');
|
||||
|
||||
selectLinks(href).addClass('hover');
|
||||
},
|
||||
|
||||
onMouseLeave = function () {
|
||||
|
||||
var href = $(this).attr('href');
|
||||
|
||||
selectLinks(href).removeClass('hover');
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
if (settings.enabled) {
|
||||
$('body')
|
||||
.on('mouseenter', selector, onMouseEnter)
|
||||
.on('mouseleave', selector, onMouseLeave);
|
||||
}
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
56
src/_h5ai/js/inc/ext/qrcode.js
Normal file
56
src/_h5ai/js/inc/ext/qrcode.js
Normal file
|
@ -0,0 +1,56 @@
|
|||
|
||||
module.define('ext/qrcode', [jQuery, 'core/settings', 'core/event'], function ($, allsettings, event) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false,
|
||||
size: 150
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.qrcode),
|
||||
|
||||
template = '<div id="context"><div class="qrcode" /></div>',
|
||||
|
||||
$context, hideTimeoutId,
|
||||
|
||||
update = function (entry) {
|
||||
|
||||
$context.find('.qrcode').empty().qrcode({
|
||||
render: Modernizr.canvas ? 'canvas' : 'div',
|
||||
width: settings.size,
|
||||
height: settings.size,
|
||||
color: '#333',
|
||||
text: 'http://' + document.domain + entry.absHref
|
||||
});
|
||||
},
|
||||
|
||||
onMouseenter = function (entry) {
|
||||
|
||||
if (!entry.isFolder()) {
|
||||
update(entry);
|
||||
clearTimeout(hideTimeoutId);
|
||||
$context.stop(true, true).fadeIn(400);
|
||||
}
|
||||
},
|
||||
|
||||
onMouseleave = function (entry) {
|
||||
|
||||
hideTimeoutId = setTimeout(function () {
|
||||
|
||||
$context.stop(true, true).fadeOut(400);
|
||||
}, 200);
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$context = $(template).appendTo('body');
|
||||
|
||||
event.sub('entry.mouseenter', onMouseenter);
|
||||
event.sub('entry.mouseleave', onMouseleave);
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
114
src/_h5ai/js/inc/ext/select.js
Normal file
114
src/_h5ai/js/inc/ext/select.js
Normal file
|
@ -0,0 +1,114 @@
|
|||
|
||||
module.define('ext/select', [jQuery, 'core/settings', 'core/event'], function ($, allsettings, event) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.select),
|
||||
|
||||
x = 0,
|
||||
y = 0,
|
||||
$document = $(document),
|
||||
$selectionRect = $('<div id="selection-rect"></div>'),
|
||||
|
||||
publish = function () {
|
||||
|
||||
var entries = _.map($('#extended .entry.selected'), function (entryElement) {
|
||||
|
||||
return $(entryElement).data('entry');
|
||||
});
|
||||
|
||||
event.pub('selection', entries);
|
||||
},
|
||||
|
||||
selectionUpdate = function (event) {
|
||||
|
||||
var l = Math.min(x, event.pageX),
|
||||
t = Math.min(y, event.pageY),
|
||||
w = Math.abs(x - event.pageX),
|
||||
h = Math.abs(y - event.pageY),
|
||||
selRect;
|
||||
|
||||
event.preventDefault();
|
||||
$selectionRect.css({left: l, top: t, width: w, height: h});
|
||||
|
||||
selRect = $selectionRect.fracs('rect');
|
||||
$('#extended .entry').removeClass('selecting').each(function () {
|
||||
|
||||
var $entry = $(this),
|
||||
rect = $entry.find('a').fracs('rect'),
|
||||
inter = selRect.intersection(rect);
|
||||
if (inter && !$entry.hasClass('folder-parent')) {
|
||||
$entry.addClass('selecting');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
selectionEnd = function (event) {
|
||||
|
||||
event.preventDefault();
|
||||
$document.off('mousemove', selectionUpdate);
|
||||
$selectionRect.hide().css({left: 0, top: 0, width: 0, height: 0});
|
||||
$('#extended .entry.selecting.selected').removeClass('selecting').removeClass('selected');
|
||||
$('#extended .entry.selecting').removeClass('selecting').addClass('selected');
|
||||
publish();
|
||||
},
|
||||
|
||||
selectionStart = function (event) {
|
||||
|
||||
var view = $(document).fracs('viewport');
|
||||
|
||||
x = event.pageX;
|
||||
y = event.pageY;
|
||||
// only on left button and don't block the scrollbars
|
||||
if (event.button !== 0 || x >= view.right || y >= view.bottom) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
$(':focus').blur();
|
||||
if (!event.ctrlKey) {
|
||||
$('#extended .entry').removeClass('selected');
|
||||
publish();
|
||||
}
|
||||
$selectionRect.show().css({left: x, top: y, width: 0, height: 0});
|
||||
|
||||
$document
|
||||
.on('mousemove', selectionUpdate)
|
||||
.one('mouseup', selectionEnd);
|
||||
},
|
||||
|
||||
noSelection = function (event) {
|
||||
|
||||
event.stopImmediatePropagation();
|
||||
return false;
|
||||
},
|
||||
|
||||
noSelectionUnlessCtrl = function (event) {
|
||||
|
||||
if (!event.ctrlKey) {
|
||||
noSelection(event);
|
||||
}
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$selectionRect.hide().appendTo($('body'));
|
||||
|
||||
// $('#topbar,#bottombar,#tree,input').on('mousedown', noSelection);
|
||||
// $('#content').on('mousedown', 'a', noSelectionUnlessCtrl);
|
||||
// $document.on('mousedown', selectionStart);
|
||||
|
||||
$document
|
||||
.on('mousedown', '.noSelection', noSelection)
|
||||
.on('mousedown', '.noSelectionUnlessCtrl,input,a', noSelectionUnlessCtrl)
|
||||
.on('mousedown', selectionStart);
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
145
src/_h5ai/js/inc/ext/sort.js
Normal file
145
src/_h5ai/js/inc/ext/sort.js
Normal file
|
@ -0,0 +1,145 @@
|
|||
|
||||
module.define('ext/sort', [jQuery, 'core/settings', 'core/resource', 'core/store'], function ($, allsettings, resource, store) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false,
|
||||
order: 'na'
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.sort),
|
||||
|
||||
storekey = 'h5ai.sortorder',
|
||||
|
||||
type = function (entry) {
|
||||
|
||||
var $entry = $(entry);
|
||||
|
||||
if ($entry.hasClass('folder-parent')) {
|
||||
return 0;
|
||||
} else if ($entry.hasClass('folder')) {
|
||||
return 1;
|
||||
}
|
||||
return 2;
|
||||
},
|
||||
|
||||
cmpFn = function (rev, getVal) {
|
||||
|
||||
return function (entry1, entry2) {
|
||||
|
||||
var res, val1, val2;
|
||||
|
||||
res = type(entry1) - type(entry2);
|
||||
if (res !== 0) {
|
||||
return res;
|
||||
}
|
||||
|
||||
val1 = getVal(entry1);
|
||||
val2 = getVal(entry2);
|
||||
if (val1 < val2) {
|
||||
return rev ? 1 : -1;
|
||||
} else if (val1 > val2) {
|
||||
return rev ? -1 : 1;
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
},
|
||||
|
||||
getName = function (entry) {
|
||||
|
||||
return $(entry).find('.label').text().toLowerCase();
|
||||
},
|
||||
getTime = function (entry) {
|
||||
|
||||
return $(entry).find('.date').data('time');
|
||||
},
|
||||
getSize = function (entry) {
|
||||
|
||||
return $(entry).find('.size').data('bytes');
|
||||
},
|
||||
|
||||
$all, orders,
|
||||
|
||||
sortBy = function (id) {
|
||||
|
||||
var order = orders[id];
|
||||
|
||||
store.put(storekey, id);
|
||||
|
||||
$all.removeClass('ascending').removeClass('descending');
|
||||
order.head.addClass(order.clas);
|
||||
$('#extended .entry').detach().sort(order.fn).appendTo($('#extended > ul'));
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $ascending = $('<img src="' + resource.image('ascending') + '" class="sort ascending" alt="ascending" />'),
|
||||
$descending = $('<img src="' + resource.image('descending') + '" class="sort descending" alt="descending" />'),
|
||||
$header = $('#extended li.header'),
|
||||
$label = $header.find('a.label'),
|
||||
$date = $header.find('a.date'),
|
||||
$size = $header.find('a.size');
|
||||
|
||||
$all = $header.find('a.label,a.date,a.size');
|
||||
orders = {
|
||||
na: {
|
||||
head: $label,
|
||||
clas: 'ascending',
|
||||
fn: cmpFn(false, getName)
|
||||
},
|
||||
nd: {
|
||||
head: $label,
|
||||
clas: 'descending',
|
||||
fn: cmpFn(true, getName)
|
||||
},
|
||||
da: {
|
||||
head: $date,
|
||||
clas: 'ascending',
|
||||
fn: cmpFn(false, getTime)
|
||||
},
|
||||
dd: {
|
||||
head: $date,
|
||||
clas: 'descending',
|
||||
fn: cmpFn(true, getTime)
|
||||
},
|
||||
sa: {
|
||||
head: $size,
|
||||
clas: 'ascending',
|
||||
fn: cmpFn(false, getSize)
|
||||
},
|
||||
sd: {
|
||||
head: $size,
|
||||
clas: 'descending',
|
||||
fn: cmpFn(true, getSize)
|
||||
}
|
||||
};
|
||||
|
||||
sortBy(store.get(storekey) || settings.order);
|
||||
|
||||
$label
|
||||
.append($ascending.clone()).append($descending.clone())
|
||||
.click(function (event) {
|
||||
sortBy('n' + ($label.hasClass('ascending') ? 'd' : 'a'));
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
$date
|
||||
.prepend($ascending.clone()).prepend($descending.clone())
|
||||
.click(function (event) {
|
||||
sortBy('d' + ($date.hasClass('ascending') ? 'd' : 'a'));
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
$size
|
||||
.prepend($ascending.clone()).prepend($descending.clone())
|
||||
.click(function (event) {
|
||||
sortBy('s' + ($size.hasClass('ascending') ? 'd' : 'a'));
|
||||
event.preventDefault();
|
||||
});
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
76
src/_h5ai/js/inc/ext/statusbar.js
Normal file
76
src/_h5ai/js/inc/ext/statusbar.js
Normal file
|
@ -0,0 +1,76 @@
|
|||
|
||||
module.define('ext/statusbar', [jQuery, 'core/settings', 'core/format', 'core/event', 'core/entry'], function ($, allsettings, format, event, entry) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.statusbar),
|
||||
|
||||
template = '<span class="statusbar">' +
|
||||
'<span class="status default">' +
|
||||
'<span class="folderTotal"></span> <span class="l10n-folders">folders</span>' +
|
||||
'<span class="sep">·</span>' +
|
||||
'<span class="fileTotal"></span> <span class="l10n-files">files</span>' +
|
||||
'</span>' +
|
||||
'<span class="status dynamic"></span>' +
|
||||
'</span>',
|
||||
sepTemplate = '<span class="sep">·</span>',
|
||||
|
||||
$statusDynamic,
|
||||
$statusDefault,
|
||||
|
||||
update = function (html) {
|
||||
|
||||
if (html) {
|
||||
$statusDefault.hide();
|
||||
$statusDynamic.empty().append(html).show();
|
||||
} else {
|
||||
$statusDynamic.empty().hide();
|
||||
$statusDefault.show();
|
||||
}
|
||||
},
|
||||
|
||||
init = function (entry) {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $statusbar = $(template),
|
||||
$folderTotal = $statusbar.find('.folderTotal'),
|
||||
$fileTotal = $statusbar.find('.fileTotal');
|
||||
|
||||
$statusDefault = $statusbar.find('.status.default');
|
||||
$statusDynamic = $statusbar.find('.status.dynamic');
|
||||
|
||||
var stats = entry.getStats();
|
||||
$folderTotal.text(stats.folders);
|
||||
$fileTotal.text(stats.files);
|
||||
|
||||
update();
|
||||
|
||||
event.sub('statusbar', update);
|
||||
$('#bottombar > .center').append($statusbar);
|
||||
|
||||
|
||||
|
||||
event.sub('entry.mouseenter', function (entry) {
|
||||
|
||||
var $span = $('<span/>').append(entry.label).append(sepTemplate).append(format.formatDate(entry.time));
|
||||
|
||||
if (!entry.isFolder()) {
|
||||
$span.append(sepTemplate).append(format.formatSize(entry.size));
|
||||
}
|
||||
|
||||
update($span);
|
||||
});
|
||||
|
||||
event.sub('entry.mouseleave', function (entry) {
|
||||
|
||||
update();
|
||||
});
|
||||
};
|
||||
|
||||
init(entry);
|
||||
});
|
59
src/_h5ai/js/inc/ext/thumbnails.js
Normal file
59
src/_h5ai/js/inc/ext/thumbnails.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
|
||||
module.define('ext/thumbnails', [jQuery, 'core/settings', 'core/resource', 'core/entry'], function ($, allsettings, resource, entry) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false,
|
||||
types: ["bmp", "gif", "ico", "image", "jpg", "png", "tiff"],
|
||||
delay: 1000
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.thumbnails),
|
||||
|
||||
requestThumb = function ($img, data) {
|
||||
|
||||
$.getJSON(resource.api(), data, function (json) {
|
||||
|
||||
if (json.code === 0) {
|
||||
$img.addClass('thumb').attr('src', json.absHref);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
checkEntry = function (entry) {
|
||||
|
||||
if (entry.$extended && $.inArray(entry.type, settings.types) >= 0) {
|
||||
|
||||
var $imgSmall = entry.$extended.find('.icon.small img');
|
||||
var $imgBig = entry.$extended.find('.icon.big img');
|
||||
|
||||
requestThumb($imgSmall, {
|
||||
action: 'thumbsrc',
|
||||
href: entry.absHref,
|
||||
width: 16,
|
||||
height: 16,
|
||||
mode: 'square'
|
||||
});
|
||||
requestThumb($imgBig, {
|
||||
action: 'thumbsrc',
|
||||
href: entry.absHref,
|
||||
width: 100,
|
||||
height: 48,
|
||||
mode: 'rational'
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
init = function (entry) {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
setTimeout(function () {
|
||||
|
||||
_.each(entry.content, checkEntry);
|
||||
}, settings.delay);
|
||||
};
|
||||
|
||||
init(entry);
|
||||
});
|
27
src/_h5ai/js/inc/ext/title.js
Normal file
27
src/_h5ai/js/inc/ext/title.js
Normal file
|
@ -0,0 +1,27 @@
|
|||
|
||||
module.define('ext/title', [jQuery, 'core/settings', 'core/entry'], function ($, allsettings, entry) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.title),
|
||||
|
||||
init = function (entry) {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var labels = _.pluck(entry.getCrumb(), 'label'),
|
||||
title = labels.join(' > ');
|
||||
|
||||
if (labels.length > 1) {
|
||||
title = labels[labels.length - 1] + ' - ' + title;
|
||||
}
|
||||
|
||||
document.title = title;
|
||||
};
|
||||
|
||||
init(entry);
|
||||
});
|
227
src/_h5ai/js/inc/ext/tree.js
Normal file
227
src/_h5ai/js/inc/ext/tree.js
Normal file
|
@ -0,0 +1,227 @@
|
|||
|
||||
module.define('ext/tree', [jQuery, 'core/settings', 'core/resource', 'core/event', 'core/entry', 'core/parser'], function ($, allsettings, resource, event, entry, parser) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false,
|
||||
slide: true
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings.tree),
|
||||
|
||||
template = '<div class="entry">' +
|
||||
'<span class="indicator none">' +
|
||||
'<img src="' + resource.image('tree') + '" />' +
|
||||
'</span>' +
|
||||
'<a>' +
|
||||
'<span class="icon"><img /></span>' +
|
||||
'<span class="label"></span>' +
|
||||
'</a>' +
|
||||
'</span>',
|
||||
statusHintTemplate = '<span class="hint"></span>',
|
||||
|
||||
// updates the tree for this single entry
|
||||
update = function (entry) {
|
||||
|
||||
var $html = $(template),
|
||||
$indicator = $html.find('.indicator'),
|
||||
$a = $html.find('a'),
|
||||
$img = $html.find('.icon img'),
|
||||
$label = $html.find('.label');
|
||||
|
||||
$html
|
||||
.addClass(entry.isFolder() ? 'folder' : 'file')
|
||||
.data('entry', entry)
|
||||
.data('status', entry.status);
|
||||
|
||||
$a.attr('href', entry.absHref);
|
||||
$img.attr('src', resource.icon(entry.type));
|
||||
$label.text(entry.label);
|
||||
|
||||
if (entry.isFolder()) {
|
||||
|
||||
var subfolders = entry.getSubfolders();
|
||||
|
||||
// indicator
|
||||
if (!entry.status || (entry.status === 'h5ai' && !entry.isContentFetched) || subfolders.length) {
|
||||
|
||||
$indicator.removeClass('none');
|
||||
|
||||
if (!entry.status || (entry.status === 'h5ai' && !entry.isContentFetched)) {
|
||||
$indicator.addClass('unknown');
|
||||
} else if (entry.isContentVisible) {
|
||||
$indicator.addClass('open');
|
||||
} else {
|
||||
$indicator.addClass('close');
|
||||
}
|
||||
}
|
||||
|
||||
// is it the domain?
|
||||
if (entry.isDomain()) {
|
||||
$html.addClass('domain');
|
||||
$img.attr('src', resource.icon('folder-home'));
|
||||
}
|
||||
|
||||
// is it the current folder?
|
||||
if (entry.isCurrentFolder()) {
|
||||
$html.addClass('current');
|
||||
$img.attr('src', resource.icon('folder-open'));
|
||||
}
|
||||
|
||||
// does it have subfolders?
|
||||
if (subfolders.length) {
|
||||
var $ul = $('<ul class="content" />').appendTo($html);
|
||||
_.each(subfolders, function (e) {
|
||||
$('<li />').append(update(e)).appendTo($ul);
|
||||
});
|
||||
if (!entry.isContentVisible) {
|
||||
$ul.hide();
|
||||
}
|
||||
}
|
||||
|
||||
// reflect folder status
|
||||
if (_.isNumber(entry.status)) {
|
||||
if (entry.status === 200) {
|
||||
$img.attr('src', resource.icon('folder-page'));
|
||||
} else {
|
||||
$html.addClass('error');
|
||||
$a.append($(statusHintTemplate).text(entry.status));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (entry.$tree) {
|
||||
entry.$tree.replaceWith($html);
|
||||
}
|
||||
entry.$tree = $html;
|
||||
|
||||
return $html;
|
||||
},
|
||||
|
||||
createOnIndicatorClick = function (parser) {
|
||||
|
||||
var $tree = $('#tree'),
|
||||
tree = $tree.get(0),
|
||||
slide = function (entry, $indicator, $content, down) {
|
||||
|
||||
entry.isContentVisible = down;
|
||||
$indicator.removeClass('open close').addClass(down ? 'open' : 'close');
|
||||
tree.updateScrollbar(true);
|
||||
$content[down ? 'slideDown' : 'slideUp'](function () {
|
||||
|
||||
tree.updateScrollbar();
|
||||
});
|
||||
};
|
||||
|
||||
return function () {
|
||||
|
||||
var $indicator = $(this),
|
||||
$entry = $indicator.closest('.entry'),
|
||||
entry = $entry.data('entry'),
|
||||
$content = $entry.find('> ul.content');
|
||||
|
||||
if ($indicator.hasClass('unknown')) {
|
||||
|
||||
entry.fetchContent(parser, function (entry) {
|
||||
|
||||
entry.isContentVisible = false;
|
||||
|
||||
var $entry = update(entry),
|
||||
$indicator = $entry.find('> .indicator'),
|
||||
$content = $entry.find('> ul.content');
|
||||
|
||||
if (!$indicator.hasClass('none')) {
|
||||
slide(entry, $indicator, $content, true);
|
||||
}
|
||||
});
|
||||
|
||||
} else if ($indicator.hasClass('open')) {
|
||||
|
||||
slide(entry, $indicator, $content, false);
|
||||
|
||||
} else if ($indicator.hasClass('close')) {
|
||||
|
||||
slide(entry, $indicator, $content, true);
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
shiftTree = function (forceVisible, dontAnimate) {
|
||||
|
||||
var $tree = $("#tree"),
|
||||
$extended = $("#extended"),
|
||||
left = ((settings.slide && $tree.outerWidth() < $extended.offset().left) || forceVisible || !$extended.is(':visible')) ? 0 : 18 - $tree.outerWidth();
|
||||
|
||||
if (dontAnimate) {
|
||||
$tree.stop().css({ left: left });
|
||||
} else {
|
||||
$tree.stop().animate({ left: left });
|
||||
}
|
||||
},
|
||||
|
||||
fetchTree = function (entry, parser, callback) {
|
||||
|
||||
entry.isContentVisible = true;
|
||||
entry.fetchContent(parser, function (entry) {
|
||||
|
||||
if (entry.parent) {
|
||||
fetchTree(entry.parent, parser, callback);
|
||||
} else {
|
||||
callback(entry);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
adjustSpacing = function () {
|
||||
|
||||
var $tree = $('#tree'),
|
||||
tree = $tree[0],
|
||||
winHeight = $(window).height(),
|
||||
navHeight = $('#topbar').outerHeight(),
|
||||
footerHeight = $('#bottombar').outerHeight();
|
||||
|
||||
$tree.css({
|
||||
top: navHeight,
|
||||
height: winHeight - navHeight - footerHeight - 16
|
||||
});
|
||||
|
||||
if (tree.updateScrollbar) {
|
||||
tree.updateScrollbar();
|
||||
}
|
||||
},
|
||||
|
||||
// creates the complete tree from entry down to the root
|
||||
init = function (entry, parser) {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
var $tree = $('<div id="tree" />').appendTo($('body'));
|
||||
|
||||
fetchTree(entry, parser, function (root) {
|
||||
|
||||
$tree
|
||||
.append(update(root))
|
||||
.scrollpanel()
|
||||
.show();
|
||||
|
||||
adjustSpacing();
|
||||
shiftTree(false, true);
|
||||
setTimeout(function () { $tree.get(0).updateScrollbar(); }, 1);
|
||||
});
|
||||
|
||||
$tree
|
||||
.on('click', '.indicator', createOnIndicatorClick(parser))
|
||||
.on('mouseenter', function () { shiftTree(true); })
|
||||
.on('mouseleave', function () { shiftTree(); });
|
||||
|
||||
event.sub('ready', adjustSpacing);
|
||||
$(window).on('resize', function () {
|
||||
adjustSpacing();
|
||||
shiftTree();
|
||||
});
|
||||
};
|
||||
|
||||
init(entry, parser);
|
||||
});
|
133
src/_h5ai/js/inc/ext/zipped-download.js
Normal file
133
src/_h5ai/js/inc/ext/zipped-download.js
Normal file
|
@ -0,0 +1,133 @@
|
|||
|
||||
module.define('ext/zipped-download', [jQuery, 'core/settings', 'core/resource', 'core/event'], function ($, allsettings, resource, event) {
|
||||
|
||||
var defaults = {
|
||||
enabled: false
|
||||
},
|
||||
|
||||
settings = _.extend({}, defaults, allsettings['zipped-download']),
|
||||
|
||||
downloadBtnTemplate = '<li id="download">' +
|
||||
'<a href="#">' +
|
||||
'<img src="' + resource.image('download') + '" alt="download" />' +
|
||||
'<span class="l10n-download">download</span>' +
|
||||
'</a>' +
|
||||
'</li>',
|
||||
authTemplate = '<div id="download-auth">' +
|
||||
'<input id="download-auth-user" type="text" value="" placeholder="user" />' +
|
||||
'<input id="download-auth-password" type="text" value="" placeholder="password" />' +
|
||||
'</div>',
|
||||
|
||||
selectedHrefsStr = '',
|
||||
$download, $img, $downloadAuth, $downloadUser, $downloadPassword,
|
||||
|
||||
failed = function () {
|
||||
|
||||
$download.addClass('failed');
|
||||
setTimeout(function () {
|
||||
$download.removeClass('failed');
|
||||
}, 1000);
|
||||
},
|
||||
|
||||
handleResponse = function (response) {
|
||||
|
||||
$download.removeClass('current');
|
||||
$img.attr('src', resource.image('download'));
|
||||
|
||||
if (response) {
|
||||
if (response.status === 'ok') {
|
||||
setTimeout(function () { // wait here so the img above can be updated in time
|
||||
|
||||
window.location = resource.api() + '?action=getzip&id=' + response.id;
|
||||
}, 200);
|
||||
} else {
|
||||
if (response.code === 401) {
|
||||
$downloadAuth
|
||||
.css({
|
||||
left: $download.offset().left,
|
||||
top: $download.offset().top + $download.outerHeight()
|
||||
})
|
||||
.show();
|
||||
$downloadUser.focus();
|
||||
}
|
||||
failed();
|
||||
}
|
||||
} else {
|
||||
failed();
|
||||
}
|
||||
},
|
||||
|
||||
requestZipping = function (hrefsStr) {
|
||||
|
||||
$download.addClass('current');
|
||||
$img.attr('src', resource.image('loading.gif', true));
|
||||
$.ajax({
|
||||
url: resource.api(),
|
||||
data: {
|
||||
action: 'zip',
|
||||
hrefs: hrefsStr
|
||||
},
|
||||
type: 'POST',
|
||||
dataType: 'json',
|
||||
beforeSend: function (xhr) {
|
||||
|
||||
var user = $downloadUser.val(),
|
||||
password = $downloadPassword.val();
|
||||
|
||||
if (user) {
|
||||
xhr.setRequestHeader('Authorization', 'Basic ' + Base64.encode(user + ':' + password));
|
||||
}
|
||||
},
|
||||
success: function (response) {
|
||||
|
||||
handleResponse(response);
|
||||
},
|
||||
error: function () {
|
||||
|
||||
handleResponse();
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onSelection = function (entries) {
|
||||
|
||||
var $downloadBtn = $('#download');
|
||||
|
||||
selectedHrefsStr = '';
|
||||
if (entries.length) {
|
||||
selectedHrefsStr = _.map(entries, function (entry) {
|
||||
|
||||
return entry.absHref;
|
||||
}).join(':');
|
||||
$downloadBtn.show();
|
||||
} else {
|
||||
$downloadBtn.hide();
|
||||
$downloadAuth.hide();
|
||||
}
|
||||
},
|
||||
|
||||
init = function () {
|
||||
|
||||
if (!settings.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
$download = $(downloadBtnTemplate)
|
||||
.appendTo($('#navbar'))
|
||||
.find('a').on('click', function (event) {
|
||||
|
||||
event.preventDefault();
|
||||
$downloadAuth.hide();
|
||||
requestZipping(selectedHrefsStr);
|
||||
});
|
||||
$img = $download.find('img');
|
||||
|
||||
$downloadAuth = $(authTemplate).appendTo($('body'));
|
||||
$downloadUser = $downloadAuth.find('#download-auth-user');
|
||||
$downloadPassword = $downloadAuth.find('#download-auth-password');
|
||||
|
||||
event.sub('selection', onSelection);
|
||||
};
|
||||
|
||||
init();
|
||||
});
|
Loading…
Add table
Add a link
Reference in a new issue