r/index.js

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;