Update the news a bit, which got pretty much out of date, missing some releases
[marble] / www / scripts / History.Routing.js
1 /**\r
2  * History.Routing\r
3  *\r
4  * @version             2.0\r
5  *\r
6  * @license             MIT License\r
7  * @author              Harald Kirschner <mail [at] digitarald.de>\r
8  * @copyright   2008 Author\r
9  */\r
10 \r
11 History.implement(new Options());\r
12 \r
13 History.implement({\r
14 \r
15         options: {\r
16                 separator: ';'\r
17         },\r
18 \r
19         routes: [],\r
20 \r
21         register: function(route) {\r
22                 if (this.routes.push(route) == 1) this.addEvent('changed', this.match);\r
23         },\r
24 \r
25         unregister: function(route) {\r
26                 this.routes.remove(route);\r
27         },\r
28 \r
29         match: function(state, previous, manual) {\r
30                 if (!manual) this.routes.each(Function.methodize('match', this.state));\r
31         },\r
32 \r
33         generate: function() {\r
34                 return this.routes.map(Function.methodize('generate')).clean().join(this.options.separator);\r
35         },\r
36 \r
37         update: function() {\r
38                 return this.setState(this.generate());\r
39         }\r
40 \r
41 });\r
42 \r
43 History.Route = new Class({\r
44 \r
45         Implements: [Events, Options],\r
46 \r
47         /**\r
48          * pattern:                             Regular expression that matches the string updated from onGenerate\r
49          * defaults:                    Default values array, initially empty.\r
50          * flags:                               When regexp is a String, this is the second argument for new RegExp.\r
51          * skipDefaults:                default true; generate is not called when current values are similar to the default values.\r
52          * generate:                    Should return the string for the state string, values are first argument\r
53          * onMatch:                             Will be called when the regexp matches, with the new values as argument.\r
54          */\r
55         options: {\r
56                 skipDefaults: true,\r
57                 defaults: [],\r
58                 pattern: null,\r
59                 flags: '',\r
60                 generate: function(values) {\r
61                         return values[0];\r
62                 },\r
63                 onMatch: $empty\r
64         },\r
65 \r
66         initialize: function(options){\r
67                 this.setOptions(options);\r
68                 this.pattern = this.options.pattern || '(.*)';\r
69                 if ($type(this.pattern) == 'string') this.pattern = new RegExp(this.pattern, this.options.flags);\r
70                 this.values = this.defaults = this.options.defaults.slice();\r
71                 History.register(this);\r
72                 return this;\r
73         },\r
74 \r
75         setValues: function(values) {\r
76                 if (this.values.toString() == values.toString()) return this;\r
77                 this.values = values;\r
78                 History.update();\r
79                 return this;\r
80         },\r
81 \r
82         setValue: function(index, value) {\r
83                 if (this.values[index] == value) return this;\r
84                 this.values[index] = value;\r
85                 History.update();\r
86                 return this;\r
87         },\r
88 \r
89         build: function(values) {\r
90                 var tmp = this.values.slice();\r
91                 this.values = values;\r
92                 var state = History.generate();\r
93                 this.values = tmp;\r
94                 return state;\r
95         },\r
96 \r
97         destroy: function() {\r
98                 History.unregister(this);\r
99         },\r
100 \r
101         generate: function() {\r
102                 if (this.options.skipDefaultMatch && (String(this.values) == String(this.defaults))) return null;\r
103                 return this.options.generate.call(this, this.values);\r
104         },\r
105 \r
106         match: function(state) {\r
107                 var bits = state.match(this.pattern);\r
108                 var defaults = this.defaults;\r
109                 if (bits) {\r
110                         bits.splice(0, 1);\r
111                         for (var i = 0, j = bits.length; i < j; i++) bits[i] = $pick(bits[i], defaults[i] || null);\r
112                         if (String(bits) != String(defaults)) this.values = bits;\r
113                 } else {\r
114                         this.values = this.defaults.slice();\r
115                 }\r
116                 this.fireEvent('onMatch', [this.values, this.defaults]);\r
117         }\r
118 \r
119 });\r
120 \r
121 Function.methodize = function(name) {\r
122         var args = Array.slice(arguments, 1);\r
123         return function(obj) {\r
124                 return obj[name].apply(obj, args);\r
125         };\r
126 };\r