Initial switch to smart browsing.

This commit is contained in:
Lars Jung 2012-10-18 21:27:09 +02:00
parent ecc05d3a8b
commit 499013f4fb
12 changed files with 244 additions and 97 deletions

View File

@ -1,13 +1,5 @@
modulejs.define('core/entry', ['_', 'config', 'model/entry'], function (_, config, Entry) {
modulejs.define('core/entry', ['core/location'], function (location) {
_.each(config.entries || [], function (entry) {
Entry.get(entry.absHref, entry.time, entry.size, entry.status, entry.content);
});
var entry = Entry.get();
entry.status = '=h5ai=';
return entry;
return location.getItem();
});

View File

@ -1,7 +1,13 @@
modulejs.define('core/location', [], function () {
modulejs.define('core/location', ['_', 'modernizr', 'core/settings', 'core/event', 'core/notify'], function (_, modernizr, allsettings, event, notify) {
var doc = document,
var settings = _.extend({
smartBrowsing: false
}, allsettings.view),
doc = document,
history = settings.smartBrowsing && modernizr.history ? window.history : null,
forceEncoding = function (href) {
@ -17,36 +23,109 @@ modulejs.define('core/location', [], function () {
.replace(/\=/g, '%3D');
},
absHref = (function () {
reUriToPathname = /^.*:\/\/[^\/]*|[^\/]*$/g,
uriToPathname = function (uri) {
var rePrePathname = /.*:\/\/[^\/]*/,
rePostPathname = /[^\/]*$/,
return uri.replace(reUriToPathname, '');
},
uriToPathname = function (uri) {
hrefsAreDecoded = (function () {
return uri.replace(rePrePathname, '').replace(rePostPathname, '');
},
testpathname = '/a b',
a = doc.createElement('a'),
isDecoded, location;
var testpathname = '/a b',
a = doc.createElement('a');
a.href = testpathname;
isDecoded = uriToPathname(a.href) === testpathname;
return uriToPathname(a.href) === testpathname;
}()),
a.href = doc.location.href;
encodedHref = function (href) {
var a = doc.createElement('a'),
location;
a.href = href;
location = uriToPathname(a.href);
if (isDecoded) {
if (hrefsAreDecoded) {
location = encodeURIComponent(location).replace(/%2F/ig, '/');
}
return forceEncoding(location);
}());
};
var absHref = null,
getDomain = function () {
return doc.domain;
},
getAbsHref = function () {
return absHref;
},
getItem = function () {
return modulejs.require('model/entry').get(absHref);
},
setLocation = function (newAbsHref, keepBrowserUrl) {
newAbsHref = encodedHref(newAbsHref);
if (absHref !== newAbsHref) {
absHref = newAbsHref;
event.pub('location.changed', absHref);
notify.set('loading...');
modulejs.require('core/refresh')(function () { notify.set(); });
if (history) {
if (keepBrowserUrl) {
history.replaceState({absHref: absHref}, '', absHref);
} else {
history.pushState({absHref: absHref}, '', absHref);
}
}
}
},
setLink = function ($el, item) {
$el.attr('href', item.absHref);
if (history && item.isFolder() && item.status === '=h5ai=') {
$el.on('click', function () {
setLocation(item.absHref);
return false;
});
}
if (item.status !== '=h5ai=') {
$el.attr('target', '_blank');
}
};
if (history) {
window.onpopstate = function (e) {
if (e.state && e.state.absHref) {
setLocation(e.state.absHref, true);
}
};
}
return {
domain: doc.domain,
absHref: absHref,
forceEncoding: forceEncoding
forceEncoding: forceEncoding,
encodedHref: encodedHref,
getDomain: getDomain,
getAbsHref: getAbsHref,
getItem: getItem,
setLocation: setLocation,
setLink: setLink
};
});

View File

@ -1,5 +1,5 @@
modulejs.define('core/refresh', ['_', 'core/server', 'model/entry'], function (_, server, Entry) {
modulejs.define('core/refresh', ['_', 'config', 'core/server', 'model/entry', 'core/location'], function (_, config, server, Entry, location) {
var parseJson = function (entry, json) {
@ -20,7 +20,7 @@ modulejs.define('core/refresh', ['_', 'core/server', 'model/entry'], function (_
refresh = function (callback) {
var entry = Entry.get();
var entry = Entry.get(location.getAbsHref());
server.request({action: 'get', entries: true, entriesHref: entry.absHref, entriesWhat: 1}, function (json) {

View File

@ -1,5 +1,5 @@
modulejs.define('core/server', ['$', '_', 'config'], function ($, _, config) {
modulejs.define('core/server', ['$', '_', 'config', 'core/location'], function ($, _, config, location) {
var server = _.extend({}, config.server, {
@ -7,7 +7,7 @@ modulejs.define('core/server', ['$', '_', 'config'], function ($, _, config) {
if (server.api) {
$.ajax({
url: '.',
url: location.getAbsHref(),
data: data,
type: 'POST',
dataType: 'json',

View File

@ -1,5 +1,5 @@
modulejs.define('ext/crumb', ['_', '$', 'core/settings', 'core/resource', 'core/event', 'core/entry'], function (_, $, allsettings, resource, event, entry) {
modulejs.define('ext/crumb', ['_', '$', 'core/settings', 'core/resource', 'core/event', 'core/location'], function (_, $, allsettings, resource, event, location) {
var settings = _.extend({
enabled: false
@ -26,11 +26,11 @@ modulejs.define('ext/crumb', ['_', '$', 'core/settings', 'core/resource', 'core/
$html
.addClass(entry.isFolder() ? 'folder' : 'file')
.data('item', entry)
.data('status', entry.status);
$a
.attr('href', entry.absHref)
.find('span').text(entry.label).end();
location.setLink($a, entry);
$a.find('span').text(entry.label).end();
if (entry.isDomain()) {
$html.addClass('domain');
@ -69,25 +69,49 @@ modulejs.define('ext/crumb', ['_', '$', 'core/settings', 'core/resource', 'core/
}
},
// creates the complete crumb from entry down to the root
init = function (entry) {
onLocationChanged = function (item) {
var crumb = item.getCrumb(),
$ul = $('#navbar'),
found = false;
$ul.find('.crumb').each(function () {
var $html = $(this);
if ($html.data('item') === item) {
found = true;
$html.addClass('current');
} else {
$html.removeClass('current');
}
});
if (!found) {
$ul.find('.crumb').remove();
_.each(crumb, function (e) {
$ul.append(update(e));
});
}
},
init = function () {
if (!settings.enabled) {
return;
}
var crumb = entry.getCrumb(),
$ul = $('#navbar');
_.each(crumb, function (e) {
$ul.append(update(e));
});
// event.sub('entry.created', onContentChanged);
// event.sub('entry.removed', onContentChanged);
event.sub('entry.changed', onContentChanged);
event.sub('location.changed', function () {
onLocationChanged(location.getItem());
});
onLocationChanged(location.getItem());
};
init(entry);
init();
});

View File

@ -1,5 +1,5 @@
modulejs.define('ext/custom', ['_', '$', 'core/settings', 'core/server'], function (_, $, allsettings, server) {
modulejs.define('ext/custom', ['_', '$', 'core/settings', 'core/server', 'core/event'], function (_, $, allsettings, server, event) {
var settings = _.extend({
enabled: false,
@ -7,23 +7,35 @@ modulejs.define('ext/custom', ['_', '$', 'core/settings', 'core/server'], functi
footer: '_h5ai.footer.html'
}, allsettings.custom),
onLocationChanged = function () {
$('#content-header, #content-footer').stop(true, true).slideUp(200);
server.request({action: 'get', custom: true}, function (response) {
if (response) {
if (response.custom.header) {
$('#content-header').html(response.custom.header).stop(true, true).slideDown(400);
}
if (response.custom.footer) {
$('#content-footer').html(response.custom.footer).stop(true, true).slideDown(400);
}
}
});
},
init = function () {
if (!settings.enabled) {
return;
}
server.request({action: 'get', custom: true}, function (response) {
$('<div id="content-header"/>').hide().prependTo('#content');
$('<div id="content-footer"/>').hide().appendTo('#content');
if (response) {
if (response.custom.header) {
$('<div id="content-header">' + response.custom.header + '</div>').prependTo('#content');
}
if (response.custom.footer) {
$('<div id="content-footer">' + response.custom.footer + '</div>').appendTo('#content');
}
}
});
event.sub('location.changed', onLocationChanged);
onLocationChanged();
};
init();

View File

@ -1,5 +1,5 @@
modulejs.define('ext/link-hover-states', ['_', '$', 'core/settings'], function (_, $, allsettings) {
modulejs.define('ext/link-hover-states', ['_', '$', 'core/settings', 'core/event'], function (_, $, allsettings, event) {
var settings = _.extend({
enabled: false
@ -29,13 +29,22 @@ modulejs.define('ext/link-hover-states', ['_', '$', 'core/settings'], function (
selectLinks(href).removeClass('hover');
},
onLocationChanged = function () {
$('.hover').removeClass('hover');
},
init = function () {
if (settings.enabled) {
$('body')
.on('mouseenter', selector, onMouseEnter)
.on('mouseleave', selector, onMouseLeave);
if (!settings.enabled) {
return;
}
$('body')
.on('mouseenter', selector, onMouseEnter)
.on('mouseleave', selector, onMouseLeave);
event.sub('location.changed', onLocationChanged);
};
init();

View File

@ -3,10 +3,12 @@ modulejs.define('main', ['_', 'core/event'], function (_, event) {
event.pub('beforeView');
modulejs.require('view/extended');
modulejs.require('view/items');
modulejs.require('view/spacing');
modulejs.require('view/viewmode');
modulejs.require('core/location').setLocation(document.location.href, true);
event.pub('beforeExt');
_.each(modulejs.state(), function (state, id) {

View File

@ -1,5 +1,6 @@
modulejs.define('model/entry', ['$', '_', 'core/types', 'core/event', 'core/settings', 'core/location', 'core/server'], function ($, _, types, event, settings, location, server) {
modulejs.define('model/entry', ['$', '_', 'config', 'core/types', 'core/event', 'core/settings', 'core/server', 'core/location'], function ($, _, config, types, event, settings, server, location) {
var reEndsWithSlash = /\/$/,
@ -44,7 +45,7 @@ modulejs.define('model/entry', ['$', '_', 'core/types', 'core/event', 'core/sett
getEntry = function (absHref, time, size, status, isContentFetched) {
absHref = location.forceEncoding(absHref || location.absHref);
absHref = location.forceEncoding(absHref);
if (!startsWith(absHref, settings.rootAbsHref)) {
return null;
@ -88,7 +89,7 @@ modulejs.define('model/entry', ['$', '_', 'core/types', 'core/event', 'core/sett
removeEntry = function (absHref) {
absHref = location.forceEncoding(absHref || location.absHref);
absHref = location.forceEncoding(absHref);
var self = cache[absHref];
@ -128,6 +129,14 @@ modulejs.define('model/entry', ['$', '_', 'core/types', 'core/event', 'core/sett
callback(self);
});
}
},
init = function () {
_.each(config.entries || [], function (entry) {
getEntry(entry.absHref, entry.time, entry.size, entry.status, entry.content);
});
};
@ -142,7 +151,7 @@ modulejs.define('model/entry', ['$', '_', 'core/types', 'core/event', 'core/sett
this.absHref = absHref;
this.type = types.getType(absHref);
this.label = createLabel(absHref === '/' ? location.domain : split.name);
this.label = createLabel(absHref === '/' ? location.getDomain() : split.name);
this.time = null;
this.size = null;
this.parent = null;
@ -167,7 +176,7 @@ modulejs.define('model/entry', ['$', '_', 'core/types', 'core/event', 'core/sett
isCurrentFolder: function () {
return this.absHref === location.absHref;
return this.absHref === location.getAbsHref();
},
isInCurrentFolder: function () {
@ -177,7 +186,7 @@ modulejs.define('model/entry', ['$', '_', 'core/types', 'core/event', 'core/sett
isCurrentParentFolder: function () {
return this === getEntry().parent;
return this === getEntry(location.getAbsHref()).parent;
},
isDomain: function () {
@ -259,6 +268,9 @@ modulejs.define('model/entry', ['$', '_', 'core/types', 'core/event', 'core/sett
}
});
init();
return {
get: getEntry,
remove: removeEntry

View File

@ -1,5 +1,5 @@
modulejs.define('view/extended', ['_', '$', 'core/settings', 'core/resource', 'core/format', 'core/event', 'core/entry'], function (_, $, allsettings, resource, format, event, entry) {
modulejs.define('view/items', ['_', '$', 'core/settings', 'core/resource', 'core/format', 'core/event', 'core/location'], function (_, $, allsettings, resource, format, event, location) {
var settings = _.extend({
setParentFolderLabels: false,
@ -25,6 +25,7 @@ modulejs.define('view/extended', ['_', '$', 'core/settings', 'core/resource', 'c
'</li>' +
'</ul>',
emptyTemplate = '<div class="empty l10n-empty"/>',
contentTemplate = '<div id="content"><div id="extended" class="clearfix"/></div>',
// updates this single entry
update = function (entry, force) {
@ -40,14 +41,14 @@ modulejs.define('view/extended', ['_', '$', 'core/settings', 'core/resource', 'c
$label = $html.find('.label'),
$date = $html.find('.date'),
$size = $html.find('.size');
// escapedHref = entry.absHref.replace(/'/g, "%27").replace(/"/g, "%22");
$html
.addClass(entry.isFolder() ? 'folder' : 'file')
.data('entry', entry)
.data('status', entry.status);
$a.attr('href', entry.absHref);
location.setLink($a, entry);
$imgSmall.attr('src', resource.icon(entry.type)).attr('alt', entry.type);
$imgBig.attr('src', resource.icon(entry.type, true)).attr('alt', entry.type);
$label.text(entry.label);
@ -94,32 +95,42 @@ modulejs.define('view/extended', ['_', '$', 'core/settings', 'core/resource', 'c
event.pub('entry.mouseleave', entry);
},
// creates the view for entry content
init = function (entry) {
onLocationChanged = function (item) {
var $extended = $('#extended'),
$ul = $(listTemplate),
$emtpy = $(emptyTemplate);
$ul = $extended.find('ul'),
$empty = $extended.find('.empty');
format.setDefaultMetric(settings.binaryPrefix);
$ul.find('.entry').remove();
if (entry.parent) {
$ul.append(update(entry.parent));
if (item.parent) {
$ul.append(update(item.parent));
}
_.each(entry.content, function (e) {
_.each(item.content, function (e) {
$ul.append(update(e));
});
$extended.append($ul);
$extended.append($emtpy);
if (!entry.isEmpty()) {
$emtpy.hide();
if (item.isEmpty()) {
$empty.show();
} else {
$empty.hide();
}
},
init = function () {
var $content = $(contentTemplate),
$extended = $content.find('#extended'),
$ul = $(listTemplate),
$emtpy = $(emptyTemplate).hide();
format.setDefaultMetric(settings.binaryPrefix);
$extended
.append($ul)
.append($emtpy)
.on('mouseenter', '.entry a', onMouseenter)
.on('mouseleave', '.entry a', onMouseleave);
@ -133,24 +144,32 @@ modulejs.define('view/extended', ['_', '$', 'core/settings', 'core/resource', 'c
event.sub('entry.created', function (entry) {
if (entry.isInCurrentFolder() && !entry.$extended) {
update(entry, true).hide().appendTo($ul).slideDown(400);
$emtpy.slideUp(400);
$emtpy.fadeOut(100, function () {
update(entry, true).hide().appendTo($ul).fadeIn(400);
});
}
});
event.sub('entry.removed', function (entry) {
if (entry.isInCurrentFolder() && entry.$extended) {
entry.$extended.slideUp(400, function () {
entry.$extended.fadeOut(400, function () {
entry.$extended.remove();
if (entry.parent.isEmpty()) {
$emtpy.slideDown(400);
$emtpy.fadeIn(100);
}
});
}
});
event.sub('location.changed', function () {
onLocationChanged(location.getItem());
});
$content.appendTo('body');
};
init(entry);
init();
});

View File

@ -38,7 +38,8 @@ Options
"setParentFolderLabels": true,
"binaryPrefix": false,
"indexFiles": ["index.html", "index.htm", "index.php"],
"ignore": ["^\\.", "^_{{pkg.name}}"]
"ignore": ["^\\.", "^_{{pkg.name}}"],
"smartBrowsing": true
},
@ -67,7 +68,7 @@ Options
in each folder.
*/
"custom": {
"enabled": false,
"enabled": true,
"header": "_{{pkg.name}}.header.html",
"footer": "_{{pkg.name}}.footer.html"
},

View File

@ -27,9 +27,6 @@ html.no-js( lang="en" )
div#topbar.clearfix
ul#navbar
div#content
div#extended.clearfix
div#bottombar.clearfix
span.left
a#h5ai-reference( href="{{pkg.url}}", title="{{pkg.name}} · {{pkg.description}}" )