Index: trunk/phase3/resources/mediawiki/mediawiki.js |
— | — | @@ -55,8 +55,11 @@ |
56 | 56 | * An object which allows single and multiple get/set/exists functionality on a list of key / value pairs |
57 | 57 | * |
58 | 58 | * @param {boolean} global whether to get/set/exists values on the window object or a private object |
| 59 | + * @param {function} parser function to perform extra processing before while getting a value which accepts |
| 60 | + * value and options parameters where value is a string to be parsed and options is an object of options for the |
| 61 | + * parser |
59 | 62 | */ |
60 | | - 'configuration': function( global ) { |
| 63 | + 'configuration': function( global, parser ) { |
61 | 64 | |
62 | 65 | /* Private Members */ |
63 | 66 | |
— | — | @@ -66,52 +69,78 @@ |
67 | 70 | /* Public Methods */ |
68 | 71 | |
69 | 72 | /** |
70 | | - * Gets one or multiple configuration values using a key and an optional fallback or an array of keys |
| 73 | + * Gets one or more values |
| 74 | + * |
| 75 | + * If called with no arguments, all values will be returned. If a parser is in use, no parsing will take |
| 76 | + * place when calling with no arguments or calling with an array of names. |
| 77 | + * |
| 78 | + * @param {mixed} selection string name of value to get, array of string names of values to get, or object |
| 79 | + * of name/option pairs |
| 80 | + * @param {object} options optional set of options which are also passed to a parser if in use; only used |
| 81 | + * when selection is a string |
| 82 | + * @format options |
| 83 | + * { |
| 84 | + * // Value to use if key does not exist |
| 85 | + * 'fallback': '' |
| 86 | + * } |
71 | 87 | */ |
72 | | - this.get = function( keys, fallback ) { |
73 | | - if ( typeof keys === 'object' ) { |
74 | | - var result = {}; |
75 | | - for ( var k = 0; k < keys.length; k++ ) { |
76 | | - if ( typeof values[keys[k]] !== 'undefined' ) { |
77 | | - result[keys[k]] = values[keys[k]]; |
| 88 | + this.get = function( selection, options ) { |
| 89 | + if ( typeof selection === 'object' ) { |
| 90 | + var results = {}; |
| 91 | + for ( s in selection ) { |
| 92 | + if ( selection.hasOwnProperty( s ) ) { |
| 93 | + if ( typeof s === 'string' ) { |
| 94 | + return that.get( values[s], selection[s] ); |
| 95 | + } else { |
| 96 | + return that.get( selection[s] ); |
| 97 | + } |
78 | 98 | } |
79 | 99 | } |
80 | | - return result; |
81 | | - } else if ( typeof keys === 'string' ) { |
82 | | - if ( typeof values[keys] === 'undefined' ) { |
83 | | - return typeof fallback !== 'undefined' ? fallback : null; |
| 100 | + return results; |
| 101 | + } else if ( typeof selection === 'string' ) { |
| 102 | + if ( typeof values[selection] === 'undefined' ) { |
| 103 | + return 'fallback' in options !== 'undefined' ? options.fallback : null; |
84 | 104 | } else { |
85 | | - return values[keys]; |
| 105 | + if ( typeof parser === 'function' ) { |
| 106 | + return parser( values[selection], options ); |
| 107 | + } else { |
| 108 | + return values[selection]; |
| 109 | + } |
86 | 110 | } |
87 | 111 | } else { |
88 | 112 | return values; |
89 | 113 | } |
90 | 114 | }; |
| 115 | + |
91 | 116 | /** |
92 | 117 | * Sets one or multiple configuration values using a key and a value or an object of keys and values |
| 118 | + * |
| 119 | + * @param {mixed} key string of name by which value will be made accessible, or object of name/value pairs |
| 120 | + * @param {mixed} value optional value to set, only in use when key is a string |
93 | 121 | */ |
94 | | - this.set = function( keys, value ) { |
95 | | - if ( typeof keys === 'object' ) { |
96 | | - for ( var k in keys ) { |
97 | | - values[k] = keys[k]; |
| 122 | + this.set = function( selection, value ) { |
| 123 | + if ( typeof selection === 'object' ) { |
| 124 | + for ( var s in selection ) { |
| 125 | + values[s] = selection[s]; |
98 | 126 | } |
99 | | - } else if ( typeof keys === 'string' && typeof value !== 'undefined' ) { |
100 | | - values[keys] = value; |
| 127 | + } else if ( typeof selection === 'string' && typeof value !== 'undefined' ) { |
| 128 | + values[selection] = value; |
101 | 129 | } |
102 | 130 | }; |
| 131 | + |
103 | 132 | /** |
104 | 133 | * Checks if one or multiple configuration fields exist |
105 | 134 | */ |
106 | | - this.exists = function( keys ) { |
| 135 | + this.exists = function( selection ) { |
107 | 136 | if ( typeof keys === 'object' ) { |
108 | | - for ( var k = 0; k < keys.length; k++ ) { |
109 | | - if ( !( keys[k] in values ) ) { |
| 137 | + for ( var s = 0; s < selection.length; s++ ) { |
| 138 | + if ( !( selection[s] in values ) ) { |
110 | 139 | return false; |
111 | 140 | } |
112 | 141 | } |
113 | 142 | return true; |
114 | 143 | } else { |
115 | | - return keys in values; |
| 144 | + return selection in values; |
116 | 145 | } |
117 | 146 | }; |
118 | 147 | } |
— | — | @@ -123,12 +152,14 @@ |
124 | 153 | * Dummy function which in debug mode can be replaced with a function that does something clever |
125 | 154 | */ |
126 | 155 | this.log = function() { }; |
| 156 | + |
127 | 157 | /* |
128 | 158 | * List of configuration values |
129 | 159 | * |
130 | 160 | * In legacy mode the values this object wraps will be in the global space |
131 | 161 | */ |
132 | 162 | this.config = new this.prototypes.configuration( LEGACY_GLOBALS ); |
| 163 | + |
133 | 164 | /* |
134 | 165 | * Information about the current user |
135 | 166 | */ |
— | — | @@ -138,44 +169,31 @@ |
139 | 170 | |
140 | 171 | this.options = new that.prototypes.configuration(); |
141 | 172 | } )(); |
| 173 | + |
142 | 174 | /* |
143 | | - * Localization system |
| 175 | + * Basic parser, can be replaced with something more robust |
144 | 176 | */ |
145 | | - this.msg = new ( function() { |
146 | | - |
147 | | - /* Private Members */ |
148 | | - |
149 | | - var that = this; |
150 | | - // List of localized messages |
151 | | - var messages = {}; |
152 | | - |
153 | | - /* Public Methods */ |
154 | | - |
155 | | - this.set = function( keys, value ) { |
156 | | - if ( typeof keys === 'object' ) { |
157 | | - for ( var k in keys ) { |
158 | | - messages[k] = keys[k]; |
159 | | - } |
160 | | - } else if ( typeof keys === 'string' && typeof value !== 'undefined' ) { |
161 | | - messages[keys] = value; |
| 177 | + this.parser = function( key, args ) { |
| 178 | + if ( !( key in messages ) ) { |
| 179 | + return '<' + key + '>'; |
| 180 | + } |
| 181 | + var msg = messages[key]; |
| 182 | + if ( typeof args == 'object' || typeof args == 'array' ) { |
| 183 | + for ( var a = 0; a < args.length; a++ ) { |
| 184 | + msg = msg.replace( '\$' + ( parseInt( a ) + 1 ), args[a] ); |
162 | 185 | } |
163 | | - }; |
164 | | - this.get = function( key, args ) { |
165 | | - if ( !( key in messages ) ) { |
166 | | - return '<' + key + '>'; |
167 | | - } |
168 | | - var msg = messages[key]; |
169 | | - if ( typeof args == 'object' || typeof args == 'array' ) { |
170 | | - for ( var a = 0; a < args.length; a++ ) { |
171 | | - msg = msg.replace( '\$' + ( parseInt( a ) + 1 ), args[a] ); |
172 | | - } |
173 | | - } else if ( typeof args == 'string' || typeof args == 'number' ) { |
174 | | - msg = msg.replace( '$1', args ); |
175 | | - } |
176 | | - return msg; |
177 | | - }; |
178 | | - } )(); |
| 186 | + } else if ( typeof args == 'string' || typeof args == 'number' ) { |
| 187 | + msg = msg.replace( '$1', args ); |
| 188 | + } |
| 189 | + return msg; |
| 190 | + }; |
| 191 | + |
179 | 192 | /* |
| 193 | + * Localization system |
| 194 | + */ |
| 195 | + this.msg = new that.prototypes.configuration( false, this.parser ); |
| 196 | + |
| 197 | + /* |
180 | 198 | * Client-side module loader which integrates with the MediaWiki ResourceLoader |
181 | 199 | */ |
182 | 200 | this.loader = new ( function() { |
— | — | @@ -236,6 +254,7 @@ |
237 | 255 | pad1( date.getUTCSeconds() ) + |
238 | 256 | 'Z'; |
239 | 257 | } |
| 258 | + |
240 | 259 | /** |
241 | 260 | * Recursively resolves dependencies and detects circular references |
242 | 261 | */ |
— | — | @@ -263,6 +282,7 @@ |
264 | 283 | resolved[resolved.length] = module; |
265 | 284 | unresolved.splice( unresolved.indexOf( module ), 1 ); |
266 | 285 | } |
| 286 | + |
267 | 287 | /** |
268 | 288 | * Gets a list of modules names that a module dependencies in their proper dependency order |
269 | 289 | * |
— | — | @@ -292,6 +312,7 @@ |
293 | 313 | } |
294 | 314 | throw new Error( 'Invalid module argument: ' + module ); |
295 | 315 | }; |
| 316 | + |
296 | 317 | /** |
297 | 318 | * Narrows a list of module names down to those matching a specific state. Possible states are 'undefined', |
298 | 319 | * 'registered', 'loading', 'loaded', or 'ready' |
— | — | @@ -326,6 +347,7 @@ |
327 | 348 | } |
328 | 349 | return list; |
329 | 350 | } |
| 351 | + |
330 | 352 | /** |
331 | 353 | * Executes a loaded module, making it ready to use |
332 | 354 | * |
— | — | @@ -393,6 +415,7 @@ |
394 | 416 | } |
395 | 417 | } |
396 | 418 | } |
| 419 | + |
397 | 420 | /** |
398 | 421 | * Adds a dependencies to the queue with optional callbacks to be run when the dependencies are ready or fail |
399 | 422 | * |
— | — | @@ -518,6 +541,7 @@ |
519 | 542 | } |
520 | 543 | } |
521 | 544 | }; |
| 545 | + |
522 | 546 | /** |
523 | 547 | * Registers a module, letting the system know about it and it's dependencies. loader.js files contain calls |
524 | 548 | * to this function. |
— | — | @@ -555,6 +579,7 @@ |
556 | 580 | registry[module].dependencies = dependencies; |
557 | 581 | } |
558 | 582 | }; |
| 583 | + |
559 | 584 | /** |
560 | 585 | * Implements a module, giving the system a course of action to take upon loading. Results of a request for |
561 | 586 | * one or more modules contain calls to this function. |
— | — | @@ -594,6 +619,7 @@ |
595 | 620 | request( module ); |
596 | 621 | } |
597 | 622 | }; |
| 623 | + |
598 | 624 | /** |
599 | 625 | * Executes a function as soon as one or more required modules are ready |
600 | 626 | * |
— | — | @@ -630,6 +656,7 @@ |
631 | 657 | request( dependencies, ready, error ); |
632 | 658 | } |
633 | 659 | }; |
| 660 | + |
634 | 661 | /** |
635 | 662 | * Loads one or more modules for future use |
636 | 663 | */ |
— | — | @@ -658,6 +685,7 @@ |
659 | 686 | return true; |
660 | 687 | } |
661 | 688 | }; |
| 689 | + |
662 | 690 | /** |
663 | 691 | * Flushes the request queue and begin executing load requests on demand |
664 | 692 | */ |
— | — | @@ -665,6 +693,7 @@ |
666 | 694 | suspended = false; |
667 | 695 | that.work(); |
668 | 696 | }; |
| 697 | + |
669 | 698 | /** |
670 | 699 | * Changes the state of a module |
671 | 700 | * |