226 lines
5.2 KiB
JavaScript
226 lines
5.2 KiB
JavaScript
/*
|
|
Usage:
|
|
var r = require('routrly');
|
|
|
|
var module = {
|
|
onCreate: function() {
|
|
},
|
|
onPostCreate: function() {
|
|
},
|
|
onDestroy: function() {
|
|
},
|
|
onPreDestroy: function(onfinish) {
|
|
onfinish(); // calls onDestroy when finished
|
|
}
|
|
};
|
|
|
|
//
|
|
r.route("/place", InfoBox);
|
|
r.route("/thing", [
|
|
r("div", "okay"),
|
|
r(InfoBox, {name: "Test", msg: "okay"})
|
|
]);
|
|
|
|
//
|
|
|
|
var InfoBox = {};
|
|
InfoBox.onCreate = function(props) {
|
|
return r("div", "Info Box");
|
|
};
|
|
InfoBox.onPostCreate = function(node) {
|
|
};
|
|
InfoBox.onPreDestroy = function(node, done) {
|
|
window.setTimeout(1000, function() {
|
|
done(); // calls onDestroy
|
|
});
|
|
};
|
|
|
|
// these assume the current hashbang location
|
|
r.manage(module); // basic object with handlers and whatnot
|
|
r.manage(new Module(thing)); // created object with handler and whatnot
|
|
// these specify hashbang locations
|
|
r.manage(module, "/api/thing"); // basic object in /api/thing context
|
|
|
|
// all amalgamations of r()
|
|
r("div");
|
|
r("span", "test");
|
|
r(InfoBox, "test");
|
|
r("span", {onclick: function(e){ e.target.value = "pressed"; }, value: "click me"});
|
|
r("ul", [
|
|
r("li"),
|
|
r("li")
|
|
r("ul", {
|
|
onclick: function(e) { },
|
|
value: [
|
|
r("li"),
|
|
r("li")
|
|
]
|
|
]);
|
|
|
|
*/
|
|
var routrly = function(type, attr) {
|
|
if (typeof attr == 'undefined') {
|
|
}
|
|
if (obj.constructor === Array) {
|
|
} else if (obj.constructor === RouteNode) {
|
|
} else if (obj.constructor === Object) {
|
|
}
|
|
// if RouteNode
|
|
// else if string (div,etc.)
|
|
// else if Object
|
|
};
|
|
|
|
function getRouteParts(routename) {
|
|
return routename.split(/(?=\/)/g); // "/1/2/3" -> ["/1", "/2", "/3"]
|
|
}
|
|
|
|
function getRouteFromHash(hash) {
|
|
return getRouteParts(hash.replace('#!',''));
|
|
}
|
|
|
|
routrly.activateRoute = function(path) {
|
|
var parts = getRouteParts(path);
|
|
var ctx = routrly.mRoutes;
|
|
var i = 0;
|
|
|
|
do {
|
|
ctx.activate();
|
|
ctx = ctx.parts[parts[i]];
|
|
i++;
|
|
} while(i <= parts.length && ctx)
|
|
}
|
|
|
|
routrly.deactivateRoute = function(path) {
|
|
var parts = getRouteParts(path);
|
|
var ctx = routrly.mRoutes;
|
|
var i = 0;
|
|
|
|
for (var i = 0; i < parts.length; i++) {
|
|
ctx = ctx.parts[parts[i]];
|
|
}
|
|
if (ctx) {
|
|
ctx.deactivate();
|
|
}
|
|
}
|
|
|
|
routrly.hashchange = function(e) {
|
|
var old_path, new_path;
|
|
var old_parts, new_parts;
|
|
var ctx;
|
|
// on hashchange, check if any of our routes have gone out of scope
|
|
var hash = location.hash.replace('^#/', '').replace('#!', '');
|
|
routrly.mRoute = hash;
|
|
|
|
old_parts = getRouteParts(routrly.mLastHash);
|
|
new_parts = getRouteParts(hash);
|
|
|
|
// traverse up to change
|
|
ctx = routrly.mRoutes;
|
|
for (var i = 0; i < old_parts.length; i++) {
|
|
if (new_parts[i] != old_parts[i]) {
|
|
// found our out of scope spot
|
|
routrly.deactivateRoute(old_parts.slice(0,i+1).join(''));
|
|
break;
|
|
}
|
|
}
|
|
routrly.activateRoute(hash);
|
|
routrly.mLastHash = hash;
|
|
}
|
|
|
|
function RouteGroup(parent) {
|
|
this.parent = parent;
|
|
this.parts = {};
|
|
this.procs = [];
|
|
this.activate = function() {
|
|
for (var i = 0; i < this.procs.length; i++) {
|
|
this.procs[i].doActivate();
|
|
}
|
|
}
|
|
this.deactivate = function() {
|
|
for (var i in this.parts) {
|
|
this.parts[i].deactivate();
|
|
}
|
|
var i = this.procs.length;
|
|
while (i--) {
|
|
this.procs[i].doDeactivate();
|
|
if (this.procs[i].proc.destroy) {
|
|
this.procs.splice(i,1);
|
|
}
|
|
}
|
|
}
|
|
this.render = function() {
|
|
}
|
|
}
|
|
|
|
function RouteProc(proc) {
|
|
this.active = false;
|
|
this.proc = proc;
|
|
this.doActivate = function() {
|
|
if (this.active) return;
|
|
if (this.proc.activate) this.proc.activate();
|
|
this.active = true;
|
|
}
|
|
this.doDeactivate = function() {
|
|
if (!this.active) return;
|
|
if (this.proc.deactivate) this.proc.deactivate();
|
|
this.active = false;
|
|
}
|
|
this.doRender = function(attr) {
|
|
if (this.proc.render) return this.proc.render(attr);
|
|
}
|
|
}
|
|
|
|
/**
|
|
Adds a process module to the given route path.
|
|
*/
|
|
routrly.manage = function(proc, routepath) {
|
|
if (!routepath) routepath = routrly.route();
|
|
var rpaths, ctx;
|
|
|
|
rparts = getRouteParts(routepath);
|
|
ctx = routrly.mRoutes;
|
|
for (var i = 0; i < rparts.length; i++) {
|
|
if (!ctx.parts[rparts[i]]) {
|
|
ctx.parts[rparts[i]] = new RouteGroup(ctx);
|
|
}
|
|
ctx = ctx.parts[rparts[i]];
|
|
}
|
|
// at this point ctx should point to where we want the proc to reside
|
|
if (ctx) {
|
|
ctx.procs.push(new RouteProc(proc));
|
|
// TODO: check if our current location (window.hash?) matches our routepath and thereafter run the proc's onCreate
|
|
if (routepath == location.hash.replace("#!", "")) {
|
|
ctx.procs[ctx.procs.length-1].doActivate();
|
|
}
|
|
}
|
|
}
|
|
/**
|
|
Routes to the given path -- basically sets hash
|
|
*/
|
|
routrly.route = function(routepath) {
|
|
if (!routepath) return routrly.mRoute;
|
|
routrly.mRoute = routepath;
|
|
location.hash = '!'+routepath;
|
|
return routrly.mRoute;
|
|
}
|
|
/**
|
|
Calls render for current route's procs
|
|
*/
|
|
routrly.render = function() {
|
|
do {
|
|
for (var j = 0; j < ctx.procs.length; j++) {
|
|
ctx.procs[j].doRender();
|
|
}
|
|
ctx = ctx.parts[parts[i]];
|
|
i++;
|
|
} while(i <= parts.length && ctx)
|
|
}
|
|
|
|
routrly.mRoute = "";
|
|
routrly.mRoutes = new RouteGroup();
|
|
routrly.mLastHash = location.hash.replace('^#/', '').replace('#!','');
|
|
|
|
addEventListener('hashchange', routrly.hashchange);
|
|
|
|
module.exports = routrly;
|