From 24f4a03bc0166a57e32d42c82bc06ec5be0596f3 Mon Sep 17 00:00:00 2001 From: pkarl Date: Mon, 11 Feb 2013 15:52:21 -0500 Subject: [PATCH 1/9] added support for query string parameters --- .DS_Store | Bin 0 -> 6148 bytes path.js | 19 +++++++++++++++++++ tests/.DS_Store | Bin 0 -> 6148 bytes 3 files changed, 19 insertions(+) create mode 100644 .DS_Store create mode 100644 tests/.DS_Store diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..94cc540d1571314346074f3c9f0cbc6bc19af08b GIT binary patch literal 6148 zcmeHKO>fgc6r4@d)>c8}g4Cnc6Nf4a0@POG;6`ah4@jt~)B{CeAHplON-3q1q+>M+MZgTSXrcO7t-I{AA1?H7)k(Po~-!0c&&BXGoFX%KCYO z^$3U9!!9~_O>E+fBM$Hd2_#0y&77HyDGqP2mw9!kDA?NBbyfLWRnoDqI2yduaT%4vq8$x% z&zq?1u}8;8Qf7=#Z1r)Pl)d+j_3?On=f!65e5W0qO`0K_`e+8C>!M#Tv%h88P>?4b!mB^s)*TMS|7%m=nE zv{)H5bO=2%&tpdxc84PL=*$PY93nL6TBm?h;JN}!=CGmG|GmHO|F4tWkyF4aaIX{) z^-j0b<}KN^b>ZgJS{u+m(3PpW%HS1+fnJJPtCr$*x;Ewm6%a# 0) { + var url_params = path.match(/\?[a-z0-9\-_=&]+/i), + param; + + // remove the ?, split params on & if applicable + param = url_params.substring(1).split('&'); + + // add params to route params array, allowing fully qualified params (like :id in URL match) + // to overwrite query string params + for(var u in param) { + params[ param[u].split('=')[0] || param[u] ] = param[u].split('=')[1] || true; + } + + // remove url query params from path & re-assign + path = path.substring(0, path.search(/\?[a-z0-9\-_=&]+/gi)); + } + for (j = 0; j < possible_routes.length; j++) { slice = possible_routes[j]; compare = path; diff --git a/tests/.DS_Store b/tests/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..d1c09643489ddc2aa4c9500a54fe13ea3402b8dc GIT binary patch literal 6148 zcmeHKO-lno41LiaDqiYA@Hj_L3;u(pRKctM0j(BV*;=9PeSe_;Nnbwv*t&2YkDgBHdvy$ZdMP|W;JEBQguZ=e>0&4oPMjY!~)NIS9;y4bi_(qayX}MY*(}H z+H$j#q3fq41Ia)#kPIXP`!m2hTV;6cm}4@K3?u`e4Cwh#sET!9>u5&@2WtU{1G-IU z>jPPHN?;w>I&y|0o=Wsoi55dVo&FMWbztl0>5ynXBv$@tUc^>s{bJ#e+A+suAQ|W~ zpuI0;r1$?N|1!NzzJ=tF3?u{pl>r${ZYN`YUEHldzEkhoLcOD^Xk4oXg?8r=z#n>! foY|z$7quBz2eyt{Mg5je%!hyxl0!1^3k Date: Mon, 11 Feb 2013 15:54:40 -0500 Subject: [PATCH 2/9] minified path.js to path.min.js --- path.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/path.min.js b/path.min.js index f44e647..4a9ab08 100644 --- a/path.min.js +++ b/path.min.js @@ -1 +1 @@ -var Path={version:"0.8.4",map:function(a){if(Path.routes.defined.hasOwnProperty(a)){return Path.routes.defined[a]}else{return new Path.core.route(a)}},root:function(a){Path.routes.root=a},rescue:function(a){Path.routes.rescue=a},history:{initial:{},pushState:function(a,b,c){if(Path.history.supported){if(Path.dispatch(c)){history.pushState(a,b,c)}}else{if(Path.history.fallback){window.location.hash="#"+c}}},popState:function(a){var b=!Path.history.initial.popped&&location.href==Path.history.initial.URL;Path.history.initial.popped=true;if(b)return;Path.dispatch(document.location.pathname)},listen:function(a){Path.history.supported=!!(window.history&&window.history.pushState);Path.history.fallback=a;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(a,b){var c={},d=null,e,f,g,h,i;for(d in Path.routes.defined){if(d!==null&&d!==undefined){d=Path.routes.defined[d];e=d.partition();for(h=0;h0){for(g=0;g=8)){window.onhashchange=a}else{setInterval(a,50)}if(location.hash!==""){Path.dispatch(location.hash)}},core:{route:function(a){this.path=a;this.action=null;this.do_enter=[];this.do_exit=null;this.params={};Path.routes.defined[a]=this}},routes:{current:null,root:null,rescue:null,previous:null,defined:{}}};Path.core.route.prototype={to:function(a){this.action=a;return this},enter:function(a){if(a instanceof Array){this.do_enter=this.do_enter.concat(a)}else{this.do_enter.push(a)}return this},exit:function(a){this.do_exit=a;return this},partition:function(){var a=[],b=[],c=/\(([^}]+?)\)/g,d,e;while(d=c.exec(this.path)){a.push(d[1])}b.push(this.path.split("(")[0]);for(e=0;e0){for(b=0;b0){var url_params=path.match(/\?[a-z0-9\-_=&]+/i),param;param=url_params.substring(1).split('&');for(var u in param){params[param[u].split('=')[0]||param[u]]=param[u].split('=')[1]||true}path=path.substring(0,path.search(/\?[a-z0-9\-_=&]+/gi))}for(j=0;j0){for(i=0;i=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;i0){for(i=0;i Date: Mon, 11 Feb 2013 16:21:54 -0500 Subject: [PATCH 3/9] updated query string search to exclude query strings without data ("?" vs. "?key=value") --- path.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/path.js b/path.js index 296881d..1e61be8 100644 --- a/path.js +++ b/path.js @@ -60,12 +60,12 @@ var Path = { possible_routes = route.partition(); // if a ? is present... - if (path.search(/\?/) > 0) { - var url_params = path.match(/\?[a-z0-9\-_=&]+/i), + if (path.search(/\?[a-z0-9\-_=&]{1,}/i) > 0) { + var url_params = path.match(/\?[a-z0-9\-_=&]{1,}/i), param; // remove the ?, split params on & if applicable - param = url_params.substring(1).split('&'); + param = url_params[0].substring(1).split('&'); // add params to route params array, allowing fully qualified params (like :id in URL match) // to overwrite query string params From bb93b6179d9d520ddb8ad657da7b37a9367d11a6 Mon Sep 17 00:00:00 2001 From: pkarl Date: Mon, 11 Feb 2013 16:22:28 -0500 Subject: [PATCH 4/9] updated expected test results --- tests/path.js.test.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/path.js.test.html b/tests/path.js.test.html index 9d870fa..5809aad 100644 --- a/tests/path.js.test.html +++ b/tests/path.js.test.html @@ -176,12 +176,12 @@

Test Suite

H(one=N/A, two=N/A) Optional parameters with only the require part submitted H(one=10, two=N/A) Optional parameters with one optional part submitted H(one=10, two=20) Optional parameters two levels deep - H(one=10, two=N/A) Testing "back" functionality + H(one=10, two=N/A) Testing "back" functionality

-

Expected

-
F[enter]::F[action]::A[enter]::A[action]::A[exit]::B[enter]::B[action]::C[action]::C[exit]::RESCUE::RESCUE::E[enter](parse id=1)::E[action](parse id=1)::E[enter](parse id=2)::E[action](parse id=2)::E[action](check id=3)::E[exit](check id=3)::F[enter]::F[action]::G[enter 1]::G[enter 2]::G[enter 3]::G[enter 4]::H(one=N/A, two=N/A)::H(one=10, two=N/A)::H(one=10, two=20)::H(one=10, two=N/A)
+

Expected

+
F[enter]::F[action]::A[enter]::A[action]::A[exit]::B[enter]::B[action]::C[action]::C[exit]::RESCUE::RESCUE::E[enter](parse id=1)::E[action](parse id=1)::E[enter](parse id=2)::E[action](parse id=2)::E[action](check id=3)::E[exit](check id=3)::F[enter]::F[action]::G[enter 1]::G[enter 2]::G[enter 3]::G[enter 4]::H(one=N/A, two=N/A)::H(one=10, two=N/A)::H(one=10, two=20)::I(debug=true)::I(debug=false)::I(debug=true, id=10)::RESCUE::H(one=10, two=N/A)

Actual

Grade

From b915199d1a4839b5b19cec75cf2ea431e29ff5d3 Mon Sep 17 00:00:00 2001 From: pkarl Date: Mon, 11 Feb 2013 16:25:29 -0500 Subject: [PATCH 5/9] updated token + reason table with query string param data --- tests/path.js.test.html | 185 ++++++++++++++++++++++------------------ 1 file changed, 102 insertions(+), 83 deletions(-) diff --git a/tests/path.js.test.html b/tests/path.js.test.html index 5809aad..2ce57b6 100644 --- a/tests/path.js.test.html +++ b/tests/path.js.test.html @@ -5,143 +5,158 @@ -
-

Test Suite

+
+

Test Suite

- Path.js uses a very straightforward method of testing. We manually construct + Path.js uses a very straightforward method of testing. We manually construct a series of method calls that the library should execute under normal working conditions. We then use JavaScript to simulate the URL changes, and compare the final result with what the result should actually be. If the end result @@ -149,34 +164,38 @@

Test Suite

is not suitable for use. The expected test results are as follows:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Token Reason
F[enter] Enter method of F, as it is root
F[action] True action of F, as it is root
A[enter] Enter method of A, as it is looped
A[action] True action of A, as it is looped
A[exit] Exit method of A, as we move to next route
B[enter] Enter method of B, as it is looped
B[action] True action of B, as it is looped
C[action] True action of C
C[exit] Exit method of C, as we move to next route
RESCUE Rescue a route that wasn't found (D1)
RESCUE Rescue a route that wasn't found (D2)
E[enter](parse id=1) Enter method of a param parsed route
E[action](parse id=1) True action of the route, with param of id=1
E[enter](parse id=2) Enter method of the same route again
E[action](parse id=2) True action of the route, with param of id=2
E[action](check id=3) True action of the next route, with param id=3
E[exit](check id=3) Exit method of parameterized route
F[enter] Enter method of F again, our final route
F[action] True action of F, our final route
G[enter 1] First enter method of G
G[enter 2] Second enter method of G
G[enter 3] Third enter method of G
G[enter 4] Last enter method of G - Returns false, stops execution
H(one=N/A, two=N/A) Optional parameters with only the require part submitted
H(one=10, two=N/A) Optional parameters with one optional part submitted
H(one=10, two=20) Optional parameters two levels deep
H(one=10, two=N/A) Testing "back" functionality
Token Reason
F[enter] Enter method of F, as it is root
F[action] True action of F, as it is root
A[enter] Enter method of A, as it is looped
A[action] True action of A, as it is looped
A[exit] Exit method of A, as we move to next route
B[enter] Enter method of B, as it is looped
B[action] True action of B, as it is looped
C[action] True action of C
C[exit] Exit method of C, as we move to next route
RESCUE Rescue a route that wasn't found (D1)
RESCUE Rescue a route that wasn't found (D2)
E[enter](parse id=1) Enter method of a param parsed route
E[action](parse id=1) True action of the route, with param of id=1
E[enter](parse id=2) Enter method of the same route again
E[action](parse id=2) True action of the route, with param of id=2
E[action](check id=3) True action of the next route, with param id=3
E[exit](check id=3) Exit method of parameterized route
F[enter] Enter method of F again, our final route
F[action] True action of F, our final route
G[enter 1] First enter method of G
G[enter 2] Second enter method of G
G[enter 3] Third enter method of G
G[enter 4] Last enter method of G - Returns false, stops execution
H(one=N/A, two=N/A) Optional parameters with only the require part submitted
H(one=10, two=N/A) Optional parameters with one optional part submitted
H(one=10, two=20) Optional parameters two levels deep
I(debug=true) Query string parameter present, but not set
I(debug=false) Query string parameter set
I(debug=true, id=10) Multiple query string parameters, one present (but unset), one set
RESCUE Empty query string with ? should fail to match
H(one=10, two=N/A) Testing "back" functionality


From a56a681808481e3049a4e85a1f12c3b22cf7726c Mon Sep 17 00:00:00 2001 From: pkarl Date: Mon, 11 Feb 2013 17:53:58 -0500 Subject: [PATCH 6/9] added minified path.js and updated minified tests --- path.min.js | 2 +- tests/.DS_Store | Bin 6148 -> 0 bytes tests/path.min.js.test.html | 189 ++++++++++++++++++++---------------- 3 files changed, 105 insertions(+), 86 deletions(-) delete mode 100644 tests/.DS_Store diff --git a/path.min.js b/path.min.js index 4a9ab08..2e1a055 100644 --- a/path.min.js +++ b/path.min.js @@ -1 +1 @@ -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':{},'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){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();if(path.search(/\?/)>0){var url_params=path.match(/\?[a-z0-9\-_=&]+/i),param;param=url_params.substring(1).split('&');for(var u in param){params[param[u].split('=')[0]||param[u]]=param[u].split('=')[1]||true}path=path.substring(0,path.search(/\?[a-z0-9\-_=&]+/gi))}for(j=0;j0){for(i=0;i=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;i0){for(i=0;i0){var f=e.match(/\?[a-z0-9\-_=&]{1,}/i),l;l=f[0].substring(1).split("&");for(var c in l){n[l[c].split("=")[0]||l[c]]=l[c].split("=")[1]||true}e=e.substring(0,e.search(/\?[a-z0-9\-_=&]+/gi))}for(u=0;u0){for(o=0;o=8)){window.onhashchange=e}else{setInterval(e,50)}if(location.hash!==""){Path.dispatch(location.hash)}},core:{route:function(e){this.path=e;this.action=null;this.do_enter=[];this.do_exit=null;this.params={};Path.routes.defined[e]=this}},routes:{current:null,root:null,rescue:null,previous:null,defined:{}}};Path.core.route.prototype={to:function(e){this.action=e;return this},enter:function(e){if(e instanceof Array){this.do_enter=this.do_enter.concat(e)}else{this.do_enter.push(e)}return this},exit:function(e){this.do_exit=e;return this},partition:function(){var e=[],t=[],n=/\(([^}]+?)\)/g,r,i;while(r=n.exec(this.path)){e.push(r[1])}t.push(this.path.split("(")[0]);for(i=0;i0){for(t=0;t2YkDgBHdvy$ZdMP|W;JEBQguZ=e>0&4oPMjY!~)NIS9;y4bi_(qayX}MY*(}H z+H$j#q3fq41Ia)#kPIXP`!m2hTV;6cm}4@K3?u`e4Cwh#sET!9>u5&@2WtU{1G-IU z>jPPHN?;w>I&y|0o=Wsoi55dVo&FMWbztl0>5ynXBv$@tUc^>s{bJ#e+A+suAQ|W~ zpuI0;r1$?N|1!NzzJ=tF3?u{pl>r${ZYN`YUEHldzEkhoLcOD^Xk4oXg?8r=z#n>! foY|z$7quBz2eyt{Mg5je%!hyxl0!1^3k -
-

Test Suite

+
+

Test Suite

- Path.js uses a very straightforward method of testing. We manually construct + Path.js uses a very straightforward method of testing. We manually construct a series of method calls that the library should execute under normal working conditions. We then use JavaScript to simulate the URL changes, and compare the final result with what the result should actually be. If the end result @@ -149,39 +164,43 @@

Test Suite

is not suitable for use. The expected test results are as follows:

- - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Token Reason
F[enter] Enter method of F, as it is root
F[action] True action of F, as it is root
A[enter] Enter method of A, as it is looped
A[action] True action of A, as it is looped
A[exit] Exit method of A, as we move to next route
B[enter] Enter method of B, as it is looped
B[action] True action of B, as it is looped
C[action] True action of C
C[exit] Exit method of C, as we move to next route
RESCUE Rescue a route that wasn't found (D1)
RESCUE Rescue a route that wasn't found (D2)
E[enter](parse) Enter method of a param parsed route
E[action](parse id=1) True action of the route, with param of id=1
E[enter](parse) Enter method of the same route again
E[action](parse id=2) True action of the route, with param of id=2
E[action](check id=3) True action of the next route, with param id=3
E[exit](check) Exit method of parameterized route
F[enter] Enter method of F again, our final route
F[action] True action of F, our final route
G[enter 1] First enter method of G
G[enter 2] Second enter method of G
G[enter 3] Third enter method of G
G[enter 4] Last enter method of G - Returns false, stops execution
H(one=N/A, two=N/A) Optional parameters with only the require part submitted
H(one=10, two=N/A) Optional parameters with one optional part submitted
H(one=10, two=20) Optional parameters two levels deep
H(one=10, two=N/A) Testing "back" functionality
Token Reason
F[enter] Enter method of F, as it is root
F[action] True action of F, as it is root
A[enter] Enter method of A, as it is looped
A[action] True action of A, as it is looped
A[exit] Exit method of A, as we move to next route
B[enter] Enter method of B, as it is looped
B[action] True action of B, as it is looped
C[action] True action of C
C[exit] Exit method of C, as we move to next route
RESCUE Rescue a route that wasn't found (D1)
RESCUE Rescue a route that wasn't found (D2)
E[enter](parse id=1) Enter method of a param parsed route
E[action](parse id=1) True action of the route, with param of id=1
E[enter](parse id=2) Enter method of the same route again
E[action](parse id=2) True action of the route, with param of id=2
E[action](check id=3) True action of the next route, with param id=3
E[exit](check id=3) Exit method of parameterized route
F[enter] Enter method of F again, our final route
F[action] True action of F, our final route
G[enter 1] First enter method of G
G[enter 2] Second enter method of G
G[enter 3] Third enter method of G
G[enter 4] Last enter method of G - Returns false, stops execution
H(one=N/A, two=N/A) Optional parameters with only the require part submitted
H(one=10, two=N/A) Optional parameters with one optional part submitted
H(one=10, two=20) Optional parameters two levels deep
I(debug=true) Query string parameter present, but not set
I(debug=false) Query string parameter set
I(debug=true, id=10) Multiple query string parameters, one present (but unset), one set
RESCUE Empty query string with ? should fail to match
H(one=10, two=N/A) Testing "back" functionality


-

Expected

-
F[enter]::F[action]::A[enter]::A[action]::A[exit]::B[enter]::B[action]::C[action]::C[exit]::RESCUE::RESCUE::E[enter](parse)::E[action](parse id=1)::E[enter](parse)::E[action](parse id=2)::E[action](check id=3)::E[exit](check)::F[enter]::F[action]::G[enter 1]::G[enter 2]::G[enter 3]::G[enter 4]::H(one=N/A, two=N/A)::H(one=10, two=N/A)::H(one=10, two=20)::H(one=10, two=N/A)
+

Expected

+
F[enter]::F[action]::A[enter]::A[action]::A[exit]::B[enter]::B[action]::C[action]::C[exit]::RESCUE::RESCUE::E[enter](parse id=1)::E[action](parse id=1)::E[enter](parse id=2)::E[action](parse id=2)::E[action](check id=3)::E[exit](check id=3)::F[enter]::F[action]::G[enter 1]::G[enter 2]::G[enter 3]::G[enter 4]::H(one=N/A, two=N/A)::H(one=10, two=N/A)::H(one=10, two=20)::I(debug=true)::I(debug=false)::I(debug=true, id=10)::RESCUE::H(one=10, two=N/A)

Actual

Grade

From 6482a77b8b1483a2f88ea0c211cccc1f851d0179 Mon Sep 17 00:00:00 2001 From: pkarl Date: Tue, 12 Feb 2013 08:53:25 -0500 Subject: [PATCH 7/9] made pathjs AMD/require compatible, updated min --- path.js | 360 +++++++++++++++++++++++++++------------------------- path.min.js | 2 +- 2 files changed, 185 insertions(+), 177 deletions(-) diff --git a/path.js b/path.js index 1e61be8..a495d59 100644 --- a/path.js +++ b/path.js @@ -1,211 +1,219 @@ -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); - } +!function (ctx) { + + var Path = { + 'version': "0.8.4", + 'map': function (path) { + if (Path.routes.defined.hasOwnProperty(path)) { + return Path.routes.defined[path]; } else { - if(Path.history.fallback){ - window.location.hash = "#" + path; - } + return new Path.core.route(path); } }, - 'popState': function(event){ - 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); + 'root': function (path) { + Path.routes.root = path; }, - 'listen': function(fallback){ - Path.history.supported = !!(window.history && window.history.pushState); - Path.history.fallback = fallback; + '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){ + 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; + 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(); } - 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(); + }, + '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(); - // if a ? is present... - if (path.search(/\?[a-z0-9\-_=&]{1,}/i) > 0) { - var url_params = path.match(/\?[a-z0-9\-_=&]{1,}/i), - param; + // if a ? is present... + if (path.search(/\?[a-z0-9\-_=&]{1,}/i) > 0) { + var url_params = path.match(/\?[a-z0-9\-_=&]{1,}/i), + param; - // remove the ?, split params on & if applicable - param = url_params[0].substring(1).split('&'); + // remove the ?, split params on & if applicable + param = url_params[0].substring(1).split('&'); - // add params to route params array, allowing fully qualified params (like :id in URL match) - // to overwrite query string params - for(var u in param) { - params[ param[u].split('=')[0] || param[u] ] = param[u].split('=')[1] || true; - } + // add params to route params array, allowing fully qualified params (like :id in URL match) + // to overwrite query string params + for(var u in param) { + params[ param[u].split('=')[0] || param[u] ] = param[u].split('=')[1] || true; + } - // remove url query params from path & re-assign - path = path.substring(0, path.search(/\?[a-z0-9\-_=&]+/gi)); - } + // remove url query params from path & re-assign + path = path.substring(0, path.search(/\?[a-z0-9\-_=&]+/gi)); + } - 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]); + 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) { - route.params = params; + if (slice === compare) { + if (parameterize) { + route.params = params; + } + return route; } - 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); + 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 (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(); + 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); } + }, + 'listen': function () { + var fn = function(){ Path.dispatch(location.hash); } - if (location.hash === "") { - if (Path.routes.root !== null) { - location.hash = Path.routes.root; + 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); - } + // 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]); + 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': {} } - return options; - }, - 'run': function () { - var halt_execution = false, i, result, previous; + }; + 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 (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(); + } } - if (!halt_execution) { - Path.routes.defined[this.path].action(); - } - } -}; \ No newline at end of file + }; + + typeof module !== 'undefined' && module.exports ? + (module.exports.pathjs = Path) : + (ctx.pathjs = Path); + +}(this); \ No newline at end of file diff --git a/path.min.js b/path.min.js index 2e1a055..10466e7 100644 --- a/path.min.js +++ b/path.min.js @@ -1 +1 @@ -var Path={version:"0.8.4",map:function(e){if(Path.routes.defined.hasOwnProperty(e)){return Path.routes.defined[e]}else{return new Path.core.route(e)}},root:function(e){Path.routes.root=e},rescue:function(e){Path.routes.rescue=e},history:{initial:{},pushState:function(e,t,n){if(Path.history.supported){if(Path.dispatch(n)){history.pushState(e,t,n)}}else{if(Path.history.fallback){window.location.hash="#"+n}}},popState:function(e){var t=!Path.history.initial.popped&&location.href==Path.history.initial.URL;Path.history.initial.popped=true;if(t)return;Path.dispatch(document.location.pathname)},listen:function(e){Path.history.supported=!!(window.history&&window.history.pushState);Path.history.fallback=e;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(e,t){var n={},r=null,i,s,o,u,a;for(r in Path.routes.defined){if(r!==null&&r!==undefined){r=Path.routes.defined[r];i=r.partition();if(e.search(/\?[a-z0-9\-_=&]{1,}/i)>0){var f=e.match(/\?[a-z0-9\-_=&]{1,}/i),l;l=f[0].substring(1).split("&");for(var c in l){n[l[c].split("=")[0]||l[c]]=l[c].split("=")[1]||true}e=e.substring(0,e.search(/\?[a-z0-9\-_=&]+/gi))}for(u=0;u0){for(o=0;o=8)){window.onhashchange=e}else{setInterval(e,50)}if(location.hash!==""){Path.dispatch(location.hash)}},core:{route:function(e){this.path=e;this.action=null;this.do_enter=[];this.do_exit=null;this.params={};Path.routes.defined[e]=this}},routes:{current:null,root:null,rescue:null,previous:null,defined:{}}};Path.core.route.prototype={to:function(e){this.action=e;return this},enter:function(e){if(e instanceof Array){this.do_enter=this.do_enter.concat(e)}else{this.do_enter.push(e)}return this},exit:function(e){this.do_exit=e;return this},partition:function(){var e=[],t=[],n=/\(([^}]+?)\)/g,r,i;while(r=n.exec(this.path)){e.push(r[1])}t.push(this.path.split("(")[0]);for(i=0;i0){for(t=0;t0){var url_params=path.match(/\?[a-z0-9\-_=&]{1,}/i),param;param=url_params[0].substring(1).split('&');for(var u in param){params[param[u].split('=')[0]||param[u]]=param[u].split('=')[1]||true}path=path.substring(0,path.search(/\?[a-z0-9\-_=&]+/gi))}for(j=0;j0){for(i=0;i=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;i0){for(i=0;i Date: Wed, 20 Feb 2013 15:30:55 -0500 Subject: [PATCH 8/9] changed fn overwrite to use addeventlistener onhashchange --- path.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/path.js b/path.js index a495d59..dc4b652 100644 --- a/path.js +++ b/path.js @@ -137,7 +137,7 @@ // 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; + window.addEventListener("hashchange", fn, false); } else { setInterval(fn, 50); } From 502b000c5d0df83bad27f9a0c40dcf38f4a237b6 Mon Sep 17 00:00:00 2001 From: pkarl Date: Wed, 20 Feb 2013 15:32:10 -0500 Subject: [PATCH 9/9] updated minified file --- path.min.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/path.min.js b/path.min.js index 10466e7..46dd099 100644 --- a/path.min.js +++ b/path.min.js @@ -1 +1 @@ -!function(ctx){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':{},'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){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();if(path.search(/\?[a-z0-9\-_=&]{1,}/i)>0){var url_params=path.match(/\?[a-z0-9\-_=&]{1,}/i),param;param=url_params[0].substring(1).split('&');for(var u in param){params[param[u].split('=')[0]||param[u]]=param[u].split('=')[1]||true}path=path.substring(0,path.search(/\?[a-z0-9\-_=&]+/gi))}for(j=0;j0){for(i=0;i=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;i0){for(i=0;i0){var l=e.match(/\?[a-z0-9\-_=&]{1,}/i),c;c=l[0].substring(1).split("&");for(var h in c){r[c[h].split("=")[0]||c[h]]=c[h].split("=")[1]||true}e=e.substring(0,e.search(/\?[a-z0-9\-_=&]+/gi))}for(a=0;a0){for(u=0;u=8)){window.addEventListener("hashchange",e,false)}else{setInterval(e,50)}if(location.hash!==""){t.dispatch(location.hash)}},core:{route:function(e){this.path=e;this.action=null;this.do_enter=[];this.do_exit=null;this.params={};t.routes.defined[e]=this}},routes:{current:null,root:null,rescue:null,previous:null,defined:{}}};t.core.route.prototype={to:function(e){this.action=e;return this},enter:function(e){if(e instanceof Array){this.do_enter=this.do_enter.concat(e)}else{this.do_enter.push(e)}return this},exit:function(e){this.do_exit=e;return this},partition:function(){var e=[],t=[],n=/\(([^}]+?)\)/g,r,i;while(r=n.exec(this.path)){e.push(r[1])}t.push(this.path.split("(")[0]);for(i=0;i0){for(n=0;n