file-formats-javascript-ej1.../scripts/path.js

202 строки
6.9 KiB
JavaScript

var Path = {
'version': "0.8.4",
'map': function (path) {
if (Path.routes.defined.hasOwnProperty(path)) {
return Path.routes.defined[path];
} else {
return new Path.core.route(path);
}
},
'root': function (path) {
Path.routes.root = path;
},
'rescue': function (fn) {
Path.routes.rescue = fn;
},
'history': {
'initial':{}, // Empty container for "Initial Popstate" checking variables.
'pushState': function(state, title, path){
if(Path.history.supported){
if(Path.dispatch(path)){
history.pushState(state, title, path);
}
} else {
if(Path.history.fallback){
window.location.hash = "#" + path;
}
}
},
'popState': function (event) {
alert("hi");
var initialPop = !Path.history.initial.popped && location.href == Path.history.initial.URL;
Path.history.initial.popped = true;
if(initialPop) return;
Path.dispatch(document.location.pathname);
},
'listen': function(fallback){
Path.history.supported = !!(window.history && window.history.pushState);
Path.history.fallback = fallback;
if(Path.history.supported){
Path.history.initial.popped = ('state' in window.history), Path.history.initial.URL = location.href;
window.onpopstate = Path.history.popState;
} else {
if(Path.history.fallback){
for(route in Path.routes.defined){
if(route.charAt(0) != "#"){
Path.routes.defined["#"+route] = Path.routes.defined[route];
Path.routes.defined["#"+route].path = "#"+route;
}
}
Path.listen();
}
}
}
},
'match': function (path, parameterize) {
var params = {}, route = null, possible_routes, slice, i, j, compare;
for (route in Path.routes.defined) {
if (route !== null && route !== undefined) {
route = Path.routes.defined[route];
possible_routes = route.partition();
for (j = 0; j < possible_routes.length; j++) {
slice = possible_routes[j];
compare = path;
if (slice.search(/:/) > 0) {
for (i = 0; i < slice.split("/").length; i++) {
if ((i < compare.split("/").length) && (slice.split("/")[i].charAt(0) === ":")) {
params[slice.split('/')[i].replace(/:/, '')] = compare.split("/")[i];
compare = compare.replace(compare.split("/")[i], slice.split("/")[i]);
}
}
}
if (slice === compare) {
if (parameterize) {
(j === 0) && (params["categorize1"] = "");
route.params = params;
}
return route;
}
}
if (slice !== compare) {
if (parameterize) {
route.params = params;
}
return route;
}
}
}
return null;
},
'dispatch': function (passed_route) {
var previous_route, matched_route;
if (Path.routes.current !== passed_route) {
Path.routes.previous = Path.routes.current;
Path.routes.current = passed_route;
matched_route = Path.match(passed_route, true);
if (Path.routes.previous) {
previous_route = Path.match(Path.routes.previous);
if (previous_route !== null && previous_route.do_exit !== null) {
previous_route.do_exit();
}
}
if (matched_route !== null) {
matched_route.run();
return true;
} else {
if (Path.routes.rescue !== null) {
Path.routes.rescue();
}
}
}
},
'listen': function () {
var fn = function () {
Path.dispatch(location.hash);
}
if (location.hash === "") {
if (Path.routes.root !== null) {
location.hash = Path.routes.root;
}
}
// The 'document.documentMode' checks below ensure that PathJS fires the right events
// even in IE "Quirks Mode".
if ("onhashchange" in window && (!document.documentMode || document.documentMode >= 8)) {
window.onhashchange = fn;
} else {
setInterval(fn, 50);
}
if(location.hash !== "") {
Path.dispatch(location.hash);
}
},
'core': {
'route': function (path) {
this.path = path;
this.action = null;
this.do_enter = [];
this.do_exit = null;
this.params = {};
Path.routes.defined[path] = this;
}
},
'routes': {
'current': null,
'root': null,
'rescue': null,
'previous': null,
'defined': {}
}
};
Path.core.route.prototype = {
'to': function (fn) {
this.action = fn;
return this;
},
'enter': function (fns) {
if (fns instanceof Array) {
this.do_enter = this.do_enter.concat(fns);
} else {
this.do_enter.push(fns);
}
return this;
},
'exit': function (fn) {
this.do_exit = fn;
return this;
},
'partition': function () {
var parts = [], options = [], re = /\(([^}]+?)\)/g, text, i;
while (text = re.exec(this.path)) {
parts.push(text[1]);
}
options.push(this.path.split("(")[0]);
for (i = 0; i < parts.length; i++) {
options.push(options[options.length - 1] + parts[i]);
}
return options;
},
'run': function () {
var halt_execution = false, i, result, previous;
if (Path.routes.defined[this.path].hasOwnProperty("do_enter")) {
if (Path.routes.defined[this.path].do_enter.length > 0) {
for (i = 0; i < Path.routes.defined[this.path].do_enter.length; i++) {
result = Path.routes.defined[this.path].do_enter[i].apply(this, null);
if (result === false) {
halt_execution = true;
break;
}
}
}
}
if (!halt_execution) {
Path.routes.defined[this.path].action();
}
}
};