diff --git a/src/_h5ai/client/js/inc/core/entry.js b/src/_h5ai/client/js/inc/core/entry.js
index ace3e99f..03e374a4 100644
--- a/src/_h5ai/client/js/inc/core/entry.js
+++ b/src/_h5ai/client/js/inc/core/entry.js
@@ -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();
});
diff --git a/src/_h5ai/client/js/inc/core/location.js b/src/_h5ai/client/js/inc/core/location.js
index bea9577b..8a870525 100644
--- a/src/_h5ai/client/js/inc/core/location.js
+++ b/src/_h5ai/client/js/inc/core/location.js
@@ -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
};
});
diff --git a/src/_h5ai/client/js/inc/core/refresh.js b/src/_h5ai/client/js/inc/core/refresh.js
index 23d60b84..0ac66bcf 100644
--- a/src/_h5ai/client/js/inc/core/refresh.js
+++ b/src/_h5ai/client/js/inc/core/refresh.js
@@ -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) {
diff --git a/src/_h5ai/client/js/inc/core/server.js b/src/_h5ai/client/js/inc/core/server.js
index 759b81bb..3ca818f6 100644
--- a/src/_h5ai/client/js/inc/core/server.js
+++ b/src/_h5ai/client/js/inc/core/server.js
@@ -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',
diff --git a/src/_h5ai/client/js/inc/ext/crumb.js b/src/_h5ai/client/js/inc/ext/crumb.js
index da128980..72ebfbd3 100644
--- a/src/_h5ai/client/js/inc/ext/crumb.js
+++ b/src/_h5ai/client/js/inc/ext/crumb.js
@@ -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();
});
diff --git a/src/_h5ai/client/js/inc/ext/custom.js b/src/_h5ai/client/js/inc/ext/custom.js
index 5da2495b..649fcc70 100644
--- a/src/_h5ai/client/js/inc/ext/custom.js
+++ b/src/_h5ai/client/js/inc/ext/custom.js
@@ -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) {
+ $('
').hide().prependTo('#content');
+ $('').hide().appendTo('#content');
- if (response) {
- if (response.custom.header) {
- $('').prependTo('#content');
- }
- if (response.custom.footer) {
- $('').appendTo('#content');
- }
- }
- });
+ event.sub('location.changed', onLocationChanged);
+
+ onLocationChanged();
};
init();
diff --git a/src/_h5ai/client/js/inc/ext/link-hover-states.js b/src/_h5ai/client/js/inc/ext/link-hover-states.js
index f3a84e0c..ee4eb910 100644
--- a/src/_h5ai/client/js/inc/ext/link-hover-states.js
+++ b/src/_h5ai/client/js/inc/ext/link-hover-states.js
@@ -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();
diff --git a/src/_h5ai/client/js/inc/main.js b/src/_h5ai/client/js/inc/main.js
index ed29852e..04e7a1cd 100644
--- a/src/_h5ai/client/js/inc/main.js
+++ b/src/_h5ai/client/js/inc/main.js
@@ -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) {
diff --git a/src/_h5ai/client/js/inc/model/entry.js b/src/_h5ai/client/js/inc/model/entry.js
index 21ebf124..d1e3cb6e 100644
--- a/src/_h5ai/client/js/inc/model/entry.js
+++ b/src/_h5ai/client/js/inc/model/entry.js
@@ -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
diff --git a/src/_h5ai/client/js/inc/view/extended.js b/src/_h5ai/client/js/inc/view/items.js
similarity index 75%
rename from src/_h5ai/client/js/inc/view/extended.js
rename to src/_h5ai/client/js/inc/view/items.js
index aecbe811..506bd301 100644
--- a/src/_h5ai/client/js/inc/view/extended.js
+++ b/src/_h5ai/client/js/inc/view/items.js
@@ -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
'' +
'',
emptyTemplate = '',
+ contentTemplate = '',
// 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();
});
diff --git a/src/_h5ai/conf/options.json b/src/_h5ai/conf/options.json
index ec68c0b6..dfbef51b 100644
--- a/src/_h5ai/conf/options.json
+++ b/src/_h5ai/conf/options.json
@@ -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"
},
diff --git a/src/_h5ai/server/php/index.php.jade b/src/_h5ai/server/php/index.php.jade
index c9f0bd2d..8ea6cbe1 100644
--- a/src/_h5ai/server/php/index.php.jade
+++ b/src/_h5ai/server/php/index.php.jade
@@ -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}}" )