Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/LocalSettings.php |
— | — | @@ -2,7 +2,11 @@ |
3 | 3 | /** |
4 | 4 | * This file store all of mwEmbed local configuration ( in a default svn check out this file is empty ) |
5 | 5 | * |
6 | | - * See includes/DefaultSettings.php for a configuration options |
| 6 | + * For core configuration see: includes/DefaultSettings.php f |
| 7 | + * |
| 8 | + * For per module configuration see modules/{moduleName}/{moduleName}.config.php |
| 9 | + * Module configuration options can be set via: |
| 10 | + * $wgMwEmbedModuleConfig[ {ModuleName} ][ {configuration name} ] = value; |
7 | 11 | */ |
8 | 12 | |
9 | 13 | |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/tests/README |
— | — | @@ -1,2 +1,4 @@ |
2 | 2 | This folder contains stand alone tests of js2/mwEmbed components. |
3 | | -The tests folder does not need to be included or exposed in a production environment. |
\ No newline at end of file |
| 3 | +The tests folder does not need to be included or exposed in a production environment. |
| 4 | + |
| 5 | +Note these tests have not yet been ported to RL_1_17 |
\ No newline at end of file |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedWebStartSetup.php |
— | — | @@ -99,6 +99,7 @@ |
100 | 100 | MwEmbedResourceManager::register( $modulePath ); |
101 | 101 | } |
102 | 102 | } |
| 103 | + |
103 | 104 | # Add the resource loader hook: |
104 | 105 | $wgHooks['ResourceLoaderRegisterModules'][] = 'MwEmbedResourceManager::registerModules'; |
105 | 106 | |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/MwEmbedResourceManager.php |
— | — | @@ -35,8 +35,7 @@ |
36 | 36 | $wgExtensionMessagesFiles[ 'MwEmbed.' . $moduleName ] = $fullResourcePath . '/' . $moduleName . '.i18n.php'; |
37 | 37 | |
38 | 38 | // Get the mwEmbed module config |
39 | | - $moduleInfo = require_once( $fullResourcePath . '/' . $moduleName . '.php' ); |
40 | | - $resourceList = $moduleInfo['resources']; |
| 39 | + $resourceList = require_once( $fullResourcePath . '/' . $moduleName . '.php' ); |
41 | 40 | // Look for special 'messages' => 'moduleFile' key and load all modules file messages: |
42 | 41 | foreach( $resourceList as $name => $resources ){ |
43 | 42 | if( isset( $resources['messageFile'] ) && is_file( $fullResourcePath . '/' .$resources['messageFile'] ) ){ |
— | — | @@ -46,12 +45,7 @@ |
47 | 46 | $resourceList[ $name ][ 'messages' ][] = $msgKey; |
48 | 47 | } |
49 | 48 | } |
50 | | - }; |
51 | | - |
52 | | - // If the module has a loader.js add it to the resource list: |
53 | | - if( is_file( $fullResourcePath . '/loader.js' ) ){ |
54 | | - $resourceList[$moduleName. '.loader'] = array( 'loaderScripts' => 'loader.js' ); |
55 | | - } |
| 49 | + }; |
56 | 50 | // @@TODO add $moduleInfo['config'] |
57 | 51 | |
58 | 52 | // Add the resource list into the module set with its provided path |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/includes/DefaultSettings.php |
— | — | @@ -28,6 +28,13 @@ |
29 | 29 | } |
30 | 30 | } |
31 | 31 | |
| 32 | +// Also populate $wgMwEmbedModuleConfig[ {ModuleName} ] array so that LocalSettings.php does not |
| 33 | +// get unset array errors |
| 34 | +$wgMwEmbedModuleConfig = array(); |
| 35 | +foreach( $wgMwEmbedEnabledModules as $mwEmbedModuleName ){ |
| 36 | + $wgMwEmbedModuleConfig[ $mwEmbedModuleName ] = array(); |
| 37 | +} |
| 38 | + |
32 | 39 | /** |
33 | 40 | * Client-side resource modules. Extensions should add their module definitions |
34 | 41 | * here. The mwEmbed |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MediaWikiSupport/mwEmbed.js |
— | — | @@ -1,2800 +0,0 @@ |
2 | | -// Add support for html5 / mwEmbed elements to browsers that do not support the elements natively |
3 | | -// For discussion and comments, see: http://ejohn.org/blog/html5-shiv/ |
4 | | -'video audio source track'.replace(/\w+/g, function(n){ document.createElement(n); }); |
5 | | - |
6 | | -/** |
7 | | - * @license mwEmbed Dual licensed under the MIT or GPL Version 2 licenses. |
8 | | - * |
9 | | - * @copyright (C) 2010 Kaltura |
10 | | - * @author Michael Dale ( michael.dale at kaltura.com ) |
11 | | - * |
12 | | - * @url http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library |
13 | | - * |
14 | | - * Libraries used include code license in headers |
15 | | - */ |
16 | | - |
17 | | -/** |
18 | | - * Setup the "mw" global: |
19 | | - */ |
20 | | -if ( typeof window.mw == 'undefined' ) { |
21 | | - window.mw = { }; |
22 | | -} |
23 | | -/** |
24 | | - * Set the mwEmbedVersion |
25 | | - */ |
26 | | -var MW_EMBED_VERSION = '1.1h'; |
27 | | - |
28 | | -// Globals to pre-set ready functions in dynamic loading of mwEmbed |
29 | | -if( typeof preMwEmbedReady == 'undefined'){ |
30 | | - var preMwEmbedReady = []; |
31 | | -} |
32 | | -// Globals to pre-set config values in dynamic loading of mwEmbed |
33 | | -if( typeof preMwEmbedConfig == 'undefined') { |
34 | | - var preMwEmbedConfig = []; |
35 | | -} |
36 | | - |
37 | | -/** |
38 | | - * The global mw object: |
39 | | - */ |
40 | | -( function( mw ) { |
41 | | - // The version of mwEmbed |
42 | | - mw.version = MW_EMBED_VERSION; |
43 | | - |
44 | | - // List valid skins here: |
45 | | - mw.validSkins = [ 'mvpcf', 'kskin' ]; |
46 | | - |
47 | | - // Storage variable for loaded style sheet keys |
48 | | - if( ! mw.style ){ |
49 | | - mw.style = { }; |
50 | | - } |
51 | | - |
52 | | - /** |
53 | | - * Configuration System: |
54 | | - */ |
55 | | - |
56 | | - // Local scope configuration var: |
57 | | - if( !mwConfig ){ |
58 | | - var mwConfig = { }; |
59 | | - } |
60 | | - |
61 | | - if( !mwNonDefaultConfigList ){ |
62 | | - var mwNonDefaultConfigList = []; |
63 | | - } |
64 | | - |
65 | | - // mw scope mwUserConfig var. Stores user configuration |
66 | | - var mwUserConfig = { }; |
67 | | - |
68 | | - /** |
69 | | - * Setter for configuration values |
70 | | - * |
71 | | - * @param [Mixed] |
72 | | - * name Name of configuration value {Object} Will iderate through |
73 | | - * each key and call setConfig {String} Will set configuration by |
74 | | - * string name to value |
75 | | - * @param {String} |
76 | | - * value Value of configuration name {Object} value Set of values |
77 | | - * to be merged |
78 | | - */ |
79 | | - mw.setConfig = function ( name, value ) { |
80 | | - if( typeof name == 'object' ) { |
81 | | - for( var i in name ) { |
82 | | - mw.setConfig( i, name[ i ] ); |
83 | | - } |
84 | | - return ; |
85 | | - } |
86 | | - mwConfig[ name ] = value; |
87 | | - mwNonDefaultConfigList.push( name ); |
88 | | - }; |
89 | | - |
90 | | - // Apply any pre-setup config: |
91 | | - mw.setConfig( preMwEmbedConfig ); |
92 | | - |
93 | | - /** |
94 | | - * Merge in a configuration value: |
95 | | - */ |
96 | | - mw.mergeConfig = function( name, value ){ |
97 | | - if( typeof name == 'object' ) { |
98 | | - $j.each( name, function( inx, val) { |
99 | | - mw.setConfig( inx, val ); |
100 | | - }); |
101 | | - return ; |
102 | | - } |
103 | | - // Check if we should "merge" the config |
104 | | - if( typeof value == 'object' && typeof mwConfig[ name ] == 'object' ) { |
105 | | - if ( value.constructor.toString().indexOf("Array") != -1 && |
106 | | - mwConfig[ name ].constructor.toString().indexOf("Array") != -1 ){ |
107 | | - // merge in the array |
108 | | - mwConfig[ name ] = $j.merge( mwConfig[ name ], value ); |
109 | | - } else { |
110 | | - for( var i in value ){ |
111 | | - mwConfig[ name ][ i ] = value[ i ]; |
112 | | - } |
113 | | - } |
114 | | - return ; |
115 | | - } |
116 | | - // else do a normal setConfig |
117 | | - mwConfig[ name ] = value; |
118 | | - mwNonDefaultConfigList.push( name ); |
119 | | - }; |
120 | | - |
121 | | - /** |
122 | | - * Set a default config value Will only update configuration if no value is |
123 | | - * present |
124 | | - * |
125 | | - * @param [Mixed] |
126 | | - * value Set configuration name to value {Object} Will idorate |
127 | | - * through each key and call setDefaultConfig {String} Will set |
128 | | - * configuration by string name to value |
129 | | - */ |
130 | | - mw.setDefaultConfig = function( name, value ) { |
131 | | - if( typeof name == 'object' ) { |
132 | | - for( var i in name ) { |
133 | | - mw.setDefaultConfig( i, name[ i ] ); |
134 | | - } |
135 | | - return ; |
136 | | - } |
137 | | - if( typeof mwConfig[ name ] == 'undefined' ) { |
138 | | - mwConfig[ name ] = value; |
139 | | - return ; |
140 | | - } |
141 | | - }; |
142 | | - |
143 | | - /** |
144 | | - * Getter for configuration values |
145 | | - * |
146 | | - * @param {String} |
147 | | - * name of configuration value to get |
148 | | - * @return {Mixed} value of configuration key returns "false" if key not |
149 | | - * found |
150 | | - */ |
151 | | - mw.getConfig = function ( name ) { |
152 | | - if( mwConfig[ name ] ) |
153 | | - return mwConfig[ name ]; |
154 | | - return false; |
155 | | - }; |
156 | | - /** |
157 | | - * Get all the non-default configuration ( useful for passing state to |
158 | | - * iframes in limited hash url length of a few K ) |
159 | | - */ |
160 | | - mw.getNonDefaultConfigObject = function(){ |
161 | | - var nonDefaultConfig = {}; |
162 | | - for( var i =0 ; i < mwNonDefaultConfigList.length; i ++){ |
163 | | - var configKey = mwNonDefaultConfigList[i]; |
164 | | - nonDefaultConfig[ configKey ] = mw.getConfig( configKey ); |
165 | | - } |
166 | | - return nonDefaultConfig; |
167 | | - } |
168 | | - |
169 | | - /** |
170 | | - * Loads the mwUserConfig from a cookie. |
171 | | - * |
172 | | - * Modules that want to use "User Config" should call this setup function in |
173 | | - * their moduleLoader code. |
174 | | - * |
175 | | - * For performance interfaces using "user config" should load '$j.cookie' & |
176 | | - * 'JSON' in their module loader |
177 | | - * |
178 | | - * By abstracting user preference we could eventually integrate a persistent |
179 | | - * per-account preference system on the server. |
180 | | - * |
181 | | - * @parma {Function} callback Function to be called once userPrefrences are |
182 | | - * loaded |
183 | | - */ |
184 | | - var setupUserConfigFlag = false; |
185 | | - mw.setupUserConfig = function( callback ) { |
186 | | - if( setupUserConfigFlag ) { |
187 | | - if( callback ) { |
188 | | - callback(); |
189 | | - } |
190 | | - return ; |
191 | | - } |
192 | | - // Do Setup user config: |
193 | | - mw.load( [ '$j.cookie', 'JSON' ], function() { |
194 | | - if( $j.cookie( 'mwUserConfig' ) ) { |
195 | | - mwUserConfig = JSON.parse( $j.cookie( 'mwUserConfig' ) ); |
196 | | - } |
197 | | - setupUserConfigFlag = true; |
198 | | - if( callback ) { |
199 | | - callback(); |
200 | | - } |
201 | | - }); |
202 | | - }; |
203 | | - |
204 | | - /** |
205 | | - * Save a user configuration var to a cookie & local global variable Loads |
206 | | - * the cookie plugin if not already loaded |
207 | | - * |
208 | | - * @param {String} |
209 | | - * name Name of user configuration value |
210 | | - * @param {String} |
211 | | - * value Value of configuration name |
212 | | - */ |
213 | | - mw.setUserConfig = function ( name, value, cookieOptions ) { |
214 | | - if( ! setupUserConfigFlag ) { |
215 | | - mw.log( "Error: userConfig not setup" ); |
216 | | - return false; |
217 | | - } |
218 | | - // Update local value |
219 | | - mwUserConfig[ name ] = value; |
220 | | - |
221 | | - // Update the cookie ( '$j.cookie' & 'JSON' should already be loaded ) |
222 | | - $j.cookie( 'mwUserConfig', JSON.stringify( mwUserConfig ) ); |
223 | | - }; |
224 | | - |
225 | | - /** |
226 | | - * Save a user configuration var to a cookie & local global variable |
227 | | - * |
228 | | - * @param {String} |
229 | | - * name Name of user configuration value |
230 | | - * @return value of the configuration name false if the configuration name |
231 | | - * could not be found |
232 | | - */ |
233 | | - mw.getUserConfig = function ( name ) { |
234 | | - if( mwUserConfig[ name ] ) |
235 | | - return mwUserConfig[ name ]; |
236 | | - return false; |
237 | | - }; |
238 | | - |
239 | | - /** |
240 | | - * Add a hook system for a target object / interface |
241 | | - * |
242 | | - * depricated you should instead use jQuery's bind and trigger |
243 | | - * |
244 | | - * @param {Object} |
245 | | - * targetObj Interface Object to add hook system to. |
246 | | - */ |
247 | | - mw.addHookSystem = function( targetObj ) { |
248 | | - |
249 | | - // Setup the target object hook holder: |
250 | | - targetObj[ 'hooks' ] = { }; |
251 | | - |
252 | | - /** |
253 | | - * Adds a hook to the target object |
254 | | - * |
255 | | - * Should be called by clients to setup named hooks |
256 | | - * |
257 | | - * @param {String} |
258 | | - * hookName Name of hook to be added |
259 | | - * @param {Function} |
260 | | - * hookFunction Function to be called at hook time |
261 | | - */ |
262 | | - targetObj.addHook = function( hookName, hookFunction ) { |
263 | | - if( ! this.hooks[ hookName ] ) { |
264 | | - this.hooks[ hookName ] = [ ]; |
265 | | - } |
266 | | - this.hooks[ hookName ].push( hookFunction ); |
267 | | - }; |
268 | | - |
269 | | - /** |
270 | | - * Runs all the hooks by a given name with reference to the host object |
271 | | - * |
272 | | - * Should be called by the host object at named execution points |
273 | | - * |
274 | | - * @param {String} |
275 | | - * hookName Name of hook to be called |
276 | | - * @return Value of hook result true interface should continue function |
277 | | - * execution false interface should stop or return from method |
278 | | - */ |
279 | | - targetObj.runHook = function( hookName, options ) { |
280 | | - if( this.hooks[ hookName ] ) { |
281 | | - for( var i =0; i < this.hooks[ hookName ].length; i ++ ) { |
282 | | - if( typeof( this.hooks[ hookName ][ i ] ) == 'function' ) { |
283 | | - this.hooks[ hookName ][ i ]( options ); |
284 | | - } |
285 | | - } |
286 | | - } |
287 | | - }; |
288 | | - }; |
289 | | - |
290 | | - // Add hooks system to the core "mw" object |
291 | | - mw.addHookSystem( mw ); |
292 | | - |
293 | | - // Stores callbacks for resource loader loading |
294 | | - var mwLoadDoneCB = { }; |
295 | | - |
296 | | - |
297 | | - /** |
298 | | - * Top level loader prototype: |
299 | | - */ |
300 | | - mw.loader = { |
301 | | - /** |
302 | | - * Javascript Module Loader functions |
303 | | - * |
304 | | - * @key Name of Module |
305 | | - * @value function code to load module |
306 | | - */ |
307 | | - moduleLoaders : [], |
308 | | - |
309 | | - /** |
310 | | - * Module resource list queue. |
311 | | - * |
312 | | - * @key Name of Module |
313 | | - * @value .resourceList list of resources to be loaded .functionQueue |
314 | | - * list of functions to be run once module is ready |
315 | | - */ |
316 | | - moduleLoadQueue: { }, |
317 | | - |
318 | | - /** |
319 | | - * Javascript Class Paths |
320 | | - * |
321 | | - * @key Name of resource |
322 | | - * @value Class file path |
323 | | - */ |
324 | | - resourcePaths : { }, |
325 | | - |
326 | | - /** |
327 | | - * Stores resources that have been requested ( to avoid re-requesting |
328 | | - * the same resources ) in concurrent requests ) |
329 | | - */ |
330 | | - requestedResourceQueue: { }, |
331 | | - |
332 | | - /** |
333 | | - * javascript Resource Paths |
334 | | - * |
335 | | - * @key Name of resource |
336 | | - * @value Name of depenent style sheet |
337 | | - */ |
338 | | - resourceStyleDependency: { }, |
339 | | - |
340 | | - /** |
341 | | - * Core load function: |
342 | | - * |
343 | | - * @param {Mixed} |
344 | | - * loadRequest: |
345 | | - * |
346 | | - * {String} Name of a module to be loaded Modules are added via |
347 | | - * addModuleLoader and can define custom code needed to check config and |
348 | | - * return a list of resources to be loaded |
349 | | - * |
350 | | - * {String} Name of a resource to loaded. Resources are added via |
351 | | - * addResourcePaths function Using defined resource names avoids loading |
352 | | - * the same resource twice by first checking if the named resource is |
353 | | - * defined in the global javascript scope variable |
354 | | - * |
355 | | - * {String} Absolute or relative to url path The same file won't be |
356 | | - * loaded twice |
357 | | - * |
358 | | - * {Array} can be an array of any combination of the above strings. Will |
359 | | - * be loaded in-order or in a single resource loader request if |
360 | | - * scriptLoader is available. |
361 | | - * |
362 | | - * {Array} {Array} Can be a set of Arrays for loading. Some browsers |
363 | | - * execute included scripts out of order. This lets you chain sets of |
364 | | - * request for those browsers. If using the server side resource loader |
365 | | - * order is preserved in output and a single request will be used. |
366 | | - * |
367 | | - * @param {Function} |
368 | | - * callback Function called once loading is complete |
369 | | - * |
370 | | - */ |
371 | | - load: function( loadRequest, instanceCallback ) { |
372 | | - // mw.log("mw.load:: " + loadRequest ); |
373 | | - var _this = this; |
374 | | - |
375 | | - // Throw out any loadRequests that are not strings |
376 | | - loadRequest = this.cleanLoadRequest( loadRequest ); |
377 | | - |
378 | | - // Ensure the callback is only called once per load instance |
379 | | - var callback = function(){ |
380 | | - // mw.log( 'instanceCallback::running callback: ' + |
381 | | - // instanceCallback ); |
382 | | - if( instanceCallback ){ |
383 | | - // We pass the loadRequest back to the callback for easy |
384 | | - // debugging of concurrency issues. |
385 | | - // ( normally its not used ) |
386 | | - instanceCallback( loadRequest ); |
387 | | - instanceCallback = null; |
388 | | - } |
389 | | - }; |
390 | | - |
391 | | - // Check for empty loadRequest ( directly return the callback ) |
392 | | - if( mw.isEmpty( loadRequest ) ) { |
393 | | - mw.log( 'Empty load request: ( ' + loadRequest + ' ) ' ); |
394 | | - callback( loadRequest ); |
395 | | - return ; |
396 | | - } |
397 | | - |
398 | | - |
399 | | - // Check if its a multi-part request: |
400 | | - if( typeof loadRequest == 'object' ) { |
401 | | - if( loadRequest.length > 1 ) { |
402 | | - this.loadMany ( loadRequest, callback ); |
403 | | - return ; |
404 | | - }else{ |
405 | | - // If an array of length 1 set as first element |
406 | | - loadRequest = loadRequest[0]; |
407 | | - } |
408 | | - } |
409 | | - |
410 | | - // Check for the module name loader function |
411 | | - if( this.moduleLoaders[ loadRequest ] ) { |
412 | | - var resourceSet = this.getModuleResourceSet( loadRequest ); |
413 | | - if( !resourceSet ){ |
414 | | - mw.log( "mw.load:: Error with module loader: " + loadRequest + ' ( no resource set defined )' ); |
415 | | - return ; |
416 | | - } |
417 | | - |
418 | | - // xxx should use refactor "ready" stuff into a "domReady" class |
419 | | - // So we would not have local scope globals like this: |
420 | | - // if ( mwReadyFlag ) { |
421 | | - // Load the module directly if load request is after |
422 | | - // mw.ready has run |
423 | | - this.load( resourceSet, callback ); |
424 | | - // } else { |
425 | | - // this.addToModuleLoaderQueue( |
426 | | - // loadRequest, |
427 | | - // resourceSet, |
428 | | - // callback |
429 | | - // ); |
430 | | - // } |
431 | | - return ; |
432 | | - } |
433 | | - |
434 | | - // Check for javascript resource |
435 | | - if( this.getResourcePath( loadRequest ) ) { |
436 | | - this.loadResource( loadRequest, callback ); |
437 | | - return ; |
438 | | - } |
439 | | - |
440 | | - // Try loading as a "file" or via ScriptLoader |
441 | | - if( loadRequest ) { |
442 | | - // Check if this resource was already requested |
443 | | - if( typeof this.requestedResourceQueue[ loadRequest ] == 'object' ){ |
444 | | - this.requestedResourceQueue[ loadRequest ].push( callback ); |
445 | | - return ; |
446 | | - } else { |
447 | | - this.requestedResourceQueue[ loadRequest ] = []; |
448 | | - } |
449 | | - |
450 | | - if( loadRequest.indexOf( '.js' ) == -1 && !mw.getResourceLoaderPath() ) { |
451 | | - mw.log( 'Error: are you sure ' + loadRequest + ' is a file ( is it missing a resource path? ) ' ); |
452 | | - } |
453 | | - mw.getScript( loadRequest, function(){ |
454 | | - // Check if we have requestedResources queue items: |
455 | | - while( _this.requestedResourceQueue[ loadRequest ].length ){ |
456 | | - _this.requestedResourceQueue[ loadRequest ].shift()( loadRequest ); |
457 | | - } |
458 | | - callback( loadRequest ); |
459 | | - // empty the load request queue: |
460 | | - _this.requestedResourceQueue[ loadRequest ] = []; |
461 | | - }); |
462 | | - return ; |
463 | | - } |
464 | | - |
465 | | - // Possible error? |
466 | | - mw.log( "Error could not handle load request: " + loadRequest ); |
467 | | - }, |
468 | | - |
469 | | - getModuleResourceSet: function( moduleName ){ |
470 | | - // Check if the module loader is a function ~run that function~ |
471 | | - if( typeof ( this.moduleLoaders[ moduleName ] ) == 'function' ) { |
472 | | - // Add the result of the module loader function |
473 | | - return this.moduleLoaders[ moduleName ](); |
474 | | - } else if( typeof ( this.moduleLoaders[ moduleName ] ) == 'object' ){ |
475 | | - // set resourceSet directly |
476 | | - return this.moduleLoaders[ moduleName ]; |
477 | | - } |
478 | | - return false; |
479 | | - }, |
480 | | - |
481 | | - /** |
482 | | - * Clean the loadRequest ( throw out any non-string items ) |
483 | | - */ |
484 | | - cleanLoadRequest: function( loadRequest ){ |
485 | | - var cleanRequest = []; |
486 | | - if( ! loadRequest ){ |
487 | | - return []; |
488 | | - } |
489 | | - if( typeof loadRequest == 'string' ) |
490 | | - return loadRequest; |
491 | | - for( var i =0;i < loadRequest.length; i++ ){ |
492 | | - if( typeof loadRequest[i] == 'object' ) { |
493 | | - cleanRequest[i] = this.cleanLoadRequest( loadRequest[i] ); |
494 | | - } else if( typeof loadRequest[i] == 'string' ){ |
495 | | - cleanRequest[i] = $j.trim( loadRequest[i] ); |
496 | | - } else{ |
497 | | - // bad request type skip |
498 | | - } |
499 | | - } |
500 | | - return cleanRequest; |
501 | | - }, |
502 | | - |
503 | | - /** |
504 | | - * Load a set of scripts. Will issue many load requests or package the |
505 | | - * request for the resource loader |
506 | | - * |
507 | | - * @param {Object} |
508 | | - * loadSet Set of scripts to be loaded |
509 | | - * @param {Function} |
510 | | - * callback Function to call once all scripts are loaded. |
511 | | - */ |
512 | | - loadMany: function( loadSet, callback ) { |
513 | | - var _this = this; |
514 | | - // Setup up the local "loadStates" |
515 | | - var loadStates = { }; |
516 | | - |
517 | | - // Check if we can load via the "resource loader" ( mwEmbed was |
518 | | - // included via scriptLoader ) |
519 | | - if( mw.getResourceLoaderPath() ) { |
520 | | - // Get the grouped loadStates variable |
521 | | - loadStates = this.getGroupLoadState( loadSet ); |
522 | | - if( mw.isEmpty( loadStates ) ) { |
523 | | - // mw.log( 'loadMany:all resources already loaded'); |
524 | | - callback(); |
525 | | - return ; |
526 | | - } |
527 | | - }else{ |
528 | | - // Check if its a dependency set ( nested objects ) |
529 | | - if( typeof loadSet [ 0 ] == 'object' ) { |
530 | | - _this.dependencyChainCallFlag[ loadSet ] = false; |
531 | | - // Load sets of resources ( to preserver order for some |
532 | | - // browsers ) |
533 | | - _this.loadDependencyChain( loadSet, callback ); |
534 | | - return ; |
535 | | - } |
536 | | - |
537 | | - // Set the initial load state for every item in the loadSet |
538 | | - for( var i = 0; i < loadSet.length ; i++ ) { |
539 | | - var loadName = loadSet[ i ]; |
540 | | - loadStates[ loadName ] = 0; |
541 | | - } |
542 | | - } |
543 | | - |
544 | | - // We are infact loading many: |
545 | | - // mw.log("mw.load: LoadMany:: " + loadSet ); |
546 | | - |
547 | | - // Issue the load request check check loadStates to see if we are |
548 | | - // "done" |
549 | | - for( var loadName in loadStates ) { |
550 | | - // mw.log("loadMany: load: " + loadName ); |
551 | | - this.load( loadName, function ( loadName ) { |
552 | | - loadStates[ loadName ] = 1; |
553 | | - |
554 | | - /* |
555 | | - * for( var i in loadStates ) { mw.log( loadName + ' |
556 | | - * finished of: ' + i + ' : ' + loadStates[i] ); } |
557 | | - */ |
558 | | - |
559 | | - // Check if all load request states are set 1 |
560 | | - var loadDone = true; |
561 | | - for( var j in loadStates ) { |
562 | | - if( loadStates[ j ] === 0 ) |
563 | | - loadDone = false; |
564 | | - } |
565 | | - // Run the parent scope callback for "loadMany" |
566 | | - if( loadDone ) { |
567 | | - callback( loadName ); |
568 | | - } |
569 | | - } ); |
570 | | - } |
571 | | - }, |
572 | | - |
573 | | - /** |
574 | | - * Get grouped load state for script loader |
575 | | - * |
576 | | - * Groups the scriptRequest where possible: Modules include "loader |
577 | | - * code" so they are separated into pre-condition code to be run for |
578 | | - * subsequent requests |
579 | | - * |
580 | | - * @param {Object} |
581 | | - * loadSet Loadset to return grouped |
582 | | - * @return {Object} grouped loadSet |
583 | | - */ |
584 | | - getGroupLoadState: function( loadSet ) { |
585 | | - var groupedLoadSet = []; |
586 | | - var loadStates = { }; |
587 | | - // Merge load set into new groupedLoadSet |
588 | | - if( typeof loadSet[0] == 'object' ) { |
589 | | - for( var i = 0; i < loadSet.length ; i++ ) { |
590 | | - for( var j = 0; j < loadSet[i].length ; j++ ) { |
591 | | - // Make sure we have not already included it: |
592 | | - groupedLoadSet.push( loadSet[i][j] ); |
593 | | - } |
594 | | - } |
595 | | - } else { |
596 | | - // Use the loadSet directly: |
597 | | - groupedLoadSet = loadSet; |
598 | | - } |
599 | | - |
600 | | - // Setup grouped loadStates Set: |
601 | | - var groupClassKey = ''; |
602 | | - var coma = ''; |
603 | | - var uniqueResourceName = {}; |
604 | | - for( var i=0; i < groupedLoadSet.length; i++ ) { |
605 | | - var loadName = groupedLoadSet[ i ]; |
606 | | - if( this.getResourcePath( loadName ) ) { |
607 | | - // Check if not already in request queue and not defined in |
608 | | - // global namespace |
609 | | - if( !mw.isset( loadName ) && ! uniqueResourceName[ loadName] ){ |
610 | | - groupClassKey += coma + loadName; |
611 | | - coma = ','; |
612 | | - |
613 | | - // Check for style sheet dependencies |
614 | | - if( this.resourceStyleDependency[ loadName ] ){ |
615 | | - groupClassKey += coma + this.resourceStyleDependency[ loadName ]; |
616 | | - } |
617 | | - } |
618 | | - } else if ( this.moduleLoaders[ loadName ] ) { |
619 | | - |
620 | | - // Module loaders break up grouped script requests ( add the |
621 | | - // current groupClassKey ) |
622 | | - if( groupClassKey != '' ) { |
623 | | - loadStates[ groupClassKey ] = 0; |
624 | | - groupClassKey = coma = ''; |
625 | | - } |
626 | | - if( ! uniqueResourceName[ loadName] ){ |
627 | | - // Add the module to the loadSate |
628 | | - loadStates[ loadName ] = 0; |
629 | | - } |
630 | | - } |
631 | | - uniqueResourceName[ loadName] = true; |
632 | | - } |
633 | | - |
634 | | - // Add groupClassKey if set: |
635 | | - if( groupClassKey != '' ) { |
636 | | - loadStates [ groupClassKey ] = 0; |
637 | | - } |
638 | | - |
639 | | - return loadStates; |
640 | | - }, |
641 | | - |
642 | | - // Array to register that a callback has been called |
643 | | - dependencyChainCallFlag: { }, |
644 | | - |
645 | | - /** |
646 | | - * Load a sets of scripts satisfy dependency order for browsers that |
647 | | - * execute dynamically included scripts out of order |
648 | | - * |
649 | | - * @param {Object} |
650 | | - * loadChain A set of javascript arrays to be loaded. Sets |
651 | | - * are requested in array order. |
652 | | - */ |
653 | | - loadDependencyChain: function( loadChain, callback ) { |
654 | | - var _this = this; |
655 | | - // Load with dependency checks |
656 | | - var callSet = loadChain.shift(); |
657 | | - this.load( callSet, function( cbname ) { |
658 | | - if ( loadChain.length != 0 ) { |
659 | | - _this.loadDependencyChain( loadChain, callback ); |
660 | | - } else { |
661 | | - // NOTE: IE gets called twice so we have check the |
662 | | - // dependencyChainCallFlag before calling the callback |
663 | | - if( _this.dependencyChainCallFlag[ callSet ] == callback ) { |
664 | | - mw.log("... already called this callback for " + callSet ); |
665 | | - return ; |
666 | | - } |
667 | | - _this.dependencyChainCallFlag[ callSet ] = callback; |
668 | | - callback( ); |
669 | | - } |
670 | | - } ); |
671 | | - }, |
672 | | - |
673 | | - /** |
674 | | - * Add to the module loader queue |
675 | | - */ |
676 | | - addToModuleLoaderQueue: function( moduleName, resourceSet, callback ) { |
677 | | - mw.log(" addToModuleLoaderQueue:: " + moduleName + ' resourceSet: ' + resourceSet ); |
678 | | - if( this.moduleLoadQueue[ moduleName ] ){ |
679 | | - // If the module is already in the queue just add its callback: |
680 | | - this.moduleLoadQueue[ moduleName ].functionQueue.push( callback ); |
681 | | - } else { |
682 | | - // create the moduleLoadQueue item |
683 | | - this.moduleLoadQueue[ moduleName ] = { |
684 | | - 'resourceSet' : resourceSet, |
685 | | - 'functionQueue' : [ callback ], |
686 | | - 'loaded' : false |
687 | | - }; |
688 | | - } |
689 | | - }, |
690 | | - |
691 | | - /** |
692 | | - * Loops over all modules in queue, builds request sets based on config |
693 | | - * request type |
694 | | - */ |
695 | | - runModuleLoadQueue: function(){ |
696 | | - var _this = this; |
697 | | - mw.log( "mw.runModuleLoadQueue:: " ); |
698 | | - var runModuleFunctionQueue = function(){ |
699 | | - // Run all the callbacks |
700 | | - for( var moduleName in _this.moduleLoadQueue ){ |
701 | | - while( _this.moduleLoadQueue[moduleName].functionQueue.length ) { |
702 | | - _this.moduleLoadQueue[moduleName].functionQueue.shift()(); |
703 | | - } |
704 | | - } |
705 | | - }; |
706 | | - |
707 | | - // Check for single request or javascript debug based loading: |
708 | | - if( !mw.getResourceLoaderPath() || mw.getConfig( 'loader.groupStrategy' ) == 'single' ){ |
709 | | - // if not using the resource load just do a normal array merge |
710 | | - // ( for browsers like IE that don't follow first append first |
711 | | - // execute rule ) |
712 | | - var fullResourceList = []; |
713 | | - for( var moduleName in this.moduleLoadQueue ) { |
714 | | - var resourceSet = this.moduleLoadQueue[ moduleName ].resourceSet; |
715 | | - // Lets try a global merge |
716 | | - fullResourceList = $j.merge( fullResourceList, resourceSet ); |
717 | | - } |
718 | | - mw.load( fullResourceList, function(){ |
719 | | - runModuleFunctionQueue(); |
720 | | - }); |
721 | | - return ; |
722 | | - } |
723 | | - |
724 | | - // Else do per module group loading |
725 | | - if( mw.getConfig( 'loader.groupStrategy' ) == 'module' ) { |
726 | | - var fullResourceList = []; |
727 | | - var sharedResourceList = []; |
728 | | - |
729 | | - for( var moduleName in this.moduleLoadQueue ) { |
730 | | - // Build a shared dependencies list and load that separately |
731 | | - // "first" |
732 | | - // ( in IE we have to wait until its "ready" since it does |
733 | | - // not follow dom order ) |
734 | | - var moduleResourceList = this.getFlatModuleResourceList( moduleName ); |
735 | | - // Build the sharedResourceList |
736 | | - for( var i=0; i < moduleResourceList.length; i++ ){ |
737 | | - var moduleResource = moduleResourceList[i]; |
738 | | - // Check if already in the full resource list if so add |
739 | | - // to shared. |
740 | | - if( fullResourceList[ moduleResource ] ){ |
741 | | - if( $j.inArray( moduleResource, sharedResourceList ) == -1 ){ |
742 | | - sharedResourceList.push( moduleResource ); |
743 | | - } |
744 | | - } |
745 | | - // Add to the fullResourceList |
746 | | - fullResourceList[ moduleResource ] = true; |
747 | | - } |
748 | | - } |
749 | | - |
750 | | - // Local module request set ( stores the actual request we will |
751 | | - // make after grouping shared resources |
752 | | - var moduleRequestSet = {}; |
753 | | - |
754 | | - // Only add non-shared to respective modules load requests |
755 | | - for( var moduleName in this.moduleLoadQueue ) { |
756 | | - moduleRequestSet[ moduleName ] = []; |
757 | | - var moduleResourceList = this.getFlatModuleResourceList( moduleName ); |
758 | | - for( var i =0; i < moduleResourceList.length; i++ ){ |
759 | | - var moduleResource = moduleResourceList[i]; |
760 | | - if( $j.inArray( moduleResource, sharedResourceList ) == -1 ){ |
761 | | - moduleRequestSet[ moduleName ].push( moduleResource ); |
762 | | - } |
763 | | - } |
764 | | - } |
765 | | - var sharedResourceLoadDone = false; |
766 | | - // Check if modules are done |
767 | | - var checkModulesDone = function(){ |
768 | | - if( !sharedResourceLoadDone ){ |
769 | | - return false; |
770 | | - } |
771 | | - for( var moduleName in _this.moduleLoadQueue ) { |
772 | | - if( ! _this.moduleLoadQueue[ moduleName ].loaded ){ |
773 | | - return false; |
774 | | - } |
775 | | - } |
776 | | - runModuleFunctionQueue(); |
777 | | - }; |
778 | | - // Local instance of load requests to retain resourceSet |
779 | | - // context: |
780 | | - var localLoadCallInstance = function( moduleName, resourceSet ){ |
781 | | - mw.load( resourceSet, function(){ |
782 | | - _this.moduleLoadQueue[ moduleName ].loaded = true; |
783 | | - checkModulesDone(); |
784 | | - }); |
785 | | - }; |
786 | | - |
787 | | - // Load the shared resources |
788 | | - mw.load( sharedResourceList, function(){ |
789 | | - // mw.log("Shared Resources loaded"); |
790 | | - // xxx check if we are in "IE" and dependencies need to be |
791 | | - // loaded "first" |
792 | | - sharedResourceLoadDone = true; |
793 | | - checkModulesDone(); |
794 | | - }); |
795 | | - // Load all module Request Set |
796 | | - for( var moduleName in moduleRequestSet ){ |
797 | | - localLoadCallInstance( moduleName, moduleRequestSet[ moduleName ] ); |
798 | | - } |
799 | | - } |
800 | | - // xxx Here we could also do some "intelligent" grouping |
801 | | - }, |
802 | | - |
803 | | - getFlatModuleResourceList: function( moduleName ){ |
804 | | - var moduleList = []; |
805 | | - for( var j in this.moduleLoadQueue[moduleName].resourceSet ){ |
806 | | - // Check if we have a multi-set array: |
807 | | - if( typeof this.moduleLoadQueue[moduleName].resourceSet[j] == 'object' ){ |
808 | | - moduleList = $j.merge( moduleList, this.moduleLoadQueue[moduleName].resourceSet[j] ); |
809 | | - } else { |
810 | | - moduleList = $j.merge( moduleList, [ this.moduleLoadQueue[moduleName].resourceSet[j] ] ); |
811 | | - } |
812 | | - } |
813 | | - return moduleList; |
814 | | - }, |
815 | | - |
816 | | - /** |
817 | | - * Loads javascript or css associated with a resourceName |
818 | | - * |
819 | | - * @param {String} |
820 | | - * resourceName Name of resource to load |
821 | | - * @param {Function} |
822 | | - * callback Function to run once resource is loaded |
823 | | - */ |
824 | | - loadResource: function( resourceName , callback) { |
825 | | - // mw.log("LoadResource:" + resourceName ); |
826 | | - var _this = this; |
827 | | - |
828 | | - // Check for css dependency on resource name |
829 | | - if( this.resourceStyleDependency[ resourceName ] ) { |
830 | | - if( ! mw.isset( this.resourceStyleDependency[ resourceName ] )){ |
831 | | - mw.log("loadResource:: dependent css resource: " + this.resourceStyleDependency[ resourceName ] ); |
832 | | - _this.loadResource( this.resourceStyleDependency[ resourceName ] , function() { |
833 | | - // Continue the original loadResource request. |
834 | | - _this.loadResource( resourceName, callback ); |
835 | | - }); |
836 | | - return ; |
837 | | - } |
838 | | - } |
839 | | - |
840 | | - // Make sure the resource is not already defined: |
841 | | - if ( mw.isset( resourceName ) ) { |
842 | | - // mw.log( 'Class ( ' + resourceName + ' ) already defined ' ); |
843 | | - callback( resourceName ); |
844 | | - return ; |
845 | | - } |
846 | | - |
847 | | - // Setup the Script Request var: |
848 | | - var scriptRequest = null; |
849 | | - |
850 | | - |
851 | | - // If the scriptloader is enabled use the resourceName as the |
852 | | - // scriptRequest: |
853 | | - if( mw.getResourceLoaderPath() ) { |
854 | | - scriptRequest = resourceName; |
855 | | - }else{ |
856 | | - // Get the resource url: |
857 | | - var baseClassPath = this.getResourcePath( resourceName ); |
858 | | - // Add the mwEmbed path if not a root path or a full url |
859 | | - if( baseClassPath.indexOf( '/' ) !== 0 && |
860 | | - baseClassPath.indexOf( '://' ) === -1 ) { |
861 | | - scriptRequest = mw.getMwEmbedPath() + baseClassPath; |
862 | | - }else{ |
863 | | - scriptRequest = baseClassPath; |
864 | | - } |
865 | | - if( ! scriptRequest ) { |
866 | | - mw.log( "Error Could not get url for resource " + resourceName ); |
867 | | - return false; |
868 | | - } |
869 | | - } |
870 | | - // Include resource defined check for older browsers |
871 | | - var resourceDone = false; |
872 | | - |
873 | | - // Set the loadDone callback per the provided resourceName |
874 | | - mw.setLoadDoneCB( resourceName, callback ); |
875 | | - // Issue the request to load the resource (include resource name in |
876 | | - // result callback: |
877 | | - mw.getScript( scriptRequest, function( scriptRequest ) { |
878 | | - // If its a "style sheet" manually set its resource to true |
879 | | - var ext = scriptRequest.substr( scriptRequest.split('?')[0].lastIndexOf( '.' ), 4 ).toLowerCase(); |
880 | | - if( ext == '.css' && resourceName.substr(0,8) == 'mw.style' ){ |
881 | | - mw.style[ resourceName.substr( 9 ) ] = true; |
882 | | - } |
883 | | - |
884 | | - // Send warning if resourceName is not defined |
885 | | - if(! mw.isset( resourceName ) |
886 | | - && mwLoadDoneCB[ resourceName ] != 'done' ) { |
887 | | - // mw.log( 'Possible Error: ' + resourceName +' not set in |
888 | | - // time, or not defined in:' + "\n" |
889 | | - // + _this.getResourcePath( resourceName ) ); |
890 | | - } |
891 | | - |
892 | | - // If ( debug mode ) and the script include is missing resource |
893 | | - // messages |
894 | | - // do a separate request to retrieve the msgs |
895 | | - if( mw.currentClassMissingMessages ) { |
896 | | - mw.log( " resourceName " + resourceName + " is missing messages" ); |
897 | | - // Reset the currentClassMissingMessages flag |
898 | | - mw.currentClassMissingMessages = false; |
899 | | - |
900 | | - // Load msgs for this resource: |
901 | | - mw.loadResourceMessages( resourceName, function() { |
902 | | - // Run the onDone callback |
903 | | - mw.loadDone( resourceName ); |
904 | | - } ); |
905 | | - } else { |
906 | | - // If not using the resource loader make sure the |
907 | | - // resourceName is available before firing the loadDone |
908 | | - if( !mw.getResourceLoaderPath() ) { |
909 | | - mw.waitForObject( resourceName, function( resourceName ) { |
910 | | - // Once object is ready run loadDone |
911 | | - mw.loadDone( resourceName ); |
912 | | - } ); |
913 | | - } else { |
914 | | - // loadDone should be appended to the bottom of the |
915 | | - // resource loader response |
916 | | - // mw.loadDone( resourceName ); |
917 | | - } |
918 | | - } |
919 | | - } ); |
920 | | - }, |
921 | | - |
922 | | - /** |
923 | | - * Adds a module to the mwLoader object |
924 | | - * |
925 | | - * @param {String} |
926 | | - * name Name of module |
927 | | - * @param {Function} |
928 | | - * moduleLoader Function that loads dependencies for a module |
929 | | - */ |
930 | | - addModuleLoader: function( name, moduleLoader ) { |
931 | | - this.moduleLoaders [ name ] = moduleLoader; |
932 | | - }, |
933 | | - |
934 | | - /** |
935 | | - * Adds resource file path key value pairs |
936 | | - * |
937 | | - * @param {Object} |
938 | | - * resourceSet JSON formated list of resource name file path |
939 | | - * pairs. |
940 | | - * |
941 | | - * resourceSet must be strict JSON to allow the php scriptLoader to |
942 | | - * parse the file paths. |
943 | | - */ |
944 | | - addResourcePaths: function( resourceSet ) { |
945 | | - var prefix = ( mw.getConfig( 'loaderContext' ) )? |
946 | | - mw.getConfig( 'loaderContext' ): ''; |
947 | | - |
948 | | - for( var i in resourceSet ) { |
949 | | - this.resourcePaths[ i ] = prefix + resourceSet[ i ]; |
950 | | - } |
951 | | - }, |
952 | | - |
953 | | - /* |
954 | | - * Adds a named style sheet dependency to a named resource |
955 | | - * |
956 | | - * @parma {Object} resourceSet JSON formated list of resource names and |
957 | | - * associated style sheet names |
958 | | - */ |
959 | | - addStyleResourceDependency: function( resourceSet ){ |
960 | | - for( var i in resourceSet ){ |
961 | | - this.resourceStyleDependency[ i ] = resourceSet[i]; |
962 | | - } |
963 | | - }, |
964 | | - |
965 | | - /** |
966 | | - * Get a resource path from a resourceName if no resource found return |
967 | | - * false |
968 | | - */ |
969 | | - getResourcePath: function( resourceName ) { |
970 | | - if( this.resourcePaths[ resourceName ] ) |
971 | | - return this.resourcePaths[ resourceName ]; |
972 | | - return false; |
973 | | - } |
974 | | - }; |
975 | | - |
976 | | - /** |
977 | | - * Load done callback for script loader |
978 | | - * |
979 | | - * @param {String} |
980 | | - * requestName Name of the load request |
981 | | - */ |
982 | | - mw.loadDone = function( requestName ) { |
983 | | - if( !mwLoadDoneCB[ requestName ] ) { |
984 | | - return true; |
985 | | - } |
986 | | - while( mwLoadDoneCB[ requestName ].length ) { |
987 | | - // check if mwLoadDoneCB is already "done" |
988 | | - // the function list is not an object |
989 | | - if( typeof mwLoadDoneCB[ requestName ] != 'object' ) |
990 | | - { |
991 | | - break; |
992 | | - } |
993 | | - var func = mwLoadDoneCB[ requestName ].pop(); |
994 | | - if( typeof func == 'function' ) { |
995 | | - // mw.log( "LoadDone: " + requestName + ' run callback::' + |
996 | | - // func); |
997 | | - func( requestName ); |
998 | | - }else{ |
999 | | - mw.log('mwLoadDoneCB: Error non callback function on stack'); |
1000 | | - } |
1001 | | - } |
1002 | | - // Set the load request name to done |
1003 | | - mwLoadDoneCB[ requestName ] = 'done'; |
1004 | | - }; |
1005 | | - |
1006 | | - /** |
1007 | | - * Set a load done callback |
1008 | | - * |
1009 | | - * @param {String} |
1010 | | - * requestName Name of resource or request set |
1011 | | - * @param {Function} |
1012 | | - * callback Function called once requestName is ready |
1013 | | - */ |
1014 | | - mw.setLoadDoneCB = function( requestName, callback ) { |
1015 | | - // If the requestName is already done loading just callback |
1016 | | - if( mwLoadDoneCB[ requestName ] == 'done' ) { |
1017 | | - callback( requestName ); |
1018 | | - } |
1019 | | - // Setup the function queue if unset |
1020 | | - if( typeof mwLoadDoneCB[ requestName ] != 'object' ) { |
1021 | | - mwLoadDoneCB[ requestName ] = []; |
1022 | | - } |
1023 | | - mwLoadDoneCB[ requestName ].push( callback ); |
1024 | | - }; |
1025 | | - |
1026 | | - /** |
1027 | | - * Shortcut entry points / convenience functions: Lets you write mw.load() |
1028 | | - * instead of mw.loader.load() only these entry points should be used. |
1029 | | - * |
1030 | | - * future closure optimizations could minify internal function names |
1031 | | - */ |
1032 | | - |
1033 | | - /** |
1034 | | - * Load Object entry point: Loads a requested set of javascript |
1035 | | - */ |
1036 | | - mw.load = function( loadRequest, callback ) { |
1037 | | - return mw.loader.load( loadRequest, callback ); |
1038 | | - }; |
1039 | | - |
1040 | | - /** |
1041 | | - * Add module entry point: Adds a module to the mwLoader object |
1042 | | - */ |
1043 | | - mw.addModuleLoader = function ( name, loaderFunction ) { |
1044 | | - return mw.loader.addModuleLoader( name, loaderFunction ); |
1045 | | - }; |
1046 | | - |
1047 | | - /** |
1048 | | - * Add Class File Paths entry point: |
1049 | | - */ |
1050 | | - mw.addResourcePaths = function ( resourceSet ) { |
1051 | | - return mw.loader.addResourcePaths( resourceSet ); |
1052 | | - }; |
1053 | | - |
1054 | | - mw.addStyleResourceDependency = function ( resourceSet ) { |
1055 | | - return mw.loader.addStyleResourceDependency( resourceSet ); |
1056 | | - }; |
1057 | | - |
1058 | | - /** |
1059 | | - * Get Class File Path entry point: |
1060 | | - */ |
1061 | | - mw.getResourcePath = function( resourceName ) { |
1062 | | - return mw.loader.getResourcePath( resourceName ); |
1063 | | - }; |
1064 | | - |
1065 | | - |
1066 | | - /** |
1067 | | - * Utility Functions |
1068 | | - */ |
1069 | | - |
1070 | | - /** |
1071 | | - * addLoaderDialog small helper for displaying a loading dialog |
1072 | | - * |
1073 | | - * @param {String} |
1074 | | - * dialogHtml text Html of the loader msg |
1075 | | - */ |
1076 | | - mw.addLoaderDialog = function( dialogHtml ) { |
1077 | | - if( typeof dialogHtml == 'undefined'){ |
1078 | | - dialogHtml =''; |
1079 | | - } |
1080 | | - var $dialog = mw.addDialog( { |
1081 | | - 'title' : dialogHtml, |
1082 | | - 'content' : dialogHtml + '<br>' + |
1083 | | - $j('<div />') |
1084 | | - .loadingSpinner() |
1085 | | - .html() |
1086 | | - }); |
1087 | | - return $dialog; |
1088 | | - }; |
1089 | | - |
1090 | | - /** |
1091 | | - * Close the loader dialog created with addLoaderDialog |
1092 | | - */ |
1093 | | - mw.closeLoaderDialog = function() { |
1094 | | - // Make sure the dialog resource is present |
1095 | | - if( !mw.isset( '$j.ui.dialog' ) ) { |
1096 | | - return false; |
1097 | | - } |
1098 | | - // Close with timeout since jquery ui binds with timeout: |
1099 | | - // ui dialog line 530 |
1100 | | - setTimeout( function(){ |
1101 | | - $j( '#mwTempLoaderDialog' ) |
1102 | | - .dialog( 'destroy' ); |
1103 | | - } , 10); |
1104 | | - }; |
1105 | | - |
1106 | | - /** |
1107 | | - * Add a (temporary) dialog window: |
1108 | | - * |
1109 | | - * @param {Object} |
1110 | | - * with following keys: title: {String} Title string for the |
1111 | | - * dialog content: {String} to be inserted in msg box buttons: |
1112 | | - * {Object} A button object for the dialog Can be a string for |
1113 | | - * the close button any jquery.ui.dialog option |
1114 | | - */ |
1115 | | - mw.addDialog = function ( options ) { |
1116 | | - // Remove any other dialog |
1117 | | - $j( '#mwTempLoaderDialog' ).remove(); |
1118 | | - |
1119 | | - if( !options){ |
1120 | | - options = {}; |
1121 | | - } |
1122 | | - |
1123 | | - // Extend the default options with provided options |
1124 | | - var options = $j.extend({ |
1125 | | - 'bgiframe': true, |
1126 | | - 'draggable': true, |
1127 | | - 'resizable': false, |
1128 | | - 'modal': true, |
1129 | | - 'position' : ['center', 'center'] |
1130 | | - }, options ); |
1131 | | - |
1132 | | - if( ! options.title || ! options.content ){ |
1133 | | - mw.log("Error: mwEmbed addDialog missing required options ( title, content ) "); |
1134 | | - return ; |
1135 | | - } |
1136 | | - |
1137 | | - // Append the dialog div on top: |
1138 | | - $j( 'body' ).append( |
1139 | | - $j('<div />') |
1140 | | - .attr( { |
1141 | | - 'id' : "mwTempLoaderDialog", |
1142 | | - 'title' : options.title |
1143 | | - }) |
1144 | | - .hide() |
1145 | | - .append( options.content ) |
1146 | | - ); |
1147 | | - |
1148 | | - // Build the uiRequest |
1149 | | - var uiRequest = [ '$j.ui.dialog' ]; |
1150 | | - if( options.draggable ){ |
1151 | | - uiRequest.push( '$j.ui.mouse' ); |
1152 | | - uiRequest.push( '$j.ui.draggable' ); |
1153 | | - } |
1154 | | - if( options.resizable ){ |
1155 | | - uiRequest.push( '$j.ui.resizable' ); |
1156 | | - } |
1157 | | - |
1158 | | - // Special button string |
1159 | | - if ( typeof options.buttons == 'string' ) { |
1160 | | - var buttonMsg = options.buttons; |
1161 | | - buttons = { }; |
1162 | | - options.buttons[ buttonMsg ] = function() { |
1163 | | - $j( this ).dialog( 'close' ); |
1164 | | - }; |
1165 | | - } |
1166 | | - |
1167 | | - // Load the dialog resources |
1168 | | - mw.load([ |
1169 | | - [ |
1170 | | - '$j.ui', |
1171 | | - '$j.widget', |
1172 | | - '$j.ui.mouse', |
1173 | | - '$j.ui.position' |
1174 | | - ], |
1175 | | - uiRequest |
1176 | | - ], function() { |
1177 | | - var $dialog = $j( '#mwTempLoaderDialog' ).show().dialog( options ); |
1178 | | - } ); |
1179 | | - return $j( '#mwTempLoaderDialog' ); |
1180 | | - }; |
1181 | | - |
1182 | | - mw.isIphone = function(){ |
1183 | | - return ( navigator.userAgent.indexOf('iPhone') != -1 && ! mw.isIpad() ); |
1184 | | - }; |
1185 | | - // Uses hack described at: |
1186 | | - // http://www.bdoran.co.uk/2010/07/19/detecting-the-iphone4-and-resolution-with-javascript-or-php/ |
1187 | | - mw.isIphone4 = function(){ |
1188 | | - return ( mw.isIphone() && ( window.devicePixelRatio && window.devicePixelRatio >= 2 ) ); |
1189 | | - }; |
1190 | | - mw.isIpod = function(){ |
1191 | | - return ( navigator.userAgent.indexOf('iPod') != -1 ); |
1192 | | - }; |
1193 | | - mw.isIpad = function(){ |
1194 | | - return ( navigator.userAgent.indexOf('iPad') != -1 ); |
1195 | | - }; |
1196 | | - // Android 2 has some restrictions vs other mobile platforms |
1197 | | - mw.isAndroid2 = function(){ |
1198 | | - return ( navigator.userAgent.indexOf( 'Android 2.') != -1 ); |
1199 | | - }; |
1200 | | - |
1201 | | - /** |
1202 | | - * Fallforward system by default prefers flash. |
1203 | | - * |
1204 | | - * This is separate from the EmbedPlayer library detection to provide |
1205 | | - * package loading control NOTE: should be phased out in favor of browser |
1206 | | - * feature detection where possible |
1207 | | - * |
1208 | | - */ |
1209 | | - mw.isHTML5FallForwardNative = function(){ |
1210 | | - if( mw.isMobileHTML5() ){ |
1211 | | - return true; |
1212 | | - } |
1213 | | - // Check for url flag to force html5: |
1214 | | - if( document.URL.indexOf('forceMobileHTML5') != -1 ){ |
1215 | | - return true; |
1216 | | - } |
1217 | | - // Fall forward native: |
1218 | | - // if the browser supports flash ( don't use html5 ) |
1219 | | - if( mw.supportsFlash() ){ |
1220 | | - return false; |
1221 | | - } |
1222 | | - // No flash return true if the browser supports html5 video tag with |
1223 | | - // basic support for canPlayType: |
1224 | | - if( mw.supportsHTML5() ){ |
1225 | | - return true; |
1226 | | - } |
1227 | | - |
1228 | | - return false; |
1229 | | - } |
1230 | | - |
1231 | | - mw.isMobileHTML5 = function(){ |
1232 | | - // Check for a mobile html5 user agent: |
1233 | | - if ( mw.isIphone() || |
1234 | | - mw.isIpod() || |
1235 | | - mw.isIpad() || |
1236 | | - mw.isAndroid2() |
1237 | | - ){ |
1238 | | - return true; |
1239 | | - } |
1240 | | - return false; |
1241 | | - } |
1242 | | - mw.supportsHTML5 = function(){ |
1243 | | - // Blackberry is evil in its response to canPlayType calls. |
1244 | | - if( navigator.userAgent.indexOf('BlackBerry') != -1 ){ |
1245 | | - return false ; |
1246 | | - } |
1247 | | - var dummyvid = document.createElement( "video" ); |
1248 | | - if( dummyvid.canPlayType ) { |
1249 | | - return true; |
1250 | | - } |
1251 | | - return false; |
1252 | | - } |
1253 | | - |
1254 | | - mw.supportsFlash = function(){ |
1255 | | - // Check if the client does not have flash and has the video tag |
1256 | | - if ( navigator.mimeTypes && navigator.mimeTypes.length > 0 ) { |
1257 | | - for ( var i = 0; i < navigator.mimeTypes.length; i++ ) { |
1258 | | - var type = navigator.mimeTypes[i].type; |
1259 | | - var semicolonPos = type.indexOf( ';' ); |
1260 | | - if ( semicolonPos > -1 ) { |
1261 | | - type = type.substr( 0, semicolonPos ); |
1262 | | - } |
1263 | | - if (type == 'application/x-shockwave-flash' ) { |
1264 | | - // flash is installed |
1265 | | - return true; |
1266 | | - } |
1267 | | - } |
1268 | | - } |
1269 | | - |
1270 | | - // for IE: |
1271 | | - var hasObj = true; |
1272 | | - if( typeof ActiveXObject != 'undefined' ){ |
1273 | | - try { |
1274 | | - var obj = new ActiveXObject( 'ShockwaveFlash.ShockwaveFlash' ); |
1275 | | - } catch ( e ) { |
1276 | | - hasObj = false; |
1277 | | - } |
1278 | | - if( hasObj ){ |
1279 | | - return true; |
1280 | | - } |
1281 | | - } |
1282 | | - return false; |
1283 | | - }; |
1284 | | - /** |
1285 | | - * Similar to php isset function checks if the variable exists. Does a safe |
1286 | | - * check of a descendant method or variable |
1287 | | - * |
1288 | | - * @param {String} |
1289 | | - * objectPath |
1290 | | - * @return {Boolean} true if objectPath exists false if objectPath is |
1291 | | - * undefined |
1292 | | - */ |
1293 | | - mw.isset = function( objectPath ) { |
1294 | | - if ( !objectPath || typeof objectPath != 'string') { |
1295 | | - return false; |
1296 | | - } |
1297 | | - var pathSet = objectPath.split( '.' ); |
1298 | | - var cur_path = ''; |
1299 | | - |
1300 | | - for ( var p = 0; p < pathSet.length; p++ ) { |
1301 | | - cur_path = ( cur_path == '' ) ? cur_path + pathSet[p] : cur_path + '.' + pathSet[p]; |
1302 | | - eval( 'var ptest = typeof ( ' + cur_path + ' ); ' ); |
1303 | | - if ( ptest == 'undefined' ) { |
1304 | | - return false; |
1305 | | - } |
1306 | | - } |
1307 | | - return true; |
1308 | | - }; |
1309 | | - |
1310 | | - /** |
1311 | | - * Wait for a object to be defined and the call the callback |
1312 | | - * |
1313 | | - * @param {Object} |
1314 | | - * objectName Name of object to be defined |
1315 | | - * @param {Function} |
1316 | | - * callback Function to call once object is defined |
1317 | | - * @param {Null} |
1318 | | - * callNumber Used internally to keep track of number of times |
1319 | | - * waitForObject has been called |
1320 | | - */ |
1321 | | - var waitTime = 1200; // About 30 seconds |
1322 | | - mw.waitForObject = function( objectName, callback, _callNumber) { |
1323 | | - // mw.log( 'waitForObject: ' + objectName + ' cn: ' + _callNumber); |
1324 | | - |
1325 | | - // Increment callNumber: |
1326 | | - if( !_callNumber ) { |
1327 | | - _callNumber = 1; |
1328 | | - } else { |
1329 | | - _callNumber++; |
1330 | | - } |
1331 | | - |
1332 | | - if( _callNumber > waitTime ) { |
1333 | | - mw.log( "Error: waiting for object: " + objectName + ' timeout ' ); |
1334 | | - callback( false ); |
1335 | | - return ; |
1336 | | - } |
1337 | | - |
1338 | | - // If the object is defined ( or we are done loading from a callback ) |
1339 | | - if ( mw.isset( objectName ) || mwLoadDoneCB[ objectName ] == 'done' ) { |
1340 | | - callback( objectName ); |
1341 | | - }else{ |
1342 | | - setTimeout( function( ) { |
1343 | | - mw.waitForObject( objectName, callback, _callNumber); |
1344 | | - }, 25); |
1345 | | - } |
1346 | | - }; |
1347 | | - |
1348 | | - /** |
1349 | | - * Check if an object is empty or if its an empty string. |
1350 | | - * |
1351 | | - * @param {Object} |
1352 | | - * object Object to be checked |
1353 | | - */ |
1354 | | - mw.isEmpty = function( object ) { |
1355 | | - if( typeof object == 'string' ) { |
1356 | | - if( object == '' ) return true; |
1357 | | - // Non empty string: |
1358 | | - return false; |
1359 | | - } |
1360 | | - |
1361 | | - // If an array check length: |
1362 | | - if( Object.prototype.toString.call( object ) === "[object Array]" |
1363 | | - && object.length == 0 ) { |
1364 | | - return true; |
1365 | | - } |
1366 | | - |
1367 | | - // Else check as an object: |
1368 | | - for( var i in object ) { return false; } |
1369 | | - |
1370 | | - // Else object is empty: |
1371 | | - return true; |
1372 | | - }; |
1373 | | - |
1374 | | - /** |
1375 | | - * Log a string msg to the console |
1376 | | - * |
1377 | | - * all mw.log statements will be removed on minification so lots of mw.log |
1378 | | - * calls will not impact performance in non debug mode |
1379 | | - * |
1380 | | - * @param {String} |
1381 | | - * string String to output to console |
1382 | | - */ |
1383 | | - mw.log = function( string ) { |
1384 | | - // Add any prepend debug strings if necessary |
1385 | | - if ( mw.getConfig( 'Mw.LogPrepend' ) ){ |
1386 | | - string = mw.getConfig( 'Mw.LogPrepend' ) + string; |
1387 | | - } |
1388 | | - // To debug stack size ( useful for iPad / safari that have a 100 call |
1389 | | - // stack limit |
1390 | | - // string = mw.getCallStack().length -1 + ' : ' + string; |
1391 | | - |
1392 | | - if ( window.console ) { |
1393 | | - window.console.log( string ); |
1394 | | - } else { |
1395 | | - /** |
1396 | | - * Old IE and non-Firebug debug: ( commented out for now ) |
1397 | | - */ |
1398 | | - |
1399 | | - /* |
1400 | | - * var log_elm = document.getElementById('mv_js_log'); if(!log_elm) { |
1401 | | - * document.getElementsByTagName("body")[0].innerHTML += '<div ' + |
1402 | | - * 'style="position:absolute;z-index:500;bottom:0px;left:0px;right:0px;height:200px;">' + '<textarea |
1403 | | - * id="mv_js_log" cols="120" rows="12"></textarea>' + '</div>'; } |
1404 | | - * var log_elm = document.getElementById('mv_js_log'); if(log_elm) { |
1405 | | - * log_elm.value+=string+"\n"; // scroll to bottom: |
1406 | | - * log_elm.scrollTop = log_elm.scrollHeight; } |
1407 | | - */ |
1408 | | - } |
1409 | | - }; |
1410 | | - mw.getCallStack = function(){ |
1411 | | - var stringifyArguments = function(args) { |
1412 | | - for (var i = 0; i < args.length; ++i) { |
1413 | | - var arg = args[i]; |
1414 | | - if (arg === undefined) { |
1415 | | - args[i] = 'undefined'; |
1416 | | - } else if (arg === null) { |
1417 | | - args[i] = 'null'; |
1418 | | - } else if (arg.constructor) { |
1419 | | - if (arg.constructor === Array) { |
1420 | | - if (arg.length < 3) { |
1421 | | - args[i] = '[' + stringifyArguments(arg) + ']'; |
1422 | | - } else { |
1423 | | - args[i] = '[' + stringifyArguments(Array.prototype.slice.call(arg, 0, 1)) + '...' + stringifyArguments(Array.prototype.slice.call(arg, -1)) + ']'; |
1424 | | - } |
1425 | | - } else if (arg.constructor === Object) { |
1426 | | - args[i] = '#object'; |
1427 | | - } else if (arg.constructor === Function) { |
1428 | | - args[i] = '#function'; |
1429 | | - } else if (arg.constructor === String) { |
1430 | | - args[i] = '"' + arg + '"'; |
1431 | | - } |
1432 | | - } |
1433 | | - } |
1434 | | - return args.join(','); |
1435 | | - }; |
1436 | | - var getStack = function(curr){ |
1437 | | - var ANON = '{anonymous}', fnRE = /function\s*([\w\-$]+)?\s*\(/i, |
1438 | | - stack = [], fn, args, maxStackSize = 100; |
1439 | | - |
1440 | | - while (curr && stack.length < maxStackSize) { |
1441 | | - fn = fnRE.test(curr.toString()) ? RegExp.$1 || ANON : ANON; |
1442 | | - args = Array.prototype.slice.call(curr['arguments']); |
1443 | | - stack[stack.length] = fn + '(' + stringifyArguments(args) + ')'; |
1444 | | - curr = curr.caller; |
1445 | | - } |
1446 | | - return stack; |
1447 | | - } |
1448 | | - // Add stack size ( iPad has 100 stack size limit ) |
1449 | | - var stack = getStack( arguments.callee ); |
1450 | | - return stack; |
1451 | | - } |
1452 | | - |
1453 | | - // Setup the local mwOnLoadFunctions array: |
1454 | | - var mwOnLoadFunctions = []; |
1455 | | - |
1456 | | - // mw Ready flag ( set once mwEmbed is ready ) |
1457 | | - var mwReadyFlag = false; |
1458 | | - |
1459 | | - /** |
1460 | | - * Enables load hooks to run once mwEmbeed is "ready" Will ensure jQuery is |
1461 | | - * available, is in the $j namespace and mw interfaces and configuration has |
1462 | | - * been loaded and applied |
1463 | | - * |
1464 | | - * This is different from jQuery(document).ready() ( jQuery ready is not |
1465 | | - * friendly with dynamic includes and not friendly with core interface |
1466 | | - * asynchronous build out. ) |
1467 | | - * |
1468 | | - * @param {Function} |
1469 | | - * callback Function to run once DOM and jQuery are ready |
1470 | | - */ |
1471 | | - mw.ready = function( callback ) { |
1472 | | - if( mwReadyFlag === false ) { |
1473 | | - // Add the callbcak to the onLoad function stack |
1474 | | - mwOnLoadFunctions.push ( callback ); |
1475 | | - } else { |
1476 | | - // If mwReadyFlag is already "true" issue the callback directly: |
1477 | | - callback(); |
1478 | | - } |
1479 | | - }; |
1480 | | - |
1481 | | - /** |
1482 | | - * Runs all the queued functions called by mwEmbedSetup |
1483 | | - */ |
1484 | | - mw.runReadyFunctions = function ( ) { |
1485 | | - mw.log('mw.runReadyFunctions: ' + mwOnLoadFunctions.length ); |
1486 | | - // Run any pre-setup ready functions |
1487 | | - while( preMwEmbedReady.length ){ |
1488 | | - preMwEmbedReady.shift()(); |
1489 | | - } |
1490 | | - // Run all the queued functions: |
1491 | | - while( mwOnLoadFunctions.length ) { |
1492 | | - mwOnLoadFunctions.shift()(); |
1493 | | - } |
1494 | | - // Sets mwReadyFlag to true so that future mw.ready run the |
1495 | | - // callback directly |
1496 | | - mwReadyFlag = true; |
1497 | | - |
1498 | | - // Once we have run all the queued functions |
1499 | | - setTimeout(function(){ |
1500 | | - mw.loader.runModuleLoadQueue(); |
1501 | | - },1); |
1502 | | - }; |
1503 | | - |
1504 | | - |
1505 | | - /** |
1506 | | - * Wrapper for jQuery getScript, Uses the scriptLoader if enabled |
1507 | | - * |
1508 | | - * |
1509 | | - * @param {String} |
1510 | | - * scriptRequest The requested path or resourceNames for the |
1511 | | - * scriptLoader |
1512 | | - * @param {Function} |
1513 | | - * callback Function to call once script is loaded |
1514 | | - */ |
1515 | | - mw.getScript = function( scriptRequest, callback ) { |
1516 | | - // mw.log( "mw.getScript::" + scriptRequest ); |
1517 | | - // Setup the local scope callback instace |
1518 | | - var myCallback = function(){ |
1519 | | - if( callback ) { |
1520 | | - callback( scriptRequest ); |
1521 | | - } |
1522 | | - }; |
1523 | | - // Set the base url based scriptLoader availability & type of |
1524 | | - // scriptRequest |
1525 | | - // ( presently script loader only handles "classes" not relative urls: |
1526 | | - var scriptLoaderPath = mw.getResourceLoaderPath(); |
1527 | | - |
1528 | | - // Check if its a resource name, ( ie does not start with "/" and does |
1529 | | - // not include :// |
1530 | | - var isResourceName = ( scriptRequest.indexOf('://') == -1 && scriptRequest.indexOf('/') !== 0 )? true : false; |
1531 | | - |
1532 | | - var ext = scriptRequest.substr( scriptRequest.lastIndexOf( '.' ), 4 ).toLowerCase(); |
1533 | | - var isCssFile = ( ext == '.css') ? true : false ; |
1534 | | - |
1535 | | - if( scriptLoaderPath && isResourceName ) { |
1536 | | - url = scriptLoaderPath + '?class=' + scriptRequest ; |
1537 | | - } else { |
1538 | | - // Add the mwEmbed path if a relative path request |
1539 | | - url = ( isResourceName ) ? mw.getMwEmbedPath() : ''; |
1540 | | - url+= scriptRequest; |
1541 | | - } |
1542 | | - |
1543 | | - // Add on the request parameters to the url: |
1544 | | - url += ( url.indexOf( '?' ) == -1 )? '?' : '&'; |
1545 | | - url += mw.getUrlParam(); |
1546 | | - |
1547 | | - // Only log sciprts ( Css is logged via "add css" ) |
1548 | | - if( !isCssFile ){ |
1549 | | - mw.log( 'mw.getScript: ' + url ); |
1550 | | - } |
1551 | | - |
1552 | | - // If jQuery is available and debug is off load the script via jQuery |
1553 | | - // ( will use XHR if on same domain ) |
1554 | | - if( mw.isset( 'window.jQuery' ) |
1555 | | - && mw.getConfig( 'debug' ) === false |
1556 | | - && typeof $j != 'undefined' |
1557 | | - && mw.parseUri( url ).protocal != 'file' |
1558 | | - && !isCssFile ) |
1559 | | - { |
1560 | | - $j.getScript( url, myCallback); |
1561 | | - return ; |
1562 | | - } |
1563 | | - |
1564 | | - /** |
1565 | | - * No jQuery OR In debug mode OR Is css file :: inject the script |
1566 | | - * instead of doing an XHR eval |
1567 | | - */ |
1568 | | - |
1569 | | - // load style sheet directly if requested loading css |
1570 | | - if( isCssFile ){ |
1571 | | - mw.getStyleSheet( url, myCallback); |
1572 | | - return ; |
1573 | | - } |
1574 | | - |
1575 | | - // Load and bind manually: ( copied from jQuery ajax function ) |
1576 | | - var head = document.getElementsByTagName("head")[ 0 ]; |
1577 | | - var script = document.createElement("script"); |
1578 | | - script.setAttribute( 'src', url ); |
1579 | | - |
1580 | | - // Attach handlers ( if using script loader it issues onDone callback as |
1581 | | - // well ) |
1582 | | - script.onload = script.onreadystatechange = function() { |
1583 | | - if (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") { |
1584 | | - myCallback(); |
1585 | | - } |
1586 | | - }; |
1587 | | - // mw.log(" append script: " + script.src ); |
1588 | | - // Append the script to the DOM: |
1589 | | - head.appendChild( script ); |
1590 | | - }; |
1591 | | - |
1592 | | - /** |
1593 | | - * Add a style sheet string to the document head |
1594 | | - * |
1595 | | - * @param {String} |
1596 | | - * cssResourceName Name of style sheet that has been defined |
1597 | | - * @param {String} |
1598 | | - * cssString Css Payload to be added to head of document |
1599 | | - */ |
1600 | | - mw.addStyleString = function( cssResourceName, cssString ) { |
1601 | | - if( mw.style[ cssResourceName ] ) { |
1602 | | - mw.log(" Style: ( " + cssResourceName + ' ) already set' ); |
1603 | | - return true; |
1604 | | - } |
1605 | | - // Set the style to true ( to not request it again ) |
1606 | | - mw.style[ cssResourceName ] = true; |
1607 | | - // Add the spinner directly ( without jQuery in case we have to |
1608 | | - // dynamically load jQuery ) |
1609 | | - mw.log( 'Adding style:' + cssResourceName + " to dom " ); |
1610 | | - var styleNode = document.createElement('style'); |
1611 | | - styleNode.type = "text/css"; |
1612 | | - // Use cssText or createTextNode depending on browser: |
1613 | | - if( ( window.attachEvent && !window.opera ) ) { |
1614 | | - styleNode.styleSheet.cssText = cssString; |
1615 | | - } else { |
1616 | | - var styleText = document.createTextNode( cssString ); |
1617 | | - styleNode.appendChild( styleText ); |
1618 | | - } |
1619 | | - var head = document.getElementsByTagName("head")[0]; |
1620 | | - head.appendChild( styleNode ); |
1621 | | - }; |
1622 | | - |
1623 | | - /** |
1624 | | - * Get a style sheet and append the style sheet to the DOM |
1625 | | - * |
1626 | | - * @param {Mixed} |
1627 | | - * {String} url Url of the style sheet to be loaded {Function} |
1628 | | - * callback Function called once sheet is ready |
1629 | | - */ |
1630 | | - mw.getStyleSheet = function( url , callback) { |
1631 | | - // Add URL params ( if not already included ) |
1632 | | - if ( url.indexOf( '?' ) == -1 ) { |
1633 | | - url += '?' + mw.getUrlParam(); |
1634 | | - } |
1635 | | - |
1636 | | - // Check if style sheet is already included: |
1637 | | - var foundSheet = false; |
1638 | | - $j( 'link' ).each( function() { |
1639 | | - var currentSheet = $j( this) .attr( 'href' ); |
1640 | | - var sheetParts = currentSheet.split('?'); |
1641 | | - var urlParts = url.split('?'); |
1642 | | - // if the base url's match check the parameters: |
1643 | | - if( sheetParts[0] == urlParts[0] && sheetParts[1]) { |
1644 | | - // Check if url params match ( sort to do string compare ) |
1645 | | - if( sheetParts[1].split( '&' ).sort().join('') == |
1646 | | - urlParts[1].split('&').sort().join('') ) { |
1647 | | - foundSheet = true; |
1648 | | - } |
1649 | | - } |
1650 | | - } ); |
1651 | | - if( foundSheet ) { |
1652 | | - mw.log( 'skiped sheet: ' + url); |
1653 | | - if( callback) { |
1654 | | - callback(); |
1655 | | - } |
1656 | | - return ; |
1657 | | - } |
1658 | | - |
1659 | | - mw.log( ' add css: ' + url ); |
1660 | | - $j( 'head' ).append( |
1661 | | - $j('<link />').attr( { |
1662 | | - 'rel' : 'stylesheet', |
1663 | | - 'type' : 'text/css', |
1664 | | - 'href' : url |
1665 | | - } ) |
1666 | | - ); |
1667 | | - // No easy way to check css "onLoad" attribute |
1668 | | - // In production sheets are loaded via resource loader and fire the |
1669 | | - // onDone function call. |
1670 | | - if( callback ) { |
1671 | | - callback(); |
1672 | | - } |
1673 | | - }; |
1674 | | - |
1675 | | - mw.getRelativeMwEmbedPath = function(){ |
1676 | | - return mw.getMwEmbedPath(true); |
1677 | | - }; |
1678 | | - /** |
1679 | | - * Get the path to the mwEmbed folder |
1680 | | - */ |
1681 | | - mw.getMwEmbedPath = function( relativePath ) { |
1682 | | - // Get mwEmbed src: |
1683 | | - var src = mw.getMwEmbedSrc(); |
1684 | | - var mwpath = null; |
1685 | | - |
1686 | | - // Check for direct include of the mwEmbed.js |
1687 | | - if ( src.indexOf( 'mwEmbed.js' ) !== -1 ) { |
1688 | | - alert( 'Direct Refrece to mwEmbed is no longer suported, please update to ResourceLoader.php?class=window.jQuery,mwEmbed& instead'); |
1689 | | - mwpath = src.substr( 0, src.indexOf( 'mwEmbed.js' ) ); |
1690 | | - } |
1691 | | - |
1692 | | - // Check for scriptLoader include of mwEmbed: |
1693 | | - if ( src.indexOf( 'mwResourceLoader.php' ) !== -1 ) { |
1694 | | - // Script loader is in the root of MediaWiki, Include the default |
1695 | | - // mwEmbed extension path: |
1696 | | - mwpath = src.substr( 0, src.indexOf( 'mwResourceLoader.php' ) ) + mw.getConfig( 'mediaWikiEmbedPath' ); |
1697 | | - } |
1698 | | - |
1699 | | - // resource loader has ResourceLoader name when local: |
1700 | | - if( src.indexOf( 'ResourceLoader.php' ) !== -1 ) { |
1701 | | - mwpath = src.substr( 0, src.indexOf( 'ResourceLoader.php' ) ); |
1702 | | - } |
1703 | | - |
1704 | | - // For static packages mwEmbed packages start with: "mwEmbed-" |
1705 | | - if( src.indexOf( 'mwEmbed-' ) !== -1 && src.indexOf( '-static' ) !== -1 ) { |
1706 | | - mwpath = src.substr( 0, src.indexOf( 'mwEmbed-' ) ); |
1707 | | - } |
1708 | | - |
1709 | | - // Error out if we could not get the path: |
1710 | | - if( mwpath === null ) { |
1711 | | - mw.log( "Error could not get mwEmbed path " ); |
1712 | | - return ; |
1713 | | - } |
1714 | | - |
1715 | | - // Update the cached var with the absolute path: |
1716 | | - if( !relativePath ){ |
1717 | | - mwpath = mw.absoluteUrl( mwpath ) ; |
1718 | | - } |
1719 | | - return mwpath; |
1720 | | - }; |
1721 | | - |
1722 | | - /** |
1723 | | - * Get Script loader path |
1724 | | - * |
1725 | | - * @returns {String}|{Boolean} Url of the scriptLodaer false if the |
1726 | | - * scriptLoader is not used |
1727 | | - */ |
1728 | | - mw.getResourceLoaderPath = function( ) { |
1729 | | - var src = mw.getMwEmbedSrc(); |
1730 | | - if ( src.indexOf( 'mwResourceLoader.php' ) !== -1 || |
1731 | | - src.indexOf( 'ResourceLoader.php' ) !== -1 ) |
1732 | | - { |
1733 | | - // Return just the script part of the url |
1734 | | - return src.split('?')[0]; |
1735 | | - } |
1736 | | - return false; |
1737 | | - }; |
1738 | | - /** |
1739 | | - * Given a float number of seconds, returns npt format response. ( ignore |
1740 | | - * days for now ) |
1741 | | - * |
1742 | | - * @param {Float} |
1743 | | - * sec Seconds |
1744 | | - * @param {Boolean} |
1745 | | - * verbose If hours and milliseconds should padded be displayed. |
1746 | | - * @return {Float} String npt format |
1747 | | - */ |
1748 | | - mw.seconds2npt = function( sec, verbose ) { |
1749 | | - if ( isNaN( sec ) ) { |
1750 | | - mw.log("Warning: trying to get npt time on NaN:" + sec); |
1751 | | - return '0:00:00'; |
1752 | | - } |
1753 | | - |
1754 | | - var tm = mw.seconds2Measurements( sec ); |
1755 | | - |
1756 | | - // Round the number of seconds to the required number of significant |
1757 | | - // digits |
1758 | | - if ( verbose ) { |
1759 | | - tm.seconds = Math.round( tm.seconds * 1000 ) / 1000; |
1760 | | - } else { |
1761 | | - tm.seconds = Math.round( tm.seconds ); |
1762 | | - } |
1763 | | - if ( tm.seconds < 10 ){ |
1764 | | - tm.seconds = '0' + tm.seconds; |
1765 | | - } |
1766 | | - if( tm.hours == 0 && !verbose ){ |
1767 | | - hoursStr = ''; |
1768 | | - } else { |
1769 | | - if ( tm.minutes < 10 && verbose) { |
1770 | | - tm.minutes = '0' + tm.minutes; |
1771 | | - } |
1772 | | - |
1773 | | - if( tm.hours < 10 && verbose){ |
1774 | | - tm.hours = '0' + tm.hours; |
1775 | | - } |
1776 | | - |
1777 | | - hoursStr = tm.hours + ':'; |
1778 | | - } |
1779 | | - return hoursStr + tm.minutes + ":" + tm.seconds; |
1780 | | - }; |
1781 | | - /** |
1782 | | - * Given seconds return array with 'days', 'hours', 'min', 'seconds' |
1783 | | - * |
1784 | | - * @param {float} |
1785 | | - * sec Seconds to be converted into time measurements |
1786 | | - */ |
1787 | | - mw.seconds2Measurements = function ( sec ){ |
1788 | | - var tm = {}; |
1789 | | - tm.days = Math.floor( sec / ( 3600 * 24 ) ); |
1790 | | - tm.hours = Math.floor( sec / 3600 ); |
1791 | | - tm.minutes = Math.floor( ( sec / 60 ) % 60 ); |
1792 | | - tm.seconds = sec % 60; |
1793 | | - return tm; |
1794 | | - }; |
1795 | | - |
1796 | | - /** |
1797 | | - * Given a float number of seconds, returns npt format response. ( ignore |
1798 | | - * days for now ) |
1799 | | - * |
1800 | | - * @param {Float} |
1801 | | - * sec Seconds |
1802 | | - * @param {Boolean} |
1803 | | - * verbose If hours and milliseconds should padded be displayed. |
1804 | | - * @return {Float} String npt format |
1805 | | - */ |
1806 | | - mw.npt2seconds = function ( npt_str ) { |
1807 | | - if ( !npt_str ) { |
1808 | | - // mw.log('npt2seconds:not valid ntp:'+ntp); |
1809 | | - return false; |
1810 | | - } |
1811 | | - // Strip {npt:}01:02:20 or 32{s} from time if present |
1812 | | - npt_str = npt_str.replace( /npt:|s/g, '' ); |
1813 | | - |
1814 | | - var hour = 0; |
1815 | | - var min = 0; |
1816 | | - var sec = 0; |
1817 | | - |
1818 | | - times = npt_str.split( ':' ); |
1819 | | - if ( times.length == 3 ) { |
1820 | | - sec = times[2]; |
1821 | | - min = times[1]; |
1822 | | - hour = times[0]; |
1823 | | - } else if ( times.length == 2 ) { |
1824 | | - sec = times[1]; |
1825 | | - min = times[0]; |
1826 | | - } else { |
1827 | | - sec = times[0]; |
1828 | | - } |
1829 | | - // Sometimes a comma is used instead of period for ms |
1830 | | - sec = sec.replace( /,\s?/, '.' ); |
1831 | | - // Return seconds float |
1832 | | - return parseInt( hour * 3600 ) + parseInt( min * 60 ) + parseFloat( sec ); |
1833 | | - }; |
1834 | | - |
1835 | | - // Local mwEmbedSrc variable ( for cache of mw.getMwEmbedSrc ) |
1836 | | - var mwEmbedSrc = null; |
1837 | | - |
1838 | | - /** |
1839 | | - * Gets the mwEmbed script src attribute |
1840 | | - */ |
1841 | | - mw.getMwEmbedSrc = function() { |
1842 | | - if ( mwEmbedSrc ) { |
1843 | | - return mwEmbedSrc; |
1844 | | - } |
1845 | | - |
1846 | | - // Get all the javascript includes: |
1847 | | - var js_elements = document.getElementsByTagName( "script" ); |
1848 | | - for ( var i = 0; i < js_elements.length; i++ ) { |
1849 | | - // Check for mwEmbed.js and/or script loader |
1850 | | - var src = js_elements[i].getAttribute( "src" ); |
1851 | | - if ( src ) { |
1852 | | - if ( // Check for mwEmbed.js ( debug mode ) |
1853 | | - ( src.indexOf( 'mwEmbed.js' ) !== -1 && src.indexOf( 'MediaWiki:Gadget') == -1 ) |
1854 | | - || // Check for resource loader |
1855 | | - ( |
1856 | | - ( src.indexOf( 'mwResourceLoader.php' ) !== -1 || src.indexOf( 'ResourceLoader.php' ) !== -1 ) |
1857 | | - && |
1858 | | - src.indexOf( 'mwEmbed' ) !== -1 |
1859 | | - ) |
1860 | | - || // Check for static mwEmbed package |
1861 | | - ( src.indexOf( 'mwEmbed' ) !== -1 && src.indexOf( 'static' ) !== -1 ) |
1862 | | - ) { |
1863 | | - mwEmbedSrc = src; |
1864 | | - return mwEmbedSrc; |
1865 | | - } |
1866 | | - } |
1867 | | - } |
1868 | | - mw.log( 'Error: getMwEmbedSrc failed to get script path' ); |
1869 | | - return false; |
1870 | | - }; |
1871 | | - |
1872 | | - // Local mwUrlParam variable ( for cache of mw.getUrlParam ) |
1873 | | - var mwUrlParam = null; |
1874 | | - |
1875 | | - /** |
1876 | | - * Get URL Parameters per parameters in the host script include |
1877 | | - */ |
1878 | | - mw.getUrlParam = function() { |
1879 | | - if ( mwUrlParam ) { |
1880 | | - return mwUrlParam; |
1881 | | - } |
1882 | | - |
1883 | | - var mwEmbedSrc = mw.getMwEmbedSrc(); |
1884 | | - var req_param = ''; |
1885 | | - |
1886 | | - // If we already have a URI, add it to the param request: |
1887 | | - var urid = mw.parseUri( mwEmbedSrc ).queryKey['urid']; |
1888 | | - |
1889 | | - // If we're in debug mode, get a fresh unique request key and pass on |
1890 | | - // "debug" param |
1891 | | - if ( mw.parseUri( mwEmbedSrc ).queryKey['debug'] == 'true' ) { |
1892 | | - mw.setConfig( 'debug', true ); |
1893 | | - var d = new Date(); |
1894 | | - req_param += 'urid=' + d.getTime() + '&debug=true'; |
1895 | | - |
1896 | | - } else if ( urid ) { |
1897 | | - // Just pass on the existing urid: |
1898 | | - req_param += 'urid=' + urid; |
1899 | | - } else { |
1900 | | - // Otherwise, Use the mwEmbed version |
1901 | | - req_param += 'urid=' + mw.version; |
1902 | | - } |
1903 | | - |
1904 | | - // Add the language param if present: |
1905 | | - var langKey = mw.parseUri( mwEmbedSrc ).queryKey['uselang']; |
1906 | | - if ( langKey ) |
1907 | | - req_param += '&uselang=' + langKey; |
1908 | | - |
1909 | | - // Update the local cache and return the value |
1910 | | - mwUrlParam = req_param; |
1911 | | - return mwUrlParam; |
1912 | | - }; |
1913 | | - |
1914 | | - /** |
1915 | | - * Replace url parameters via newParams key value pairs |
1916 | | - * |
1917 | | - * @param {String} |
1918 | | - * url Source url to be updated |
1919 | | - * @param {Object} |
1920 | | - * newParams key, value paris to swap in |
1921 | | - * @return {String} the updated url |
1922 | | - */ |
1923 | | - mw.replaceUrlParams = function( url, newParams ) { |
1924 | | - var parsedUrl = mw.parseUri( url ); |
1925 | | - |
1926 | | - if ( parsedUrl.protocol != '' ) { |
1927 | | - var new_url = parsedUrl.protocol + '://' + parsedUrl.authority + parsedUrl.path + '?'; |
1928 | | - } else { |
1929 | | - var new_url = parsedUrl.path + '?'; |
1930 | | - } |
1931 | | - |
1932 | | - // Merge new params: |
1933 | | - for( var key in newParams ) { |
1934 | | - parsedUrl.queryKey[ key ] = newParams[ key ]; |
1935 | | - } |
1936 | | - |
1937 | | - // Output to new_url |
1938 | | - var amp = ''; |
1939 | | - for ( var key in parsedUrl.queryKey ) { |
1940 | | - var val = parsedUrl.queryKey[ key ]; |
1941 | | - new_url += amp + key + '=' + val; |
1942 | | - amp = '&'; |
1943 | | - } |
1944 | | - return new_url; |
1945 | | - }; |
1946 | | - |
1947 | | - /** |
1948 | | - * parseUri 1.2.2 (c) Steven Levithan <stevenlevithan.com> MIT License |
1949 | | - */ |
1950 | | - mw.parseUri = function (str) { |
1951 | | - var o = mw.parseUri.options, |
1952 | | - m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), |
1953 | | - uri = {}, |
1954 | | - i = 14; |
1955 | | - |
1956 | | - while (i--) uri[o.key[i]] = m[i] || ""; |
1957 | | - |
1958 | | - uri[o.q.name] = {}; |
1959 | | - uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { |
1960 | | - if ($1) uri[o.q.name][$1] = $2; |
1961 | | - }); |
1962 | | - |
1963 | | - return uri; |
1964 | | - }; |
1965 | | - |
1966 | | - /** |
1967 | | - * Parse URI function |
1968 | | - * |
1969 | | - * For documentation on its usage see: |
1970 | | - * http://stevenlevithan.com/demo/parseuri/js/ |
1971 | | - */ |
1972 | | - mw.parseUri.options = { |
1973 | | - strictMode: false, |
1974 | | - key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", |
1975 | | - "port", "relative", "path", "directory", "file", "query", "anchor"], |
1976 | | - q: { |
1977 | | - name: "queryKey", |
1978 | | - parser: /(?:^|&)([^&=]*)=?([^&]*)/g |
1979 | | - }, |
1980 | | - parser: { |
1981 | | - strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, |
1982 | | - loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ |
1983 | | - } |
1984 | | - }; |
1985 | | - |
1986 | | - /** |
1987 | | - * getAbsoluteUrl takes a src and returns the absolute location given the |
1988 | | - * document.URL or a contextUrl param |
1989 | | - * |
1990 | | - * @param {String} |
1991 | | - * src path or url |
1992 | | - * @param {String} |
1993 | | - * contextUrl The domain / context for creating an absolute url |
1994 | | - * from a relative path |
1995 | | - * @return {String} absolute url |
1996 | | - */ |
1997 | | -mw.absoluteUrl = function( src, contextUrl ) { |
1998 | | - |
1999 | | - var parsedSrc = mw.parseUri( src ); |
2000 | | - |
2001 | | - // Source is already absolute return: |
2002 | | - if( parsedSrc.protocol != '') { |
2003 | | - return src; |
2004 | | - } |
2005 | | - |
2006 | | - // Get parent Url location the context URL |
2007 | | - if( !contextUrl ) { |
2008 | | - contextUrl = document.URL; |
2009 | | - } |
2010 | | - var parsedUrl = mw.parseUri( contextUrl ); |
2011 | | - |
2012 | | - // Check for IE local file that does not flip the slashes |
2013 | | - if( parsedUrl.directory == '' && parsedUrl.protocol == 'file' ){ |
2014 | | - // pop off the file |
2015 | | - var fileUrl = contextUrl.split( '\\'); |
2016 | | - fileUrl.pop(); |
2017 | | - return fileUrl.join('\\') + '\\' + src; |
2018 | | - } |
2019 | | - |
2020 | | - // Check for leading slash: |
2021 | | - if( src.indexOf( '/' ) === 0 ) { |
2022 | | - return parsedUrl.protocol + '://' + parsedUrl.authority + src; |
2023 | | - }else{ |
2024 | | - return parsedUrl.protocol + '://' + parsedUrl.authority + parsedUrl.directory + src; |
2025 | | - } |
2026 | | - }; |
2027 | | - /** |
2028 | | - * Check if a given source string is likely a url |
2029 | | - * |
2030 | | - * @return {boolean} true if a url false if a string |
2031 | | - */ |
2032 | | - mw.isUrl = function( src ){ |
2033 | | - var parsedSrc = mw.parseUri( src ); |
2034 | | - // if the url is just a string source and host will match |
2035 | | - return ( parsedSrc.host != parsedSrc.source ); |
2036 | | - }; |
2037 | | - |
2038 | | - /** |
2039 | | - * Escape quotes in a text string |
2040 | | - * |
2041 | | - * @param {String} |
2042 | | - * text String to be escaped |
2043 | | - * @return {string} escaped text string |
2044 | | - */ |
2045 | | - mw.escapeQuotes = function( text ) { |
2046 | | - var re = new RegExp("'","g"); |
2047 | | - text = text.replace(re,"\\'"); |
2048 | | - re = new RegExp("\\n","g"); |
2049 | | - text = text.replace(re,"\\n"); |
2050 | | - return mw.escapeQuotesHTML(text); |
2051 | | - }; |
2052 | | - |
2053 | | - /** |
2054 | | - * Escape an HTML text string |
2055 | | - * |
2056 | | - * @param {String} |
2057 | | - * text String to be escaped |
2058 | | - * @return {string} escaped text html string |
2059 | | - */ |
2060 | | - mw.escapeQuotesHTML = function( text ) { |
2061 | | - var replaceMap = { |
2062 | | - "&" : "&", |
2063 | | - '"' : """, |
2064 | | - '<' : "<", |
2065 | | - '>' : ">" |
2066 | | - }; |
2067 | | - for( var i in replaceMap ){ |
2068 | | - text = text.split(i).join( replaceMap[i]); |
2069 | | - } |
2070 | | - return text; |
2071 | | - }; |
2072 | | - |
2073 | | - |
2074 | | - // Array of setup functions |
2075 | | - var mwSetupFunctions = []; |
2076 | | - |
2077 | | - /** |
2078 | | - * Add a function to be run during setup ( prior to mw.ready) this is useful |
2079 | | - * for building out interfaces that should be ready before mw.ready is |
2080 | | - * called. |
2081 | | - * |
2082 | | - * @param {callback} |
2083 | | - * Function Callback function must accept a ready function |
2084 | | - * callback to be called once setup is done |
2085 | | - */ |
2086 | | - mw.addSetupHook = function( callback ) { |
2087 | | - mwSetupFunctions.push ( callback ) ; |
2088 | | - }; |
2089 | | - |
2090 | | - /** |
2091 | | - * One time "setup" for mwEmbed run onDomReady ( so calls to setConfg apply |
2092 | | - * to setup ) |
2093 | | - */ |
2094 | | - // Flag to ensure setup is only run once: |
2095 | | - var mwSetupFlag = false; |
2096 | | - mw.setupMwEmbed = function ( ) { |
2097 | | - // Only run the setup once: |
2098 | | - if( mwSetupFlag ) { |
2099 | | - return ; |
2100 | | - } |
2101 | | - mwSetupFlag = true; |
2102 | | - |
2103 | | - mw.log( 'mw:setupMwEmbed SRC:: ' + mw.getMwEmbedSrc() ); |
2104 | | - |
2105 | | - // Check core mwEmbed loader.js file ( to get configuration and paths ) |
2106 | | - mw.checkCoreLoaderFile( function(){ |
2107 | | - // Make sure we have jQuery |
2108 | | - mw.load( 'window.jQuery', function() { |
2109 | | - |
2110 | | - // Add jQuery to $j var. |
2111 | | - if ( ! window[ '$j' ] ) { |
2112 | | - window[ '$j' ] = jQuery.noConflict(); |
2113 | | - } |
2114 | | - |
2115 | | - // Set up mvEmbed utility jQuery bindings |
2116 | | - mw.dojQueryBindings(); |
2117 | | - |
2118 | | - // Setup user config: |
2119 | | - mw.setupUserConfig( function(){ |
2120 | | - // Get module loader.js, and language files |
2121 | | - // ( will hit callback directly if set via resource loader ) |
2122 | | - mw.checkModuleLoaderFiles( function() { |
2123 | | - |
2124 | | - // Set the User language |
2125 | | - if( typeof wgUserLanguage != 'undefined' && mw.isValidLang( wgUserLanguage) ) { |
2126 | | - mw.setConfig( 'userLanguage', wgUserLanguage ); |
2127 | | - }else{ |
2128 | | - // Grab it from the included url |
2129 | | - var langKey = mw.parseUri( mw.getMwEmbedSrc() ).queryKey['uselang']; |
2130 | | - if ( langKey && mw.isValidLang( langKey ) ) { |
2131 | | - mw.setConfig( 'userLanguage', langKey); |
2132 | | - } |
2133 | | - } |
2134 | | - |
2135 | | - // Update the image path |
2136 | | - mw.setConfig( 'imagesPath', mw.getMwEmbedPath() + 'skins/common/images/' ); |
2137 | | - |
2138 | | - // Set up AJAX to not send dynamic URLs for loading |
2139 | | - // scripts |
2140 | | - $j.ajaxSetup( { |
2141 | | - cache: true |
2142 | | - } ); |
2143 | | - |
2144 | | - // Update the magic keywords |
2145 | | - mw.Language.magicSetup(); |
2146 | | - |
2147 | | - |
2148 | | - // Special Hack for conditional jquery ui inclusion ( |
2149 | | - // once |
2150 | | - // Usability extension |
2151 | | - // registers the jquery.ui skin in mw.style |
2152 | | - if( mw.hasJQueryUiCss() ){ |
2153 | | - mw.style[ 'ui_' + mw.getConfig( 'jQueryUISkin' ) ] = true; |
2154 | | - } |
2155 | | - |
2156 | | - |
2157 | | - // Make sure style sheets are loaded: |
2158 | | - mw.load( ['mw.style.mwCommon'] , function(){ |
2159 | | - // Run all the setup function hooks |
2160 | | - // NOTE: setup functions are added via addSetupHook |
2161 | | - // calls |
2162 | | - // and must include a callback. |
2163 | | - // |
2164 | | - // Once complete we can run .ready() queued |
2165 | | - // functions |
2166 | | - function runSetupFunctions() { |
2167 | | - if( mwSetupFunctions.length ) { |
2168 | | - mwSetupFunctions.shift()( function() { |
2169 | | - runSetupFunctions(); |
2170 | | - } ); |
2171 | | - }else{ |
2172 | | - mw.runReadyFunctions(); |
2173 | | - } |
2174 | | - } |
2175 | | - runSetupFunctions(); |
2176 | | - } ); |
2177 | | - |
2178 | | - } ); |
2179 | | - }); |
2180 | | - }); |
2181 | | - }); |
2182 | | - }; |
2183 | | - |
2184 | | - /** |
2185 | | - * Checks for jquery ui css by name jquery-ui-1.7.2.css NOTE: this is a hack |
2186 | | - * for usability jquery-ui in the future usability should register a |
2187 | | - * resource in mw.skin |
2188 | | - * |
2189 | | - * @return true if found, return false if not found |
2190 | | - */ |
2191 | | - mw.hasJQueryUiCss = function(){ |
2192 | | - var hasUiCss = false; |
2193 | | - var cssStyleSheetNames = ['jquery-ui-1.7.2.css', 'jquery-ui.css']; |
2194 | | - // Load the jQuery ui skin if usability skin not set |
2195 | | - $j( 'link' ).each( function( na, linkNode ){ |
2196 | | - $j.each( cssStyleSheetNames, function(inx, sheetName ){ |
2197 | | - if( $j( linkNode ).attr( 'href' ).indexOf( sheetName ) != -1 ){ |
2198 | | - hasUiCss = true; |
2199 | | - return true; |
2200 | | - } |
2201 | | - }); |
2202 | | - } ); |
2203 | | - // Check all the "style" nodes for @import for sheet name |
2204 | | - // xxx Note: we could do this a bit cleaner with regEx |
2205 | | - $j( 'style' ).each( function( na, styleNode ){ |
2206 | | - $j.each( cssStyleSheetNames, function(inx, sheetName ){ |
2207 | | - if( $j( styleNode ).text().indexOf( '@import' ) != -1 |
2208 | | - && |
2209 | | - $j( styleNode ).text().indexOf( sheetName ) != -1 ) |
2210 | | - { |
2211 | | - hasUiCss=true; |
2212 | | - return true; |
2213 | | - } |
2214 | | - }); |
2215 | | - }); |
2216 | | - return hasUiCss; |
2217 | | - }; |
2218 | | - |
2219 | | - /** |
2220 | | - * Loads the core mwEmbed "loader.js" file config |
2221 | | - * |
2222 | | - * NOTE: if using the ScriptLoader all the loaders and localization |
2223 | | - * converters are included automatically |
2224 | | - * |
2225 | | - * @param {Function} |
2226 | | - * callback Function called once core loader file is loaded |
2227 | | - */ |
2228 | | - mw.checkCoreLoaderFile = function( callback ) { |
2229 | | - // Check if we are using scriptloader ( handles loader include |
2230 | | - // automatically ) |
2231 | | - if( mw.getResourceLoaderPath() ) { |
2232 | | - callback(); |
2233 | | - return ; |
2234 | | - } |
2235 | | - |
2236 | | - // Check if we are using a static package ( mwEmbed path includes |
2237 | | - // -static ) |
2238 | | - if( mw.isStaticPackge() ){ |
2239 | | - callback(); |
2240 | | - return ; |
2241 | | - } |
2242 | | - |
2243 | | - // Add the Core loader to the request |
2244 | | - // The follow code is ONLY RUN in debug / raw file mode |
2245 | | - mw.load( 'loader.js', callback ); |
2246 | | - }; |
2247 | | - |
2248 | | - /** |
2249 | | - * Checks if the javascript is a static package ( not using resource loader ) |
2250 | | - * |
2251 | | - * @return {boolean} true the included script is static false the included |
2252 | | - * script |
2253 | | - */ |
2254 | | - mw.isStaticPackge = function(){ |
2255 | | - var src = mw.getMwEmbedSrc(); |
2256 | | - if( src.indexOf('-static') !== -1 ){ |
2257 | | - return true; |
2258 | | - } |
2259 | | - return false; |
2260 | | - }; |
2261 | | - |
2262 | | - /** |
2263 | | - * Check for resource loader module loaders, and localization files |
2264 | | - * |
2265 | | - * NOTE: if using the ScriptLoader all the loaders and localization |
2266 | | - * converters are included automatically. |
2267 | | - */ |
2268 | | - mw.checkModuleLoaderFiles = function( callback ) { |
2269 | | - mw.log( 'doLoaderCheck::' ); |
2270 | | - |
2271 | | - // Check if we are using scriptloader ( handles loader include |
2272 | | - // automatically ) |
2273 | | - // Or if mwEmbed is a static package ( all resources are already loaded |
2274 | | - // ) |
2275 | | - if( mw.getResourceLoaderPath() || mw.isStaticPackge() ) { |
2276 | | - callback(); |
2277 | | - return ; |
2278 | | - } |
2279 | | - |
2280 | | - // Load the configured modules / components |
2281 | | - // The follow code is ONLY RUN in debug / raw file mode |
2282 | | - var loaderRequest = []; |
2283 | | - |
2284 | | - // Load enabled components |
2285 | | - var enabledComponents = mw.getConfig( 'coreComponents' ); |
2286 | | - function loadEnabledComponents( enabledComponents ){ |
2287 | | - if( ! enabledComponents.length ){ |
2288 | | - // If no more components load modules:: |
2289 | | - |
2290 | | - // Add the enabledModules loaders: |
2291 | | - var enabledModules = mw.getConfig( 'enabledModules' ); |
2292 | | - loadEnabledModules( enabledModules ); |
2293 | | - return ; |
2294 | | - } |
2295 | | - var componentName = enabledComponents.shift(); |
2296 | | - componentName = componentName.replace(/"/g,''); |
2297 | | - mw.load( componentName, function(){ |
2298 | | - loadEnabledComponents( enabledComponents ); |
2299 | | - } ); |
2300 | | - } |
2301 | | - loadEnabledComponents( enabledComponents ); |
2302 | | - |
2303 | | - |
2304 | | - // Set the loader context and get each loader individually |
2305 | | - function loadEnabledModules( enabledModules ){ |
2306 | | - if( ! enabledModules.length ){ |
2307 | | - // If no more modules left load the LanguageFile |
2308 | | - addLanguageFile(); |
2309 | | - return ; |
2310 | | - } |
2311 | | - var moduleName = enabledModules.shift(); |
2312 | | - moduleName = moduleName.replace(/"/g,''); |
2313 | | - mw.setConfig( 'loaderContext', 'modules/' + moduleName + '/' ); |
2314 | | - mw.load( 'modules/' + moduleName + '/loader.js', function(){ |
2315 | | - loadEnabledModules( enabledModules ); |
2316 | | - } ); |
2317 | | - } |
2318 | | - |
2319 | | - function addLanguageFile(){ |
2320 | | - // Add the language file |
2321 | | - var langLoaderRequest = []; |
2322 | | - |
2323 | | - if( mw.getConfig( 'userLanguage' ) ) { |
2324 | | - var langCode = mw.getConfig( 'userLanguage' ); |
2325 | | - |
2326 | | - // Load the language resource if not default 'en' |
2327 | | - var transformKey = mw.getLangTransformKey( langCode ); |
2328 | | - if( transformKey != 'en' ){ |
2329 | | - // Upper case the first letter: |
2330 | | - langCode = langCode.substr(0,1).toUpperCase() + langCode.substr( 1, langCode.length ); |
2331 | | - langLoaderRequest.push( 'languages/classes/Language' + |
2332 | | - langCode + '.js' ); |
2333 | | - } |
2334 | | - |
2335 | | - } |
2336 | | - if ( ! langLoaderRequest.length ) { |
2337 | | - addLocalSettings(); |
2338 | | - return ; |
2339 | | - } |
2340 | | - |
2341 | | - // Load the language if set |
2342 | | - mw.load( langLoaderRequest, function(){ |
2343 | | - mw.log( 'Done moduleLoaderCheck request' ); |
2344 | | - addLocalSettings(); |
2345 | | - } ); |
2346 | | - } |
2347 | | - function addLocalSettings(){ |
2348 | | - var continueCallback = function(){ |
2349 | | - // Set the mwModuleLoaderCheckFlag flag to true |
2350 | | - mwModuleLoaderCheckFlag = true; |
2351 | | - callback(); |
2352 | | - }; |
2353 | | - if( mw.getConfig( 'LoadLocalSettings') != true ){ |
2354 | | - continueCallback(); |
2355 | | - return; |
2356 | | - } |
2357 | | - mw.log("Load loacal settings"); |
2358 | | - mw.load( 'localSettings.js', function(){ |
2359 | | - continueCallback(); |
2360 | | - }); |
2361 | | - } |
2362 | | - |
2363 | | - }; |
2364 | | - |
2365 | | - /** |
2366 | | - * Checks if a css style rule exists |
2367 | | - * |
2368 | | - * On a page with lots of rules it can take some time so avoid calling this |
2369 | | - * function where possible and cache its result |
2370 | | - * |
2371 | | - * NOTE: this only works for style sheets on the same domain :( |
2372 | | - * |
2373 | | - * @param {String} |
2374 | | - * styleRule Style rule name to check |
2375 | | - * @return {Boolean} true if the rule exists false if the rule does not |
2376 | | - * exist |
2377 | | - */ |
2378 | | - mw.styleRuleExists = function ( styleRule ) { |
2379 | | - // Set up the skin paths configuration |
2380 | | - for( var i=0 ; i < document.styleSheets.length ; i++ ) { |
2381 | | - var rules = null; |
2382 | | - try{ |
2383 | | - if ( document.styleSheets[i].cssRules ) |
2384 | | - rules = document.styleSheets[i].cssRules; |
2385 | | - else if (document.styleSheets[0].rules) |
2386 | | - rules = document.styleSheets[i].rules; |
2387 | | - for(var j=0 ; j < rules.length ; j++ ) { |
2388 | | - var rule = rules[j].selectorText; |
2389 | | - if( rule && rule.indexOf( styleRule ) != -1 ) { |
2390 | | - return true; |
2391 | | - } |
2392 | | - } |
2393 | | - }catch ( e ) { |
2394 | | - mw.log( 'Error: cant check rule on cross domain style sheet:' + document.styleSheets[i].href ); |
2395 | | - } |
2396 | | - } |
2397 | | - return false; |
2398 | | - }; |
2399 | | - |
2400 | | - // Flag to register the domReady has been called |
2401 | | - var mwDomReadyFlag = false; |
2402 | | - |
2403 | | - // Flag to register if the domreadyHooks have been called |
2404 | | - var mwModuleLoaderCheckFlag = false; |
2405 | | - |
2406 | | - /** |
2407 | | - * This will get called when the DOM is ready Will check configuration and |
2408 | | - * issue a mw.setupMwEmbed call if needed |
2409 | | - */ |
2410 | | - mw.domReady = function ( ) { |
2411 | | - if( mwDomReadyFlag ) { |
2412 | | - return ; |
2413 | | - } |
2414 | | - mw.log( 'run:domReady:: ' + document.getElementsByTagName('video').length ); |
2415 | | - // Set the onDomReady Flag |
2416 | | - mwDomReadyFlag = true; |
2417 | | - |
2418 | | - // Give us a chance to get to the bottom of the script. |
2419 | | - // When loading mwEmbed asynchronously the dom ready gets called |
2420 | | - // directly and in some browsers beets the $j = jQuery.noConflict(); |
2421 | | - // call |
2422 | | - // and causes symbol undefined errors. |
2423 | | - setTimeout(function(){ |
2424 | | - mw.setupMwEmbed(); |
2425 | | - },1); |
2426 | | - }; |
2427 | | - |
2428 | | - /** |
2429 | | - * A version comparison utility function Handles version of types |
2430 | | - * {Major}.{MinorN}.{Patch} |
2431 | | - * |
2432 | | - * Note this just handles version numbers not patch letters. |
2433 | | - * |
2434 | | - * @param {String} |
2435 | | - * minVersion Minnium version needed |
2436 | | - * @param {String} |
2437 | | - * clientVersion Client version to be checked |
2438 | | - * |
2439 | | - * @return true if the version is at least of minVersion false if the |
2440 | | - * version is less than minVersion |
2441 | | - */ |
2442 | | - mw.versionIsAtLeast = function( minVersion, clientVersion ) { |
2443 | | - var minVersionParts = minVersion.split('.'); |
2444 | | - var clientVersionParts = clientVersion.split('.'); |
2445 | | - for( var i =0; i < minVersionParts.length; i++ ) { |
2446 | | - if( parseInt( clientVersionParts[i] ) > parseInt( minVersionParts[i] ) ) { |
2447 | | - return true; |
2448 | | - } |
2449 | | - if( parseInt( clientVersionParts[i] ) < parseInt( minVersionParts[i] ) ) { |
2450 | | - return false; |
2451 | | - } |
2452 | | - } |
2453 | | - // Same version: |
2454 | | - return true; |
2455 | | - }; |
2456 | | - |
2457 | | - /** |
2458 | | - * Utility jQuery bindings Setup after jQuery is available ). |
2459 | | - */ |
2460 | | - mw.dojQueryBindings = function() { |
2461 | | - mw.log( 'mw.dojQueryBindings' ); |
2462 | | - ( function( $ ) { |
2463 | | - |
2464 | | - /** |
2465 | | - * Runs all the triggers on all the named bindings of an object with |
2466 | | - * a single callback |
2467 | | - * |
2468 | | - * NOTE THIS REQUIRES JQUERY 1.4.2 and above |
2469 | | - * |
2470 | | - * Normal jQuery tirgger calls will run the callback directly |
2471 | | - * multiple times for every binded function. |
2472 | | - * |
2473 | | - * With triggerQueueCallback() callback is not called until all the |
2474 | | - * binded events have been run. |
2475 | | - * |
2476 | | - * @param {string} |
2477 | | - * triggerName Name of trigger to be run |
2478 | | - * @param {object=} |
2479 | | - * arguments Optional arguments object to be passed to |
2480 | | - * the callback |
2481 | | - * @param {function} |
2482 | | - * callback Function called once all triggers have been |
2483 | | - * run |
2484 | | - * |
2485 | | - */ |
2486 | | - $.fn.triggerQueueCallback = function( triggerName, triggerParam, callback ){ |
2487 | | - var targetObject = this; |
2488 | | - // Support optional triggerParam data |
2489 | | - if( !callback && typeof triggerParam == 'function' ){ |
2490 | | - callback = triggerParam; |
2491 | | - triggerParam = null; |
2492 | | - } |
2493 | | - // Support namespaced event segmentation ( jQuery |
2494 | | - var triggerBaseName = triggerName.split(".")[0]; |
2495 | | - var triggerNamespace = triggerName.split(".")[1]; |
2496 | | - // Get the callback set |
2497 | | - var callbackSet = []; |
2498 | | - if( ! triggerNamespace ){ |
2499 | | - callbackSet = $j( targetObject ).data( 'events' )[ triggerBaseName ]; |
2500 | | - } else{ |
2501 | | - $j.each( $j( targetObject ).data( 'events' )[ triggerBaseName ], function( inx, bindObject ){ |
2502 | | - if( bindObject.namespace == triggerNamespace ){ |
2503 | | - callbackSet.push( bindObject ); |
2504 | | - } |
2505 | | - }); |
2506 | | - } |
2507 | | - |
2508 | | - if( !callbackSet || callbackSet.length === 0 ){ |
2509 | | - mw.log( '"mwEmbed::jQuery.triggerQueueCallback: No events run the callback directly: ' + triggerName ); |
2510 | | - // No events run the callback directly |
2511 | | - callback(); |
2512 | | - return ; |
2513 | | - } |
2514 | | - |
2515 | | - // Set the callbackCount |
2516 | | - var callbackCount = ( callbackSet.length )? callbackSet.length : 1; |
2517 | | - // mw.log("mwEmbed::jQuery.triggerQueueCallback: " + triggerName |
2518 | | - // + ' number of queued functions:' + callbackCount ); |
2519 | | - var callInx = 0; |
2520 | | - var doCallbackCheck = function() { |
2521 | | - // mw.log( 'callback for: ' + mw.getCallStack()[0] + |
2522 | | - // callInx); |
2523 | | - callInx++; |
2524 | | - if( callInx == callbackCount ){ |
2525 | | - callback(); |
2526 | | - } |
2527 | | - }; |
2528 | | - if( triggerParam ){ |
2529 | | - $( this ).trigger( triggerName, [ triggerParam, doCallbackCheck ]); |
2530 | | - } else { |
2531 | | - $( this ).trigger( triggerName, [ doCallbackCheck ] ); |
2532 | | - } |
2533 | | - }; |
2534 | | - |
2535 | | - /** |
2536 | | - * Set a given selector html to the loading spinner: |
2537 | | - */ |
2538 | | - $.fn.loadingSpinner = function( ) { |
2539 | | - if ( this ) { |
2540 | | - $( this ).html( |
2541 | | - $( '<div />' ) |
2542 | | - .addClass( "loadingSpinner" ) |
2543 | | - ); |
2544 | | - } |
2545 | | - return this; |
2546 | | - }; |
2547 | | - |
2548 | | - /** |
2549 | | - * Add an absolute overlay spinner useful for cases where the |
2550 | | - * element does not display child elements, ( images, video ) |
2551 | | - */ |
2552 | | - $.fn.getAbsoluteOverlaySpinner = function(){ |
2553 | | - var pos = $j( this ).offset(); |
2554 | | - var posLeft = ( $j( this ).width() ) ? |
2555 | | - parseInt( pos.left + ( .5 * $j( this ).width() ) -16 ) : |
2556 | | - pos.left + 30; |
2557 | | - |
2558 | | - var posTop = ( $j( this ).height() ) ? |
2559 | | - parseInt( pos.top + ( .5 * $j( this ).height() ) -16 ) : |
2560 | | - pos.top + 30; |
2561 | | - |
2562 | | - var $spinner = $j('<div />') |
2563 | | - .loadingSpinner() |
2564 | | - .css({ |
2565 | | - 'width' : 32, |
2566 | | - 'height' : 32, |
2567 | | - 'position': 'absolute', |
2568 | | - 'top' : posTop + 'px', |
2569 | | - 'left' : posLeft + 'px' |
2570 | | - }); |
2571 | | - $j('body').append( $spinner ); |
2572 | | - return $spinner; |
2573 | | - }; |
2574 | | - |
2575 | | - /** |
2576 | | - * dragDrop file loader |
2577 | | - */ |
2578 | | - $.fn.dragFileUpload = function ( conf ) { |
2579 | | - if ( this.selector ) { |
2580 | | - var _this = this; |
2581 | | - // load the dragger and "setup" |
2582 | | - mw.load( ['$j.fn.dragDropFile'], function() { |
2583 | | - $j( _this.selector ).dragDropFile(); |
2584 | | - } ); |
2585 | | - } |
2586 | | - }; |
2587 | | - |
2588 | | - /** |
2589 | | - * Shortcut to a themed button Should be depreciated for $.button |
2590 | | - * bellow |
2591 | | - */ |
2592 | | - $.btnHtml = function( msg, styleClass, iconId, opt ) { |
2593 | | - if ( !opt ) |
2594 | | - opt = { }; |
2595 | | - var href = ( opt.href ) ? opt.href : '#'; |
2596 | | - var target_attr = ( opt.target ) ? ' target="' + opt.target + '" ' : ''; |
2597 | | - var style_attr = ( opt.style ) ? ' style="' + opt.style + '" ' : ''; |
2598 | | - return '<a href="' + href + '" ' + target_attr + style_attr + |
2599 | | - ' class="ui-state-default ui-corner-all ui-icon_link ' + |
2600 | | - styleClass + '"><span class="ui-icon ui-icon-' + iconId + '" ></span>' + |
2601 | | - '<span class="btnText">' + msg + '</span></a>'; |
2602 | | - }; |
2603 | | - |
2604 | | - // Shortcut to jQuery button ( should replace all btnHtml with |
2605 | | - // button ) |
2606 | | - var mw_default_button_options = { |
2607 | | - // The class name for the button link |
2608 | | - 'class' : '', |
2609 | | - |
2610 | | - // The style properties for the button link |
2611 | | - 'style' : { }, |
2612 | | - |
2613 | | - // The text of the button link |
2614 | | - 'text' : '', |
2615 | | - |
2616 | | - // The icon id that precedes the button link: |
2617 | | - 'icon' : 'carat-1-n' |
2618 | | - }; |
2619 | | - |
2620 | | - $.button = function( options ) { |
2621 | | - var options = $j.extend( {}, mw_default_button_options, options); |
2622 | | - |
2623 | | - // Button: |
2624 | | - var $button = $j('<a />') |
2625 | | - .attr('href', '#') |
2626 | | - .addClass( 'ui-state-default ui-corner-all ui-icon_link' ); |
2627 | | - // Add css if set: |
2628 | | - if( options.css ) { |
2629 | | - $button.css( options.css ); |
2630 | | - } |
2631 | | - |
2632 | | - if( options['class'] ) { |
2633 | | - $button.addClass( options['class'] ); |
2634 | | - } |
2635 | | - |
2636 | | - // return the button: |
2637 | | - $button.append( |
2638 | | - $j('<span />').addClass( 'ui-icon ui-icon-' + options.icon ), |
2639 | | - $j('<span />').addClass( 'btnText' ) |
2640 | | - ) |
2641 | | - .buttonHover(); // add buttonHover binding; |
2642 | | - |
2643 | | - if( options.text ){ |
2644 | | - $button.find('.btnText').text( options.text ); |
2645 | | - } else { |
2646 | | - $button.css('padding', '1em'); |
2647 | | - } |
2648 | | - return $button; |
2649 | | - }; |
2650 | | - |
2651 | | - // Shortcut to bind hover state |
2652 | | - $.fn.buttonHover = function() { |
2653 | | - $j( this ).hover( |
2654 | | - function() { |
2655 | | - $j( this ).addClass( 'ui-state-hover' ); |
2656 | | - }, |
2657 | | - function() { |
2658 | | - $j( this ).removeClass( 'ui-state-hover' ); |
2659 | | - } |
2660 | | - ); |
2661 | | - return this; |
2662 | | - }; |
2663 | | - |
2664 | | - /** |
2665 | | - * Resize a dialog to fit the window |
2666 | | - * |
2667 | | - * @param {Object} |
2668 | | - * options horizontal and vertical space ( default 50 ) |
2669 | | - */ |
2670 | | - $.fn.dialogFitWindow = function( options ) { |
2671 | | - var opt_default = { 'hspace':50, 'vspace':50 }; |
2672 | | - if ( !options ) |
2673 | | - var options = { }; |
2674 | | - options = $j.extend( opt_default, options ); |
2675 | | - $j( this.selector ).dialog( 'option', 'width', $j( window ).width() - options.hspace ); |
2676 | | - $j( this.selector ).dialog( 'option', 'height', $j( window ).height() - options.vspace ); |
2677 | | - $j( this.selector ).dialog( 'option', 'position', 'center' ); |
2678 | | - // update the child position: (some of this should be pushed |
2679 | | - // up-stream via dialog config options |
2680 | | - $j( this.selector + '~ .ui-dialog-buttonpane' ).css( { |
2681 | | - 'position':'absolute', |
2682 | | - 'left':'0px', |
2683 | | - 'right':'0px', |
2684 | | - 'bottom':'0px' |
2685 | | - } ); |
2686 | | - }; |
2687 | | - |
2688 | | - } )( jQuery ); |
2689 | | - }; |
2690 | | - |
2691 | | -} )( window.mw ); |
2692 | | - |
2693 | | - |
2694 | | -/** |
2695 | | - * Set DOM-ready call We copy jQuery( document ).ready here since sometimes |
2696 | | - * mwEmbed.js is included without jQuery and we need our own "ready" system so |
2697 | | - * that mwEmbed interfaces can support async built out and the include of |
2698 | | - * jQuery. |
2699 | | - */ |
2700 | | -// Check if already ready: |
2701 | | -if ( document.readyState === "complete" ) { |
2702 | | - mw.domReady(); |
2703 | | -} |
2704 | | - |
2705 | | -// Cleanup functions for the document ready method |
2706 | | -if ( document.addEventListener ) { |
2707 | | - DOMContentLoaded = function() { |
2708 | | - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); |
2709 | | - mw.domReady(); |
2710 | | - }; |
2711 | | - |
2712 | | -} else if ( document.attachEvent ) { |
2713 | | - DOMContentLoaded = function() { |
2714 | | - // Make sure body exists, at least, in case IE gets a little overzealous |
2715 | | - // (ticket #5443). |
2716 | | - if ( document.readyState === "complete" ) { |
2717 | | - document.detachEvent( "onreadystatechange", DOMContentLoaded ); |
2718 | | - mw.domReady(); |
2719 | | - } |
2720 | | - }; |
2721 | | -} |
2722 | | -// Mozilla, Opera and webkit nightlies currently support this event |
2723 | | -if ( document.addEventListener ) { |
2724 | | - // Use the handy event callback |
2725 | | - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); |
2726 | | - |
2727 | | - // A fallback to window.onload, that will always work |
2728 | | - window.addEventListener( "load", mw.domReady, false ); |
2729 | | - |
2730 | | -// If IE event model is used |
2731 | | -} else if ( document.attachEvent ) { |
2732 | | - // ensure firing before onload, |
2733 | | - // maybe late but safe also for iframes |
2734 | | - document.attachEvent("onreadystatechange", DOMContentLoaded); |
2735 | | - |
2736 | | - // A fallback to window.onload, that will always work |
2737 | | - window.attachEvent( "onload", mw.domReady ); |
2738 | | - |
2739 | | - // If IE and not a frame |
2740 | | - // continually check to see if the document is ready |
2741 | | - var toplevel = false; |
2742 | | - |
2743 | | - try { |
2744 | | - toplevel = window.frameElement == null; |
2745 | | - } catch(e) {} |
2746 | | - |
2747 | | - if ( document.documentElement.doScroll && toplevel ) { |
2748 | | - doScrollCheck(); |
2749 | | - } |
2750 | | -} |
2751 | | -// The DOM ready check for Internet Explorer |
2752 | | -function doScrollCheck() { |
2753 | | - try { |
2754 | | - // If IE is used, use the trick by Diego Perini |
2755 | | - // http://javascript.nwbox.com/IEContentLoaded/ |
2756 | | - document.documentElement.doScroll("left"); |
2757 | | - } catch( error ) { |
2758 | | - setTimeout( doScrollCheck, 1 ); |
2759 | | - return; |
2760 | | - } |
2761 | | - mw.domReady(); |
2762 | | -} |
2763 | | - |
2764 | | -// If using the resource loader and jQuery has not been set give a warning to |
2765 | | -// the user: |
2766 | | -// (this is needed because packaged loader.js files could refrence jQuery ) |
2767 | | -if( mw.getResourceLoaderPath() && !window.jQuery ) { |
2768 | | - mw.log( 'Error: jQuery is required for mwEmbed, please update your resource loader request' ); |
2769 | | -} |
2770 | | - |
2771 | | -if( mw.isStaticPackge() && !window.jQuery ){ |
2772 | | - alert( 'Error: jQuery is required for mwEmbed '); |
2773 | | -} |
2774 | | - |
2775 | | -/** |
2776 | | - * Hack to keep jQuery in $ when its already there, but also use noConflict to |
2777 | | - * get $j = jQuery |
2778 | | - * |
2779 | | - * This way sites that use $ for jQuery continue to work after including mwEmbed |
2780 | | - * javascript. |
2781 | | - * |
2782 | | - * Also if jQuery is included prior to mwEmbed we ensure $j is set |
2783 | | - */ |
2784 | | - |
2785 | | -if( window.jQuery ){ |
2786 | | - if( ! mw.versionIsAtLeast( '1.4.2', jQuery.fn.jquery ) ){ |
2787 | | - if( window.console && window.console.log ) { |
2788 | | - console.log( 'Error mwEmbed requires jQuery 1.4 or above' ); |
2789 | | - } |
2790 | | - } |
2791 | | - var dollarFlag = false; |
2792 | | - if( $ && $.fn && $.fn.jquery ) { |
2793 | | - // NOTE we could check the version of |
2794 | | - // jQuery and do a removal call if too old |
2795 | | - dollarFlag = true; |
2796 | | - } |
2797 | | - window[ '$j' ] = jQuery.noConflict(); |
2798 | | - if( dollarFlag ) { |
2799 | | - window[ '$' ] = jQuery.noConflict(); |
2800 | | - } |
2801 | | -} |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/PlayerThemer/loader.js |
— | — | @@ -9,7 +9,7 @@ |
10 | 10 | }); |
11 | 11 | |
12 | 12 | // Add the mw.PlayerThemer to the embedPlayer loader request if we have special playerThemer class |
13 | | - $j( mw ).bind( 'LoaderEmbedPlayerUpdateRequest', function( event, playerElement, classRequest ) { |
| 13 | + $j( mw ).bind( 'EmbedPlayerUpdateDependencies', function( event, playerElement, classRequest ) { |
14 | 14 | if( $j( playerElement ).hasClass('PlayerThemer') ){ |
15 | 15 | // Set the player useNativeControls attribute |
16 | 16 | $j( playerElement ).attr('usenativecontrols', true); |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/SmilPlayer/loader.js |
— | — | @@ -29,7 +29,7 @@ |
30 | 30 | } ); |
31 | 31 | |
32 | 32 | // Add the mw.SmilPlayer to the embedPlayer loader: |
33 | | - $j( mw ).bind( 'LoaderEmbedPlayerUpdateRequest', function( event, playerElement, resourceRequest ) { |
| 33 | + $j( mw ).bind( 'EmbedPlayerUpdateDependencies', function( event, playerElement, resourceRequest ) { |
34 | 34 | var smilPlayerLibrarySet = [ |
35 | 35 | "mw.SmilHooks", |
36 | 36 | "mw.Smil", |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/SwarmTransport/loader.js |
— | — | @@ -36,7 +36,7 @@ |
37 | 37 | }); |
38 | 38 | |
39 | 39 | // Add the mw.SwarmTransport to the embedPlayer loader: |
40 | | - $j( mw ).bind( 'LoaderEmbedPlayerUpdateRequest', function( event, playerElement, classRequest ) { |
| 40 | + $j( mw ).bind( 'EmbedPlayerUpdateDependencies', function( event, playerElement, classRequest ) { |
41 | 41 | // If the swarm transport is enabled add mw.SwarmTransport to the request. |
42 | 42 | if( mw.getConfig( 'SwarmTransport.Enable' ) ) { |
43 | 43 | |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/TimedText/loader.js |
— | — | @@ -58,7 +58,7 @@ |
59 | 59 | |
60 | 60 | // Update the player loader request with timedText library if the embedPlayer |
61 | 61 | // includes timedText tracks. |
62 | | - $j( mw ).bind( 'LoaderEmbedPlayerUpdateRequest', function( event, playerElement, classRequest ) { |
| 62 | + $j( mw ).bind( 'EmbedPlayerUpdateDependencies', function( event, playerElement, classRequest ) { |
63 | 63 | if( mw.isTimedTextSupported( playerElement ) ) { |
64 | 64 | classRequest = $j.merge( classRequest, mwTimedTextRequestSet ); |
65 | 65 | } |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/AddMedia/mw.RemoteSearchDriver.js |
— | — | @@ -2302,7 +2302,7 @@ |
2303 | 2303 | ); |
2304 | 2304 | mw.log( 'append html: ' + embedHtml ); |
2305 | 2305 | $j( '#clip_edit_disp' ).html( embedHtml ); |
2306 | | - var cat = $j.fn.embedPlayer; |
| 2306 | + |
2307 | 2307 | // Make sure we have the 'EmbedPlayer' module: |
2308 | 2308 | mw.load( 'EmbedPlayer', function() { |
2309 | 2309 | // Strange concurrency issue with callbacks |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/EmbedPlayer/loader.js |
— | — | @@ -1,159 +0,0 @@ |
2 | | -/** |
3 | | -* EmbedPlayer loader |
4 | | -*/ |
5 | | -/** |
6 | | -* Default player module configuration |
7 | | -*/ |
8 | | -( function( mw, $ ) { |
9 | | - /** |
10 | | - * Check the current DOM for any tags in "EmbedPlayer.RewriteTags" |
11 | | - */ |
12 | | - mw.documentHasPlayerTags = function() { |
13 | | - var rewriteTags = mw.getConfig( 'EmbedPlayer.RewriteTags' ); |
14 | | - if( $( rewriteTags ).length != 0 ) { |
15 | | - return true; |
16 | | - } |
17 | | - return false; |
18 | | - }; |
19 | | - |
20 | | - /** |
21 | | - * Add a DOM ready check for player tags |
22 | | - * |
23 | | - * We use mw.addSetupHook instead of mw.ready so that |
24 | | - * mwEmbed player is setup before any other mw.ready calls |
25 | | - */ |
26 | | - $( mw ).bind( 'SetupInterface', function( event, callback ){ |
27 | | - |
28 | | - mw.log( 'Loader::EmbedPlayer:rewritePagePlayerTags:' + mw.documentHasPlayerTags() ); |
29 | | - |
30 | | - // Allow modules to do tag rewrites as well: |
31 | | - var doModuleTagRewrites = function(){ |
32 | | - $(mw).triggerQueueCallback( 'LoadeRewritePlayerTags', callback ); |
33 | | - } |
34 | | - |
35 | | - if( mw.documentHasPlayerTags() ) { |
36 | | - var rewriteElementCount = 0; |
37 | | - |
38 | | - // Set each player to loading ( as early on as possible ) |
39 | | - $( mw.getConfig( 'EmbedPlayer.RewriteTags' ) ).each( function( index, element ){ |
40 | | - |
41 | | - // Assign an the element an ID ( if its missing one ) |
42 | | - if ( $( element ).attr( "id" ) == '' ) { |
43 | | - $( element ).attr( "id", 'v' + ( rewriteElementCount++ ) ); |
44 | | - } |
45 | | - // Add an absolute positioned loader |
46 | | - $( element ) |
47 | | - .getAbsoluteOverlaySpinner() |
48 | | - .attr('id', 'loadingSpinner_' + $( element ).attr('id') ) |
49 | | - .addClass( 'playerLoadingSpinner' ); |
50 | | - |
51 | | - }); |
52 | | - // Load the embedPlayer module ( then run queued hooks ) |
53 | | - mw.load( 'EmbedPlayer', function ( ) { |
54 | | - // Rewrite the EmbedPlayer.RewriteTags with the |
55 | | - $( mw.getConfig( 'EmbedPlayer.RewriteTags' ) ).embedPlayer( doModuleTagRewrites ); |
56 | | - }) |
57 | | - } else { |
58 | | - doModuleTagRewrites(); |
59 | | - } |
60 | | - }); |
61 | | - |
62 | | - /** |
63 | | - * Add the module loader function: |
64 | | - */ |
65 | | - mw.addModuleLoader( 'EmbedPlayer', function() { |
66 | | - var _this = this; |
67 | | - // Hide videonojs class |
68 | | - $( '.videonojs' ).hide(); |
69 | | - |
70 | | - // Set up the embed video player class request: (include the skin js as well) |
71 | | - var dependencyRequest = [ |
72 | | - [ |
73 | | - 'mw.EmbedPlayer' |
74 | | - ], |
75 | | - [ |
76 | | - 'mw.PlayerControlBuilder', |
77 | | - '$.fn.hoverIntent', |
78 | | - 'mw.style.EmbedPlayer', |
79 | | - '$.cookie', |
80 | | - // Add JSON lib if browsers does not define "JSON" natively |
81 | | - 'JSON', |
82 | | - '$.ui', |
83 | | - '$.widget' |
84 | | - ], |
85 | | - [ |
86 | | - '$.ui.mouse', |
87 | | - '$.fn.menu', |
88 | | - 'mw.style.jquerymenu', |
89 | | - '$.ui.slider' |
90 | | - ] |
91 | | - ]; |
92 | | - |
93 | | - // Pass every tag being rewritten through the update request function |
94 | | - $( mw.getConfig( 'EmbedPlayer.RewriteTags' ) ).each( function(inx, playerElement) { |
95 | | - mw.embedPlayerUpdateLibraryRequest( playerElement, dependencyRequest[ 1 ] ) |
96 | | - } ); |
97 | | - |
98 | | - // Add PNG fix code needed: |
99 | | - if ( $.browser.msie && $.browser.version < 7 ) { |
100 | | - dependencyRequest[0].push( '$.fn.pngFix' ); |
101 | | - } |
102 | | - |
103 | | - // Do short detection, to avoid extra player library request in ~most~ cases. |
104 | | - //( If browser is firefox include native, if browser is IE include java ) |
105 | | - if( $.browser.msie ) { |
106 | | - dependencyRequest[0].push( 'mw.EmbedPlayerJava' ); |
107 | | - } |
108 | | - |
109 | | - // Safari gets slower load since we have to detect ogg support |
110 | | - if( !!document.createElement('video').canPlayType && !$.browser.safari ) { |
111 | | - dependencyRequest[0].push( 'mw.EmbedPlayerNative' ) |
112 | | - } |
113 | | - // Check if the iFrame player api is enabled and we have a parent iframe url: |
114 | | - if ( mw.getConfig('EmbedPlayer.EnableIframeApi') |
115 | | - && |
116 | | - mw.getConfig( 'EmbedPlayer.IframeParentUrl' ) |
117 | | - ){ |
118 | | - dependencyRequest[0].push('mw.EmbedPlayerNative'); |
119 | | - dependencyRequest[0].push('$.postMessage'); |
120 | | - dependencyRequest[0].push('mw.IFramePlayerApiServer'); |
121 | | - } |
122 | | - |
123 | | - // Return the set of libs to be loaded |
124 | | - return dependencyRequest; |
125 | | - } ); |
126 | | - |
127 | | - /** |
128 | | - * Takes a embed player element and updates a request object with any |
129 | | - * dependent libraries per that tags attributes. |
130 | | - * |
131 | | - * For example a player skin class name could result in adding some |
132 | | - * css and javascirpt to the player library request. |
133 | | - * |
134 | | - * @param {Object} playerElement The tag to check for library dependent request classes. |
135 | | - * @param {Array} dependencyRequest The library request array |
136 | | - */ |
137 | | - mw.embedPlayerUpdateLibraryRequest = function(playerElement, dependencyRequest ){ |
138 | | - var skinName = $( playerElement ).attr( 'class' ); |
139 | | - // Set playerClassName to default if unset or not a valid skin |
140 | | - if( ! skinName || $.inArray( skinName.toLowerCase(), mw.validSkins ) == -1 ){ |
141 | | - skinName = mw.getConfig( 'EmbedPlayer.SkinName' ); |
142 | | - } |
143 | | - skinName = skinName.toLowerCase(); |
144 | | - // Add the skin to the request |
145 | | - var skinCaseName = skinName.charAt(0).toUpperCase() + skinName.substr(1); |
146 | | - // The skin js: |
147 | | - if( $.inArray( 'mw.PlayerSkin' + skinCaseName, dependencyRequest ) == -1 ){ |
148 | | - dependencyRequest.push( 'mw.PlayerSkin' + skinCaseName ); |
149 | | - } |
150 | | - // The skin css |
151 | | - if( $.inArray( 'mw.style.PlayerSkin' + skinCaseName, dependencyRequest ) == -1 ){ |
152 | | - dependencyRequest.push( 'mw.style.PlayerSkin' + skinCaseName ); |
153 | | - } |
154 | | - |
155 | | - // Allow extension to extend the request. |
156 | | - $( mw ).trigger( 'LoaderEmbedPlayerUpdateRequest', |
157 | | - [ playerElement, dependencyRequest ] ); |
158 | | - } |
159 | | - |
160 | | -} )( mediaWiki, jQuery ); |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/EmbedPlayer/EmbedPlayer.php |
— | — | @@ -1,12 +1,23 @@ |
2 | 2 | <?php |
3 | 3 | |
4 | | - // Register all the EmbedPlayer modules in the $wgResourceModules global array |
5 | | - return array( |
6 | | - 'resources' => array( |
| 4 | + // Register all the EmbedPlayer modules |
| 5 | + return array( |
7 | 6 | "mw.EmbedPlayer" => array( |
8 | | - 'scripts' => array( "mw.EmbedPlayer.js", "skins/mw.PlayerControlBuilder.js" ), |
| 7 | + 'scripts' => array( |
| 8 | + "mw.EmbedPlayer.js", |
| 9 | + "skins/mw.PlayerControlBuilder.js", |
| 10 | + ), |
| 11 | + 'dependencies' => array( |
| 12 | + // jQuery dependencies: |
| 13 | + 'jquery.hoverIntent', |
| 14 | + 'jquery.cookie', |
| 15 | + 'jquery.ui.mouse', |
| 16 | + '$.fn.menu', |
| 17 | + 'mw.style.jquerymenu', |
| 18 | + '$.ui.slider' |
| 19 | + ), |
9 | 20 | 'styles' => "skins/mw.style.EmbedPlayer.css", |
10 | | - 'messageFile' => 'EmbedPlayer.i18n.php' |
| 21 | + 'messageFile' => 'EmbedPlayer.i18n.php', |
11 | 22 | ), |
12 | 23 | |
13 | 24 | "mw.EmbedPlayerKplayer" => array( 'scripts'=> "mw.EmbedPlayerKplayer.js" ), |
— | — | @@ -24,264 +35,6 @@ |
25 | 36 | |
26 | 37 | "mw.PlayerSkinMvpcf" => array( 'scripts'=> "skins/mvpcf/mw.PlayerSkinMvpcf.js", |
27 | 38 | 'styles'=> "skins/mvpcf/mw.style.PlayerSkinMvpcf.css"), |
28 | | - ), |
29 | | - // Set any default configuration |
30 | | - 'config' => array( |
31 | | - // If the player controls should be overlaid on top of the video ( if supported by playback method) |
32 | | - // can be set to false per embed player via overlayControls attribute |
33 | | - 'EmbedPlayer.OverlayControls' => true, |
34 | | - |
35 | | - // If the iPad should use html controls ( can't use fullscreen or control volume, |
36 | | - // but lets you support overlays ie html controls ads etc. ) |
37 | | - 'EmbedPlayer.EnableIpadHTMLControls'=> false, |
38 | | - |
39 | | - 'EmbedPlayer.LibraryPage'=> 'http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library', |
40 | | - |
41 | | - // A default apiProvider ( ie where to lookup subtitles, video properties etc ) |
42 | | - // NOTE: Each player instance can also specify a specific provider |
43 | | - "EmbedPlayer.ApiProvider" => "local", |
44 | | - |
45 | | - // What tags will be re-written to video player by default |
46 | | - // Set to empty string or null to avoid automatic video tag rewrites to embedPlayer |
47 | | - "EmbedPlayer.RewriteTags" => "video,audio,playlist", |
48 | | - |
49 | | - // Default video size ( if no size provided ) |
50 | | - "EmbedPlayer.DefaultSize" => "400x300", |
51 | | - |
52 | | - // If the video player should attribute kaltura |
53 | | - "EmbedPlayer.KalturaAttribution" => true, |
54 | | - |
55 | | - // The attribution button |
56 | | - 'EmbedPlayer.AttributionButton' => array( |
57 | | - 'title' => 'Kaltura html5 video library', |
58 | | - 'href' => 'http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library', |
59 | | - // Style icon to be applied |
60 | | - 'class' => 'kaltura-icon', |
61 | | - // An icon image url ( should be a 12x12 image or data url ) |
62 | | - 'iconurl' => false |
63 | | - ), |
64 | | - |
65 | | - // If the player should wait for metadata like video size and duration, before trying to draw |
66 | | - // the player interface. |
67 | | - 'EmbedPlayer.WaitForMeta' => true, |
68 | | - |
69 | | - // Set the browser player warning flag displays warning for non optimal playback |
70 | | - "EmbedPlayer.ShowNativeWarning" => true, |
71 | | - |
72 | | - // If fullscreen is global enabled. |
73 | | - "EmbedPlayer.EnableFullscreen" => true, |
74 | | - |
75 | | - // If mwEmbed should use the Native player controls |
76 | | - // this will prevent video tag rewriting and skinning |
77 | | - // useful for devices such as iPad / iPod that |
78 | | - // don't fully support DOM overlays or don't expose full-screen |
79 | | - // functionality to javascript |
80 | | - "EmbedPlayer.NativeControls" => false, |
81 | | - |
82 | | - // If mwEmbed should use native controls on mobile safari |
83 | | - "EmbedPlayer.NativeControlsMobileSafari" => true, |
84 | | - |
85 | | - |
86 | | - // The z-index given to the player interface during full screen ( high z-index ) |
87 | | - "EmbedPlayer.fullScreenZIndex" => 999998, |
88 | | - |
89 | | - // The default share embed mode ( can be "object" or "videojs" ) |
90 | | - // |
91 | | - // "iframe" will provide a <iframe tag pointing to mwEmbedFrame.php |
92 | | - // Object embedding should be much more compatible with sites that |
93 | | - // let users embed flash applets |
94 | | - // "videojs" will include the source javascript and video tag to |
95 | | - // rewrite the player on the remote page DOM |
96 | | - // Video tag embedding is much more mash-up friendly but exposes |
97 | | - // the remote site to the mwEmbed javascript and can be a xss issue. |
98 | | - "EmbedPlayer.ShareEmbedMode" => 'iframe', |
99 | | - |
100 | | - // Default player skin name |
101 | | - "EmbedPlayer.SkinName" => "mvpcf", |
102 | | - |
103 | | - // Number of milliseconds between interface updates |
104 | | - 'EmbedPlayer.MonitorRate' => 250, |
105 | | - |
106 | | - // If the embedPlayer should accept arguments passed in from iframe postMessages calls |
107 | | - 'EmbedPlayer.EnalbeIFramePlayerServer' => false, |
108 | | - |
109 | | - // If embedPlayer should support server side temporal urls for seeking options are |
110 | | - // flash|always|none default is support for flash only. |
111 | | - 'EmbedPlayer.EnableURLTimeEncoding' => 'flash', |
112 | | - |
113 | | - // The domains which can read and send events to the video player |
114 | | - 'EmbedPLayer.IFramePlayer.DomainWhiteList' => '*', |
115 | | - |
116 | | - // If the iframe should send and receive javascript events across domains via postMessage |
117 | | - 'EmbedPlayer.EnableIframeApi' => true, |
118 | | - |
119 | | - /** |
120 | | - * The base source attribute checks also see: |
121 | | - * http://dev.w3.org/html5/spec/Overview.html#the-source-element |
122 | | - */ |
123 | | - 'EmbedPlayer.SourceAttributes' => array( |
124 | | - // source id |
125 | | - 'id', |
126 | | - |
127 | | - // media url |
128 | | - 'src', |
129 | | - |
130 | | - // Title string for the source asset |
131 | | - 'title', |
132 | | - |
133 | | - // boolean if we support temporal url requests on the source media |
134 | | - 'URLTimeEncoding', |
135 | | - |
136 | | - // Media has a startOffset ( used for plugins that |
137 | | - // display ogg page time rather than presentation time |
138 | | - 'startOffset', |
139 | | - |
140 | | - // A hint to the duration of the media file so that duration |
141 | | - // can be displayed in the player without loading the media file |
142 | | - 'durationHint', |
143 | | - |
144 | | - // Media start time |
145 | | - 'start', |
146 | | - |
147 | | - // Media end time |
148 | | - 'end', |
149 | | - |
150 | | - // If the source is the default source |
151 | | - 'default', |
152 | | - |
153 | | - // Title of the source |
154 | | - 'title', |
155 | | - |
156 | | - // titleKey ( used for api lookups TODO move into mediaWiki specific support |
157 | | - 'titleKey' |
158 | | - ), |
159 | | - /** |
160 | | - * Merge in the default video attributes supported by embedPlayer: |
161 | | - */ |
162 | | - 'EmbedPlayer.Attributes' => array( |
163 | | - /* |
164 | | - * Base html element attributes: |
165 | | - */ |
166 | | - |
167 | | - // id: Auto-populated if unset |
168 | | - "id" => null, |
169 | | - |
170 | | - // Width: alternate to "style" to set player width |
171 | | - "width" => null, |
172 | | - |
173 | | - // Height: alternative to "style" to set player height |
174 | | - "height" => null, |
175 | | - |
176 | | - /* |
177 | | - * Base html5 video element attributes / states also see: |
178 | | - * http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html |
179 | | - */ |
180 | | - |
181 | | - // Media src URI, can be relative or absolute URI |
182 | | - "src" => null, |
183 | | - |
184 | | - // Poster attribute for displaying a place holder image before loading |
185 | | - // or playing the video |
186 | | - "poster" => null, |
187 | | - |
188 | | - // Autoplay if the media should start playing |
189 | | - "autoplay" => false, |
190 | | - |
191 | | - // Loop attribute if the media should repeat on complete |
192 | | - "loop" => false, |
193 | | - |
194 | | - // If the player controls should be displayed |
195 | | - "controls" => true, |
196 | | - |
197 | | - // Video starts "paused" |
198 | | - "paused" => true, |
199 | | - |
200 | | - // ReadyState an attribute informs clients of video loading state: |
201 | | - // see: http://www.whatwg.org/specs/web-apps/current-work/#readystate |
202 | | - "readyState" => 0, |
203 | | - |
204 | | - // Loading state of the video element |
205 | | - "networkState" => 0, |
206 | | - |
207 | | - // Current playback position |
208 | | - "currentTime" => 0, |
209 | | - |
210 | | - // Previous player set time |
211 | | - // Lets javascript use $j('#videoId').get(0).currentTime = newTime; |
212 | | - "previousTime" => 0, |
213 | | - |
214 | | - // Previous player set volume |
215 | | - // Lets javascript use $j('#videoId').get(0).volume = newVolume; |
216 | | - "previousVolume" => 1, |
217 | | - |
218 | | - // Initial player volume: |
219 | | - "volume" => 0.75, |
220 | | - |
221 | | - // Caches the volume before a mute toggle |
222 | | - "preMuteVolume" => 0.75, |
223 | | - |
224 | | - // Media duration: Value is populated via |
225 | | - // custom durationHint attribute or via the media file once its played |
226 | | - "duration" => null, |
227 | | - |
228 | | - // Mute state |
229 | | - "muted" => false, |
230 | | - |
231 | | - /** |
232 | | - * Custom attributes for embedPlayer player: (not part of the html5 |
233 | | - * video spec) |
234 | | - */ |
235 | | - |
236 | | - // Default video aspect ratio |
237 | | - 'videoAspect' => '4:3', |
238 | | - |
239 | | - // Start time of the clip |
240 | | - "start" => 0, |
241 | | - |
242 | | - // End time of the clip |
243 | | - "end" => null, |
244 | | - |
245 | | - // A apiTitleKey for looking up subtitles, credits and related videos |
246 | | - // TODO move to data-mwTitleKey and into mediaWikiSupport module |
247 | | - "apiTitleKey" => null, |
248 | | - |
249 | | - // The apiProvider where to lookup the title key |
250 | | - // TODO move to data-mwApiProvider and into mediaWikiSupport module |
251 | | - "apiProvider" => null, |
252 | | - |
253 | | - // If the player controls should be overlaid |
254 | | - // ( Global default via config EmbedPlayer.OverlayControls in module |
255 | | - // loader.js) |
256 | | - "overlaycontrols" => true, |
257 | | - |
258 | | - // Attribute to use 'native' controls |
259 | | - "usenativecontrols" => false, |
260 | | - |
261 | | - // If the player should include an attribution button: |
262 | | - 'attributionbutton' => true, |
263 | | - |
264 | | - // ROE url ( for xml based metadata ) |
265 | | - // also see: http://wiki.xiph.org/ROE |
266 | | - "roe" => null, |
267 | | - |
268 | | - // If serving an ogg_chop segment use this to offset the presentation |
269 | | - // time |
270 | | - // ( for some plugins that use ogg page time rather than presentation |
271 | | - // time ) |
272 | | - "startOffset" => 0, |
273 | | - |
274 | | - // Source page for media asset ( used for linkbacks in remote embedding |
275 | | - // ) |
276 | | - "linkback" => null, |
277 | | - |
278 | | - // If the download link should be shown |
279 | | - "download_link" => true, |
280 | | - |
281 | | - // Content type of the media |
282 | | - "type" => null |
283 | | - ), |
284 | | - ), |
285 | 39 | ); |
286 | 40 | |
287 | | - |
288 | 41 | ?> |
\ No newline at end of file |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/EmbedPlayer/EmbedPlayer.config.php |
— | — | @@ -0,0 +1,101 @@ |
| 2 | +<?php |
| 3 | + /** |
| 4 | + * Do not edit this file instead use LocalSettings.php and |
| 5 | + * $wgMwEmbedModuleConfig[ {ModuleName} ][ {configuration name} ] = value; format |
| 6 | + */ |
| 7 | + |
| 8 | + return array( |
| 9 | + // If the player controls should be overlaid on top of the video ( if supported by playback method) |
| 10 | + // can be set to false per embed player via overlayControls attribute |
| 11 | + 'EmbedPlayer.OverlayControls' => true, |
| 12 | + |
| 13 | + // The preferred media codec preference |
| 14 | + // Note user selected format order |
| 15 | + 'EmbedPlayer.CodecPreference' => array( 'webm', 'h264', 'ogg' ), |
| 16 | + |
| 17 | + // If the iPad should use html controls ( can't use fullscreen or control volume, |
| 18 | + // but lets you support overlays ie html controls ads etc. ) |
| 19 | + 'EmbedPlayer.EnableIpadHTMLControls'=> false, |
| 20 | + |
| 21 | + 'EmbedPlayer.LibraryPage'=> 'http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library', |
| 22 | + |
| 23 | + // A default apiProvider ( ie where to lookup subtitles, video properties etc ) |
| 24 | + // NOTE: Each player instance can also specify a specific provider |
| 25 | + "EmbedPlayer.ApiProvider" => "local", |
| 26 | + |
| 27 | + // What tags will be re-written to video player by default |
| 28 | + // Set to empty string or null to avoid automatic video tag rewrites to embedPlayer |
| 29 | + "EmbedPlayer.RewriteTags" => "video,audio,playlist", |
| 30 | + |
| 31 | + // Default video size ( if no size provided ) |
| 32 | + "EmbedPlayer.DefaultSize" => "400x300", |
| 33 | + |
| 34 | + // If the video player should attribute kaltura |
| 35 | + "EmbedPlayer.KalturaAttribution" => true, |
| 36 | + |
| 37 | + // The attribution button |
| 38 | + 'EmbedPlayer.AttributionButton' => array( |
| 39 | + 'title' => 'Kaltura html5 video library', |
| 40 | + 'href' => 'http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library', |
| 41 | + // Style icon to be applied |
| 42 | + 'class' => 'kaltura-icon', |
| 43 | + // An icon image url ( should be a 12x12 image or data url ) |
| 44 | + 'iconurl' => false |
| 45 | + ), |
| 46 | + |
| 47 | + // If the player should wait for metadata like video size and duration, before trying to draw |
| 48 | + // the player interface. |
| 49 | + 'EmbedPlayer.WaitForMeta' => true, |
| 50 | + |
| 51 | + // Set the browser player warning flag displays warning for non optimal playback |
| 52 | + "EmbedPlayer.ShowNativeWarning" => true, |
| 53 | + |
| 54 | + // If fullscreen is global enabled. |
| 55 | + "EmbedPlayer.EnableFullscreen" => true, |
| 56 | + |
| 57 | + // If mwEmbed should use the Native player controls |
| 58 | + // this will prevent video tag rewriting and skinning |
| 59 | + // useful for devices such as iPad / iPod that |
| 60 | + // don't fully support DOM overlays or don't expose full-screen |
| 61 | + // functionality to javascript |
| 62 | + "EmbedPlayer.NativeControls" => false, |
| 63 | + |
| 64 | + // If mwEmbed should use native controls on mobile safari |
| 65 | + "EmbedPlayer.NativeControlsMobileSafari" => true, |
| 66 | + |
| 67 | + |
| 68 | + // The z-index given to the player interface during full screen ( high z-index ) |
| 69 | + "EmbedPlayer.fullScreenZIndex" => 999998, |
| 70 | + |
| 71 | + // The default share embed mode ( can be "iframe" or "xssVideo" ) |
| 72 | + // |
| 73 | + // "iframe" will provide a <iframe tag pointing to mwEmbedFrame.php |
| 74 | + // Object embedding should be much more compatible with sites that |
| 75 | + // let users embed flash applets |
| 76 | + // "xssVideo" will include the source javascript and video tag to |
| 77 | + // rewrite the player on the remote page DOM |
| 78 | + // Video tag embedding is much more mash-up friendly but exposes |
| 79 | + // the remote site to the mwEmbed javascript and can be a xss issue. |
| 80 | + "EmbedPlayer.ShareEmbedMode" => 'iframe', |
| 81 | + |
| 82 | + // Default player skin name |
| 83 | + "EmbedPlayer.DefaultSkin" => "mvpcf", |
| 84 | + |
| 85 | + // Number of milliseconds between interface updates |
| 86 | + 'EmbedPlayer.MonitorRate' => 250, |
| 87 | + |
| 88 | + // If the embedPlayer should accept arguments passed in from iframe postMessages calls |
| 89 | + 'EmbedPlayer.EnalbeIFramePlayerServer' => false, |
| 90 | + |
| 91 | + // If embedPlayer should support server side temporal urls for seeking options are |
| 92 | + // flash|always|none default is support for flash only. |
| 93 | + 'EmbedPlayer.EnableURLTimeEncoding' => 'flash', |
| 94 | + |
| 95 | + // The domains which can read and send events to the video player |
| 96 | + 'EmbedPLayer.IFramePlayer.DomainWhiteList' => '*', |
| 97 | + |
| 98 | + // If the iframe should send and receive javascript events across domains via postMessage |
| 99 | + 'EmbedPlayer.EnableIframeApi' => true, |
| 100 | + |
| 101 | + ); |
| 102 | +?> |
\ No newline at end of file |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayer.js |
— | — | @@ -7,12 +7,7 @@ |
8 | 8 | * mw.PlayerControlBuilder Handles skinning of the player controls |
9 | 9 | */ |
10 | 10 | |
11 | | -/** |
12 | | - * Add the messages text: |
13 | | - */ |
14 | 11 | |
15 | | -mw.includeAllModuleMessages(); |
16 | | - |
17 | 12 | /** |
18 | 13 | * The base source attribute checks also see: |
19 | 14 | * http://dev.w3.org/html5/spec/Overview.html#the-source-element |
— | — | @@ -52,172 +47,18 @@ |
53 | 48 | ] ); |
54 | 49 | |
55 | 50 | /** |
56 | | - * Adds jQuery binding for embedPlayer |
57 | | - */ |
58 | | -( function( $ ) { |
59 | | - |
60 | | - /* |
61 | | - * embeds all players that match the rewrite player tags config Passes off |
62 | | - * request to the embedPlayer selector: |
63 | | - * |
64 | | - * @param {Object} attributes Attributes to apply to embed players @param |
65 | | - * {Function} callback Function to call once embedding is done |
66 | | - */ |
67 | | - $.embedPlayers = function( attributes, callback) { |
68 | | - $j( mw.getConfig( 'EmbedPlayer.RewriteTags' ) ).embedPlayer( attributes, callback ); |
69 | | - }; |
70 | | - |
71 | | - /** |
72 | | - * Selector based embedPlayer jQuery binding |
73 | | - * |
74 | | - * Rewrites all tags via a given selector |
75 | | - * |
76 | | - * @param {object=} attributes |
77 | | - * Optional embedPlayer attributes for the given video |
78 | | - * interface. Attributes Object can include any key value pair |
79 | | - * that would otherwise be an attribute in the html element. |
80 | | - * |
81 | | - * also see: mw.getConfig( 'EmbedPlayer.Attributes' ) |
82 | | - * |
83 | | - * @param {Function=} |
84 | | - * callback Optional Function to be called once video interfaces |
85 | | - * are ready |
86 | | - * |
87 | | - */ |
88 | | - $.fn.embedPlayer = function( attributes, callback ) { |
89 | | - mw.log( 'EmbedPlayer:: fn.embedPlayer' ); |
90 | | - if( this.selector ){ |
91 | | - var playerSelect = this.selector; |
92 | | - } else { |
93 | | - var playerSelect = this; |
94 | | - } |
95 | | - |
96 | | - // Define attributes if unset |
97 | | - if( !attributes ) { |
98 | | - attributes = {}; |
99 | | - } |
100 | | - |
101 | | - // Handle optional include of attributes argument: |
102 | | - if( typeof attributes == 'function' ){ |
103 | | - callback = attributes; |
104 | | - attributes = {}; |
105 | | - } |
106 | | - |
107 | | - $j( playerSelect ).each( function( index, playerElement) { |
108 | | - // make sure the playerElement has an id: |
109 | | - if( !$j( playerElement ).attr('id') ){ |
110 | | - $j( playerElement ).attr( "id", 'mwe_v' + ( index ) ); |
111 | | - } |
112 | | - |
113 | | - // If we are dynamically embedding on a "div" check if we can |
114 | | - // add a poster image behind the loader: |
115 | | - if( playerElement.nodeName.toLowerCase() == 'div' |
116 | | - && ( attributes.poster || $j(playerElement).attr( 'poster' ) ) ){ |
117 | | - var posterSrc = ( attributes.poster ) ? attributes.poster : $j(playerElement).attr( 'poster' ); |
118 | | - |
119 | | - // Set image size: |
120 | | - var width = $j( playerElement ).width(); |
121 | | - var height = $j( playerElement ).height(); |
122 | | - if( !width ){ |
123 | | - var width = ( attributes.width )? attributes.width : '100%'; |
124 | | - } |
125 | | - if( !height ){ |
126 | | - var height = ( attributes.height )? attributes.height : '100%'; |
127 | | - } |
128 | | - |
129 | | - mw.log('EmbedPlayer:: set loading background: ' + posterSrc); |
130 | | - $j( playerElement ).append( |
131 | | - $j( '<img />' ) |
132 | | - .attr( 'src', posterSrc) |
133 | | - .css({ |
134 | | - 'position' : 'absolute', |
135 | | - 'width' : width, |
136 | | - 'height' : height |
137 | | - }) |
138 | | - ); |
139 | | - } |
140 | | - }); |
141 | | - |
142 | | - // If we have not detected browser plugin embed types do that now |
143 | | - if( ! mw.EmbedTypes.players ){ |
144 | | - mw.EmbedTypes.init(); |
145 | | - } |
146 | | - |
147 | | - // Create the Global Embed Player Manager ( if not already created ) |
148 | | - if( ! mw.playerManager ) { |
149 | | - mw.log( "EmbedPlayer::Create the player manager:" ); |
150 | | - mw.playerManager = new EmbedPlayerManager(); |
151 | | - // Run the global hooks that mw.playerManager is ready |
152 | | - mw.log( 'EmbedPlayer::trigger: EmbedPlayerManagerReady'); |
153 | | - $j( mw ).trigger( 'EmbedPlayerManagerReady' ); |
154 | | - } |
155 | | - // Make sure we have user preference setup ( for setting preferences on |
156 | | - // video selection ) |
157 | | - mw.setupUserConfig( function() { |
158 | | - |
159 | | - var addedToPlayerManager = false; |
160 | | - mw.log("EmbedPlayer:: do: " + $j( playerSelect ).length + ' players '); |
161 | | - |
162 | | - // Add each selected element to the player manager: |
163 | | - $j( playerSelect ).each( function( index, playerElement) { |
164 | | - // Make sure the video tag was not generated by our library: |
165 | | - if( $j( playerElement ).hasClass( 'nativeEmbedPlayerPid' ) ){ |
166 | | - $j('#loadingSpinner_' + $j( playerElement ).attr('id') ).hide(); |
167 | | - mw.log( 'EmbedPlayer::$j.embedPlayer skip embedPlayer gennerated video: ' + playerElement ); |
168 | | - } else { |
169 | | - addedToPlayerManager = true; |
170 | | - // Add the player |
171 | | - mw.playerManager.addPlayerElement( playerElement, attributes); |
172 | | - } |
173 | | - } ); |
174 | | - if( addedToPlayerManager ){ |
175 | | - if( callback ){ |
176 | | - $j( mw ).bind( "playersReadyEvent", callback ); |
177 | | - } |
178 | | - } else { |
179 | | - // Run the callback directly if no players were added to the |
180 | | - if( callback ){ |
181 | | - callback(); |
182 | | - } |
183 | | - } |
184 | | - |
185 | | - }); |
186 | | - }; |
187 | | - |
188 | | -} )( jQuery ); |
189 | | - |
190 | | -/** |
191 | | - * EmbedPlayerManager |
| 51 | + * Selector based embedPlayer processing |
| 52 | + * |
| 53 | + * @param {Function=} |
| 54 | + * callback Optional Function to be called once video interfaces |
| 55 | + * are ready |
192 | 56 | * |
193 | | - * Manages calls to embed video interfaces |
194 | 57 | */ |
195 | | -var EmbedPlayerManager = function( ) { |
196 | | - // Create a Player Manage |
197 | | - return this.init( ); |
198 | | -}; |
199 | | -EmbedPlayerManager.prototype = { |
200 | | - |
201 | | - // Functions to run after the video interface is ready |
202 | | - callbackFunctions : null, |
203 | | - |
204 | | - playerElementQueue: [], |
205 | | - |
| 58 | +mw.processEmbedPlayers = function( playerSelect, callback ) { |
| 59 | + mw.log( 'EmbedPlayer:: processEmbedPlayers' ); |
| 60 | + |
| 61 | + |
206 | 62 | /** |
207 | | - * Constructor initializes callbackFunctions and playerList |
208 | | - */ |
209 | | - init: function( ) { |
210 | | - this.callbackFunctions = []; |
211 | | - this.playerList = []; |
212 | | - }, |
213 | | - |
214 | | - /** |
215 | | - * Get the list of players |
216 | | - */ |
217 | | - getPlayerList: function( ) { |
218 | | - return this.playerList; |
219 | | - }, |
220 | | - |
221 | | - /** |
222 | 63 | * Adds a player element for the embedPlayer to rewrite |
223 | 64 | * |
224 | 65 | * uses embedPlayer interface on audio / video elements uses mvPlayList |
— | — | @@ -238,102 +79,79 @@ |
239 | 80 | * [Optional] attributes Extra attributes to apply to the player |
240 | 81 | * interface |
241 | 82 | */ |
242 | | - addPlayerElement: function( playerElement, attributes ) { |
| 83 | + var addPlayerElement = function( playerElement ) { |
243 | 84 | var _this = this; |
244 | | - if ( !playerElement.id || playerElement.id == '' ) { |
245 | | - // give the playerElement an id: |
246 | | - playerElement.id = 'vid' + ( this.playerList.length + 1 ); |
247 | | - } |
248 | 85 | mw.log('EmbedPlayerManager: addElement:: ' + playerElement.id ); |
249 | 86 | |
250 | | - // Add the element id to playerList |
251 | | - this.playerList.push( playerElement.id ); |
| 87 | + var waitForMeta = true; |
252 | 88 | |
253 | | - // Check for player attributes such as skins or plugins attributes |
254 | | - // that add to the request set |
255 | | - var playerDependencyRequest = []; |
256 | | - |
257 | | - // Merge in any custom attributes |
258 | | - $j.extend( playerElement, attributes ); |
259 | | - |
260 | | - // Update the list of dependent libraries for the player |
261 | | - // ( allows modules to add to the player dependency list ) |
262 | | - mw.embedPlayerUpdateLibraryRequest( playerElement, playerDependencyRequest ); |
| 89 | + // Be sure to "stop" the target ( Firefox 3x keeps playing |
| 90 | + // the video even though its been removed from the DOM ) |
| 91 | + if( playerElement.pause ){ |
| 92 | + playerElement.pause(); |
| 93 | + } |
263 | 94 | |
264 | | - // Load any skins we need then swap in the interface |
265 | | - mw.load( playerDependencyRequest, function() { |
266 | | - |
267 | | - var waitForMeta = true; |
| 95 | + // Allow modules to override the wait for metadata flag: |
| 96 | + $j( mw ).trigger( 'checkPlayerWaitForMetaData', playerElement ); |
268 | 97 | |
269 | | - // Be sure to "stop" the target ( Firefox 3x keeps playing |
270 | | - // the video even though its been removed from the DOM ) |
271 | | - if( playerElement.pause ){ |
272 | | - playerElement.pause(); |
273 | | - } |
274 | | - |
275 | | - // Allow modules to override the wait for metadata flag: |
276 | | - $j( mw ).trigger( 'checkPlayerWaitForMetaData', playerElement ); |
| 98 | + // Update the waitForMeta object if set to boolean false: |
| 99 | + waitForMeta = ( playerElement.waitForMeta === false )? false : true; |
277 | 100 | |
278 | | - // Update the waitForMeta object if set to boolean false: |
279 | | - waitForMeta = ( playerElement.waitForMeta === false )? false : true; |
280 | 101 | |
| 102 | + // Confirm we want to wait for meta data ( if not already set to false by module ) |
| 103 | + if( waitForMeta ){ |
| 104 | + waitForMeta = waitForMetaCheck( playerElement ); |
| 105 | + } |
281 | 106 | |
282 | | - // Confirm we want to wait for meta data ( if not already set to false by module ) |
283 | | - if( waitForMeta ){ |
284 | | - waitForMeta = _this.waitForMetaCheck( playerElement ); |
| 107 | + var ranPlayerSwapFlag = false; |
| 108 | + |
| 109 | + // Local callback to runPlayer swap once playerElement has metadata |
| 110 | + function runPlayerSwap() { |
| 111 | + // Don't run player swap twice |
| 112 | + if( ranPlayerSwapFlag ){ |
| 113 | + return ; |
285 | 114 | } |
| 115 | + ranPlayerSwapFlag = true; |
| 116 | + mw.log("EmbedPlayer::runPlayerSwap::" + $j( playerElement ).attr('id') ); |
286 | 117 | |
287 | | - var ranPlayerSwapFlag = false; |
| 118 | + var playerInterface = new mw.EmbedPlayer( playerElement , attributes); |
| 119 | + var swapPlayer = swapEmbedPlayerElement( playerElement, playerInterface ); |
| 120 | + |
288 | 121 | |
289 | | - // Local callback to runPlayer swap once playerElement has metadata |
290 | | - function runPlayerSwap() { |
291 | | - // Don't run player swap twice |
292 | | - if( ranPlayerSwapFlag ){ |
293 | | - return ; |
294 | | - } |
295 | | - ranPlayerSwapFlag = true; |
296 | | - mw.log("EmbedPlayer::runPlayerSwap::" + $j( playerElement ).attr('id') ); |
| 122 | + // Trigger the newEmbedPlayerEvent for embedPlayer interface |
| 123 | + mw.log("EmbedPlayer::addPlayerElement :trigger " + playerInterface.id ); |
| 124 | + $j( mw ).trigger ( 'newEmbedPlayerEvent', $j( '#' + playerInterface.id ).get(0) ); |
297 | 125 | |
298 | | - var playerInterface = new mw.EmbedPlayer( playerElement , attributes); |
299 | | - var swapPlayer = _this.swapEmbedPlayerElement( playerElement, playerInterface ); |
300 | | - |
| 126 | + // Issue the checkPlayerSources call to the new player |
| 127 | + // interface: make sure to use the element that is in the DOM: |
| 128 | + $j( '#' + playerInterface.id ).get(0).checkPlayerSources(); |
| 129 | + } |
301 | 130 | |
302 | | - // Trigger the newEmbedPlayerEvent for embedPlayer interface |
303 | | - mw.log("EmbedPlayer::addPlayerElement :trigger " + playerInterface.id ); |
304 | | - $j( mw ).trigger ( 'newEmbedPlayerEvent', $j( '#' + playerInterface.id ).get(0) ); |
| 131 | + if( waitForMeta && mw.getConfig('EmbedPlayer.WaitForMeta' ) ) { |
| 132 | + mw.log('EmbedPlayer::WaitForMeta ( video missing height (' + |
| 133 | + $j( playerElement ).attr('height') + '), width (' + |
| 134 | + $j( playerElement ).attr('width') + ') or duration: ' + |
| 135 | + $j( playerElement ).attr('duration') |
| 136 | + ); |
| 137 | + $j( playerElement ).bind("loadedmetadata", runPlayerSwap ); |
305 | 138 | |
306 | | - // Issue the checkPlayerSources call to the new player |
307 | | - // interface: make sure to use the element that is in the DOM: |
308 | | - $j( '#' + playerInterface.id ).get(0).checkPlayerSources(); |
309 | | - } |
| 139 | + // Time-out of 5 seconds ( maybe still playable but no timely |
| 140 | + // metadata ) |
| 141 | + setTimeout( runPlayerSwap, 5000 ); |
| 142 | + return ; |
| 143 | + } else { |
| 144 | + runPlayerSwap(); |
| 145 | + return ; |
| 146 | + } |
| 147 | + }; |
310 | 148 | |
311 | | - if( waitForMeta && mw.getConfig('EmbedPlayer.WaitForMeta' ) ) { |
312 | | - mw.log('EmbedPlayer::WaitForMeta ( video missing height (' + |
313 | | - $j( playerElement ).attr('height') + '), width (' + |
314 | | - $j( playerElement ).attr('width') + ') or duration: ' + |
315 | | - $j( playerElement ).attr('duration') |
316 | | - ); |
317 | | - $j( playerElement ).bind("loadedmetadata", runPlayerSwap ); |
318 | | - |
319 | | - // Time-out of 5 seconds ( maybe still playable but no timely |
320 | | - // metadata ) |
321 | | - setTimeout( runPlayerSwap, 5000 ); |
322 | | - return ; |
323 | | - } else { |
324 | | - runPlayerSwap(); |
325 | | - return ; |
326 | | - } |
327 | | - }); |
328 | | - }, |
329 | | - |
330 | 149 | /** |
331 | | - * Check for bogus resolutions of the media asset that has not loaded. |
| 150 | + * Check if we should wait for metadata. |
332 | 151 | * |
333 | | - * @return true if the resolution is "likely" to be updated by waiting for |
334 | | - * metadata false if the resolution has been set via an attribute or |
335 | | - * is already loaded |
| 152 | + * @return true if the size is "likely" to be updated by waiting for metadata |
| 153 | + * false if the size has been set via an attribute or is already loaded |
336 | 154 | */ |
337 | | - waitForMetaCheck: function( playerElement ){ |
| 155 | + var waitForMetaCheck = function( playerElement ){ |
338 | 156 | var waitForMeta = false; |
339 | 157 | |
340 | 158 | // Don't wait for metadata for non html5 media elements |
— | — | @@ -344,9 +162,9 @@ |
345 | 163 | return false; |
346 | 164 | } |
347 | 165 | // If we don't have a native player don't wait for metadata |
348 | | - if( !mw.EmbedTypes.players.isSupportedPlayer( 'oggNative') && |
349 | | - !mw.EmbedTypes.players.isSupportedPlayer( 'webmNative') && |
350 | | - !mw.EmbedTypes.players.isSupportedPlayer( 'h264Native' ) ) |
| 166 | + if( !mw.EmbedTypes.getMediaPlayers().isSupportedPlayer( 'oggNative') && |
| 167 | + !mw.EmbedTypes.getMediaPlayers().isSupportedPlayer( 'webmNative') && |
| 168 | + !mw.EmbedTypes.getMediaPlayers().isSupportedPlayer( 'h264Native' ) ) |
351 | 169 | { |
352 | 170 | return false; |
353 | 171 | } |
— | — | @@ -355,9 +173,9 @@ |
356 | 174 | var width = $j( playerElement ).css( 'width' ); |
357 | 175 | var height = $j( playerElement ).css( 'height' ); |
358 | 176 | |
359 | | - // Css video defaults |
| 177 | + // Css video defaults ( firefox ) |
360 | 178 | if( $j( playerElement ).css( 'width' ) == '300px' && |
361 | | - $j( playerElement ).css( 'height' ) == '150px' |
| 179 | + $j( playerElement ).css( 'height' ) == '150px' |
362 | 180 | ){ |
363 | 181 | waitForMeta = true; |
364 | 182 | } else { |
— | — | @@ -372,7 +190,7 @@ |
373 | 191 | } |
374 | 192 | } |
375 | 193 | |
376 | | - // Firefox ~ sometimes ~ gives -1 for unloaded media |
| 194 | + // Firefox ~ sometimes~ gives -1 for unloaded media |
377 | 195 | if ( $j(playerElement).attr( 'width' ) == -1 || $j(playerElement).attr( 'height' ) == -1 ) { |
378 | 196 | waitForMeta = true; |
379 | 197 | } |
— | — | @@ -409,15 +227,14 @@ |
410 | 228 | /** |
411 | 229 | * swapEmbedPlayerElement |
412 | 230 | * |
413 | | - * Takes a video element as input and swaps it out with an embed player |
414 | | - * interface |
| 231 | + * Takes a video element as input and swaps it out with an embed player interface |
415 | 232 | * |
416 | 233 | * @param {Element} |
417 | 234 | * targetElement Element to be swapped |
418 | 235 | * @param {Object} |
419 | 236 | * playerInterface Interface to swap into the target element |
420 | 237 | */ |
421 | | - swapEmbedPlayerElement: function( targetElement, playerInterface ) { |
| 238 | + var swapEmbedPlayerElement = function( targetElement, playerInterface ) { |
422 | 239 | mw.log( 'EmbedPlayer::swapEmbedPlayerElement: ' + targetElement.id ); |
423 | 240 | // Create a new element to swap the player interface into |
424 | 241 | var swapPlayerElement = document.createElement('div'); |
— | — | @@ -460,46 +277,88 @@ |
461 | 278 | $spinner.attr('id', 'loadingSpinner_' + playerInterface.id ); |
462 | 279 | } |
463 | 280 | return swapPlayerElement; |
464 | | - }, |
| 281 | + }; |
465 | 282 | |
| 283 | + |
| 284 | + |
| 285 | + |
| 286 | + |
| 287 | + // Add a loader for <div> embed player rewrites: |
| 288 | + $j( playerSelect ).each( function( index, playerElement) { |
| 289 | + |
| 290 | + // Make sure the playerElement has an id: |
| 291 | + if( !$j( playerElement ).attr('id') ){ |
| 292 | + $j( playerElement ).attr( "id", 'mwe_v' + ( index ) ); |
| 293 | + } |
466 | 294 | |
467 | | - /** |
468 | | - * Player ready will run the global callbacks once players are "ready" |
469 | | - * |
470 | | - * This enables mw.ready event to expose video tag elements as if the |
471 | | - * videotag was supported natively. |
472 | | - * |
473 | | - * @param {Object} |
474 | | - * player The EmbedPlayer object |
475 | | - */ |
476 | | - playerReady: function( player ) { |
477 | | - var _this = this; |
478 | | - mw.log( 'EmbedPlayer::ReadyToPlay callback player:' + player.id ); |
479 | | - player.readyToPlay = true; |
| 295 | + // If we are dynamically embedding on a "div" check if we can |
| 296 | + // add a poster image behind the loader: |
| 297 | + if( playerElement.nodeName.toLowerCase() == 'div' |
| 298 | + && ( attributes.poster || $j(playerElement).attr( 'poster' ) ) ){ |
| 299 | + var posterSrc = ( attributes.poster ) ? attributes.poster : $j(playerElement).attr( 'poster' ); |
480 | 300 | |
481 | | - // Remove the player loader spinner: |
482 | | - $j('#loadingSpinner_' + player.id ).remove(); |
483 | | - |
484 | | - // Run the player ready trigger |
485 | | - $j( player ).trigger( 'playerReady' ); |
486 | | - |
487 | | - var is_ready = true; |
488 | | - for ( var i = 0; i < this.playerList.length; i++ ) { |
489 | | - var currentPlayer = $j( '#' + this.playerList[i] ).get( 0 ); |
490 | | - if ( player ) { |
491 | | - // Check if the current video is ready ( or has an error out ) |
492 | | - is_ready = ( player.readyToPlay || player.loadError ) ? is_ready : false; |
| 301 | + // Set image size: |
| 302 | + var width = $j( playerElement ).width(); |
| 303 | + var height = $j( playerElement ).height(); |
| 304 | + if( !width ){ |
| 305 | + var width = ( attributes.width )? attributes.width : '100%'; |
493 | 306 | } |
| 307 | + if( !height ){ |
| 308 | + var height = ( attributes.height )? attributes.height : '100%'; |
| 309 | + } |
| 310 | + |
| 311 | + mw.log('EmbedPlayer:: set loading background: ' + posterSrc); |
| 312 | + $j( playerElement ).append( |
| 313 | + $j( '<img />' ) |
| 314 | + .attr( 'src', posterSrc) |
| 315 | + .css({ |
| 316 | + 'position' : 'absolute', |
| 317 | + 'width' : width, |
| 318 | + 'height' : height |
| 319 | + }) |
| 320 | + ); |
494 | 321 | } |
495 | | - if ( is_ready ) { |
496 | | - // Be sure to remove any player loader spinners |
497 | | - $j('.loadingSpinner').remove(); |
| 322 | + }); |
498 | 323 | |
499 | | - mw.log( "EmbedPlayer::All on-page players ready run playerManager callbacks" ); |
| 324 | + // Create the Global Embed Player Manager ( if not already created ) |
| 325 | + if( ! mw.playerManager ) { |
| 326 | + mw.log( "EmbedPlayer::Create the player manager:" ); |
| 327 | + mw.playerManager = new EmbedPlayerManager(); |
| 328 | + // Run the global hooks that mw.playerManager is ready |
| 329 | + mw.log( 'EmbedPlayer::trigger: EmbedPlayerManagerReady'); |
| 330 | + $j( mw ).trigger( 'EmbedPlayerManagerReady' ); |
| 331 | + } |
| 332 | + |
| 333 | + // Make sure we have user preference setup for setting preferences on video selection |
| 334 | + mw.setupUserConfig( function() { |
500 | 335 | |
501 | | - $j(mw).trigger( 'playersReadyEvent' ); |
| 336 | + var addedToPlayerManager = false; |
| 337 | + mw.log("EmbedPlayer:: do: " + $j( playerSelect ).length + ' players '); |
| 338 | + |
| 339 | + // Add each selected element to the player manager: |
| 340 | + $j( playerSelect ).each( function( index, playerElement) { |
| 341 | + // Make sure the video tag was not generated by our library: |
| 342 | + if( $j( playerElement ).hasClass( 'nativeEmbedPlayerPid' ) ){ |
| 343 | + $j('#loadingSpinner_' + $j( playerElement ).attr('id') ).hide(); |
| 344 | + mw.log( 'EmbedPlayer::$j.embedPlayer skip embedPlayer gennerated video: ' + playerElement ); |
| 345 | + } else { |
| 346 | + addedToPlayerManager = true; |
| 347 | + // Add the player |
| 348 | + mw.playerManager.addPlayerElement( playerElement ); |
| 349 | + } |
| 350 | + } ); |
| 351 | + if( addedToPlayerManager ){ |
| 352 | + if( callback ){ |
| 353 | + $j( mw ).bind( "playersReadyEvent", callback ); |
| 354 | + } |
| 355 | + } else { |
| 356 | + // Run the callback directly if no players were added to the |
| 357 | + if( callback ){ |
| 358 | + callback(); |
| 359 | + } |
502 | 360 | } |
503 | | - } |
| 361 | + |
| 362 | + }); |
504 | 363 | }; |
505 | 364 | |
506 | 365 | /** |
— | — | @@ -787,45 +646,45 @@ |
788 | 647 | // http://www.jibbering.com/2002/4/httprequest.html |
789 | 648 | var urlParts = mw.parseUri( uri ); |
790 | 649 | // Get the extension from the url or from the relative name: |
791 | | - var ext = ( urlParts.file )? urlParts.file.substr( -4 ) : uri.substr( -4 ); |
792 | | - switch( ext.toLowerCase() ) { |
| 650 | + var ext = ( urlParts.file )? /[^.]+$/.exec( urlParts.file ) : /[^.]+$/.exec( uri ); |
| 651 | + switch( ext.toString().toLowerCase() ) { |
793 | 652 | case 'smil': |
794 | | - case '.sml': |
| 653 | + case 'sml': |
795 | 654 | return 'application/smil'; |
796 | 655 | break; |
797 | | - case '.m4v': |
798 | | - case '.mp4': |
| 656 | + case 'm4v': |
| 657 | + case 'mp4': |
799 | 658 | return 'video/h264'; |
800 | 659 | break; |
801 | 660 | case 'webm': |
802 | 661 | return 'video/webm'; |
803 | 662 | break; |
804 | | - case '.srt': |
| 663 | + case 'srt': |
805 | 664 | return 'text/x-srt'; |
806 | 665 | break; |
807 | | - case '.flv': |
| 666 | + case 'flv': |
808 | 667 | return 'video/x-flv'; |
809 | 668 | break; |
810 | | - case '.ogg': |
811 | | - case '.ogv': |
| 669 | + case 'ogg': |
| 670 | + case 'ogv': |
812 | 671 | return 'video/ogg'; |
813 | 672 | break; |
814 | | - case '.oga': |
| 673 | + case 'oga': |
815 | 674 | return 'audio/ogg'; |
816 | 675 | break; |
817 | | - case '.anx': |
| 676 | + case 'anx': |
818 | 677 | return 'video/ogg'; |
819 | 678 | break; |
820 | | - case '.xml': |
| 679 | + case 'xml': |
821 | 680 | return 'text/xml'; |
822 | 681 | break; |
823 | | - case '.avi': |
| 682 | + case 'avi': |
824 | 683 | return 'video/x-msvideo'; |
825 | 684 | break; |
826 | | - case '.mpg': |
| 685 | + case 'mpg': |
827 | 686 | return 'video/mpeg'; |
828 | 687 | break; |
829 | | - case '.mpeg': |
| 688 | + case 'mpeg': |
830 | 689 | return 'video/mpeg'; |
831 | 690 | break; |
832 | 691 | } |
— | — | @@ -859,6 +718,9 @@ |
860 | 719 | // Selected mediaSource element. |
861 | 720 | selectedSource: null, |
862 | 721 | |
| 722 | + // Media element thumbnail |
| 723 | + thumbnail: null, |
| 724 | + |
863 | 725 | // Media element linkback |
864 | 726 | linkback: null, |
865 | 727 | |
— | — | @@ -973,7 +835,7 @@ |
974 | 836 | if ( i == index ) { |
975 | 837 | this.selectedSource = playableSources[i]; |
976 | 838 | // Update the user selected format: |
977 | | - mw.EmbedTypes.players.setFormatPreference( playableSources[i].mimeType ); |
| 839 | + mw.EmbedTypes.getMediaPlayers().setFormatPreference( playableSources[i].mimeType ); |
978 | 840 | break; |
979 | 841 | } |
980 | 842 | } |
— | — | @@ -985,6 +847,7 @@ |
986 | 848 | */ |
987 | 849 | autoSelectSource: function() { |
988 | 850 | mw.log( 'EmbedPlayer::mediaElement::autoSelectSource' ); |
| 851 | + var _this = this; |
989 | 852 | // Select the default source |
990 | 853 | var playableSources = this.getPlayableSources(); |
991 | 854 | var flash_flag = ogg_flag = false; |
— | — | @@ -993,13 +856,16 @@ |
994 | 857 | if( playableSources.length == 0 ){ |
995 | 858 | return false; |
996 | 859 | } |
| 860 | + var setSelectedSource = function( source ){ |
| 861 | + _this.selectedSource = source; |
| 862 | + }; |
997 | 863 | |
998 | 864 | // Set via user-preference |
999 | 865 | for ( var source = 0; source < playableSources.length; source++ ) { |
1000 | 866 | var mimeType = playableSources[source].mimeType; |
1001 | | - if ( mw.EmbedTypes.players.preference[ 'format_preference' ] == mimeType ) { |
1002 | | - mw.log( 'Set via preference: ' + playableSources[source].mimeType ); |
1003 | | - this.selectedSource = playableSources[source]; |
| 867 | + if ( mw.EmbedTypes.getMediaPlayers().preference[ 'format_preference' ] == mimeType ) { |
| 868 | + mw.log( 'EmbedPlayer::autoSelectSource: Set via preference: ' + playableSources[source].mimeType ); |
| 869 | + setSelectedSource( playableSources[source] ); |
1004 | 870 | return true; |
1005 | 871 | } |
1006 | 872 | } |
— | — | @@ -1007,8 +873,8 @@ |
1008 | 874 | // Set via marked default: |
1009 | 875 | for ( var source = 0; source < playableSources.length; source++ ) { |
1010 | 876 | if ( playableSources[ source ].markedDefault ) { |
1011 | | - mw.log( 'Set via marked default: ' + playableSources[source].markedDefault ); |
1012 | | - this.selectedSource = playableSources[source]; |
| 877 | + mw.log( 'EmbedPlayer::autoSelectSource: Set via marked default: ' + playableSources[source].markedDefault ); |
| 878 | + setSelectedSource( playableSources[source] ); |
1013 | 879 | return true; |
1014 | 880 | } |
1015 | 881 | } |
— | — | @@ -1016,10 +882,10 @@ |
1017 | 883 | // Prefer native playback |
1018 | 884 | for ( var source = 0; source < playableSources.length; source++ ) { |
1019 | 885 | var mimeType = playableSources[source].mimeType; |
1020 | | - var player = mw.EmbedTypes.players.defaultPlayer( mimeType ); |
| 886 | + var player = mw.EmbedTypes.getMediaPlayers().defaultPlayer( mimeType ); |
1021 | 887 | if ( player && player.library == 'Native' ) { |
1022 | | - mw.log('EmbedPlayer::Set native playback'); |
1023 | | - this.selectedSource = playableSources[ source ]; |
| 888 | + mw.log('EmbedPlayer::autoSelectSource: Set via native playback'); |
| 889 | + setSelectedSource( playableSources[ source ] ); |
1024 | 890 | return true; |
1025 | 891 | } |
1026 | 892 | } |
— | — | @@ -1027,7 +893,7 @@ |
1028 | 894 | // Set h264 via native or flash fallback |
1029 | 895 | for ( var source = 0; source < playableSources.length; source++ ) { |
1030 | 896 | var mimeType = playableSources[source].mimeType; |
1031 | | - var player = mw.EmbedTypes.players.defaultPlayer( mimeType ); |
| 897 | + var player = mw.EmbedTypes.getMediaPlayers().defaultPlayer( mimeType ); |
1032 | 898 | if ( mimeType == 'video/h264' |
1033 | 899 | && player |
1034 | 900 | && ( |
— | — | @@ -1036,16 +902,16 @@ |
1037 | 903 | player.library == 'Kplayer' |
1038 | 904 | ) |
1039 | 905 | ) { |
1040 | | - mw.log('Set h264 via native or flash fallback'); |
1041 | | - this.selectedSource = playableSources[ source ]; |
| 906 | + mw.log('EmbedPlayer::autoSelectSource: Set h264 via native or flash fallback'); |
| 907 | + setSelectedSource( playableSources[ source ] ); |
1042 | 908 | return true; |
1043 | 909 | } |
1044 | 910 | }; |
1045 | 911 | |
1046 | 912 | // Else just select first source |
1047 | 913 | if ( !this.selectedSource ) { |
1048 | | - mw.log( 'set via first source:' + playableSources[0] ); |
1049 | | - this.selectedSource = playableSources[0]; |
| 914 | + mw.log( 'EmbedPlayer::autoSelectSource: Set via first source:' + playableSources[0] ); |
| 915 | + setSelectedSource( playableSources[0] ); |
1050 | 916 | return true; |
1051 | 917 | } |
1052 | 918 | // No Source found so no source selected |
— | — | @@ -1067,9 +933,9 @@ |
1068 | 934 | }, |
1069 | 935 | |
1070 | 936 | /** |
1071 | | - * Returns the poster URL for the media element. |
| 937 | + * Returns the thumbnail URL for the media element. |
1072 | 938 | * |
1073 | | - * @returns {String} poster URL |
| 939 | + * @returns {String} thumbnail URL |
1074 | 940 | */ |
1075 | 941 | getPosterSrc: function( ) { |
1076 | 942 | return this.poster; |
— | — | @@ -1097,7 +963,7 @@ |
1098 | 964 | * Checks if media is a playable type |
1099 | 965 | */ |
1100 | 966 | isPlayableType: function( mimeType ) { |
1101 | | - if ( mw.EmbedTypes.players.defaultPlayer( mimeType ) ) { |
| 967 | + if ( mw.EmbedTypes.getMediaPlayers().defaultPlayer( mimeType ) ) { |
1102 | 968 | return true; |
1103 | 969 | } else { |
1104 | 970 | return false; |
— | — | @@ -1252,7 +1118,10 @@ |
1253 | 1119 | // Buffer flags |
1254 | 1120 | 'bufferStartFlag' : false, |
1255 | 1121 | 'bufferEndFlag' : false, |
1256 | | - |
| 1122 | + |
| 1123 | + // For supporting media fragments stores the play end time |
| 1124 | + 'pauseTime' : null, |
| 1125 | + |
1257 | 1126 | // On done playing |
1258 | 1127 | 'donePlayingCount' : 0 |
1259 | 1128 | , |
— | — | @@ -1275,6 +1144,7 @@ |
1276 | 1145 | */ |
1277 | 1146 | init: function( element, customAttributes ) { |
1278 | 1147 | var _this = this; |
| 1148 | + mw.log('EmbedPlayer: initEmbedPlayer: ' + $j(element).width() ); |
1279 | 1149 | // Set customAttributes if unset: |
1280 | 1150 | if ( !customAttributes ) { |
1281 | 1151 | customAttributes = { }; |
— | — | @@ -1312,6 +1182,9 @@ |
1313 | 1183 | } |
1314 | 1184 | |
1315 | 1185 | // Set the poster: |
| 1186 | + if ( $j( element ).attr( 'thumbnail' ) ) { |
| 1187 | + _this.poster = $j( element ).attr( 'thumbnail' ); |
| 1188 | + } |
1316 | 1189 | if ( $j( element ).attr( 'poster' ) ) { |
1317 | 1190 | _this.poster = $j( element ).attr( 'poster' ); |
1318 | 1191 | } |
— | — | @@ -1435,7 +1308,15 @@ |
1436 | 1309 | loadPlayerSize: function( element ) { |
1437 | 1310 | this.height = $j(element).css( 'height' ); |
1438 | 1311 | this.width = $j(element).css( 'width' ); |
1439 | | - |
| 1312 | + // Special check for chrome 100% with re-mapping to 32px |
| 1313 | + // ( hopefully no one embeds video at 32x32 ) |
| 1314 | + if( this.height == '32px' || this.height =='32px' ){ |
| 1315 | + var defaultSize = mw.getConfig( 'EmbedPlayer.DefaultSize' ).split( 'x' ); |
| 1316 | + this.width = '100%'; |
| 1317 | + this.height = '100%'; |
| 1318 | + } |
| 1319 | + mw.log('EmbedPlayer::loadPlayerSize: css size:' + this.width + ' h: ' + this.height); |
| 1320 | + |
1440 | 1321 | // Set to parent size ( resize events will cause player size updates) |
1441 | 1322 | if( this.height.indexOf('100%') != -1 || this.width.indexOf('100%') != -1 ){ |
1442 | 1323 | $relativeParent = $j(element).parents().filter(function() { |
— | — | @@ -1691,7 +1572,7 @@ |
1692 | 1573 | if ( !this.mediaElement.selectedSource ) { |
1693 | 1574 | mw.log( 'setupSourcePlayer:: no sources, type:' + this.type ); |
1694 | 1575 | } else { |
1695 | | - this.selectedPlayer = mw.EmbedTypes.players.defaultPlayer( this.mediaElement.selectedSource.mimeType ); |
| 1576 | + this.selectedPlayer = mw.EmbedTypes.getMediaPlayers().defaultPlayer( this.mediaElement.selectedSource.mimeType ); |
1696 | 1577 | } |
1697 | 1578 | |
1698 | 1579 | if ( this.selectedPlayer ) { |
— | — | @@ -1923,9 +1804,8 @@ |
1924 | 1805 | // actions ) |
1925 | 1806 | mw.log("EmbedPlayer::onClipDone:Trigger ended"); |
1926 | 1807 | |
1927 | | - this.tempDisableEvents(); |
1928 | 1808 | // TOOD we should improve the end event flow |
1929 | | - $j( this ).trigger( 'ended' ); |
| 1809 | + $j( this ).trigger( 'ended' ); |
1930 | 1810 | |
1931 | 1811 | if( this.onDoneInterfaceFlag ){ |
1932 | 1812 | |
— | — | @@ -1965,7 +1845,7 @@ |
1966 | 1846 | // Close Menu Overlay: |
1967 | 1847 | this.controlBuilder.closeMenuOverlay(); |
1968 | 1848 | |
1969 | | - // update the Poster html: |
| 1849 | + // update the thumbnail html: |
1970 | 1850 | this.updatePosterHTML(); |
1971 | 1851 | |
1972 | 1852 | this.paused = true; |
— | — | @@ -1973,7 +1853,7 @@ |
1974 | 1854 | // Make sure the controlBuilder bindings are up-to-date |
1975 | 1855 | this.controlBuilder.addControlBindings(); |
1976 | 1856 | |
1977 | | - // Once the Poster is shown run the mediaReady trigger (if not using |
| 1857 | + // Once the thumbnail is shown run the mediaReady trigger (if not using |
1978 | 1858 | // native controls) |
1979 | 1859 | if( !this.useNativePlayerControls() ){ |
1980 | 1860 | mw.log("mediaLoaded"); |
— | — | @@ -2044,17 +1924,51 @@ |
2045 | 1925 | this.$interface.hide(); |
2046 | 1926 | } |
2047 | 1927 | |
| 1928 | + // Update temporal url if present |
| 1929 | + this.updateTemporalUrl(); |
| 1930 | + |
| 1931 | + |
2048 | 1932 | if ( this.autoplay ) { |
2049 | 1933 | mw.log( 'EmbedPlayer::showPlayer::activating autoplay' ); |
2050 | 1934 | // Issue a non-blocking play request |
2051 | 1935 | setTimeout(function(){ |
2052 | 1936 | _this.play(); |
2053 | | - },1) |
| 1937 | + },1); |
2054 | 1938 | } |
2055 | 1939 | |
2056 | 1940 | }, |
2057 | | - |
2058 | 1941 | /** |
| 1942 | + * Media framgments handler based on: |
| 1943 | + * http://www.w3.org/2008/WebVideo/Fragments/WD-media-fragments-spec/#fragment-dimensions |
| 1944 | + * |
| 1945 | + * We support seconds and npt ( normal play time ) |
| 1946 | + * |
| 1947 | + * Updates the player per fragment url info if present |
| 1948 | + * |
| 1949 | + */ |
| 1950 | + updateTemporalUrl: function(){ |
| 1951 | + var sourceHash = /[^\#]+$/.exec( this.getSrc() ).toString(); |
| 1952 | + if( sourceHash.indexOf('t=') === 0 ){ |
| 1953 | + // parse the times |
| 1954 | + var times = sourceHash.substr(2).split(','); |
| 1955 | + if( times[0] ){ |
| 1956 | + // update the current time |
| 1957 | + this.currentTime = mw.npt2seconds( times[0].toString() ); |
| 1958 | + } |
| 1959 | + if( times[1] ){ |
| 1960 | + this.pauseTime = mw.npt2seconds( times[1].toString() ); |
| 1961 | + // ignore invalid ranges: |
| 1962 | + if( this.pauseTime < this.currentTime ){ |
| 1963 | + this.pauseTime = null; |
| 1964 | + } |
| 1965 | + } |
| 1966 | + // Update the play head |
| 1967 | + this.updatePlayHead( this.currentTime / this.duration ); |
| 1968 | + // Update status: |
| 1969 | + this.controlBuilder.setStatus( mw.seconds2npt( this.currentTime ) ); |
| 1970 | + } |
| 1971 | + }, |
| 1972 | + /** |
2059 | 1973 | * Get missing plugin html (check for user included code) |
2060 | 1974 | * |
2061 | 1975 | * @param {String} |
— | — | @@ -2438,7 +2352,7 @@ |
2439 | 2353 | case 'iframe': |
2440 | 2354 | return this.getShareIframeObject(); |
2441 | 2355 | break; |
2442 | | - case 'videojs': |
| 2356 | + case 'xssVideo': |
2443 | 2357 | return this.getShareEmbedVideoJs(); |
2444 | 2358 | break; |
2445 | 2359 | } |
— | — | @@ -2600,7 +2514,7 @@ |
2601 | 2515 | play: function() { |
2602 | 2516 | var _this = this; |
2603 | 2517 | mw.log( "EmbedPlayer:: play: " + this._propagateEvents ); |
2604 | | - if( ! this._propagateEvents){ |
| 2518 | + if( ! this._propagateEvents ){ |
2605 | 2519 | return ; |
2606 | 2520 | } |
2607 | 2521 | // Hide any overlay: |
— | — | @@ -2614,21 +2528,17 @@ |
2615 | 2529 | } else { |
2616 | 2530 | this.posterDisplayed = false; |
2617 | 2531 | // Hide any button if present: |
2618 | | - this.$interface.find( '.play-btn-large' ).remove(); |
| 2532 | + this.$interface.find( '.play-btn-large' ).remove(); |
2619 | 2533 | this.doEmbedHTML(); |
2620 | 2534 | } |
2621 | 2535 | } |
2622 | | - |
2623 | 2536 | |
2624 | 2537 | if( this.paused === true ){ |
2625 | 2538 | this.paused = false; |
2626 | 2539 | // Check if we should Trigger the play event |
2627 | | - if( this.bubbleEventCheck() ) { |
2628 | | - mw.log("EmbedPlayer:: trigger play even::" + !this.paused); |
2629 | | - if( this._propagateEvents ){ |
2630 | | - $j( this ).trigger( 'play' ); |
2631 | | - _this.tempDisableEvents(); |
2632 | | - } |
| 2540 | + mw.log("EmbedPlayer:: trigger play even::" + !this.paused); |
| 2541 | + if( ! this.doMethodsAutoTrigger() ) { |
| 2542 | + $j( this ).trigger( 'play' ); |
2633 | 2543 | } |
2634 | 2544 | } |
2635 | 2545 | |
— | — | @@ -2654,18 +2564,6 @@ |
2655 | 2565 | this.monitor(); |
2656 | 2566 | }, |
2657 | 2567 | /** |
2658 | | - * Returns true if the event should be triggered or false if not |
2659 | | - * |
2660 | | - * @@FIXME:: firefox nightlies now Do NOT bubble events. Once release tag |
2661 | | - * every version after that |
2662 | | - */ |
2663 | | - bubbleEventCheck: function(){ |
2664 | | - if( $j.browser.webkit ){ |
2665 | | - return true; |
2666 | | - } |
2667 | | - return false; |
2668 | | - }, |
2669 | | - /** |
2670 | 2568 | * Base embed pause Updates the play/pause button state. |
2671 | 2569 | * |
2672 | 2570 | * There is no general way to pause the video must be overwritten by embed |
— | — | @@ -2677,14 +2575,9 @@ |
2678 | 2576 | // controls: |
2679 | 2577 | if( this.paused === false ){ |
2680 | 2578 | this.paused = true; |
2681 | | - mw.log( "EmbedPlayer:: pause: " + this._propagateEvents ); |
2682 | | - |
2683 | | - if( this.bubbleEventCheck() ){ |
2684 | | - mw.log('EmbedPlayer:trigger pause:' + this.paused); |
2685 | | - if( this._propagateEvents ){ |
2686 | | - $j( this ).trigger( 'pause' ); |
2687 | | - _this.tempDisableEvents(); |
2688 | | - } |
| 2579 | + mw.log('EmbedPlayer:trigger pause:' + this.paused); |
| 2580 | + if( ! this.doMethodsAutoTrigger() ){ |
| 2581 | + $j( this ).trigger( 'pause' ); |
2689 | 2582 | } |
2690 | 2583 | } |
2691 | 2584 | |
— | — | @@ -2694,23 +2587,20 @@ |
2695 | 2588 | .addClass( 'ui-icon-play' ); |
2696 | 2589 | |
2697 | 2590 | this.$interface.find('.play-btn' ) |
2698 | | - .unbind() |
| 2591 | + .unbind('click') |
2699 | 2592 | .buttonHover() |
2700 | 2593 | .click( function() { |
2701 | 2594 | _this.play(); |
2702 | 2595 | } ) |
2703 | 2596 | .attr( 'title', gM( 'mwe-embedplayer-play_clip' ) ); |
2704 | 2597 | }, |
2705 | | - |
2706 | | - /** |
2707 | | - * Disable event _propagateEvents for 10ms ( helps avoid event stacking ) |
2708 | | - */ |
2709 | | - tempDisableEvents: function(){ |
2710 | | - var _this = this; |
2711 | | - this._propagateEvents = false; |
2712 | | - setTimeout( function(){ |
2713 | | - _this._propagateEvents = true; |
2714 | | - }, 10); |
| 2598 | + // special per browser check for autoTrigger events |
| 2599 | + // ideally jQuery would not have this inconsistency. |
| 2600 | + doMethodsAutoTrigger: function(){ |
| 2601 | + if( $j.browser.mozilla && ! mw.versionIsAtLeast('2.0', $j.browser.version ) ){ |
| 2602 | + return true; |
| 2603 | + } |
| 2604 | + return false; |
2715 | 2605 | }, |
2716 | 2606 | |
2717 | 2607 | /** |
— | — | @@ -2866,7 +2756,7 @@ |
2867 | 2757 | /** |
2868 | 2758 | * Passes a fullscreen request to the controlBuilder interface |
2869 | 2759 | */ |
2870 | | - fullscreen: function() { |
| 2760 | + fullscreen: function() { |
2871 | 2761 | this.controlBuilder.toggleFullscreen(); |
2872 | 2762 | }, |
2873 | 2763 | |
— | — | @@ -2965,6 +2855,11 @@ |
2966 | 2856 | // Update the previousTime ( so we can know if the user-javascript |
2967 | 2857 | // changed currentTime ) |
2968 | 2858 | _this.previousTime = _this.currentTime; |
| 2859 | + |
| 2860 | + if( _this.pauseTime && _this.currentTime > _this.pauseTime ){ |
| 2861 | + _this.pause(); |
| 2862 | + _this.pauseTime = null; |
| 2863 | + } |
2969 | 2864 | |
2970 | 2865 | |
2971 | 2866 | // Check if volume was set outside of embed player function |
— | — | @@ -3122,68 +3017,8 @@ |
3123 | 3018 | $j( this ).trigger('updatePlayHeadPercent', perc); |
3124 | 3019 | }, |
3125 | 3020 | |
3126 | | - /** |
3127 | | - * Highlight a section of video on the playhead |
3128 | | - * |
3129 | | - * @param {Object} |
3130 | | - * options Provides "start" time & "end" time to highlight |
3131 | | - */ |
3132 | | - highlightPlaySection:function( options ) { |
3133 | | - mw.log( 'highlightPlaySection' ); |
3134 | | - var eid = ( this.pc ) ? this.pc.pp.id:this.id; |
3135 | | - var dur = this.getDuration(); |
3136 | | - // set the left percet and update the slider: |
3137 | | - rel_start_sec = mw.npt2seconds( options['start'] ); |
3138 | | - // remove the startOffset if relevent: |
3139 | | - if ( this.startOffset ) |
3140 | | - rel_start_sec = rel_start_sec - this.startOffset |
3141 | 3021 | |
3142 | | - var slider_perc = 0; |
3143 | | - if ( rel_start_sec <= 0 ) { |
3144 | | - left_perc = 0; |
3145 | | - options['start'] = mw.seconds2npt( this.startOffset ); |
3146 | | - rel_start_sec = 0; |
3147 | | - this.updatePlayHead( 0 ); |
3148 | | - } else { |
3149 | | - left_perc = parseInt( ( rel_start_sec / dur ) * 100 ) ; |
3150 | | - slider_perc = ( left_perc / 100 ); |
3151 | | - } |
3152 | | - |
3153 | | - mw.log( "slider perc:" + slider_perc ); |
3154 | | - if ( ! this.isPlaying() ) { |
3155 | | - this.updatePlayHead( slider_perc ); |
3156 | | - } |
3157 | | - |
3158 | | - width_perc = parseInt( ( ( mw.npt2seconds( options['end'] ) - mw.npt2seconds( options['start'] ) ) / dur ) * 100 ) ; |
3159 | | - if ( ( width_perc + left_perc ) > 100 ) { |
3160 | | - width_perc = 100 - left_perc; |
3161 | | - } |
3162 | | - // mw.log('should hl: '+rel_start_sec+ '/' + dur + ' re:' + |
3163 | | - // rel_end_sec+' lp:' + left_perc + ' width: ' + width_perc); |
3164 | | - $j( '#mv_seeker_' + eid + ' .mv_highlight' ).css( { |
3165 | | - 'left' : left_perc + '%', |
3166 | | - 'width' : width_perc + '%' |
3167 | | - } ).show(); |
3168 | | - |
3169 | | - this.jump_time = options['start']; |
3170 | | - this.serverSeekTime = mw.npt2seconds( options['start'] ); |
3171 | | - // trim output to |
3172 | | - this.controlBuilder.setStatus( gM( 'mwe-embedplayer-seek_to', mw.seconds2npt( this.serverSeekTime ) ) ); |
3173 | | - mw.log( 'DO update: ' + this.jump_time ); |
3174 | | - this.updateThumbTime( rel_start_sec ); |
3175 | | - }, |
3176 | | - |
3177 | 3022 | /** |
3178 | | - * Hides the playhead highlight |
3179 | | - */ |
3180 | | - hideHighlight: function() { |
3181 | | - var eid = ( this.pc ) ? this.pc.pp.id:this.id; |
3182 | | - $j( '#mv_seeker_' + eid + ' .mv_highlight' ).hide(); |
3183 | | - this.controlBuilder.setStatus( this.getTimeRange() ); |
3184 | | - }, |
3185 | | - |
3186 | | - |
3187 | | - /** |
3188 | 3023 | * Helper Functions for selected source |
3189 | 3024 | */ |
3190 | 3025 | |
— | — | @@ -3543,8 +3378,8 @@ |
3544 | 3379 | */ |
3545 | 3380 | mw.EmbedTypes = { |
3546 | 3381 | |
3547 | | - // List of players supported |
3548 | | - players: null, |
| 3382 | + // MediaPlayers object ( supports methods for quering set of browser players ) |
| 3383 | + mediaPlayers: null, |
3549 | 3384 | |
3550 | 3385 | // Detect flag for completion |
3551 | 3386 | detect_done:false, |
— | — | @@ -3559,6 +3394,16 @@ |
3560 | 3395 | this.detect(); |
3561 | 3396 | this.detect_done = true; |
3562 | 3397 | }, |
| 3398 | + |
| 3399 | + getMediaPlayers: function(){ |
| 3400 | + if( this.mediaPlayers ){ |
| 3401 | + return this.mediaPlayers; |
| 3402 | + } |
| 3403 | + this.mediaPlayers = new mediaPlayers(); |
| 3404 | + // detect available players |
| 3405 | + this.detectPlayers(); |
| 3406 | + return this.mediaPlayers; |
| 3407 | + }, |
3563 | 3408 | |
3564 | 3409 | /** |
3565 | 3410 | * If the browsers supports a given mimetype |
— | — | @@ -3578,13 +3423,11 @@ |
3579 | 3424 | /** |
3580 | 3425 | * Detects what plug-ins the client supports |
3581 | 3426 | */ |
3582 | | - detect: function() { |
3583 | | - mw.log( "embedPlayer: running detect" ); |
3584 | | - this.players = new mediaPlayers(); |
| 3427 | + detectPlayers: function() { |
| 3428 | + mw.log( "embedPlayer: running detect" ); |
3585 | 3429 | // every browser supports html rendering: |
3586 | | - this.players.addPlayer( htmlPlayer ); |
3587 | | - // In Mozilla, navigator.javaEnabled() only tells us about preferences, |
3588 | | - // we need to |
| 3430 | + this.mediaPlayers.addPlayer( htmlPlayer ); |
| 3431 | + // In Mozilla, navigator.javaEnabled() only tells us about preferences, we need to |
3589 | 3432 | // search navigator.mimeTypes to see if it's installed |
3590 | 3433 | try{ |
3591 | 3434 | var javaEnabled = navigator.javaEnabled(); |
— | — | @@ -3595,34 +3438,33 @@ |
3596 | 3439 | var uniqueMimesOnly = $j.browser.opera || $j.browser.safari; |
3597 | 3440 | |
3598 | 3441 | // Opera will switch off javaEnabled in preferences if java can't be |
3599 | | - // found. |
3600 | | - // And it doesn't register an application/x-java-applet mime type like |
| 3442 | + // found. And it doesn't register an application/x-java-applet mime type like |
3601 | 3443 | // Mozilla does. |
3602 | 3444 | if ( javaEnabled && ( navigator.appName == 'Opera' ) ) { |
3603 | | - this.players.addPlayer( cortadoPlayer ); |
| 3445 | + this.mediaPlayers.addPlayer( cortadoPlayer ); |
3604 | 3446 | } |
3605 | 3447 | |
3606 | 3448 | // ActiveX plugins |
3607 | 3449 | if ( $j.browser.msie ) { |
3608 | 3450 | // check for flash |
3609 | 3451 | if ( this.testActiveX( 'ShockwaveFlash.ShockwaveFlash' ) ) { |
3610 | | - this.players.addPlayer( kplayer ); |
3611 | | - // this.players.addPlayer( flowPlayer ); |
| 3452 | + this.mediaPlayers.addPlayer( kplayer ); |
| 3453 | + // this.mediaPlayers.addPlayer( flowPlayer ); |
3612 | 3454 | } |
3613 | 3455 | // VLC |
3614 | 3456 | if ( this.testActiveX( 'VideoLAN.VLCPlugin.2' ) ) { |
3615 | | - this.players.addPlayer( vlcPlayer ); |
| 3457 | + this.mediaPlayers.addPlayer( vlcPlayer ); |
3616 | 3458 | } |
3617 | 3459 | |
3618 | 3460 | // Java ActiveX |
3619 | 3461 | if ( this.testActiveX( 'JavaWebStart.isInstalled' ) ) { |
3620 | | - this.players.addPlayer( cortadoPlayer ); |
| 3462 | + this.mediaPlayers.addPlayer( cortadoPlayer ); |
3621 | 3463 | } |
3622 | 3464 | |
3623 | 3465 | // quicktime (currently off) |
3624 | 3466 | // if ( this.testActiveX( |
3625 | 3467 | // 'QuickTimeCheckObject.QuickTimeCheck.1' ) ) |
3626 | | - // this.players.addPlayer(quicktimeActiveXPlayer); |
| 3468 | + // this.mediaPlayers.addPlayer(quicktimeActiveXPlayer); |
3627 | 3469 | } |
3628 | 3470 | // <video> element |
3629 | 3471 | if ( typeof HTMLVideoElement == 'object' // Firefox, Safari |
— | — | @@ -3634,26 +3476,26 @@ |
3635 | 3477 | if( dummyvid.canPlayType ) { |
3636 | 3478 | // Add the webm player |
3637 | 3479 | if( dummyvid.canPlayType('video/webm; codecs="vp8, vorbis"') ){ |
3638 | | - this.players.addPlayer( webmNativePlayer ); |
| 3480 | + this.mediaPlayers.addPlayer( webmNativePlayer ); |
3639 | 3481 | } |
3640 | 3482 | |
3641 | 3483 | // Test for h264: |
3642 | 3484 | if ( dummyvid.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"' ) ) { |
3643 | | - this.players.addPlayer( h264NativePlayer ); |
| 3485 | + this.mediaPlayers.addPlayer( h264NativePlayer ); |
3644 | 3486 | } |
3645 | 3487 | // For now if Android assume we support h264Native (FIXME |
3646 | 3488 | // test on real devices ) |
3647 | 3489 | if ( mw.isAndroid2() ){ |
3648 | | - this.players.addPlayer( h264NativePlayer ); |
| 3490 | + this.mediaPlayers.addPlayer( h264NativePlayer ); |
3649 | 3491 | } |
3650 | 3492 | |
3651 | 3493 | // Test for ogg |
3652 | 3494 | if ( dummyvid.canPlayType( 'video/ogg; codecs="theora,vorbis"' ) ) { |
3653 | | - this.players.addPlayer( oggNativePlayer ); |
| 3495 | + this.mediaPlayers.addPlayer( oggNativePlayer ); |
3654 | 3496 | // older versions of safari do not support canPlayType, |
3655 | 3497 | // but xiph qt registers mimetype via quicktime plugin |
3656 | 3498 | } else if ( this.supportedMimeType( 'video/ogg' ) ) { |
3657 | | - this.players.addPlayer( oggNativePlayer ); |
| 3499 | + this.mediaPlayers.addPlayer( oggNativePlayer ); |
3658 | 3500 | } |
3659 | 3501 | } |
3660 | 3502 | } catch ( e ) { |
— | — | @@ -3676,43 +3518,43 @@ |
3677 | 3519 | pluginName = ''; |
3678 | 3520 | } |
3679 | 3521 | if ( pluginName.toLowerCase() == 'vlc multimedia plugin' || pluginName.toLowerCase() == 'vlc multimedia plug-in' ) { |
3680 | | - this.players.addPlayer( vlcPlayer ); |
| 3522 | + this.mediaPlayers.addPlayer( vlcPlayer ); |
3681 | 3523 | continue; |
3682 | 3524 | } |
3683 | 3525 | |
3684 | 3526 | if ( type == 'application/x-java-applet' ) { |
3685 | | - this.players.addPlayer( cortadoPlayer ); |
| 3527 | + this.mediaPlayers.addPlayer( cortadoPlayer ); |
3686 | 3528 | continue; |
3687 | 3529 | } |
3688 | 3530 | |
3689 | 3531 | if ( (type == 'video/mpeg' || type == 'video/x-msvideo') && |
3690 | 3532 | pluginName.toLowerCase() == 'vlc multimedia plugin' ) { |
3691 | | - this.players.addPlayer( vlcMozillaPlayer ); |
| 3533 | + this.mediaPlayers.addPlayer( vlcMozillaPlayer ); |
3692 | 3534 | } |
3693 | 3535 | |
3694 | 3536 | if ( type == 'application/ogg' ) { |
3695 | 3537 | if ( pluginName.toLowerCase() == 'vlc multimedia plugin' ) { |
3696 | | - this.players.addPlayer( vlcMozillaPlayer ); |
| 3538 | + this.mediaPlayers.addPlayer( vlcMozillaPlayer ); |
3697 | 3539 | // else if ( pluginName.indexOf( 'QuickTime' ) > -1 ) |
3698 | | - // this.players.addPlayer(quicktimeMozillaPlayer); |
| 3540 | + // this.mediaPlayers.addPlayer(quicktimeMozillaPlayer); |
3699 | 3541 | } else { |
3700 | | - this.players.addPlayer( oggPluginPlayer ); |
| 3542 | + this.mediaPlayers.addPlayer( oggPluginPlayer ); |
3701 | 3543 | } |
3702 | 3544 | continue; |
3703 | 3545 | } else if ( uniqueMimesOnly ) { |
3704 | 3546 | if ( type == 'application/x-vlc-player' ) { |
3705 | | - this.players.addPlayer( vlcMozillaPlayer ); |
| 3547 | + this.mediaPlayers.addPlayer( vlcMozillaPlayer ); |
3706 | 3548 | continue; |
3707 | 3549 | } else if ( type == 'video/quicktime' ) { |
3708 | | - // this.players.addPlayer(quicktimeMozillaPlayer); |
| 3550 | + // this.mediaPlayers.addPlayer(quicktimeMozillaPlayer); |
3709 | 3551 | continue; |
3710 | 3552 | } |
3711 | 3553 | } |
3712 | 3554 | |
3713 | 3555 | if ( type == 'application/x-shockwave-flash' ) { |
3714 | 3556 | |
3715 | | - this.players.addPlayer( kplayer ); |
3716 | | - // this.players.addPlayer( flowPlayer ); |
| 3557 | + this.mediaPlayers.addPlayer( kplayer ); |
| 3558 | + // this.mediaPlayers.addPlayer( flowPlayer ); |
3717 | 3559 | |
3718 | 3560 | // check version to add omtk: |
3719 | 3561 | if( navigator.plugins["Shockwave Flash"] ){ |
— | — | @@ -3729,7 +3571,7 @@ |
3730 | 3572 | |
3731 | 3573 | // Allow extensions to detect and add their own "players" |
3732 | 3574 | mw.log("trigger::embedPlayerUpdateMediaPlayersEvent"); |
3733 | | - $j( mw ).trigger( 'embedPlayerUpdateMediaPlayersEvent' , this.players ); |
| 3575 | + $j( mw ).trigger( 'embedPlayerUpdateMediaPlayersEvent' , this.mediaPlayers ); |
3734 | 3576 | |
3735 | 3577 | }, |
3736 | 3578 | |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/EmbedPlayer/mw.IFramePlayerApiClient.js |
— | — | @@ -24,8 +24,11 @@ |
25 | 25 | // Set the iframe server |
26 | 26 | var srcParts = mw.parseUri( mw.absoluteUrl( $j(this.iframe).attr('src') ) ); |
27 | 27 | this.iframeServer = srcParts.protocol + '://' + srcParts.authority; |
| 28 | + |
28 | 29 | this.addPlayerSendApi(); |
29 | 30 | this.addPlayerReciveApi(); |
| 31 | + |
| 32 | + this.addIframeFullscreenBinding(); |
30 | 33 | }, |
31 | 34 | 'addPlayerSendApi': function(){ |
32 | 35 | var _this = this; |
— | — | @@ -46,31 +49,65 @@ |
47 | 50 | var _this = this; |
48 | 51 | $j.receiveMessage( function( event ){ |
49 | 52 | _this.hanldeReciveMsg( event ) |
50 | | - }); |
| 53 | + }, this.iframeServer); |
51 | 54 | }, |
| 55 | + 'addIframeFullscreenBinding': function(){ |
| 56 | + var _this = this; |
| 57 | + parentsAbsoluteList = []; |
| 58 | + var fullscreenMode = false; |
| 59 | + var orgSize = { |
| 60 | + 'width' : $j( _this.iframe ).width(), |
| 61 | + 'height' : $j( _this.iframe ).height(), |
| 62 | + 'position' : null |
| 63 | + } |
| 64 | + |
| 65 | + var doFullscreen = function(){ |
| 66 | + // Make the iframe fullscreen |
| 67 | + $j( _this.iframe ).css({ |
| 68 | + 'z-index': mw.getConfig( 'EmbedPlayer.fullScreenZIndex' ) + 1, |
| 69 | + 'position': 'absolute', |
| 70 | + 'top' : 0, |
| 71 | + 'left' : 0, |
| 72 | + 'width' : $j(window).width(), |
| 73 | + 'height' : $j(window).height() |
| 74 | + }) |
| 75 | + |
| 76 | + // Remove absolute css of the interface parents |
| 77 | + $j( _this.iframe ).parents().each( function() { |
| 78 | + //mw.log(' parent : ' + $j( this ).attr('id' ) + ' class: ' + $j( this ).attr('class') + ' pos: ' + $j( this ).css( 'position' ) ); |
| 79 | + if( $j( this ).css( 'position' ) == 'absolute' ) { |
| 80 | + parentsAbsoluteList.push( $j( this ) ); |
| 81 | + $j( this ).css( 'position', null ); |
| 82 | + } |
| 83 | + } ); |
| 84 | + } |
| 85 | + var restoreWindowMode = function(){ |
| 86 | + $j( _this.iframe ).css( orgSize ); |
| 87 | + // restore any parent absolute pos: |
| 88 | + $j(parentsAbsoluteList).each( function() { |
| 89 | + $j( this ).css( 'position', 'absolute' ); |
| 90 | + } ); |
| 91 | + }; |
| 92 | + |
| 93 | + $j( this.playerProxy ).bind( 'onOpenFullScreen', doFullscreen); |
| 94 | + $j( this.playerProxy ).bind( 'onCloseFullScreen', restoreWindowMode); |
| 95 | + |
| 96 | + }, |
52 | 97 | /** |
53 | 98 | * Handle received events |
54 | 99 | */ |
55 | 100 | 'hanldeReciveMsg': function( event ){ |
56 | | - var _this = this; |
57 | | - // Confirm the event is coming for the target host: |
58 | | - if( event.origin != this.iframeServer){ |
59 | | - mw.log("Skip msg from host does not match iFrame player: " + event.origin + |
60 | | - ' != iframe Server: ' + this.iframeServer ) |
61 | | - return ; |
62 | | - }; |
| 101 | + var _this = this; |
| 102 | + |
63 | 103 | // Decode the message |
64 | 104 | var msgObject = JSON.parse( event.data ); |
65 | | - //mw.log("IframePlayerApiClient:: hanldeReciveMsg: " + msgObject.triggerName ); |
66 | | - |
67 | | - |
68 | 105 | var playerAttributes = mw.getConfig( 'EmbedPlayer.Attributes' ); |
69 | | - |
| 106 | + |
70 | 107 | // Before we update local attributes check that the object has not been updated by user js |
71 | 108 | for( var attrName in playerAttributes ){ |
72 | 109 | if( attrName != 'id' ){ |
73 | 110 | if( _this._prevPlayerProxy[ attrName ] != _this.playerProxy[ attrName ] ){ |
74 | | - mw.log( "IFramePlayerApiClient:: User js update:" + attrName + ' set to: ' + this.playerProxy[ attrName ] + ' != old: ' + _this._prevPlayerProxy[ attrName ] ); |
| 111 | + //mw.log( "IFramePlayerApiClient:: User js update:" + attrName + ' set to: ' + this.playerProxy[ attrName ] + ' != old: ' + _this._prevPlayerProxy[ attrName ] ); |
75 | 112 | // Send the updated attribute back to the iframe: |
76 | 113 | _this.postMessage({ |
77 | 114 | 'attrName' : attrName, |
— | — | @@ -99,7 +136,9 @@ |
100 | 137 | } |
101 | 138 | }, |
102 | 139 | 'postMessage': function( msgObject ){ |
103 | | - //mw.log( "IFramePlayerApiClient:: postMessage(): " + JSON.stringify( msgObj ) ); |
| 140 | + /*mw.log( "IFramePlayerApiClient:: postMessage(): " + JSON.stringify( msgObject ) + |
| 141 | + ' iframe: ' + this.iframe + ' cw:' + this.iframe.contentWindow + |
| 142 | + ' src: ' + mw.absoluteUrl( $j( this.iframe ).attr('src') ) );*/ |
104 | 143 | $j.postMessage( |
105 | 144 | JSON.stringify( msgObject ), |
106 | 145 | mw.absoluteUrl( $j( this.iframe ).attr('src') ), |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/EmbedPlayer/EmbedPlayer.loader.js |
— | — | @@ -0,0 +1,115 @@ |
| 2 | +/** |
| 3 | +* EmbedPlayer loader |
| 4 | +*/ |
| 5 | +( function( mw, $ ) { |
| 6 | + /** |
| 7 | + * Add a DOM ready check for player tags |
| 8 | + * |
| 9 | + * We use SetupInterface so other functions that depend on the interface can |
| 10 | + * wait for the IntefacesReady event |
| 11 | + */ |
| 12 | + $( mw ).bind( 'SetupInterface', function( event, callback ){ |
| 13 | + |
| 14 | + // Allow modules to do tag rewrites as well: |
| 15 | + var doModuleTagRewrites = function(){ |
| 16 | + $(mw).triggerQueueCallback( 'LoadeRewritePlayerTags', callback ); |
| 17 | + } |
| 18 | + // Check if we have tags to rewrite: |
| 19 | + if( $( mw.getConfig( 'EmbedPlayer.RewriteTags' ) ).length ) { |
| 20 | + var rewriteElementCount = 0; |
| 21 | + |
| 22 | + // Rewrite the embedPlayer EmbedPlayer.RewriteTags : |
| 23 | + $( mw.getConfig( 'EmbedPlayer.RewriteTags' ) ) |
| 24 | + .embedPlayer( doModuleTagRewrites ); |
| 25 | + } else { |
| 26 | + doModuleTagRewrites(); |
| 27 | + } |
| 28 | + }); |
| 29 | + |
| 30 | + /** |
| 31 | + * Add the mwEmbed jQuery loader wrapper |
| 32 | + */ |
| 33 | + $.fn.embedPlayer = function( readyCallback ){ |
| 34 | + var _this = this; |
| 35 | + |
| 36 | + if( this.selector ){ |
| 37 | + var playerSelect = this.selector; |
| 38 | + } else { |
| 39 | + var playerSelect = this; |
| 40 | + } |
| 41 | + |
| 42 | + // Hide videonojs class |
| 43 | + $( '.videonojs' ).hide(); |
| 44 | + |
| 45 | + if() |
| 46 | + |
| 47 | + // Set up the embed video player class request: (include the skin js as well) |
| 48 | + var dependencySet = [ |
| 49 | + 'mw.EmbedPlayer' |
| 50 | + ]; |
| 51 | + |
| 52 | + // Add PNG fix code needed: |
| 53 | + if ( $.browser.msie && $.browser.version < 7 ) { |
| 54 | + dependencySet.push( 'jquery.pngFix' ); |
| 55 | + } |
| 56 | + |
| 57 | + // Guess at playback system for 90+% of users the browser indicates playback mode: |
| 58 | + // NOTE: this does not affect a given playback library being loaded on-demand later. |
| 59 | + if( ( $.browser.msie && $.browser.version < 9 ) || $.browser.safari ) { |
| 60 | + dependencySet.push( 'mw.EmbedPlayerJava' ); |
| 61 | + } |
| 62 | + // If video tag is supported add native lib: |
| 63 | + if( document.createElement('video').canPlayType && !$.browser.safari) { |
| 64 | + dependencySet.push( 'mw.EmbedPlayerNative' ) |
| 65 | + } |
| 66 | + |
| 67 | + |
| 68 | + // Check if the iFrame player api is enabled and we have a parent iframe url: |
| 69 | + // TODO we might want to move the iframe api to a separate module |
| 70 | + if ( mw.getConfig('EmbedPlayer.EnableIframeApi') |
| 71 | + && |
| 72 | + mw.getConfig( 'EmbedPlayer.IframeParentUrl' ) |
| 73 | + ){ |
| 74 | + dependencySet.push('mw.EmbedPlayerNative'); |
| 75 | + dependencySet.push('$.postMessage'); |
| 76 | + dependencySet.push('mw.IFramePlayerApiServer'); |
| 77 | + } |
| 78 | + |
| 79 | + // Allow modules to update the set of dependencies: |
| 80 | + var rewriteElementCount = 0; |
| 81 | + $.each( playerSelect, function(inx, playerElement){ |
| 82 | + |
| 83 | + // Assign an the element an ID ( if its missing one ) |
| 84 | + if ( $( playerElement ).attr( "id" ) == '' ) { |
| 85 | + $( playerElement ).attr( "id", 'v' + ( rewriteElementCount++ ) ); |
| 86 | + } |
| 87 | + |
| 88 | + // Add an overlay loader |
| 89 | + $( playerElement ) |
| 90 | + .getAbsoluteOverlaySpinner() |
| 91 | + .attr('id', 'loadingSpinner_' + $( element ).attr('id') ) |
| 92 | + .addClass( 'playerLoadingSpinner' ); |
| 93 | + |
| 94 | + // Add core "skin/interface" loader |
| 95 | + var skinString = $( playerElement ).attr( 'class' ); |
| 96 | + if( ! skinString || $.inArray( skinName.toLowerCase(), mw.validSkins ) == -1 ){ |
| 97 | + skinName = mw.getConfig( 'EmbedPlayer.DefaultSkin' ); |
| 98 | + } |
| 99 | + skinName = skinName.toLowerCase(); |
| 100 | + |
| 101 | + // Add the skin to the request |
| 102 | + var skinCaseName = skinName.charAt(0).toUpperCase() + skinName.substr(1); |
| 103 | + dependencySet.push( 'mw.PlayerSkin' + skinCaseName ); |
| 104 | + |
| 105 | + // Allow other modules update the dependencies |
| 106 | + $j( mw ).trigger( 'EmbedPlayerUpdateDependencies', |
| 107 | + [ playerElement, dependencySet ] ); |
| 108 | + }); |
| 109 | + |
| 110 | + // Do the request and process the playerElements with updated dependency set |
| 111 | + mediaWiki.loader.using( dependencySet, function(){ |
| 112 | + // EmbedPlayer should be ready: |
| 113 | + }); |
| 114 | + }; |
| 115 | + |
| 116 | +} )( mediaWiki, jQuery ); |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayerNative.js |
— | — | @@ -199,7 +199,7 @@ |
200 | 200 | _this['on' + eventName ].apply( _this, argArray); |
201 | 201 | } else { |
202 | 202 | // No local handler directly propagate the event to the abstract object: |
203 | | - $j( _this ).trigger( eventName, argArray ) |
| 203 | + $j( _this ).trigger( eventName, argArray ); |
204 | 204 | } |
205 | 205 | } |
206 | 206 | }) |
— | — | @@ -469,7 +469,6 @@ |
470 | 470 | * calls parent_play to update the interface |
471 | 471 | */ |
472 | 472 | play: function( ) { |
473 | | - |
474 | 473 | this.getPlayerElement(); |
475 | 474 | this.parent_play(); // update interface |
476 | 475 | if ( this.playerElement && this.playerElement.play ) { |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/EmbedPlayer/mw.EmbedPlayerKplayer.js |
— | — | @@ -150,8 +150,8 @@ |
151 | 151 | |
152 | 152 | // Create an anonymous function with local player scope |
153 | 153 | var createGlobalCB = function(cName, embedPlayer) { |
154 | | - window[cName] = function(data) { |
155 | | - if (embedPlayer._propagateEvents) { |
| 154 | + window[ cName ] = function(data) { |
| 155 | + if ( embedPlayer._propagateEvents ) { |
156 | 156 | embedPlayer[methodName](data); |
157 | 157 | } |
158 | 158 | }; |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/EmbedPlayer/mw.IFramePlayerApiServer.js |
— | — | @@ -36,7 +36,9 @@ |
37 | 37 | // Exported bindings / events. ( all the native html5 events are added in 'init' ) |
38 | 38 | 'exportedBindings': [ |
39 | 39 | 'playerReady', |
40 | | - 'monitorEvent' |
| 40 | + 'monitorEvent', |
| 41 | + 'onOpenFullScreen', |
| 42 | + 'onCloseFullScreen' |
41 | 43 | ], |
42 | 44 | |
43 | 45 | 'init': function( embedPlayer ){ |
— | — | @@ -54,34 +56,37 @@ |
55 | 57 | // Allow modules to extend the list of iframeExported bindings |
56 | 58 | $j( mw ).trigger( 'AddIframePlayerBindings', [ this.exportedBindings ]); |
57 | 59 | |
58 | | - this._addIframeListener(); |
59 | | - this._addIframeSender(); |
| 60 | + this.addIframeListener(); |
| 61 | + this.addIframeSender(); |
60 | 62 | $j( mw ).trigger( 'newIframePlayerServerSide', [embedPlayer]); |
61 | 63 | }, |
62 | 64 | |
63 | 65 | /** |
64 | 66 | * Listens to requested methods and triggers their action |
65 | 67 | */ |
66 | | - '_addIframeListener': function(){ |
| 68 | + 'addIframeListener': function(){ |
67 | 69 | var _this = this; |
68 | 70 | mw.log('IFramePlayerApiServer::_addIframeListener'); |
69 | 71 | $j.receiveMessage( function( event ) { |
70 | 72 | _this.hanldeMsg( event ); |
71 | | - }, this.parentUrl ); |
| 73 | + }, this.getParentUrl() ); |
72 | 74 | }, |
73 | | - |
| 75 | + getParentUrl: function(){ |
| 76 | + var purl = mw.getConfig( 'EmbedPlayer.IframeParentUrl' ); |
| 77 | + if(!purl){ |
| 78 | + mw.log("Error: iFramePlayerApiServer:: could not parse parent url. \n" + |
| 79 | + "Player events will be dissabled"); |
| 80 | + } |
| 81 | + return purl; |
| 82 | + }, |
74 | 83 | /** |
75 | 84 | * Add iframe sender bindings: |
76 | 85 | */ |
77 | | - '_addIframeSender': function(){ |
| 86 | + 'addIframeSender': function(){ |
78 | 87 | var _this = this; |
79 | 88 | // Get the parent page URL as it was passed in, for browsers that don't support |
80 | 89 | // window.postMessage (this URL could be hard-coded). |
81 | | - this.parentUrl = mw.getConfig( 'EmbedPlayer.IframeParentUrl' ); |
82 | | - if(!this.parentUrl){ |
83 | | - mw.log("Error: iFramePlayerApiServer:: could not parse parent url. \n" + |
84 | | - "Player events will be dissabled"); |
85 | | - } |
| 90 | + |
86 | 91 | // Set the initial attributes once player is "ready" |
87 | 92 | $j( this.embedPlayer ).bind( 'playerReady', function(){ |
88 | 93 | _this.sendPlayerAttributes(); |
— | — | @@ -130,17 +135,17 @@ |
131 | 136 | } ) |
132 | 137 | }, |
133 | 138 | |
134 | | - 'postMessage': function( msgObj ){ |
| 139 | + 'postMessage': function( msgObject ){ |
135 | 140 | try { |
136 | | - var messageString = JSON.stringify( msgObj ); |
| 141 | + var messageString = JSON.stringify( msgObject ); |
137 | 142 | } catch ( e ){ |
138 | | - mw.log("Error: could not JSON object: " + msgObj + ' ' + e); |
| 143 | + mw.log("Error: could not JSON object: " + msgObject + ' ' + e); |
139 | 144 | return ; |
140 | | - } |
| 145 | + } |
141 | 146 | // By default postMessage sends the message to the parent frame: |
142 | 147 | $j.postMessage( |
143 | 148 | messageString, |
144 | | - this.parentUrl, |
| 149 | + this.getParentUrl(), |
145 | 150 | window.parent |
146 | 151 | ); |
147 | 152 | }, |
— | — | @@ -151,7 +156,7 @@ |
152 | 157 | * @param {string} event |
153 | 158 | */ |
154 | 159 | 'hanldeMsg': function( event ){ |
155 | | - //mw.log( 'IFramePlayerApiServer:: hanldeMsg '); |
| 160 | + mw.log( 'IFramePlayerApiServer:: hanldeMsg: ' + event.data ); |
156 | 161 | // Check if the server should even be enabled |
157 | 162 | if( !mw.getConfig( 'EmbedPlayer.EnableIframeApi' )){ |
158 | 163 | mw.log( 'Error: Loading iFrame playerApi but config EmbedPlayer.EnableIframeApi is false'); |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/Sequencer/loader.js |
— | — | @@ -126,7 +126,7 @@ |
127 | 127 | }); |
128 | 128 | |
129 | 129 | // If doing player overlays include remote for player hooks |
130 | | - $j( mw ).bind( 'LoaderEmbedPlayerUpdateRequest', function( event, playerElement, classRequest ) { |
| 130 | + $j( mw ).bind( 'EmbedPlayerUpdateDependencies', function( event, playerElement, classRequest ) { |
131 | 131 | if( mw.getConfig( 'Sequencer.KalturaPlayerEditOverlay' )){ |
132 | 132 | if( $j.inArray( 'mw.MediaWikiRemoteSequencer', classRequest ) == -1 ) { |
133 | 133 | classRequest.push('mw.MediaWikiRemoteSequencer'); |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MwEmbedSupport/jquery/README |
— | — | @@ -0,0 +1 @@ |
| 2 | +jQuery plugin resources specific to mwEmbed, can gradually be moved into mediaWiki/resources/jquery |
\ No newline at end of file |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MwEmbedSupport/jquery/jquery.triggerQueueCallback.js |
— | — | @@ -0,0 +1,72 @@ |
| 2 | +/** |
| 3 | + * Runs all the triggers on all the named bindings of an object with |
| 4 | + * a single callback |
| 5 | + * |
| 6 | + * NOTE THIS REQUIRES JQUERY 1.4.2 and above |
| 7 | + * |
| 8 | + * Normal jQuery tirgger calls will run the callback directly |
| 9 | + * multiple times for every binded function. |
| 10 | + * |
| 11 | + * With triggerQueueCallback() callback is not called until all the |
| 12 | + * binded events have been run. |
| 13 | + * |
| 14 | + * @param {string} |
| 15 | + * triggerName Name of trigger to be run |
| 16 | + * @param {object=} |
| 17 | + * arguments Optional arguments object to be passed to |
| 18 | + * the callback |
| 19 | + * @param {function} |
| 20 | + * callback Function called once all triggers have been |
| 21 | + * run |
| 22 | + * |
| 23 | + */ |
| 24 | +( function( $ ) { |
| 25 | + $.fn.triggerQueueCallback = function( triggerName, triggerParam, callback ){ |
| 26 | + var targetObject = this; |
| 27 | + // Support optional triggerParam data |
| 28 | + if( !callback && typeof triggerParam == 'function' ){ |
| 29 | + callback = triggerParam; |
| 30 | + triggerParam = null; |
| 31 | + } |
| 32 | + // Support namespaced event segmentation ( jQuery |
| 33 | + var triggerBaseName = triggerName.split(".")[0]; |
| 34 | + var triggerNamespace = triggerName.split(".")[1]; |
| 35 | + // Get the callback set |
| 36 | + var callbackSet = []; |
| 37 | + if( ! triggerNamespace ){ |
| 38 | + callbackSet = $j( targetObject ).data( 'events' )[ triggerBaseName ]; |
| 39 | + } else{ |
| 40 | + $j.each( $j( targetObject ).data( 'events' )[ triggerBaseName ], function( inx, bindObject ){ |
| 41 | + if( bindObject.namespace == triggerNamespace ){ |
| 42 | + callbackSet.push( bindObject ); |
| 43 | + } |
| 44 | + }); |
| 45 | + } |
| 46 | + |
| 47 | + if( !callbackSet || callbackSet.length === 0 ){ |
| 48 | + mw.log( '"mwEmbed::jQuery.triggerQueueCallback: No events run the callback directly: ' + triggerName ); |
| 49 | + // No events run the callback directly |
| 50 | + callback(); |
| 51 | + return ; |
| 52 | + } |
| 53 | + |
| 54 | + // Set the callbackCount |
| 55 | + var callbackCount = ( callbackSet.length )? callbackSet.length : 1; |
| 56 | + // mw.log("mwEmbed::jQuery.triggerQueueCallback: " + triggerName |
| 57 | + // + ' number of queued functions:' + callbackCount ); |
| 58 | + var callInx = 0; |
| 59 | + var doCallbackCheck = function() { |
| 60 | + // mw.log( 'callback for: ' + mw.getCallStack()[0] + |
| 61 | + // callInx); |
| 62 | + callInx++; |
| 63 | + if( callInx == callbackCount ){ |
| 64 | + callback(); |
| 65 | + } |
| 66 | + }; |
| 67 | + if( triggerParam ){ |
| 68 | + $( this ).trigger( triggerName, [ triggerParam, doCallbackCheck ]); |
| 69 | + } else { |
| 70 | + $( this ).trigger( triggerName, [ doCallbackCheck ] ); |
| 71 | + } |
| 72 | + }; |
| 73 | +} )( window.mw ); |
\ No newline at end of file |
Property changes on: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MwEmbedSupport/jquery/jquery.triggerQueueCallback.js |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 74 | + text/plain |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MwEmbedSupport/MwEmbedSupport.i18n.php |
— | — | @@ -0,0 +1,737 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * Localization file for mwEmbedSupport |
| 5 | + */ |
| 6 | + |
| 7 | +$messages = array(); |
| 8 | + |
| 9 | +$messages['en'] = array( |
| 10 | + 'mwe-loading_txt' => 'Loading ...', |
| 11 | + 'mwe-size-gigabytes' => '$1 GB', |
| 12 | + 'mwe-size-megabytes' => '$1 MB', |
| 13 | + 'mwe-size-kilobytes' => '$1 K', |
| 14 | + 'mwe-size-bytes' => '$1 B', |
| 15 | + 'mwe-error_load_lib' => 'Error: JavaScript $1 was not retrievable or does not define $2', |
| 16 | + 'mwe-apiproxy-setup' => 'Setting up API proxy', |
| 17 | + 'mwe-load-drag-item' => 'Loading dragged item', |
| 18 | + 'mwe-ok' => 'OK', |
| 19 | + 'mwe-cancel' => 'Cancel', |
| 20 | + 'mwe-enable-gadget' => 'Enable multimedia beta (mwEmbed) for all pages', |
| 21 | + 'mwe-enable-gadget-done' => 'Multimedia beta gadget has been enabled', |
| 22 | + 'mwe-must-login-gadget' => 'To enable gadget you must <a target="_new" href="$1">login</a>', |
| 23 | + 'mwe-test-plural' => 'I ran {{PLURAL:$1|$1 test|$1 tests}}', |
| 24 | +); |
| 25 | + |
| 26 | +/** Message documentation (Message documentation) |
| 27 | + * @author EugeneZelenko |
| 28 | + * @author Fryed-peach |
| 29 | + * @author Nike |
| 30 | + */ |
| 31 | +$messages['qqq'] = array( |
| 32 | + 'mwe-loading_txt' => '{{Identical|Loading}}', |
| 33 | + 'mwe-size-gigabytes' => 'Size (of a file, typically) in gibibytes (1 gibibyte = 1024×1024×1024 bytes).', |
| 34 | + 'mwe-error_load_lib' => 'Parameters: |
| 35 | +* $1 Corresponds to the JavaScript file that was not retrievable or does not define its class name. |
| 36 | +* $2 Is the class name that was associated with the JavaScript file that was not found or could not be retrieved.', |
| 37 | + 'mwe-ok' => '{{Identical|OK}}', |
| 38 | + 'mwe-cancel' => '{{Identical|Cancel}}', |
| 39 | +); |
| 40 | + |
| 41 | +/** Afrikaans (Afrikaans) |
| 42 | + * @author Naudefj |
| 43 | + */ |
| 44 | +$messages['af'] = array( |
| 45 | + 'mwe-loading_txt' => 'laai ...', |
| 46 | + 'mwe-error_load_lib' => 'Fout: JavaScript $1 kon nie gevind word of definieer nie $2 nie', |
| 47 | + 'mwe-ok' => 'OK', |
| 48 | + 'mwe-cancel' => 'Kanselleer', |
| 49 | +); |
| 50 | + |
| 51 | +/** Gheg Albanian (Gegë) |
| 52 | + * @author Mdupont |
| 53 | + */ |
| 54 | +$messages['aln'] = array( |
| 55 | + 'mwe-loading_txt' => 'Loading ...', |
| 56 | + 'mwe-error_load_lib' => 'Gabim: $1 JavaScript nuk ishte shikohen ose nuk define $2', |
| 57 | + 'mwe-apiproxy-setup' => 'Ngritja proxy API', |
| 58 | + 'mwe-load-drag-item' => 'Loading zvarritur artikull', |
| 59 | + 'mwe-ok' => 'Në rregull', |
| 60 | + 'mwe-cancel' => 'Anuloj', |
| 61 | + 'mwe-enable-gadget' => 'Aktivizo multimedial beta (mwEmbed) për të gjitha faqet', |
| 62 | + 'mwe-enable-gadget-done' => 'Multimedia beta vegël ka qenë i aktivizuar', |
| 63 | +); |
| 64 | + |
| 65 | +/** Aragonese (Aragonés) |
| 66 | + * @author Juanpabl |
| 67 | + */ |
| 68 | +$messages['an'] = array( |
| 69 | + 'mwe-cancel' => 'Cancelar', |
| 70 | +); |
| 71 | + |
| 72 | +/** Arabic (العربية) |
| 73 | + * @author OsamaK |
| 74 | + */ |
| 75 | +$messages['ar'] = array( |
| 76 | + 'mwe-loading_txt' => 'يحمل...', |
| 77 | + 'mwe-cancel' => 'ألغِ', |
| 78 | +); |
| 79 | + |
| 80 | +/** Belarusian (Taraškievica orthography) (Беларуская (тарашкевіца)) |
| 81 | + * @author EugeneZelenko |
| 82 | + * @author Jim-by |
| 83 | + */ |
| 84 | +$messages['be-tarask'] = array( |
| 85 | + 'mwe-loading_txt' => 'загрузка …', |
| 86 | + 'mwe-error_load_lib' => 'Памылка: JavaScript $1 не даступны альбо не вызначае $2', |
| 87 | + 'mwe-apiproxy-setup' => 'Устаноўка API-проксі', |
| 88 | + 'mwe-load-drag-item' => 'Загрузка перанесенага элемэнту', |
| 89 | + 'mwe-ok' => 'Добра', |
| 90 | + 'mwe-cancel' => 'Адмяніць', |
| 91 | + 'mwe-enable-gadget' => 'Уключыць бэта-мультымэдыя (mwEmbed) для ўсіх старонак', |
| 92 | + 'mwe-enable-gadget-done' => 'Дапаўненьне бэта-мультымэтыя ўключанае', |
| 93 | + 'mwe-must-login-gadget' => 'Для ўключэньня дапаўненьня Вам неабходна <a target="_new" href="$1">ўвайсьці ў сыстэму</a>', |
| 94 | + 'mwe-test-plural' => 'Я прайшоў $1 {{PLURAL:$1|тэст|тэсты|тэстаў}}', |
| 95 | +); |
| 96 | + |
| 97 | +/** Breton (Brezhoneg) |
| 98 | + * @author Fohanno |
| 99 | + * @author Fulup |
| 100 | + * @author Y-M D |
| 101 | + */ |
| 102 | +$messages['br'] = array( |
| 103 | + 'mwe-loading_txt' => 'o kargañ...', |
| 104 | + 'mwe-error_load_lib' => "Fazi : n'eo ket bet kavet JavaScript $1 pe n'eo ket termenet gant $2", |
| 105 | + 'mwe-apiproxy-setup' => 'Kefluniadur ar proksi API', |
| 106 | + 'mwe-load-drag-item' => 'O kargañ an elfenn digargañ', |
| 107 | + 'mwe-ok' => 'Mat eo', |
| 108 | + 'mwe-cancel' => 'Nullañ', |
| 109 | + 'mwe-enable-gadget' => 'Gweredekaat liesvedia beta (mwEmbed) war an holl bajennoù', |
| 110 | + 'mwe-enable-gadget-done' => 'Gweredekaet eo bet ar gadjet liesvedia beta', |
| 111 | + 'mwe-must-login-gadget' => 'Evit gweredekaat ar gadjet e rankit <a target="_new" href="$1">kevreañ</a>', |
| 112 | + 'mwe-test-plural' => 'Sevenet em eus $1 amprouadenn{{PLURAL:$1||}}', |
| 113 | +); |
| 114 | + |
| 115 | +/** Bosnian (Bosanski) |
| 116 | + * @author CERminator |
| 117 | + */ |
| 118 | +$messages['bs'] = array( |
| 119 | + 'mwe-loading_txt' => 'učitavam ...', |
| 120 | + 'mwe-apiproxy-setup' => 'Postavljanje API proksija', |
| 121 | + 'mwe-ok' => 'U redu', |
| 122 | + 'mwe-cancel' => 'Odustani', |
| 123 | +); |
| 124 | + |
| 125 | +/** Czech (Česky) |
| 126 | + * @author Mormegil |
| 127 | + */ |
| 128 | +$messages['cs'] = array( |
| 129 | + 'mwe-loading_txt' => 'Načítá se …', |
| 130 | + 'mwe-cancel' => 'Storno', |
| 131 | +); |
| 132 | + |
| 133 | +/** Welsh (Cymraeg) */ |
| 134 | +$messages['cy'] = array( |
| 135 | + 'mwe-loading_txt' => "wrthi'n llwytho ...", |
| 136 | +); |
| 137 | + |
| 138 | +/** German (Deutsch) |
| 139 | + * @author Kghbln |
| 140 | + * @author Metalhead64 |
| 141 | + */ |
| 142 | +$messages['de'] = array( |
| 143 | + 'mwe-loading_txt' => 'lade …', |
| 144 | + 'mwe-error_load_lib' => 'Fehler: JavaScript $1 war nicht abrufbar oder lässt $2 nicht zu', |
| 145 | + 'mwe-apiproxy-setup' => 'API-Proxy-Konfiguration', |
| 146 | + 'mwe-load-drag-item' => 'Lade eingebettetes Element', |
| 147 | + 'mwe-ok' => 'OK', |
| 148 | + 'mwe-cancel' => 'Abbrechen', |
| 149 | + 'mwe-enable-gadget' => 'Aktiviere die Beta-Version des Multimedia-Helferleins (mwEmbed) für alle Seiten', |
| 150 | + 'mwe-enable-gadget-done' => 'Beta-Version des Multimedia-Helferleins wurde aktiviert', |
| 151 | + 'mwe-must-login-gadget' => 'Um das Helferlein aktivieren zu können, musst du dich <a target="_new" href="$1">anmelden</a>', |
| 152 | + 'mwe-test-plural' => '{{PLURAL:$1|$1 Test|$1 Tests}} durchlaufen', |
| 153 | +); |
| 154 | + |
| 155 | +/** Zazaki (Zazaki) |
| 156 | + * @author Aspar |
| 157 | + */ |
| 158 | +$messages['diq'] = array( |
| 159 | + 'mwe-loading_txt' => 'bar beno...', |
| 160 | + 'mwe-error_load_lib' => 'xeta: $1 JavaScript re nêresiyeno ya zi pê $2yi şınasnaye niyo.', |
| 161 | + 'mwe-apiproxy-setup' => 'proxyê APIyi eyar beno', |
| 162 | + 'mwe-load-drag-item' => 'unsur bar beno', |
| 163 | + 'mwe-ok' => 'temam', |
| 164 | + 'mwe-cancel' => 'iptal', |
| 165 | +); |
| 166 | + |
| 167 | +/** Lower Sorbian (Dolnoserbski) |
| 168 | + * @author Michawiki |
| 169 | + */ |
| 170 | +$messages['dsb'] = array( |
| 171 | + 'mwe-loading_txt' => 'zacytujo se ...', |
| 172 | + 'mwe-error_load_lib' => 'Zmólka: JavaScript $1 njejo wótwołujobny był abo njedefiněrujo $2', |
| 173 | + 'mwe-apiproxy-setup' => 'Proksy API zarědowaś', |
| 174 | + 'mwe-load-drag-item' => 'Wlecony zapisk se zacytujo', |
| 175 | + 'mwe-ok' => 'W pórědku', |
| 176 | + 'mwe-cancel' => 'Pśetergnuś', |
| 177 | + 'mwe-enable-gadget' => 'Multimedia beta (mwEmbed) za wšykne boki zmóžniś', |
| 178 | + 'mwe-enable-gadget-done' => 'Pśisłušk Multimedia beta jo se zmóžnił', |
| 179 | + 'mwe-must-login-gadget' => 'Aby pśisłušk zmóžnił, musyš se <a target="_new" href="$1">pśizjawiś</a>', |
| 180 | + 'mwe-test-plural' => 'Som {{PLURAL:$1|$1 test|$1 testa|$1 testy|$1 testow}} pśewjadł', |
| 181 | +); |
| 182 | + |
| 183 | +/** Greek (Ελληνικά) |
| 184 | + * @author Crazymadlover |
| 185 | + */ |
| 186 | +$messages['el'] = array( |
| 187 | + 'mwe-loading_txt' => 'φόρτωση ...', |
| 188 | + 'mwe-cancel' => 'Ακύρωση', |
| 189 | +); |
| 190 | + |
| 191 | +/** Esperanto (Esperanto) |
| 192 | + * @author Yekrats |
| 193 | + */ |
| 194 | +$messages['eo'] = array( |
| 195 | + 'mwe-loading_txt' => 'ŝarĝante ...', |
| 196 | + 'mwe-cancel' => 'Nuligi', |
| 197 | +); |
| 198 | + |
| 199 | +/** Spanish (Español) |
| 200 | + * @author Translationista |
| 201 | + */ |
| 202 | +$messages['es'] = array( |
| 203 | + 'mwe-loading_txt' => 'cargando ...', |
| 204 | + 'mwe-error_load_lib' => 'Error: JavaScript $1 no ha podido ser recuperado o no define $2', |
| 205 | + 'mwe-apiproxy-setup' => 'Configurando proxi de la API', |
| 206 | + 'mwe-load-drag-item' => 'Cargando el objeto arrastrado', |
| 207 | + 'mwe-ok' => 'OK', |
| 208 | + 'mwe-cancel' => 'Cancelar', |
| 209 | + 'mwe-enable-gadget' => 'Habilitar multimedia beta (mwEmbed) en todas las páginas', |
| 210 | + 'mwe-enable-gadget-done' => 'Se ha habilitado el gadget multimedia beta', |
| 211 | + 'mwe-must-login-gadget' => 'Para habilitar el gadget debes <a target="_new" href="$1">ingresar</a>', |
| 212 | + 'mwe-test-plural' => 'Realicé {{PLURAL:$1|$1 prueba|$1 pruebas}}', |
| 213 | +); |
| 214 | + |
| 215 | +/** Basque (Euskara) |
| 216 | + * @author An13sa |
| 217 | + */ |
| 218 | +$messages['eu'] = array( |
| 219 | + 'mwe-loading_txt' => 'Kargatzen ...', |
| 220 | + 'mwe-ok' => 'Ados', |
| 221 | + 'mwe-cancel' => 'Ezeztatu', |
| 222 | +); |
| 223 | + |
| 224 | +/** Finnish (Suomi) |
| 225 | + * @author Crt |
| 226 | + * @author Str4nd |
| 227 | + */ |
| 228 | +$messages['fi'] = array( |
| 229 | + 'mwe-loading_txt' => 'Ladataan...', |
| 230 | + 'mwe-error_load_lib' => 'Virhe: JavaScript $1 ei ollut haettavissa tai se ei määrittele luokkaa $2', |
| 231 | + 'mwe-apiproxy-setup' => 'Pystytetään API-välityspalvelinta', |
| 232 | + 'mwe-ok' => 'OK', |
| 233 | + 'mwe-cancel' => 'Peruuta', |
| 234 | + 'mwe-must-login-gadget' => 'Sinun tulee <a target="_new" href="$1">kirjautua sisään</a>, jotta voisit käyttää pienoisohjelmaa', |
| 235 | + 'mwe-test-plural' => 'Ajoin {{PLURAL:$1|$1 testin|$1 testiä}}', |
| 236 | +); |
| 237 | + |
| 238 | +/** French (Français) |
| 239 | + * @author IAlex |
| 240 | + * @author Jean-Frédéric |
| 241 | + * @author PieRRoMaN |
| 242 | + */ |
| 243 | +$messages['fr'] = array( |
| 244 | + 'mwe-loading_txt' => 'chargement ...', |
| 245 | + 'mwe-error_load_lib' => "Erreur : JavaScript $1 n'a pas pu être trouvé ou ne définit pas $2", |
| 246 | + 'mwe-apiproxy-setup' => 'Configuration du proxy API', |
| 247 | + 'mwe-load-drag-item' => 'Chargement de l’élément dépose', |
| 248 | + 'mwe-ok' => 'OK', |
| 249 | + 'mwe-cancel' => 'Annuler', |
| 250 | + 'mwe-enable-gadget' => 'Activer beta multimédia (mwEmbed) sur toutes les pages', |
| 251 | + 'mwe-enable-gadget-done' => 'Le gadget multimédia beta a été activé', |
| 252 | + 'mwe-must-login-gadget' => 'Afin d\'activer le gadget vous devez vous <a target="_new" href="$1">connecter</a>', |
| 253 | + 'mwe-test-plural' => "J'ai exécuté {{PLURAL:$1|$1 test|$1 tests}}", |
| 254 | +); |
| 255 | + |
| 256 | +/** Galician (Galego) |
| 257 | + * @author Toliño |
| 258 | + */ |
| 259 | +$messages['gl'] = array( |
| 260 | + 'mwe-loading_txt' => 'cargando...', |
| 261 | + 'mwe-error_load_lib' => 'Erro: o JavaScript $1 non se puido atopar ou non definía $2', |
| 262 | + 'mwe-apiproxy-setup' => 'Configurando o proxy API', |
| 263 | + 'mwe-load-drag-item' => 'Cargando o elemento arrastrado', |
| 264 | + 'mwe-ok' => 'De acordo', |
| 265 | + 'mwe-cancel' => 'Cancelar', |
| 266 | + 'mwe-enable-gadget' => 'Activar a beta multimedia (mwEmbed) en todas as páxinas', |
| 267 | + 'mwe-enable-gadget-done' => 'Activouse o trebello beta multimedia', |
| 268 | + 'mwe-must-login-gadget' => 'Para activar o trebello ten que <a target="_new" href="$1">acceder ao sistema</a>', |
| 269 | + 'mwe-test-plural' => '{{PLURAL:$1|Fíxose unha proba|Fixéronse $1 probas}}', |
| 270 | +); |
| 271 | + |
| 272 | +/** Swiss German (Alemannisch) |
| 273 | + * @author Als-Holder |
| 274 | + */ |
| 275 | +$messages['gsw'] = array( |
| 276 | + 'mwe-loading_txt' => 'Am Lade ...', |
| 277 | + 'mwe-error_load_lib' => 'Fähler: s JavaScript $1 het nit chenne glade wäre oder s losst $2 nit zue', |
| 278 | + 'mwe-apiproxy-setup' => 'API-Proxy-Konfiguration', |
| 279 | + 'mwe-load-drag-item' => 'Am Lade vu mitgschleipfte Poschte', |
| 280 | + 'mwe-ok' => 'OK', |
| 281 | + 'mwe-cancel' => 'Abbräche', |
| 282 | + 'mwe-enable-gadget' => 'D Beta-Version vum Multimedia-Heälferli (mwEmbed) fir alli Syte aktiviere', |
| 283 | + 'mwe-enable-gadget-done' => 'Beta-Version vum Multimedia-Hälferli isch aktiviert wore', |
| 284 | + 'mwe-must-login-gadget' => 'Go s Hälferli aktiviere chenne, muesch di <a target="_new" href="$1">aamälde</a>', |
| 285 | + 'mwe-test-plural' => '{{PLURAL:$1|$1 Tescht|$1 Tescht}} uusgfiert', |
| 286 | +); |
| 287 | + |
| 288 | +/** Hausa (هَوُسَ) */ |
| 289 | +$messages['ha'] = array( |
| 290 | + 'mwe-cancel' => 'Soke', |
| 291 | +); |
| 292 | + |
| 293 | +/** Hebrew (עברית) |
| 294 | + * @author Rotemliss |
| 295 | + */ |
| 296 | +$messages['he'] = array( |
| 297 | + 'mwe-loading_txt' => 'בטעינה ...', |
| 298 | + 'mwe-error_load_lib' => 'שגיאה: לא ניתן היה לטעון את ספריית ה־JavaScript בשם $1 או שהיא אינה מגדירה את $2', |
| 299 | +); |
| 300 | + |
| 301 | +/** Upper Sorbian (Hornjoserbsce) |
| 302 | + * @author Michawiki |
| 303 | + */ |
| 304 | +$messages['hsb'] = array( |
| 305 | + 'mwe-loading_txt' => 'začituje so ...', |
| 306 | + 'mwe-size-gigabytes' => '$1 GB', |
| 307 | + 'mwe-size-megabytes' => '$1 MB', |
| 308 | + 'mwe-size-kilobytes' => '$1 KB', |
| 309 | + 'mwe-size-bytes' => '$1 B', |
| 310 | + 'mwe-error_load_lib' => 'Zmylk: JavaScript $1 njeda so wotwołać abo njedefinuje $2', |
| 311 | + 'mwe-apiproxy-setup' => 'Proksy API zarjadować', |
| 312 | + 'mwe-load-drag-item' => 'Wlečeny zapisk so začituje', |
| 313 | + 'mwe-ok' => 'W porjadku', |
| 314 | + 'mwe-cancel' => 'Přetorhnyć', |
| 315 | + 'mwe-enable-gadget' => 'Multimedia beta (mwEmbed) za wšě strony zmóžnić', |
| 316 | + 'mwe-enable-gadget-done' => 'Přisłušk za Multimedia beta je so zmóžnił', |
| 317 | + 'mwe-must-login-gadget' => 'Zo by přisłušk zmóžnił, dyrbiš so <a target="_new" href="$1">přizjewić</a>', |
| 318 | + 'mwe-test-plural' => 'Sym {{PLURAL:$1|$1 test|$1 testaj|testy|testow}} přewjedł', |
| 319 | +); |
| 320 | + |
| 321 | +/** Hungarian (Magyar) |
| 322 | + * @author Dani |
| 323 | + * @author Glanthor Reviol |
| 324 | + */ |
| 325 | +$messages['hu'] = array( |
| 326 | + 'mwe-loading_txt' => 'betöltés…', |
| 327 | + 'mwe-error_load_lib' => 'Hiba: a(z) $1 JavaScript-fájl nem elérhető, vagy nem definiálja a(z) $2 osztályt.', |
| 328 | + 'mwe-apiproxy-setup' => 'API proxy beállítása', |
| 329 | + 'mwe-load-drag-item' => 'Vonszolt elem betöltése', |
| 330 | + 'mwe-ok' => 'OK', |
| 331 | + 'mwe-cancel' => 'Mégse', |
| 332 | + 'mwe-enable-gadget' => 'A multimédia béta (mwEmbed) engedélyezése az összes lapon', |
| 333 | + 'mwe-enable-gadget-done' => 'A multimédia béta segédeszköz engedélyezve', |
| 334 | + 'mwe-must-login-gadget' => 'Hogy engedélyezni tudd a segédeszközt, <a target="_new" href="$1">be kell jelentkezned</a>', |
| 335 | + 'mwe-test-plural' => '$1 tesztet futtattam', |
| 336 | +); |
| 337 | + |
| 338 | +/** Interlingua (Interlingua) |
| 339 | + * @author McDutchie |
| 340 | + */ |
| 341 | +$messages['ia'] = array( |
| 342 | + 'mwe-loading_txt' => 'cargamento ...', |
| 343 | + 'mwe-error_load_lib' => 'Error: JavaScript $1 non esseva recuperabile o non defini $2', |
| 344 | + 'mwe-apiproxy-setup' => 'Configuration del proxy pro le API', |
| 345 | + 'mwe-load-drag-item' => 'Cargamento del file trahite', |
| 346 | + 'mwe-ok' => 'OK', |
| 347 | + 'mwe-cancel' => 'Cancella', |
| 348 | + 'mwe-enable-gadget' => 'Activar beta multimedia (mwEmbed) pro tote le paginas', |
| 349 | + 'mwe-enable-gadget-done' => 'Le gadget beta multimedia ha essite activate', |
| 350 | + 'mwe-must-login-gadget' => 'Pro activar le gadget tu debe <a target="_new" href="$1">aperir un session</a>', |
| 351 | + 'mwe-test-plural' => 'Io ha executate {{PLURAL:$1|$1 test|$1 tests}}', |
| 352 | +); |
| 353 | + |
| 354 | +/** Indonesian (Bahasa Indonesia) |
| 355 | + * @author Farras |
| 356 | + * @author Irwangatot |
| 357 | + * @author IvanLanin |
| 358 | + */ |
| 359 | +$messages['id'] = array( |
| 360 | + 'mwe-loading_txt' => 'memuat...', |
| 361 | + 'mwe-error_load_lib' => 'Kesalahan: JavaScript $1 tidak dapat diambil atau tidak mendefinisikan $2', |
| 362 | + 'mwe-apiproxy-setup' => 'Menyiapkan proksi API', |
| 363 | + 'mwe-load-drag-item' => 'Memuat butir terseret', |
| 364 | + 'mwe-ok' => 'Oke', |
| 365 | + 'mwe-cancel' => 'Batalkan', |
| 366 | + 'mwe-enable-gadget' => 'Aktifkan beta multimedia (mwEmbed) untuk semua halaman', |
| 367 | + 'mwe-enable-gadget-done' => 'Gadget beta multimedia telah diaktifkan', |
| 368 | + 'mwe-must-login-gadget' => 'Untuk mengaktifkan gadget Anda harus <a target="_new" href="$1">masuk log</a>', |
| 369 | + 'mwe-test-plural' => 'Saya menjalankan {{PLURAL:$1|$1 tes|$1 tes}}', |
| 370 | +); |
| 371 | + |
| 372 | +/** Igbo (Igbo) */ |
| 373 | +$messages['ig'] = array( |
| 374 | + 'mwe-ok' => 'Ngwanu', |
| 375 | + 'mwe-cancel' => 'Emekwàlà', |
| 376 | +); |
| 377 | + |
| 378 | +/** Italian (Italiano) |
| 379 | + * @author Gianfranco |
| 380 | + */ |
| 381 | +$messages['it'] = array( |
| 382 | + 'mwe-cancel' => 'Annulla', |
| 383 | +); |
| 384 | + |
| 385 | +/** Japanese (日本語) |
| 386 | + * @author Fryed-peach |
| 387 | + * @author 青子守歌 |
| 388 | + */ |
| 389 | +$messages['ja'] = array( |
| 390 | + 'mwe-loading_txt' => '読み込み中 …', |
| 391 | + 'mwe-error_load_lib' => 'エラー:JavaScript $1 は参照不能か、$2 を定義していません。', |
| 392 | + 'mwe-apiproxy-setup' => 'API プロキシーをセットアップ中', |
| 393 | + 'mwe-load-drag-item' => 'ドラッグされた項目を読み込み中', |
| 394 | + 'mwe-ok' => 'OK', |
| 395 | + 'mwe-cancel' => '中止', |
| 396 | + 'mwe-enable-gadget' => 'マルチメディアベータ(mwEmbed)を全ページで有効化', |
| 397 | + 'mwe-enable-gadget-done' => 'マルチメディアベータのガジェットが有効です', |
| 398 | + 'mwe-must-login-gadget' => 'ガジェットを有効にするには<a target="_new" href="$1">ログイン</a>が必要です', |
| 399 | + 'mwe-test-plural' => '{{PLURAL:$1|$1のテスト}}を実行する', |
| 400 | +); |
| 401 | + |
| 402 | +/** Korean (한국어) |
| 403 | + * @author Kwj2772 |
| 404 | + */ |
| 405 | +$messages['ko'] = array( |
| 406 | + 'mwe-loading_txt' => '불러오는 중...', |
| 407 | + 'mwe-cancel' => '취소', |
| 408 | +); |
| 409 | + |
| 410 | +/** Colognian (Ripoarisch) |
| 411 | + * @author Purodha |
| 412 | + */ |
| 413 | +$messages['ksh'] = array( |
| 414 | + 'mwe-loading_txt' => 'aam Laade …', |
| 415 | + 'mwe-size-gigabytes' => '$1 GB', |
| 416 | + 'mwe-size-megabytes' => '$1 MB', |
| 417 | + 'mwe-size-kilobytes' => '$1 KB', |
| 418 | + 'mwe-size-bytes' => '$1 Bytes', |
| 419 | + 'mwe-error_load_lib' => 'Fähler: Dat JavaSkrep „<code lang="en">$1</code>“ wohr nit ze laade udder et leiht „<code lang="en">$2</code>“ nit faß.', |
| 420 | + 'mwe-cancel' => 'Affbräsche', |
| 421 | +); |
| 422 | + |
| 423 | +/** Luxembourgish (Lëtzebuergesch) |
| 424 | + * @author Robby |
| 425 | + */ |
| 426 | +$messages['lb'] = array( |
| 427 | + 'mwe-loading_txt' => 'lueden ...', |
| 428 | + 'mwe-error_load_lib' => 'Feeler: JavaScript $1 konnt net ofgeruf ginn oder definéiert $2 net', |
| 429 | + 'mwe-apiproxy-setup' => 'API-Proxy astellen', |
| 430 | + 'mwe-load-drag-item' => 'Den agebonnen Objet gëtt gelueden', |
| 431 | + 'mwe-ok' => 'OK', |
| 432 | + 'mwe-cancel' => 'Ofbriechen', |
| 433 | + 'mwe-enable-gadget' => 'Multimedia-Beta-Gadget (mwEmbed) fir all Säiten aktivéieren', |
| 434 | + 'mwe-enable-gadget-done' => 'De Multimedia-Beta-Gadget gouf aktivéiert', |
| 435 | + 'mwe-must-login-gadget' => 'Fir de Gadget aktivéieren ze kënne musst Dir Iech <a target="_new" href="$1">aloggen</a>', |
| 436 | + 'mwe-test-plural' => 'Ech hunn {{PLURAL:$1|$1 Test|$1 Tester}} gemaach', |
| 437 | +); |
| 438 | + |
| 439 | +/** Macedonian (Македонски) |
| 440 | + * @author Bjankuloski06 |
| 441 | + */ |
| 442 | +$messages['mk'] = array( |
| 443 | + 'mwe-loading_txt' => 'Вчитувам...', |
| 444 | + 'mwe-error_load_lib' => 'Грешка: JavaScript $1 не е достапен или не определува $2', |
| 445 | + 'mwe-apiproxy-setup' => 'Поставувам API застапник (proxy)', |
| 446 | + 'mwe-load-drag-item' => 'Го вчитувам повлечениот елемент', |
| 447 | + 'mwe-ok' => 'ОК', |
| 448 | + 'mwe-cancel' => 'Откажи', |
| 449 | + 'mwe-enable-gadget' => 'Овозможи бета-мултимедија (mwEmbed) за сите страници', |
| 450 | + 'mwe-enable-gadget-done' => 'Овозможена е алатката за бета-мултимедија', |
| 451 | + 'mwe-must-login-gadget' => 'За да ја овозможите алатката морате да се <a target="_new" href="$1">најавите</a>', |
| 452 | + 'mwe-test-plural' => 'Направив {{PLURAL:$1|$1 проверка|$1 проверки}}', |
| 453 | +); |
| 454 | + |
| 455 | +/** Malayalam (മലയാളം) |
| 456 | + * @author Praveenp |
| 457 | + */ |
| 458 | +$messages['ml'] = array( |
| 459 | + 'mwe-loading_txt' => 'ശേഖരിക്കുന്നു ...', |
| 460 | + 'mwe-error_load_lib' => 'പിശക്: ജാവാസ്ക്രിപ്റ്റ് $1 ശേഖരിക്കാൻ കഴിഞ്ഞില്ല അല്ലെങ്കിൽ $2 നിർവ്വചിച്ചിട്ടില്ല', |
| 461 | + 'mwe-apiproxy-setup' => 'എ.പി.ഐ. പ്രോക്സി സജ്ജീകരിക്കുക', |
| 462 | + 'mwe-load-drag-item' => 'വലിച്ചിട്ടത് ശേഖരിക്കുന്നു', |
| 463 | + 'mwe-ok' => 'ശരി', |
| 464 | + 'mwe-cancel' => 'റദ്ദാക്കുക', |
| 465 | +); |
| 466 | + |
| 467 | +/** Erzya (Эрзянь) |
| 468 | + * @author Botuzhaleny-sodamo |
| 469 | + */ |
| 470 | +$messages['myv'] = array( |
| 471 | + 'mwe-loading_txt' => 'Йовкстамозо моли…', |
| 472 | +); |
| 473 | + |
| 474 | +/** Dutch (Nederlands) |
| 475 | + * @author Siebrand |
| 476 | + */ |
| 477 | +$messages['nl'] = array( |
| 478 | + 'mwe-loading_txt' => 'bezig met laden ...', |
| 479 | + 'mwe-error_load_lib' => 'Fout: JavaScript $1 kon niet opgehaald worden of definieert $2 niet', |
| 480 | + 'mwe-apiproxy-setup' => 'Bezig met het opzetten van een API-proxy', |
| 481 | + 'mwe-load-drag-item' => 'Bezig met het laden van het gesleepte bestand', |
| 482 | + 'mwe-ok' => 'OK', |
| 483 | + 'mwe-cancel' => 'Annuleren', |
| 484 | + 'mwe-enable-gadget' => "Multimedia beta (mwEmbed) voor alle pagina's inschakelen", |
| 485 | + 'mwe-enable-gadget-done' => 'Multimedia beta is ingeschakeld', |
| 486 | + 'mwe-must-login-gadget' => 'Om de uitbreiding in te schakelen, moet u <a target="_new" href="$1">aanmelden</a>', |
| 487 | + 'mwe-test-plural' => '{{PLURAL:$1|$1 test|$1 tests}} uitgevoerd', |
| 488 | +); |
| 489 | + |
| 490 | +/** Norwegian (bokmål) (Norsk (bokmål)) |
| 491 | + * @author Nghtwlkr |
| 492 | + */ |
| 493 | +$messages['no'] = array( |
| 494 | + 'mwe-loading_txt' => 'Laster ...', |
| 495 | + 'mwe-error_load_lib' => 'Feil: JavaScript $1 kunne ikke gjenhentes eller definerer ikke $2', |
| 496 | + 'mwe-apiproxy-setup' => 'Setter opp API-mellomtjener', |
| 497 | + 'mwe-load-drag-item' => 'Laster dratt element', |
| 498 | + 'mwe-ok' => 'OK', |
| 499 | + 'mwe-cancel' => 'Avbryt', |
| 500 | + 'mwe-enable-gadget' => 'Aktiver multimedia-beta (mwEmbed) for alle sider', |
| 501 | + 'mwe-enable-gadget-done' => 'Skjermelement for multimedia-beta har blitt aktivert', |
| 502 | + 'mwe-must-login-gadget' => 'For å aktivere skjermelement må du <a target="_new" href="$1">logge inn</a>', |
| 503 | + 'mwe-test-plural' => 'Jeg kjørte {{PLURAL:$1|én test|$1 tester}}', |
| 504 | +); |
| 505 | + |
| 506 | +/** Occitan (Occitan) |
| 507 | + * @author Cedric31 |
| 508 | + */ |
| 509 | +$messages['oc'] = array( |
| 510 | + 'mwe-loading_txt' => 'cargament ...', |
| 511 | + 'mwe-error_load_lib' => 'Error : JavaScript $1 a pas pogut èsser trobat o definís pas $2', |
| 512 | + 'mwe-apiproxy-setup' => 'Configuracion del proxy API', |
| 513 | + 'mwe-load-drag-item' => 'Cargament de l’element depausat', |
| 514 | + 'mwe-ok' => 'OK', |
| 515 | + 'mwe-cancel' => 'Anullar', |
| 516 | +); |
| 517 | + |
| 518 | +/** Deitsch (Deitsch) |
| 519 | + * @author Xqt |
| 520 | + */ |
| 521 | +$messages['pdc'] = array( |
| 522 | + 'mwe-ok' => 'OK', |
| 523 | +); |
| 524 | + |
| 525 | +/** Polish (Polski) |
| 526 | + * @author Sp5uhe |
| 527 | + */ |
| 528 | +$messages['pl'] = array( |
| 529 | + 'mwe-loading_txt' => 'ładowanie ...', |
| 530 | + 'mwe-error_load_lib' => 'Błąd – W plik JavaScript $1 brak jest możliwości pobrania oraz definicji $2', |
| 531 | + 'mwe-apiproxy-setup' => 'Konfiguracja proxy dla API', |
| 532 | + 'mwe-load-drag-item' => 'Ładowanie przeciągniętego elementu', |
| 533 | + 'mwe-ok' => 'OK', |
| 534 | + 'mwe-cancel' => 'Anuluj', |
| 535 | + 'mwe-enable-gadget' => 'Włącz wersję testową multimediów (wmEmbed) na wszystkich stronach', |
| 536 | + 'mwe-enable-gadget-done' => 'Testowy gadżet multimediów został włączony', |
| 537 | + 'mwe-must-login-gadget' => 'Gadżet można włączyć dopiero po <a target="_new" href="$1">zalogowaniu się</a>', |
| 538 | + 'mwe-test-plural' => 'Wykonałem $1 {{PLURAL:$1|test|testy|testów}}', |
| 539 | +); |
| 540 | + |
| 541 | +/** Piedmontese (Piemontèis) |
| 542 | + * @author Borichèt |
| 543 | + * @author Dragonòt |
| 544 | + */ |
| 545 | +$messages['pms'] = array( |
| 546 | + 'mwe-loading_txt' => 'A caria ...', |
| 547 | + 'mwe-error_load_lib' => 'Eror: JavaScript $1 as peul pa trovesse o a definiss pa $2', |
| 548 | + 'mwe-apiproxy-setup' => 'Amposté ël proxy API', |
| 549 | + 'mwe-load-drag-item' => "carié l'element tirà", |
| 550 | + 'mwe-ok' => 'Va bin', |
| 551 | + 'mwe-cancel' => 'Scancela', |
| 552 | + 'mwe-enable-gadget' => 'Abìlita la beta multimedia (mwEmbed) për tute le pàgine', |
| 553 | + 'mwe-enable-gadget-done' => "L'acessòri beta multimedia a l'é stàit abilità", |
| 554 | + 'mwe-must-login-gadget' => 'Për abilité l\'acessòri a dev <a target="_new" href="$1">intré ant ël sistema</a>', |
| 555 | + 'mwe-test-plural' => "I l'heu fàit {{PLURAL:$1|$1 test|$1 test}}", |
| 556 | +); |
| 557 | + |
| 558 | +/** Pashto (پښتو) |
| 559 | + * @author Ahmed-Najib-Biabani-Ibrahimkhel |
| 560 | + */ |
| 561 | +$messages['ps'] = array( |
| 562 | + 'mwe-ok' => 'ښه', |
| 563 | + 'mwe-cancel' => 'ناګارل', |
| 564 | +); |
| 565 | + |
| 566 | +/** Portuguese (Português) |
| 567 | + * @author Hamilton Abreu |
| 568 | + * @author Malafaya |
| 569 | + */ |
| 570 | +$messages['pt'] = array( |
| 571 | + 'mwe-loading_txt' => 'A carregar ...', |
| 572 | + 'mwe-error_load_lib' => 'Erro: O JavaScript $1 não pode ser importado ou não define $2', |
| 573 | + 'mwe-apiproxy-setup' => "A preparar o ''proxy'' da API", |
| 574 | + 'mwe-load-drag-item' => 'A carregar o objecto arrastado', |
| 575 | + 'mwe-ok' => 'OK', |
| 576 | + 'mwe-cancel' => 'Cancelar', |
| 577 | + 'mwe-enable-gadget' => 'Activar multimédia beta (mwEmbed) para todas as páginas', |
| 578 | + 'mwe-enable-gadget-done' => 'Gadget de multimédia beta foi activado', |
| 579 | + 'mwe-must-login-gadget' => 'Para activar o gadget tem de estar <a target="_new" href="$1">autenticado</a>', |
| 580 | + 'mwe-test-plural' => 'Fiz $1 {{PLURAL:$1|teste|testes}}', |
| 581 | +); |
| 582 | + |
| 583 | +/** Brazilian Portuguese (Português do Brasil) |
| 584 | + * @author Giro720 |
| 585 | + * @author Luckas Blade |
| 586 | + */ |
| 587 | +$messages['pt-br'] = array( |
| 588 | + 'mwe-loading_txt' => 'Carregando ...', |
| 589 | + 'mwe-error_load_lib' => 'Erro: O JavaScript $1 não pode ser importado ou não define $2', |
| 590 | + 'mwe-apiproxy-setup' => 'Configurando proxy da API', |
| 591 | + 'mwe-load-drag-item' => 'Carregando o objeto arrastado', |
| 592 | + 'mwe-ok' => 'OK', |
| 593 | + 'mwe-cancel' => 'Cancelar', |
| 594 | + 'mwe-enable-gadget' => 'Ativar multimídia beta beta (mwEmbed) para todas as páginas', |
| 595 | + 'mwe-enable-gadget-done' => 'Gadget de multimídia beta foi ativado', |
| 596 | + 'mwe-must-login-gadget' => 'Para ativar o gadget você deve estar <a target="_new" href="$1">autenticado</a>', |
| 597 | + 'mwe-test-plural' => 'Eu fiz $1 {{PLURAL:$1|teste|testes}}', |
| 598 | +); |
| 599 | + |
| 600 | +/** Russian (Русский) |
| 601 | + * @author Александр Сигачёв |
| 602 | + */ |
| 603 | +$messages['ru'] = array( |
| 604 | + 'mwe-loading_txt' => 'загрузка …', |
| 605 | + 'mwe-error_load_lib' => 'Ошибка. JavaScript $1 не доступен или не определяет $2', |
| 606 | + 'mwe-apiproxy-setup' => 'Настройка API-прокси', |
| 607 | + 'mwe-load-drag-item' => 'Загрузка перетащенного элемента', |
| 608 | + 'mwe-ok' => 'OK', |
| 609 | + 'mwe-cancel' => 'Отмена', |
| 610 | + 'mwe-enable-gadget' => 'Включить бета-мультимедиа (mwEmbed) для всех страниц', |
| 611 | + 'mwe-enable-gadget-done' => 'Включён гаджет бета-мультимедиа', |
| 612 | + 'mwe-must-login-gadget' => 'Для включения гаджета вам следует <a target="_new" href="$1">представиться</a>.', |
| 613 | + 'mwe-test-plural' => 'Я прошёл {{PLURAL:$1|$1 проверку|$1 проверки|$1 проверок}}', |
| 614 | +); |
| 615 | + |
| 616 | +/** Rusyn (Русиньскый) |
| 617 | + * @author Gazeb |
| 618 | + */ |
| 619 | +$messages['rue'] = array( |
| 620 | + 'mwe-ok' => 'ОК', |
| 621 | + 'mwe-cancel' => 'Сторно', |
| 622 | +); |
| 623 | + |
| 624 | +/** Slovak (Slovenčina) |
| 625 | + * @author Helix84 |
| 626 | + */ |
| 627 | +$messages['sk'] = array( |
| 628 | + 'mwe-loading_txt' => 'načítava sa ...', |
| 629 | + 'mwe-error_load_lib' => 'Error: JavaScript $1 nebolo možné získať alebo neobsahuje definíciu $2', |
| 630 | +); |
| 631 | + |
| 632 | +/** Serbian Cyrillic ekavian (Српски (ћирилица)) |
| 633 | + * @author Михајло Анђелковић |
| 634 | + */ |
| 635 | +$messages['sr-ec'] = array( |
| 636 | + 'mwe-loading_txt' => 'Учитавање ...', |
| 637 | + 'mwe-ok' => 'ОК', |
| 638 | + 'mwe-cancel' => 'Поништи', |
| 639 | + 'mwe-test-plural' => 'Покренуо/ла сам {{PLURAL:$1|$1 тест|$1 тестова}}', |
| 640 | +); |
| 641 | + |
| 642 | +/** Serbian Latin ekavian (Srpski (latinica)) */ |
| 643 | +$messages['sr-el'] = array( |
| 644 | + 'mwe-loading_txt' => 'Učitavanje ...', |
| 645 | + 'mwe-ok' => 'OK', |
| 646 | + 'mwe-cancel' => 'Poništi', |
| 647 | + 'mwe-test-plural' => 'Pokrenuo/la sam {{PLURAL:$1|$1 test|$1 testova}}', |
| 648 | +); |
| 649 | + |
| 650 | +/** Swedish (Svenska) |
| 651 | + * @author Dafer45 |
| 652 | + * @author GameOn |
| 653 | + */ |
| 654 | +$messages['sv'] = array( |
| 655 | + 'mwe-loading_txt' => 'Laddar…', |
| 656 | + 'mwe-ok' => 'OK', |
| 657 | + 'mwe-cancel' => 'Avbryt', |
| 658 | +); |
| 659 | + |
| 660 | +/** Telugu (తెలుగు) |
| 661 | + * @author Veeven |
| 662 | + */ |
| 663 | +$messages['te'] = array( |
| 664 | + 'mwe-ok' => 'సరే', |
| 665 | + 'mwe-cancel' => 'రద్దుచేయి', |
| 666 | +); |
| 667 | + |
| 668 | +/** Tagalog (Tagalog) |
| 669 | + * @author AnakngAraw |
| 670 | + */ |
| 671 | +$messages['tl'] = array( |
| 672 | + 'mwe-loading_txt' => 'Ikinakarga...', |
| 673 | + 'mwe-error_load_lib' => 'Kamalian: hindi makukuha ang JavaScript na $1 o hindi nagbigay kahulugan sa $2', |
| 674 | + 'mwe-apiproxy-setup' => 'Nagtatalaga ng pamalit na API', |
| 675 | + 'mwe-load-drag-item' => 'Ikinakarga ang hinilang bagay', |
| 676 | + 'mwe-ok' => 'Okey', |
| 677 | + 'mwe-cancel' => 'Huwag ituloy', |
| 678 | + 'mwe-enable-gadget' => 'Paganahin ang betang multimidya (mwEmbed) para sa lahat ng mga pahina', |
| 679 | + 'mwe-enable-gadget-done' => 'Pinagana ang gadyet na pangbetang multimidya', |
| 680 | + 'mwe-must-login-gadget' => 'Upang mapagana ang gadyet dapat kang <a target="_new" href="$1">lumagda</a>', |
| 681 | + 'mwe-test-plural' => 'Nagpatakbo ako ng {{PLURAL:$1|$1 pagsusulit|$1 mga pagsusulit}}', |
| 682 | +); |
| 683 | + |
| 684 | +/** Turkish (Türkçe) |
| 685 | + * @author Joseph |
| 686 | + */ |
| 687 | +$messages['tr'] = array( |
| 688 | + 'mwe-loading_txt' => 'yükleniyor ...', |
| 689 | + 'mwe-error_load_lib' => 'Hata: $1 JavaScripti erişilebilir değil ya da $2 tanımlı değil', |
| 690 | + 'mwe-apiproxy-setup' => 'API vekili ayarlanıyor', |
| 691 | + 'mwe-load-drag-item' => 'Sürüklenen öğe yükleniyor', |
| 692 | + 'mwe-ok' => 'Tamam', |
| 693 | + 'mwe-cancel' => 'İptal', |
| 694 | +); |
| 695 | + |
| 696 | +/** Urdu (اردو) */ |
| 697 | +$messages['ur'] = array( |
| 698 | + 'mwe-cancel' => 'منسوخ', |
| 699 | +); |
| 700 | + |
| 701 | +/** Vèneto (Vèneto) |
| 702 | + * @author Candalua |
| 703 | + */ |
| 704 | +$messages['vec'] = array( |
| 705 | + 'mwe-loading_txt' => "so' drio cargar ...", |
| 706 | + 'mwe-ok' => 'Va ben', |
| 707 | + 'mwe-cancel' => 'Anula', |
| 708 | +); |
| 709 | + |
| 710 | +/** Vietnamese (Tiếng Việt) |
| 711 | + * @author Minh Nguyen |
| 712 | + * @author Vinhtantran |
| 713 | + */ |
| 714 | +$messages['vi'] = array( |
| 715 | + 'mwe-loading_txt' => 'đang tải …', |
| 716 | + 'mwe-size-kilobytes' => '$1 kB', |
| 717 | + 'mwe-error_load_lib' => 'Lỗi: JavaScript $1 không truy xuất được hoặc không định nghĩa $2', |
| 718 | + 'mwe-apiproxy-setup' => 'Đang thiết lập proxy API', |
| 719 | + 'mwe-load-drag-item' => 'Đang tải các mục đã kéo', |
| 720 | + 'mwe-ok' => 'OK', |
| 721 | + 'mwe-cancel' => 'Hủy bỏ', |
| 722 | + 'mwe-enable-gadget' => 'Kích hoạt đa phương tiện bản beta (mwEmbed) cho mọi trang', |
| 723 | + 'mwe-enable-gadget-done' => 'Công cụ đa năng đa phương tiện bản beta đã được kích hoạt', |
| 724 | + 'mwe-must-login-gadget' => 'Để kích hoạt công cụ đa năng bạn phải <a target="_new" href="$1">đăng nhập</a>', |
| 725 | + 'mwe-test-plural' => 'Tôi đã chạy {{PLURAL:$1|$1 mẫu thử|$1 mẫu thử}}', |
| 726 | +); |
| 727 | + |
| 728 | +/** Wu (吴语) */ |
| 729 | +$messages['wuu'] = array( |
| 730 | + 'mwe-cancel' => '取消', |
| 731 | +); |
| 732 | + |
| 733 | +/** Simplified Chinese (中文(简体)) */ |
| 734 | +$messages['zh-hans'] = array( |
| 735 | + 'mwe-loading_txt' => '载入中……', |
| 736 | + 'mwe-ok' => '确定', |
| 737 | + 'mwe-cancel' => '取消', |
| 738 | +); |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MwEmbedSupport/jquery.menu/jquery.menu.css |
— | — | @@ -0,0 +1,119 @@ |
| 2 | +/* Styles for jQuery menu widget |
| 3 | +Author: Maggie Wachs, maggie@filamentgroup.com |
| 4 | +Date: September 2008 |
| 5 | +*/ |
| 6 | + |
| 7 | + |
| 8 | +/* REQUIRED STYLES - the menus will only render correctly with these rules */ |
| 9 | + |
| 10 | +.fg-menu-container { position: absolute; top:0; left:-999px; padding: .4em; overflow: hidden; } |
| 11 | +.fg-menu-container.fg-menu-flyout { overflow: visible; } |
| 12 | + |
| 13 | +.fg-menu, .fg-menu ul { list-style:none none; padding: 0; margin:0; } |
| 14 | + |
| 15 | +.fg-menu { position:relative; } |
| 16 | +.fg-menu-flyout .fg-menu { position:static; } |
| 17 | + |
| 18 | +.fg-menu ul { position:absolute; top:0; } |
| 19 | +.fg-menu ul ul { top:-1px; } |
| 20 | + |
| 21 | +.fg-menu-container.fg-menu-ipod .fg-menu-content, |
| 22 | +.fg-menu-container.fg-menu-ipod .fg-menu-content ul { background: none !important; } |
| 23 | + |
| 24 | +.fg-menu.fg-menu-scroll, |
| 25 | +.fg-menu ul.fg-menu-scroll { overflow: scroll; overflow-x: hidden; } |
| 26 | + |
| 27 | +.fg-menu li { clear:both; float:left; width:100%; margin: 0; padding:0; border: 0; } |
| 28 | +.fg-menu li li { font-size:1em; } /* inner li font size must be reset so that they don't blow up */ |
| 29 | + |
| 30 | +.fg-menu-flyout ul ul { padding: .4em; } |
| 31 | +.fg-menu-flyout li { position:relative; } |
| 32 | + |
| 33 | +.fg-menu-scroll { overflow: scroll; overflow-x: hidden; } |
| 34 | + |
| 35 | +.fg-menu-breadcrumb { margin: 0; padding: 0; } |
| 36 | + |
| 37 | +.fg-menu-footer { margin-top: .4em; |
| 38 | +padding: .4em; |
| 39 | +position:absolute; |
| 40 | +bottom:2px; |
| 41 | +width: 170px; |
| 42 | +} |
| 43 | +.fg-menu-header { margin-bottom: .4em; padding: .4em; } |
| 44 | + |
| 45 | +.fg-menu-breadcrumb li { float: left; list-style: none; margin: 0; padding: 0 .2em; font-size: .9em; opacity: .7; } |
| 46 | +.fg-menu-breadcrumb li.fg-menu-prev-list, |
| 47 | +.fg-menu-breadcrumb li.fg-menu-current-crumb { clear: left; float: none; opacity: 1; } |
| 48 | +.fg-menu-breadcrumb li.fg-menu-current-crumb { padding-top: .2em; } |
| 49 | + |
| 50 | +.fg-menu-breadcrumb a, |
| 51 | +.fg-menu-breadcrumb span { float: left; } |
| 52 | + |
| 53 | +.fg-menu-footer a:link, |
| 54 | +.fg-menu-footer a:visited { float:left; width:100%; text-decoration: none; } |
| 55 | +.fg-menu-footer a:hover, |
| 56 | +.fg-menu-footer a:active { } |
| 57 | + |
| 58 | +.fg-menu-footer a span { float:left; cursor: pointer; } |
| 59 | + |
| 60 | +.fg-menu-breadcrumb .fg-menu-prev-list a:link, |
| 61 | +.fg-menu-breadcrumb .fg-menu-prev-list a:visited, |
| 62 | +.fg-menu-breadcrumb .fg-menu-prev-list a:hover, |
| 63 | +.fg-menu-breadcrumb .fg-menu-prev-list a:active { background-image: none; text-decoration:none; } |
| 64 | + |
| 65 | +.fg-menu-breadcrumb .fg-menu-prev-list a { float: left; padding-right: .4em; } |
| 66 | +.fg-menu-breadcrumb .fg-menu-prev-list a .ui-icon { float: left; } |
| 67 | + |
| 68 | +.fg-menu-breadcrumb .fg-menu-current-crumb a:link, |
| 69 | +.fg-menu-breadcrumb .fg-menu-current-crumb a:visited, |
| 70 | +.fg-menu-breadcrumb .fg-menu-current-crumb a:hover, |
| 71 | +.fg-menu-breadcrumb .fg-menu-current-crumb a:active { display:block; background-image:none; font-size:1.3em; text-decoration:none; } |
| 72 | + |
| 73 | + |
| 74 | + |
| 75 | +/* REQUIRED LINK STYLES: links are "display:block" by default; if the menu options are split into |
| 76 | + selectable node links and 'next' links, the script floats the node links left and floats the 'next' links to the right */ |
| 77 | + |
| 78 | +.fg-menu a:link, |
| 79 | +.fg-menu a:visited, |
| 80 | +.fg-menu a:hover, |
| 81 | +.fg-menu a:active { float:left; width:92%; padding:.3em 3%; text-decoration:none; outline: 0 !important; } |
| 82 | + |
| 83 | +.fg-menu a { border: 1px dashed transparent; } |
| 84 | + |
| 85 | +.fg-menu a.ui-state-default:link, |
| 86 | +.fg-menu a.ui-state-default:visited, |
| 87 | +.fg-menu a.ui-state-default:hover, |
| 88 | +.fg-menu a.ui-state-default:active, |
| 89 | +.fg-menu a.ui-state-hover:link, |
| 90 | +.fg-menu a.ui-state-hover:visited, |
| 91 | +.fg-menu a.ui-state-hover:hover, |
| 92 | +.fg-menu a.ui-state-hover:active, |
| 93 | +.fg-menu a.ui-state-active:link, |
| 94 | +.fg-menu a.ui-state-active:visited, |
| 95 | +.fg-menu a.ui-state-active:hover, |
| 96 | +.fg-menu a.ui-state-active:active { border-style: solid; font-weight: normal; } |
| 97 | + |
| 98 | +.fg-menu a span { display:block; cursor:pointer; } |
| 99 | + |
| 100 | + |
| 101 | + /* SUGGESTED STYLES - for use with jQuery UI Themeroller CSS */ |
| 102 | + |
| 103 | +.fg-menu-indicator span { float:left; } |
| 104 | +.fg-menu-indicator span.ui-icon { float:right; } |
| 105 | + |
| 106 | +.fg-menu-content.ui-widget-content, |
| 107 | +.fg-menu-content ul.ui-widget-content { border:0; } |
| 108 | + |
| 109 | + |
| 110 | +/* ICONS AND DIVIDERS */ |
| 111 | + |
| 112 | +.fg-menu.fg-menu-has-icons a:link, |
| 113 | +.fg-menu.fg-menu-has-icons a:visited, |
| 114 | +.fg-menu.fg-menu-has-icons a:hover, |
| 115 | +.fg-menu.fg-menu-has-icons a:active { padding-left:20px; } |
| 116 | + |
| 117 | +.fg-menu .horizontal-divider hr, .fg-menu .horizontal-divider span { padding:0; margin:5px .6em; } |
| 118 | +.fg-menu .horizontal-divider hr { border:0; height:1px; } |
| 119 | +.fg-menu .horizontal-divider span { font-size:.9em; text-transform: uppercase; padding-left:.2em; } |
| 120 | + |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MwEmbedSupport/jquery.menu/jquery.menu.js |
— | — | @@ -0,0 +1,813 @@ |
| 2 | +/*-------------------------------------------------------------------- |
| 3 | +Scripts for creating and manipulating custom menus based on standard <ul> markup |
| 4 | +Version: 3.0, 03.31.2009 |
| 5 | + |
| 6 | +By: Maggie Costello Wachs (maggie@filamentgroup.com) and Scott Jehl (scott@filamentgroup.com) |
| 7 | + http://www.filamentgroup.com |
| 8 | + * reference articles: http://www.filamentgroup.com/lab/jquery_ipod_style_drilldown_menu/ |
| 9 | + |
| 10 | +* modified by Michael Dale, ( michael.dale@kaltura.com ) |
| 11 | + |
| 12 | +Copyright (c) 2009 Filament Group |
| 13 | +Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses. |
| 14 | + |
| 15 | +NOTE: mwEmbed will switch to jquery ui menu once that is released |
| 16 | +NOTE: This menu contains several customizations for use in mwEmbed modules:: |
| 17 | + |
| 18 | +* added getLineItem helper function |
| 19 | +* added special class "divider" that is non selectable menu item horizontal hr |
| 20 | +--------------------------------------------------------------------*/ |
| 21 | + |
| 22 | + |
| 23 | +var allUIMenus = []; |
| 24 | + |
| 25 | +(function($) { |
| 26 | + |
| 27 | + |
| 28 | +/** |
| 29 | +* Utility line item ( li ) from text string function |
| 30 | +* |
| 31 | +* @param {String} string Text to display for the menu item |
| 32 | +* @param {String} icon jQuery UI icon key displayed to the left of the menu item |
| 33 | +* @param {Function} callback Function called once the line item is selected |
| 34 | +*/ |
| 35 | +$.getLineItem = function( string, icon , callback) { |
| 36 | + var $li = $j( '<li>' ).append( |
| 37 | + $j('<a>') |
| 38 | + .attr('href', '#') |
| 39 | + .click( callback ) |
| 40 | + ); |
| 41 | + if( icon ) { |
| 42 | + $li.find( 'a' ).append( |
| 43 | + $j('<span style="float:left;"></span>') |
| 44 | + .addClass( 'ui-icon ui-icon-' + icon ) |
| 45 | + ); |
| 46 | + } |
| 47 | + $li.find( 'a' ).append( $j('<span>').text( string ) ); |
| 48 | + //mw.log(' li html: ' + $j('<div>').append( $li ).html() ); |
| 49 | + return $li; |
| 50 | +}; |
| 51 | + |
| 52 | +$.fn.menu = function( options ) { |
| 53 | + var caller = this; |
| 54 | + var options = options; |
| 55 | + if( ! caller.m ) { |
| 56 | + caller.m = new Menu(caller, options); |
| 57 | + allUIMenus.push( caller.m ); |
| 58 | + |
| 59 | + |
| 60 | + //Set up bindings: |
| 61 | + $(this) |
| 62 | + .mousedown(function() { |
| 63 | + if (!caller.m.menuOpen) { caller.m.showLoading(); }; |
| 64 | + }) |
| 65 | + .click(function() { |
| 66 | + if (caller.m.menuOpen == false) { |
| 67 | + caller.m.showMenu(); |
| 68 | + }else { |
| 69 | + caller.m.kill(); |
| 70 | + }; |
| 71 | + return false; |
| 72 | + }); |
| 73 | + } |
| 74 | + |
| 75 | + //Check for autoShow menu option |
| 76 | + if( options.autoShow ) { |
| 77 | + // ( handle async build out) |
| 78 | + setTimeout(function() { |
| 79 | + caller.m.showLoading(); |
| 80 | + caller.m.showMenu(); |
| 81 | + }, 0 ); |
| 82 | + } |
| 83 | + |
| 84 | + //Else process the request: |
| 85 | + if( options == 'show' ){ |
| 86 | + caller.m.showMenu(); |
| 87 | + } |
| 88 | + |
| 89 | + return this; |
| 90 | +}; |
| 91 | + |
| 92 | +function Menu(caller, options) { |
| 93 | + var menu = this; |
| 94 | + var caller = $(caller); |
| 95 | + |
| 96 | + mw.log( 'jQuery.Menu:: target container: ' + options.targetMenuContainer ); |
| 97 | + |
| 98 | + var callerClassList = 'fg-menu-container ui-widget ui-widget-content ui-corner-all'; |
| 99 | + if( options.targetMenuContainer ) { |
| 100 | + var container = $( options.targetMenuContainer ) |
| 101 | + .addClass( callerClassList ) |
| 102 | + .html( options.content ) |
| 103 | + }else{ |
| 104 | + var container = $('<div>').addClass( callerClassList ).html( options.content ); |
| 105 | + } |
| 106 | + |
| 107 | + |
| 108 | + this.menuOpen = false; |
| 109 | + this.menuExists = false; |
| 110 | + |
| 111 | + var options = jQuery.extend( { |
| 112 | + content: null, |
| 113 | + autoShow: false, |
| 114 | + width: 180, // width of menu container, must be set or passed in to calculate widths of child menus |
| 115 | + maxHeight: 180, // max height of menu (if a drilldown: height does not include breadcrumb) |
| 116 | + targetMenuContainer: null, |
| 117 | + zindex: 2, |
| 118 | + positionOpts: { |
| 119 | + posX: 'left', |
| 120 | + posY: 'bottom', |
| 121 | + offsetX: 0, |
| 122 | + offsetY: 0, |
| 123 | + directionH: 'right', |
| 124 | + directionV: 'down', |
| 125 | + detectH: true, // do horizontal collision detection |
| 126 | + detectV: true, // do vertical collision detection |
| 127 | + linkToFront: false |
| 128 | + }, |
| 129 | + showSpeed: 200, // show/hide speed in milliseconds |
| 130 | + createMenuCallback: null, |
| 131 | + callerOnState: 'ui-state-active', // class to change the appearance of the link/button when the menu is showing |
| 132 | + loadingState: 'ui-state-loading', // class added to the link/button while the menu is created |
| 133 | + linkHover: 'ui-state-hover', // class for menu option hover state |
| 134 | + linkHoverSecondary: 'li-hover', // alternate class, may be used for multi-level menus |
| 135 | + // ----- multi-level menu defaults ----- |
| 136 | + crossSpeed: 200, // cross-fade speed for multi-level menus |
| 137 | + crumbDefaultText: 'Choose an option:', |
| 138 | + backLink: true, // in the ipod-style menu: instead of breadcrumbs, show only a 'back' link |
| 139 | + backLinkText: 'Back', |
| 140 | + flyOut: false, // multi-level menus are ipod-style by default; this parameter overrides to make a flyout instead |
| 141 | + flyOutOnState: 'ui-state-default', |
| 142 | + // class to style the link (specifically, a span within the link) used in the multi-level menu to show the next level |
| 143 | + nextMenuLink: 'ui-icon-triangle-1-e', |
| 144 | + topLinkText: 'All', |
| 145 | + nextCrumbLink: 'ui-icon-carat-1-e' |
| 146 | + }, options); |
| 147 | + |
| 148 | + |
| 149 | + // Apply some custom css to container |
| 150 | + container.css( { |
| 151 | + 'left' : '0px', |
| 152 | + 'z-index': options.zindex |
| 153 | + } ); |
| 154 | + |
| 155 | + var killAllMenus = function() { |
| 156 | + $.each(allUIMenus, function(i) { |
| 157 | + if (allUIMenus[i].menuOpen) { allUIMenus[i].kill(); }; |
| 158 | + }); |
| 159 | + }; |
| 160 | + |
| 161 | + this.kill = function() { |
| 162 | + caller |
| 163 | + .removeClass(options.loadingState) |
| 164 | + .removeClass('fg-menu-open') |
| 165 | + .removeClass(options.callerOnState); |
| 166 | + container.find('li').removeClass(options.linkHoverSecondary).find('a').removeClass(options.linkHover); |
| 167 | + if (options.flyOutOnState) { container.find('li a').removeClass(options.flyOutOnState); }; |
| 168 | + if (options.callerOnState) { caller.removeClass(options.callerOnState); }; |
| 169 | + if (container.is('.fg-menu-ipod')) { menu.resetDrilldownMenu(); }; |
| 170 | + if (container.is('.fg-menu-flyout')) { menu.resetFlyoutMenu(); }; |
| 171 | + if( ! options.keepPosition ){ |
| 172 | + container.parent().hide(); |
| 173 | + } else { |
| 174 | + container.hide(); |
| 175 | + } |
| 176 | + menu.menuOpen = false; |
| 177 | + $(document).unbind('click', killAllMenus); |
| 178 | + $(document).unbind('keydown'); |
| 179 | + }; |
| 180 | + |
| 181 | + this.showLoading = function() { |
| 182 | + caller.addClass(options.loadingState); |
| 183 | + }; |
| 184 | + |
| 185 | + this.showMenu = function() { |
| 186 | + mw.log('$j.menu:: show menu' ); |
| 187 | + killAllMenus(); |
| 188 | + mw.log('jquery.menu:: killAllMenus' ); |
| 189 | + if ( ! menu.menuExists) { |
| 190 | + menu.create() |
| 191 | + }; |
| 192 | + mw.log('jquery.menu:: menu.create' ); |
| 193 | + caller |
| 194 | + .addClass('fg-menu-open') |
| 195 | + .addClass(options.callerOnState); |
| 196 | + container.parent().show().click(function() { |
| 197 | + menu.kill(); |
| 198 | + return false; |
| 199 | + }); |
| 200 | + mw.log('jquery.menu:: menu. binding container' ); |
| 201 | + |
| 202 | + container.hide().slideDown(options.showSpeed).find('.fg-menu:eq(0)'); |
| 203 | + menu.menuOpen = true; |
| 204 | + caller.removeClass(options.loadingState); |
| 205 | + $(document).click(killAllMenus); |
| 206 | + |
| 207 | + // assign key events |
| 208 | + $(document).keydown(function(event) { |
| 209 | + var e; |
| 210 | + if (event.which !="") { e = event.which; } |
| 211 | + else if (event.charCode != "") { e = event.charCode; } |
| 212 | + else if (event.keyCode != "") { e = event.keyCode; } |
| 213 | + |
| 214 | + var menuType = ($(event.target).parents('div').is('.fg-menu-flyout')) ? 'flyout' : 'ipod' ; |
| 215 | + |
| 216 | + switch(e) { |
| 217 | + case 37: // left arrow |
| 218 | + if (menuType == 'flyout') { |
| 219 | + $(event.target).trigger('mouseout'); |
| 220 | + if ($('.'+options.flyOutOnState).size() > 0) { $('.'+options.flyOutOnState).trigger('mouseover'); }; |
| 221 | + }; |
| 222 | + |
| 223 | + if (menuType == 'ipod') { |
| 224 | + $(event.target).trigger('mouseout'); |
| 225 | + if ($('.fg-menu-footer').find('a').size() > 0) { $('.fg-menu-footer').find('a').trigger('click'); }; |
| 226 | + if ($('.fg-menu-header').find('a').size() > 0) { $('.fg-menu-current-crumb').prev().find('a').trigger('click'); }; |
| 227 | + if ($('.fg-menu-current').prev().is('.fg-menu-indicator')) { |
| 228 | + $('.fg-menu-current').prev().trigger('mouseover'); |
| 229 | + }; |
| 230 | + }; |
| 231 | + return false; |
| 232 | + break; |
| 233 | + |
| 234 | + case 38: // up arrow |
| 235 | + if ($(event.target).is('.' + options.linkHover)) { |
| 236 | + var prevLink = $(event.target).parent().prev().find('a:eq(0)'); |
| 237 | + if (prevLink.size() > 0) { |
| 238 | + $(event.target).trigger('mouseout'); |
| 239 | + prevLink.trigger('mouseover'); |
| 240 | + }; |
| 241 | + } |
| 242 | + else { container.find('a:eq(0)').trigger('mouseover'); } |
| 243 | + return false; |
| 244 | + break; |
| 245 | + |
| 246 | + case 39: // right arrow |
| 247 | + if ($(event.target).is('.fg-menu-indicator')) { |
| 248 | + if (menuType == 'flyout') { |
| 249 | + $(event.target).next().find('a:eq(0)').trigger('mouseover'); |
| 250 | + } |
| 251 | + else if (menuType == 'ipod') { |
| 252 | + $(event.target).trigger('click'); |
| 253 | + setTimeout(function() { |
| 254 | + $(event.target).next().find('a:eq(0)').trigger('mouseover'); |
| 255 | + }, options.crossSpeed); |
| 256 | + }; |
| 257 | + }; |
| 258 | + return false; |
| 259 | + break; |
| 260 | + |
| 261 | + case 40: // down arrow |
| 262 | + if ($(event.target).is('.' + options.linkHover)) { |
| 263 | + var nextLink = $(event.target).parent().next().find('a:eq(0)'); |
| 264 | + if (nextLink.size() > 0) { |
| 265 | + $(event.target).trigger('mouseout'); |
| 266 | + nextLink.trigger('mouseover'); |
| 267 | + }; |
| 268 | + } |
| 269 | + else { container.find('a:eq(0)').trigger('mouseover'); } |
| 270 | + return false; |
| 271 | + break; |
| 272 | + |
| 273 | + case 27: // escape |
| 274 | + killAllMenus(); |
| 275 | + break; |
| 276 | + |
| 277 | + case 13: // enter |
| 278 | + if ($(event.target).is('.fg-menu-indicator') && menuType == 'ipod') { |
| 279 | + $(event.target).trigger('click'); |
| 280 | + setTimeout(function() { |
| 281 | + $(event.target).next().find('a:eq(0)').trigger('mouseover'); |
| 282 | + }, options.crossSpeed); |
| 283 | + }; |
| 284 | + break; |
| 285 | + }; |
| 286 | + }); |
| 287 | + }; |
| 288 | + |
| 289 | + this.create = function() { |
| 290 | + mw.log( "jquery.menu.create "); |
| 291 | + |
| 292 | + container.css({ |
| 293 | + 'width' : options.width |
| 294 | + }) |
| 295 | + .find( 'ul:first' ) |
| 296 | + .not( '.fg-menu-breadcrumb' ) |
| 297 | + .addClass('fg-menu'); |
| 298 | + |
| 299 | + if(!options.keepPosition){ |
| 300 | + container.appendTo('body') |
| 301 | + } |
| 302 | + |
| 303 | + |
| 304 | + container.find('ul, li a').addClass('ui-corner-all'); |
| 305 | + |
| 306 | + // aria roles & attributes |
| 307 | + container.find( 'ul' ).attr('role', 'menu').eq(0).attr('aria-activedescendant','active-menuitem').attr('aria-labelledby', caller.attr('id')); |
| 308 | + container.find( 'li' ).attr('role', 'menuitem'); |
| 309 | + container.find( 'li:has(ul)' ).attr('aria-haspopup', 'true').find('ul').attr('aria-expanded', 'false'); |
| 310 | + container.find( 'a' ).attr('tabindex', '-1'); |
| 311 | + |
| 312 | + // when there are multiple levels of hierarchy, create flyout or drilldown menu |
| 313 | + if ( container.find( 'ul' ).size() > 1 ) { |
| 314 | + if ( options.flyOut ) { |
| 315 | + mw.log(" call menu.flyout "); |
| 316 | + menu.flyout(container, options); |
| 317 | + } else { |
| 318 | + mw.log(" call menu.drilldown "); |
| 319 | + menu.drilldown(container, options); |
| 320 | + } |
| 321 | + } else { |
| 322 | + container.find( 'a' ).click( function() { |
| 323 | + menu.chooseItem( this ); |
| 324 | + return false; |
| 325 | + } ); |
| 326 | + }; |
| 327 | + |
| 328 | + if (options.linkHover) { |
| 329 | + var allLinks = container.find('.fg-menu li a'); |
| 330 | + allLinks.hover( |
| 331 | + function() { |
| 332 | + var menuitem = $(this); |
| 333 | + var menuli = menuitem.parent(); |
| 334 | + if( !menuli.hasClass('divider') && !menuli.hasClass('disabled') ){ |
| 335 | + $('.'+options.linkHover).removeClass(options.linkHover).blur().parent().removeAttr('id'); |
| 336 | + $(this).addClass(options.linkHover).focus().parent().addClass('active-menuitem'); |
| 337 | + } |
| 338 | + }, |
| 339 | + function() { |
| 340 | + if( typeof menuitem != 'undefined' && !menuitem.hasClass('divider') && !menuitem.hasClass('disabled') ){ |
| 341 | + $(this).removeClass(options.linkHover).blur().parent().removeClass('active-menuitem'); |
| 342 | + } |
| 343 | + } |
| 344 | + ); |
| 345 | + }; |
| 346 | + |
| 347 | + if (options.linkHoverSecondary) { |
| 348 | + container.find('.fg-menu li').hover( |
| 349 | + function() { |
| 350 | + $(this).siblings('li').removeClass(options.linkHoverSecondary); |
| 351 | + if (options.flyOutOnState) { $(this).siblings('li').find('a').removeClass(options.flyOutOnState); } |
| 352 | + $(this).addClass(options.linkHoverSecondary); |
| 353 | + }, |
| 354 | + function() { $(this).removeClass(options.linkHoverSecondary); } |
| 355 | + ); |
| 356 | + }; |
| 357 | + if( !options.keepPosition ){ |
| 358 | + menu.setPosition(container, caller, options); |
| 359 | + } |
| 360 | + menu.menuExists = true; |
| 361 | + |
| 362 | + if( typeof options.createMenuCallback == 'function' ){ |
| 363 | + options.createMenuCallback(); |
| 364 | + } |
| 365 | + }; |
| 366 | + |
| 367 | + this.chooseItem = function(item) { |
| 368 | + menu.kill(); |
| 369 | + if( options.selectItemCallback ) |
| 370 | + options.selectItemCallback( item ); |
| 371 | + }; |
| 372 | +}; |
| 373 | + |
| 374 | +Menu.prototype.flyout = function(container, options) { |
| 375 | + var menu = this; |
| 376 | + |
| 377 | + this.resetFlyoutMenu = function() { |
| 378 | + var allLists = container.find('ul ul'); |
| 379 | + allLists.removeClass('ui-widget-content').hide(); |
| 380 | + }; |
| 381 | + |
| 382 | + container.addClass('fg-menu-flyout').find('li:has(ul)').each(function() { |
| 383 | + var linkWidth = container.width(); |
| 384 | + var showTimer, hideTimer; |
| 385 | + var allSubLists = $(this).find('ul'); |
| 386 | + |
| 387 | + allSubLists.css({ left: linkWidth, width: linkWidth }).hide(); |
| 388 | + |
| 389 | + $(this).find('a:eq(0)').addClass('fg-menu-indicator').html( |
| 390 | + '<span>' + $(this).find('a:eq(0)').html() + |
| 391 | + '</span><span class="ui-icon '+options.nextMenuLink+'"></span>') |
| 392 | + .hover( |
| 393 | + function() { |
| 394 | + clearTimeout(hideTimer); |
| 395 | + var subList = $(this).next(); |
| 396 | + if (!fitVertical(subList, $(this).offset().top)) { subList.css({ top: 'auto', bottom: 0 }); }; |
| 397 | + if (!fitHorizontal(subList, $(this).offset().left + 100)) { subList.css({ left: 'auto', right: linkWidth, 'z-index': 1005 }); }; |
| 398 | + showTimer = setTimeout(function() { |
| 399 | + subList.addClass('ui-widget-content').show(options.showSpeed).attr('aria-expanded', 'true'); |
| 400 | + }, 300); |
| 401 | + }, |
| 402 | + function() { |
| 403 | + clearTimeout(showTimer); |
| 404 | + var subList = $(this).next(); |
| 405 | + hideTimer = setTimeout(function() { |
| 406 | + subList.removeClass('ui-widget-content').hide(options.showSpeed).attr('aria-expanded', 'false'); |
| 407 | + }, 400); |
| 408 | + } |
| 409 | + ); |
| 410 | + |
| 411 | + $(this).find('ul a').hover( |
| 412 | + function() { |
| 413 | + clearTimeout(hideTimer); |
| 414 | + if ($(this).parents('ul').prev().is('a.fg-menu-indicator')) { |
| 415 | + $(this).parents('ul').prev().addClass(options.flyOutOnState); |
| 416 | + } |
| 417 | + }, |
| 418 | + function() { |
| 419 | + hideTimer = setTimeout(function() { |
| 420 | + allSubLists.hide(options.showSpeed); |
| 421 | + container.find(options.flyOutOnState).removeClass(options.flyOutOnState); |
| 422 | + }, 500); |
| 423 | + } |
| 424 | + ); |
| 425 | + }); |
| 426 | + |
| 427 | + container.find('a').click(function() { |
| 428 | + menu.chooseItem(this); |
| 429 | + return false; |
| 430 | + }); |
| 431 | +}; |
| 432 | + |
| 433 | + |
| 434 | +Menu.prototype.drilldown = function(container, options) { |
| 435 | + var menu = this; |
| 436 | + var topList = container.find('.fg-menu'); |
| 437 | + var breadcrumb = $('<ul class="fg-menu-breadcrumb ui-widget-header ui-corner-all ui-helper-clearfix"></ul>'); |
| 438 | + var crumbDefaultHeader = $('<li class="fg-menu-breadcrumb-text">'+options.crumbDefaultText+'</li>'); |
| 439 | + var firstCrumbText = (options.backLink) ? options.backLinkText : options.topLinkText; |
| 440 | + var firstCrumbClass = (options.backLink) ? 'fg-menu-prev-list' : 'fg-menu-all-lists'; |
| 441 | + var firstCrumbLinkClass = (options.backLink) ? 'ui-state-default ui-corner-all' : ''; |
| 442 | + var firstCrumbIcon = (options.backLink) ? '<span class="ui-icon ui-icon-triangle-1-w"></span>' : ''; |
| 443 | + var firstCrumb = $('<li class="'+firstCrumbClass+'"><a href="#" class="'+firstCrumbLinkClass+'">'+firstCrumbIcon+firstCrumbText+'</a></li>'); |
| 444 | + |
| 445 | + container.addClass('fg-menu-ipod'); |
| 446 | + |
| 447 | + if (options.backLink) { breadcrumb.addClass('fg-menu-footer').appendTo(container).hide(); } |
| 448 | + else { breadcrumb.addClass('fg-menu-header').prependTo(container); }; |
| 449 | + breadcrumb.append(crumbDefaultHeader); |
| 450 | + |
| 451 | + var checkMenuHeight = function(el) { |
| 452 | + if (el.height() > options.maxHeight) { el.addClass('fg-menu-scroll') }; |
| 453 | + el.css({ |
| 454 | + height: options.maxHeight-30 |
| 455 | + }); |
| 456 | + }; |
| 457 | + |
| 458 | + var resetChildMenu = function(el) { el.removeClass('fg-menu-scroll').removeClass('fg-menu-current').height('auto'); }; |
| 459 | + |
| 460 | + this.resetDrilldownMenu = function() { |
| 461 | + $('.fg-menu-current').removeClass('fg-menu-current'); |
| 462 | + topList.animate({ left: 0 }, options.crossSpeed, function() { |
| 463 | + $(this).find('ul').each(function() { |
| 464 | + $(this).hide(); |
| 465 | + resetChildMenu($(this)); |
| 466 | + }); |
| 467 | + topList.addClass('fg-menu-current'); |
| 468 | + }); |
| 469 | + $('.fg-menu-all-lists').find('span').remove(); |
| 470 | + breadcrumb.empty().append(crumbDefaultHeader); |
| 471 | + $('.fg-menu-footer').empty().hide(); |
| 472 | + checkMenuHeight(topList); |
| 473 | + }; |
| 474 | + |
| 475 | + topList |
| 476 | + .addClass('fg-menu-content fg-menu-current ui-widget-content ui-helper-clearfix') |
| 477 | + .css({ width: container.width() }) |
| 478 | + .find('ul') |
| 479 | + .css({ width: container.width(), left: container.width() }) |
| 480 | + .addClass('ui-widget-content') |
| 481 | + .hide(); |
| 482 | + checkMenuHeight(topList); |
| 483 | + |
| 484 | + topList.find('a').each(function() { |
| 485 | + // if the link opens a child menu: |
| 486 | + if ($(this).next().is('ul')) { |
| 487 | + $(this) |
| 488 | + .addClass('fg-menu-indicator') |
| 489 | + .each(function() { $(this).html('<span>' + $(this).html() + '</span><span class="ui-icon '+options.nextMenuLink+'"></span>'); }) |
| 490 | + .click(function() { // ----- show the next menu |
| 491 | + var nextList = $(this).next(); |
| 492 | + var parentUl = $(this).parents('ul:eq(0)'); |
| 493 | + var parentLeft = (parentUl.is('.fg-menu-content')) ? 0 : parseFloat(topList.css('left')); |
| 494 | + var nextLeftVal = Math.round(parentLeft - parseFloat(container.width())); |
| 495 | + var footer = $('.fg-menu-footer'); |
| 496 | + |
| 497 | + // show next menu |
| 498 | + resetChildMenu(parentUl); |
| 499 | + checkMenuHeight(nextList); |
| 500 | + topList.animate({ left: nextLeftVal }, options.crossSpeed); |
| 501 | + nextList.show().addClass('fg-menu-current').attr('aria-expanded', 'true'); |
| 502 | + |
| 503 | + var setPrevMenu = function(backlink) { |
| 504 | + var b = backlink; |
| 505 | + var c = $('.fg-menu-current'); |
| 506 | + var prevList = c.parents('ul:eq(0)'); |
| 507 | + c.hide().attr('aria-expanded', 'false'); |
| 508 | + resetChildMenu(c); |
| 509 | + checkMenuHeight(prevList); |
| 510 | + prevList.addClass('fg-menu-current').attr('aria-expanded', 'true'); |
| 511 | + if (prevList.hasClass('fg-menu-content')) { b.remove(); footer.hide(); }; |
| 512 | + }; |
| 513 | + |
| 514 | + // initialize "back" link |
| 515 | + if (options.backLink) { |
| 516 | + if (footer.find('a').size() == 0) { |
| 517 | + footer.show(); |
| 518 | + $('<a href="#"><span class="ui-icon ui-icon-triangle-1-w"></span> <span>Back</span></a>') |
| 519 | + .appendTo(footer) |
| 520 | + .click(function() { // ----- show the previous menu |
| 521 | + var b = $(this); |
| 522 | + var prevLeftVal = parseFloat(topList.css('left')) + container.width(); |
| 523 | + topList.animate({ left: prevLeftVal }, options.crossSpeed, function() { |
| 524 | + setPrevMenu(b); |
| 525 | + }); |
| 526 | + return false; |
| 527 | + }); |
| 528 | + } |
| 529 | + } |
| 530 | + // or initialize top breadcrumb |
| 531 | + else { |
| 532 | + if (breadcrumb.find('li').size() == 1) { |
| 533 | + breadcrumb.empty().append(firstCrumb); |
| 534 | + firstCrumb.find('a').click(function() { |
| 535 | + menu.resetDrilldownMenu(); |
| 536 | + return false; |
| 537 | + }); |
| 538 | + } |
| 539 | + $('.fg-menu-current-crumb').removeClass('fg-menu-current-crumb'); |
| 540 | + var crumbText = $(this).find('span:eq(0)').text(); |
| 541 | + var newCrumb = $('<li class="fg-menu-current-crumb"><a href="javascript://" class="fg-menu-crumb">'+crumbText+'</a></li>'); |
| 542 | + newCrumb |
| 543 | + .appendTo(breadcrumb) |
| 544 | + .find('a').click(function() { |
| 545 | + if ($(this).parent().is('.fg-menu-current-crumb')) { |
| 546 | + menu.chooseItem(this); |
| 547 | + } |
| 548 | + else { |
| 549 | + var newLeftVal = - ($('.fg-menu-current').parents('ul').size() - 1) * 180; |
| 550 | + topList.animate({ left: newLeftVal }, options.crossSpeed, function() { |
| 551 | + setPrevMenu(); |
| 552 | + }); |
| 553 | + |
| 554 | + // make this the current crumb, delete all breadcrumbs after this one, and navigate to the relevant menu |
| 555 | + $(this).parent().addClass('fg-menu-current-crumb').find('span').remove(); |
| 556 | + $(this).parent().nextAll().remove(); |
| 557 | + }; |
| 558 | + return false; |
| 559 | + }); |
| 560 | + newCrumb.prev().append(' <span class="ui-icon '+options.nextCrumbLink+'"></span>'); |
| 561 | + }; |
| 562 | + return false; |
| 563 | + }); |
| 564 | + } |
| 565 | + // if the link is a leaf node (doesn't open a child menu) |
| 566 | + else { |
| 567 | + $(this).click(function() { |
| 568 | + menu.chooseItem(this); |
| 569 | + return false; |
| 570 | + }); |
| 571 | + }; |
| 572 | + }); |
| 573 | +}; |
| 574 | + |
| 575 | + |
| 576 | +/* Menu.prototype.setPosition parameters (defaults noted with *): |
| 577 | + referrer = the link (or other element) used to show the overlaid object |
| 578 | + settings = can override the defaults: |
| 579 | + - posX/Y: where the top left corner of the object should be positioned in relation to its referrer. |
| 580 | + X: left*, center, right |
| 581 | + Y: top, center, bottom* |
| 582 | + - offsetX/Y: the number of pixels to be offset from the x or y position. Can be a positive or negative number. |
| 583 | + - directionH/V: where the entire menu should appear in relation to its referrer. |
| 584 | + Horizontal: left*, right |
| 585 | + Vertical: up, down* |
| 586 | + - detectH/V: detect the viewport horizontally / vertically |
| 587 | + - linkToFront: copy the menu link and place it on top of the menu (visual effect to make it look like it overlaps the object) */ |
| 588 | + |
| 589 | +Menu.prototype.setPosition = function(widget, caller, options) { |
| 590 | + mw.log( 'setPosition' ); |
| 591 | + |
| 592 | + var el = widget; |
| 593 | + var referrer = caller; |
| 594 | + var dims = { |
| 595 | + refX: referrer.offset().left, |
| 596 | + refY: referrer.offset().top, |
| 597 | + refW: referrer.getTotalWidth(), |
| 598 | + refH: referrer.getTotalHeight() |
| 599 | + }; |
| 600 | + var options = options; |
| 601 | + var xVal, yVal; |
| 602 | + |
| 603 | + var helper = $( '<div class="menuPositionHelper">' ); |
| 604 | + helper.css( 'z-index', options.zindex ); |
| 605 | + |
| 606 | + mw.log("set z-index"); |
| 607 | + |
| 608 | + // Hard code width height of button if unset ( crazy IE ) |
| 609 | + if( isNaN( dims.refW ) || isNaN( dims.refH ) ) { |
| 610 | + dims.refH = 16; |
| 611 | + dims.refW = 23; |
| 612 | + } |
| 613 | + helper.css({ |
| 614 | + 'position': 'absolute', |
| 615 | + 'left': dims.refX, |
| 616 | + 'top': dims.refY, |
| 617 | + 'width': dims.refW, |
| 618 | + 'height': dims.refH |
| 619 | + }); |
| 620 | + |
| 621 | + mw.log("set helper.css "); |
| 622 | + |
| 623 | + el.wrap( helper ); |
| 624 | + |
| 625 | + mw.log("wrap helper"); |
| 626 | + |
| 627 | + xVal = yVal = 0; |
| 628 | + // get X pos |
| 629 | + switch( options.positionOpts.posX ) { |
| 630 | + case 'left': xVal = 0; |
| 631 | + break; |
| 632 | + case 'center': xVal = dims.refW / 2; |
| 633 | + break; |
| 634 | + case 'right': xVal = dims.refW; |
| 635 | + break; |
| 636 | + }; |
| 637 | + |
| 638 | + // get Y pos |
| 639 | + switch( options.positionOpts.posY ) { |
| 640 | + case 'top' : yVal = 0; |
| 641 | + break; |
| 642 | + case 'center' : yVal = dims.refH / 2; |
| 643 | + break; |
| 644 | + case 'bottom' : yVal = dims.refH; |
| 645 | + break; |
| 646 | + }; |
| 647 | + |
| 648 | + // add the offsets (zero by default) |
| 649 | + xVal += ( options.positionOpts.offsetX )? options.positionOpts.offsetX : 0; |
| 650 | + yVal += ( options.positionOpts.offsetY )? options.positionOpts.offsetY : 0; |
| 651 | + |
| 652 | + mw.log(" about to position: " + yVal ); |
| 653 | + // position the object vertically |
| 654 | + if (options.positionOpts.directionV == 'up') { |
| 655 | + el.css( { |
| 656 | + 'top': 'auto', |
| 657 | + 'bottom': yVal |
| 658 | + } ); |
| 659 | + if (options.positionOpts.detectV && !fitVertical(el)) { |
| 660 | + el.css({ |
| 661 | + 'bottom' : 'auto', |
| 662 | + 'top' : yVal |
| 663 | + }); |
| 664 | + } |
| 665 | + } else { |
| 666 | + el.css({ |
| 667 | + 'bottom' : 'auto', |
| 668 | + 'top' : yVal |
| 669 | + }); |
| 670 | + if (options.positionOpts.detectV && !fitVertical(el)) { |
| 671 | + el.css({ |
| 672 | + 'top' : 'auto', |
| 673 | + 'bottom' : yVal |
| 674 | + }); |
| 675 | + } |
| 676 | + }; |
| 677 | + |
| 678 | + mw.log(" done with add the offsets && position the object vertically"); |
| 679 | + |
| 680 | + // and horizontally |
| 681 | + if (options.positionOpts.directionH == 'left') { |
| 682 | + el.css({ left: 'auto', right: xVal }); |
| 683 | + if (options.positionOpts.detectH && !fitHorizontal(el)) { |
| 684 | + el.css({ right: 'auto', left: xVal }); |
| 685 | + } |
| 686 | + } |
| 687 | + else { |
| 688 | + el.css({ right: 'auto', left: xVal }); |
| 689 | + if (options.positionOpts.detectH && !fitHorizontal(el)) { |
| 690 | + el.css({ left: 'auto', right: xVal }); |
| 691 | + } |
| 692 | + }; |
| 693 | + |
| 694 | + mw.log(" done with position the object horizontally"); |
| 695 | + |
| 696 | + // if specified, clone the referring element and position it so that it appears on top of the menu |
| 697 | + if (options.positionOpts.linkToFront) { |
| 698 | + referrer.clone().addClass('linkClone').css({ |
| 699 | + position: 'absolute', |
| 700 | + top: 0, |
| 701 | + right: 'auto', |
| 702 | + bottom: 'auto', |
| 703 | + left: 0, |
| 704 | + width: referrer.width(), |
| 705 | + height: referrer.height() |
| 706 | + }).insertAfter(el); |
| 707 | + }; |
| 708 | + mw.log('done with all'); |
| 709 | +}; |
| 710 | + |
| 711 | + |
| 712 | +/* Utilities to sort and find viewport dimensions */ |
| 713 | + |
| 714 | +function sortBigToSmall(a, b) { return b - a; }; |
| 715 | + |
| 716 | +jQuery.fn.getTotalWidth = function() { |
| 717 | + return $(this).width() + parseInt($(this).css('paddingRight')) + parseInt($(this).css('paddingLeft')) + parseInt($(this).css('borderRightWidth')) + parseInt($(this).css('borderLeftWidth')); |
| 718 | +}; |
| 719 | + |
| 720 | +jQuery.fn.getTotalHeight = function() { |
| 721 | + return $(this).height() + parseInt($(this).css('paddingTop')) + parseInt($(this).css('paddingBottom')) + parseInt($(this).css('borderTopWidth')) + parseInt($(this).css('borderBottomWidth')); |
| 722 | +}; |
| 723 | + |
| 724 | +function getScrollTop() { |
| 725 | + return self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop; |
| 726 | +}; |
| 727 | + |
| 728 | +function getScrollLeft() { |
| 729 | + return self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft; |
| 730 | +}; |
| 731 | + |
| 732 | +function getWindowHeight() { |
| 733 | + var de = document.documentElement; |
| 734 | + return self.innerHeight || (de && de.clientHeight) || document.body.clientHeight; |
| 735 | +}; |
| 736 | + |
| 737 | +function getWindowWidth() { |
| 738 | + var de = document.documentElement; |
| 739 | + return self.innerWidth || (de && de.clientWidth) || document.body.clientWidth; |
| 740 | +}; |
| 741 | + |
| 742 | +/* Utilities to test whether an element will fit in the viewport |
| 743 | + Parameters: |
| 744 | + el = element to position, required |
| 745 | + leftOffset / topOffset = optional parameter if the offset cannot be calculated (i.e., if the object is in the DOM but is set to display: 'none') */ |
| 746 | + |
| 747 | +function fitHorizontal(el, leftOffset) { |
| 748 | + var leftVal = parseInt(leftOffset) || $(el).offset().left; |
| 749 | + return (leftVal + $(el).width() <= getWindowWidth() + getScrollLeft() && leftVal - getScrollLeft() >= 0); |
| 750 | +}; |
| 751 | + |
| 752 | +function fitVertical(el, topOffset) { |
| 753 | + var topVal = parseInt(topOffset) || $(el).offset().top; |
| 754 | + return (topVal + $(el).height() <= getWindowHeight() + getScrollTop() && topVal - getScrollTop() >= 0); |
| 755 | +}; |
| 756 | + |
| 757 | +/*-------------------------------------------------------------------- |
| 758 | + * javascript method: "pxToEm" |
| 759 | + * by: |
| 760 | + Scott Jehl (scott@filamentgroup.com) |
| 761 | + Maggie Wachs (maggie@filamentgroup.com) |
| 762 | + http://www.filamentgroup.com |
| 763 | + * |
| 764 | + * Copyright (c) 2008 Filament Group |
| 765 | + * Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses. |
| 766 | + * |
| 767 | + * Description: Extends the native Number and String objects with pxToEm method. pxToEm converts a pixel value to ems depending on inherited font size. |
| 768 | + * Article: http://www.filamentgroup.com/lab/retaining_scalable_interfaces_with_pixel_to_em_conversion/ |
| 769 | + * Demo: http://www.filamentgroup.com/examples/pxToEm/ |
| 770 | + * |
| 771 | + * Options: |
| 772 | + scope: string or jQuery selector for font-size scoping |
| 773 | + reverse: Boolean, true reverses the conversion to em-px |
| 774 | + * Dependencies: jQuery library |
| 775 | + * Usage Example: myPixelValue.pxToEm(); or myPixelValue.pxToEm({'scope':'#navigation', reverse: true}); |
| 776 | + * |
| 777 | + * Version: 2.0, 08.01.2008 |
| 778 | + * Changelog: |
| 779 | + * 08.02.2007 initial Version 1.0 |
| 780 | + * 08.01.2008 - fixed font-size calculation for IE |
| 781 | +--------------------------------------------------------------------*/ |
| 782 | + |
| 783 | +Number.prototype.pxToEm = String.prototype.pxToEm = function(settings) { |
| 784 | + //set defaults |
| 785 | + settings = jQuery.extend({ |
| 786 | + scope: 'body', |
| 787 | + reverse: false |
| 788 | + }, settings); |
| 789 | + |
| 790 | + var pxVal = (this == '') ? 0 : parseFloat(this); |
| 791 | + var scopeVal; |
| 792 | + var getWindowWidth = function() { |
| 793 | + var de = document.documentElement; |
| 794 | + return self.innerWidth || (de && de.clientWidth) || document.body.clientWidth; |
| 795 | + }; |
| 796 | + |
| 797 | + /* When a percentage-based font-size is set on the body, IE returns that percent of the window width as the font-size. |
| 798 | + For example, if the body font-size is 62.5% and the window width is 1000px, IE will return 625px as the font-size. |
| 799 | + When this happens, we calculate the correct body font-size (%) and multiply it by 16 (the standard browser font size) |
| 800 | + to get an accurate em value. */ |
| 801 | + |
| 802 | + if (settings.scope == 'body' && $.browser.msie && (parseFloat($('body').css('font-size')) / getWindowWidth()).toFixed(1) > 0.0) { |
| 803 | + var calcFontSize = function() { |
| 804 | + return (parseFloat($('body').css('font-size'))/getWindowWidth()).toFixed(3) * 16; |
| 805 | + }; |
| 806 | + scopeVal = calcFontSize(); |
| 807 | + } |
| 808 | + else { scopeVal = parseFloat(jQuery(settings.scope).css("font-size")); }; |
| 809 | + |
| 810 | + var result = (settings.reverse == true) ? (pxVal * scopeVal).toFixed(2) + 'px' : (pxVal / scopeVal).toFixed(2) + 'em'; |
| 811 | + return result; |
| 812 | +}; |
| 813 | + |
| 814 | +} )( jQuery ); |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MwEmbedSupport/mwEmbed.core.js |
— | — | @@ -0,0 +1,433 @@ |
| 2 | +// Add support for html5 / mwEmbed elements to IE |
| 3 | +// For discussion and comments, see: http://remysharp.com/2009/01/07/html5-enabling-script/ |
| 4 | +'video audio source track'.replace(/\w+/g,function( n ){ document.createElement( n ) } ); |
| 5 | + |
| 6 | +/** |
| 7 | + * mwEmbed.core includes shared mwEmbed utilities |
| 8 | + * |
| 9 | + * @license |
| 10 | + * mwEmbed |
| 11 | + * Dual licensed under the MIT or GPL Version 2 licenses. |
| 12 | + * |
| 13 | + * @copyright (C) 2010 Kaltura |
| 14 | + * @author Michael Dale ( michael.dale at kaltura.com ) |
| 15 | + * |
| 16 | + * @url http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library |
| 17 | + * |
| 18 | + * Libraries used include code license in headers |
| 19 | + */ |
| 20 | + |
| 21 | + |
| 22 | +( function( mw, $ ) { |
| 23 | + |
| 24 | + /** |
| 25 | + * Set the mwEmbedVersion |
| 26 | + */ |
| 27 | + window.MW_EMBED_VERSION = '1.1g'; |
| 28 | + |
| 29 | + // Globals to pre-set ready functions in dynamic loading of mwEmbed |
| 30 | + if( typeof window.preMwEmbedReady == 'undefined'){ |
| 31 | + window.preMwEmbedReady = []; |
| 32 | + } |
| 33 | + // Globals to pre-set config values in dynamic loading of mwEmbed |
| 34 | + if( typeof window.preMwEmbedConfig == 'undefined') { |
| 35 | + window.preMwEmbedConfig = []; |
| 36 | + } |
| 37 | + |
| 38 | + /** |
| 39 | + * Enables pages to target a "interfaces ready" state. |
| 40 | + * |
| 41 | + * TODO make it work! |
| 42 | + * |
| 43 | + * This is different from jQuery(document).ready() ( jQuery ready is not |
| 44 | + * friendly with dynamic includes and not friendly with core interface |
| 45 | + * asynchronous build out. ) |
| 46 | + * |
| 47 | + * @param {Function} |
| 48 | + * callback Function to run once DOM and jQuery are ready |
| 49 | + */ |
| 50 | + var mwOnLoadFunctions = []; // Setup the local mwOnLoadFunctions array: |
| 51 | + var mwReadyFlag = false; // mw Ready flag ( set once mwEmbed is ready ) |
| 52 | + mw.ready = function( callback ) { |
| 53 | + if( mwReadyFlag === false ) { |
| 54 | + // Add the callbcak to the onLoad function stack |
| 55 | + mwOnLoadFunctions.push ( callback ); |
| 56 | + } else { |
| 57 | + // If mwReadyFlag is already "true" issue the callback directly: |
| 58 | + callback(); |
| 59 | + } |
| 60 | + }; |
| 61 | + |
| 62 | + // add a domReady setup infterface trigger |
| 63 | + SetupInterface |
| 64 | + /** |
| 65 | + * Runs all the queued functions called by mwEmbedSetup |
| 66 | + */ |
| 67 | + mw.runReadyFunctions = function ( ) { |
| 68 | + mw.log('mw.runReadyFunctions: ' + mwOnLoadFunctions.length ); |
| 69 | + // Run any pre-setup ready functions |
| 70 | + while( preMwEmbedReady.length ){ |
| 71 | + preMwEmbedReady.shift()(); |
| 72 | + } |
| 73 | + // Run all the queued functions: |
| 74 | + while( mwOnLoadFunctions.length ) { |
| 75 | + mwOnLoadFunctions.shift()(); |
| 76 | + } |
| 77 | + // Sets mwReadyFlag to true so that future mw.ready run the |
| 78 | + // callback directly |
| 79 | + mwReadyFlag = true; |
| 80 | + |
| 81 | + }; |
| 82 | + |
| 83 | + /** |
| 84 | + * Aliased functions |
| 85 | + * |
| 86 | + * Wrap mediaWiki functionality while we port over the libraries |
| 87 | + */ |
| 88 | + mw.setConfig = function( name, value ){ |
| 89 | + mediaWiki.config.set( name, value ); |
| 90 | + }; |
| 91 | + mw.getConfig = function( name, value ){ |
| 92 | + mediaWiki.config.get( name, value ); |
| 93 | + }; |
| 94 | + mw.setDefaultConfig = function( name, value ){ |
| 95 | + if( ! mediaWiki.config.get( name ) ){ |
| 96 | + mediaWiki.config.set( name, value ); |
| 97 | + } |
| 98 | + }; |
| 99 | + mw.load = function( resources, callback ){ |
| 100 | + mediaWiki.using( resources, callback, function(){ |
| 101 | + // failed to load |
| 102 | + }); |
| 103 | + }; |
| 104 | + |
| 105 | + /** |
| 106 | + * Merge in a configuration value: |
| 107 | + */ |
| 108 | + mw.mergeConfig = function( name, value ){ |
| 109 | + if( typeof name == 'object' ) { |
| 110 | + $j.each( name, function( inx, val) { |
| 111 | + mw.mergeConfig( inx, val ); |
| 112 | + }); |
| 113 | + return ; |
| 114 | + } |
| 115 | + // Check if we should "merge" the config |
| 116 | + if( typeof value == 'object' && typeof mw.getConfig( name ) == 'object' ) { |
| 117 | + if ( value.constructor.toString().indexOf("Array") != -1 && |
| 118 | + mw.getConfig( name ).constructor.toString().indexOf("Array") != -1 |
| 119 | + ){ |
| 120 | + // merge in the array |
| 121 | + mw.setConfig( name, $j.merge( mw.getConfig( name ), value ) ); |
| 122 | + } else { |
| 123 | + mw.setConfig( name, value ); |
| 124 | + } |
| 125 | + return ; |
| 126 | + } |
| 127 | + // else do a normal setConfig |
| 128 | + mw.setConfig( name, value ); |
| 129 | + }; |
| 130 | + |
| 131 | + /** |
| 132 | + * Utility Functions |
| 133 | + * |
| 134 | + * TOOD some of these utility functions are used in the upload Wizard, break them out into |
| 135 | + * associated files. |
| 136 | + */ |
| 137 | + |
| 138 | + /** |
| 139 | + * Given a float number of seconds, returns npt format response. ( ignore |
| 140 | + * days for now ) |
| 141 | + * |
| 142 | + * @param {Float} |
| 143 | + * sec Seconds |
| 144 | + * @param {Boolean} |
| 145 | + * show_ms If milliseconds should be displayed. |
| 146 | + * @return {Float} String npt format |
| 147 | + */ |
| 148 | + mw.seconds2npt = function( sec, show_ms ) { |
| 149 | + if ( isNaN( sec ) ) { |
| 150 | + mw.log("Warning: trying to get npt time on NaN:" + sec); |
| 151 | + return '0:00:00'; |
| 152 | + } |
| 153 | + |
| 154 | + var tm = mw.seconds2Measurements( sec ) |
| 155 | + |
| 156 | + // Round the number of seconds to the required number of significant |
| 157 | + // digits |
| 158 | + if ( show_ms ) { |
| 159 | + tm.seconds = Math.round( tm.seconds * 1000 ) / 1000; |
| 160 | + } else { |
| 161 | + tm.seconds = Math.round( tm.seconds ); |
| 162 | + } |
| 163 | + if ( tm.seconds < 10 ){ |
| 164 | + tm.seconds = '0' + tm.seconds; |
| 165 | + } |
| 166 | + if( tm.hours == 0 ){ |
| 167 | + hoursStr = '' |
| 168 | + } else { |
| 169 | + if ( tm.minutes < 10 ) |
| 170 | + tm.minutes = '0' + tm.minutes; |
| 171 | + |
| 172 | + hoursStr = tm.hours + ":"; |
| 173 | + } |
| 174 | + return hoursStr + tm.minutes + ":" + tm.seconds; |
| 175 | + } |
| 176 | + |
| 177 | + /** |
| 178 | + * Given seconds return array with 'days', 'hours', 'min', 'seconds' |
| 179 | + * |
| 180 | + * @param {float} |
| 181 | + * sec Seconds to be converted into time measurements |
| 182 | + */ |
| 183 | + mw.seconds2Measurements = function ( sec ){ |
| 184 | + var tm = {}; |
| 185 | + tm.days = Math.floor( sec / ( 3600 * 24 ) ) |
| 186 | + tm.hours = Math.floor( sec / 3600 ); |
| 187 | + tm.minutes = Math.floor( ( sec / 60 ) % 60 ); |
| 188 | + tm.seconds = sec % 60; |
| 189 | + return tm; |
| 190 | + } |
| 191 | + |
| 192 | + /** |
| 193 | + * Take hh:mm:ss,ms or hh:mm:ss.ms input, return the number of seconds |
| 194 | + * |
| 195 | + * @param {String} |
| 196 | + * npt_str NPT time string |
| 197 | + * @return {Float} Number of seconds |
| 198 | + */ |
| 199 | + mw.npt2seconds = function ( npt_str ) { |
| 200 | + if ( !npt_str ) { |
| 201 | + // mw.log('npt2seconds:not valid ntp:'+ntp); |
| 202 | + return 0; |
| 203 | + } |
| 204 | + // Strip {npt:}01:02:20 or 32{s} from time if present |
| 205 | + npt_str = npt_str.replace( /npt:|s/g, '' ); |
| 206 | + |
| 207 | + var hour = 0; |
| 208 | + var min = 0; |
| 209 | + var sec = 0; |
| 210 | + |
| 211 | + times = npt_str.split( ':' ); |
| 212 | + if ( times.length == 3 ) { |
| 213 | + sec = times[2]; |
| 214 | + min = times[1]; |
| 215 | + hour = times[0]; |
| 216 | + } else if ( times.length == 2 ) { |
| 217 | + sec = times[1]; |
| 218 | + min = times[0]; |
| 219 | + } else { |
| 220 | + sec = times[0]; |
| 221 | + } |
| 222 | + // Sometimes a comma is used instead of period for ms |
| 223 | + sec = sec.replace( /,\s?/, '.' ); |
| 224 | + // Return seconds float |
| 225 | + return parseInt( hour * 3600 ) + parseInt( min * 60 ) + parseFloat( sec ); |
| 226 | + } |
| 227 | + |
| 228 | + /** |
| 229 | + * addLoaderDialog small helper for displaying a loading dialog |
| 230 | + * |
| 231 | + * @param {String} |
| 232 | + * dialogHtml text Html of the loader msg |
| 233 | + */ |
| 234 | + mw.addLoaderDialog = function( dialogHtml ) { |
| 235 | + $dialog = mw.addDialog( { |
| 236 | + 'title' : dialogHtml, |
| 237 | + 'content' : dialogHtml + '<br>' + |
| 238 | + $j('<div />') |
| 239 | + .loadingSpinner() |
| 240 | + .html() |
| 241 | + }); |
| 242 | + return $dialog; |
| 243 | + } |
| 244 | + |
| 245 | + |
| 246 | + |
| 247 | + /** |
| 248 | + * Add a (temporary) dialog window: |
| 249 | + * |
| 250 | + * @param {Object} with following keys: |
| 251 | + * title: {String} Title string for the dialog |
| 252 | + * content: {String} to be inserted in msg box |
| 253 | + * buttons: {Object} A button object for the dialog Can be a string |
| 254 | + * for the close button |
| 255 | + * any jquery.ui.dialog option |
| 256 | + */ |
| 257 | + mw.addDialog = function ( options ) { |
| 258 | + // Remove any other dialog |
| 259 | + $j( '#mwTempLoaderDialog' ).remove(); |
| 260 | + |
| 261 | + if( !options){ |
| 262 | + options = {}; |
| 263 | + } |
| 264 | + |
| 265 | + // Extend the default options with provided options |
| 266 | + var options = $j.extend({ |
| 267 | + 'bgiframe': true, |
| 268 | + 'draggable': true, |
| 269 | + 'resizable': false, |
| 270 | + 'modal': true |
| 271 | + }, options ); |
| 272 | + |
| 273 | + if( ! options.title || ! options.content ){ |
| 274 | + mw.log("Error: mwEmbed addDialog missing required options ( title, content ) ") |
| 275 | + return ; |
| 276 | + } |
| 277 | + |
| 278 | + // Append the dialog div on top: |
| 279 | + $j( 'body' ).append( |
| 280 | + $j('<div />') |
| 281 | + .attr( { |
| 282 | + 'id' : "mwTempLoaderDialog", |
| 283 | + 'title' : options.title |
| 284 | + }) |
| 285 | + .css({ |
| 286 | + 'display': 'none' |
| 287 | + }) |
| 288 | + .append( options.content ) |
| 289 | + ); |
| 290 | + |
| 291 | + // Build the uiRequest |
| 292 | + var uiRequest = [ '$j.ui.dialog' ]; |
| 293 | + if( options.draggable ){ |
| 294 | + uiRequest.push( '$j.ui.draggable' ) |
| 295 | + } |
| 296 | + if( options.resizable ){ |
| 297 | + uiRequest.push( '$j.ui.resizable' ); |
| 298 | + } |
| 299 | + |
| 300 | + // Special button string |
| 301 | + if ( typeof options.buttons == 'string' ) { |
| 302 | + var buttonMsg = options.buttons; |
| 303 | + buttons = { }; |
| 304 | + options.buttons[ buttonMsg ] = function() { |
| 305 | + $j( this ).dialog( 'close' ); |
| 306 | + } |
| 307 | + } |
| 308 | + |
| 309 | + // Load the dialog resources |
| 310 | + mw.load([ |
| 311 | + [ |
| 312 | + '$j.ui' |
| 313 | + ], |
| 314 | + uiRequest |
| 315 | + ], function() { |
| 316 | + $j( '#mwTempLoaderDialog' ).dialog( options ); |
| 317 | + } ); |
| 318 | + return $j( '#mwTempLoaderDialog' ); |
| 319 | + } |
| 320 | + |
| 321 | + /** |
| 322 | + * Close the loader dialog created with addLoaderDialog |
| 323 | + */ |
| 324 | + mw.closeLoaderDialog = function() { |
| 325 | + $j( '#mwTempLoaderDialog' ).dialog( 'destroy' ).remove(); |
| 326 | + }; |
| 327 | + |
| 328 | + // MOVE TO jquery.client |
| 329 | + // move to jquery.client |
| 330 | + mw.isIphone = function(){ |
| 331 | + return ( navigator.userAgent.indexOf('iPhone') != -1 && ! mw.isIpad() ); |
| 332 | + }; |
| 333 | + // Uses hack described at: |
| 334 | + // http://www.bdoran.co.uk/2010/07/19/detecting-the-iphone4-and-resolution-with-javascript-or-php/ |
| 335 | + mw.isIphone4 = function(){ |
| 336 | + return ( mw.isIphone() && ( window.devicePixelRatio && window.devicePixelRatio >= 2 ) ); |
| 337 | + }; |
| 338 | + mw.isIpod = function(){ |
| 339 | + return ( navigator.userAgent.indexOf('iPod') != -1 ); |
| 340 | + }; |
| 341 | + mw.isIpad = function(){ |
| 342 | + return ( navigator.userAgent.indexOf('iPad') != -1 ); |
| 343 | + }; |
| 344 | + // Android 2 has some restrictions vs other mobile platforms |
| 345 | + mw.isAndroid2 = function(){ |
| 346 | + return ( navigator.userAgent.indexOf( 'Android 2.') != -1 ); |
| 347 | + }; |
| 348 | + |
| 349 | + /** |
| 350 | + * Fallforward system by default prefers flash. |
| 351 | + * |
| 352 | + * This is separate from the EmbedPlayer library detection to provide |
| 353 | + * package loading control NOTE: should be phased out in favor of browser |
| 354 | + * feature detection where possible |
| 355 | + * |
| 356 | + */ |
| 357 | + mw.isHTML5FallForwardNative = function(){ |
| 358 | + if( mw.isMobileHTML5() ){ |
| 359 | + return true; |
| 360 | + } |
| 361 | + // Check for url flag to force html5: |
| 362 | + if( document.URL.indexOf('forceMobileHTML5') != -1 ){ |
| 363 | + return true; |
| 364 | + } |
| 365 | + // Fall forward native: |
| 366 | + // if the browser supports flash ( don't use html5 ) |
| 367 | + if( mw.supportsFlash() ){ |
| 368 | + return false; |
| 369 | + } |
| 370 | + // No flash return true if the browser supports html5 video tag with |
| 371 | + // basic support for canPlayType: |
| 372 | + if( mw.supportsHTML5() ){ |
| 373 | + return true; |
| 374 | + } |
| 375 | + |
| 376 | + return false; |
| 377 | + } |
| 378 | + |
| 379 | + mw.isMobileHTML5 = function(){ |
| 380 | + // Check for a mobile html5 user agent: |
| 381 | + if ( mw.isIphone() || |
| 382 | + mw.isIpod() || |
| 383 | + mw.isIpad() || |
| 384 | + mw.isAndroid2() |
| 385 | + ){ |
| 386 | + return true; |
| 387 | + } |
| 388 | + return false; |
| 389 | + }; |
| 390 | + mw.supportsHTML5 = function(){ |
| 391 | + // Blackberry is evil in its response to canPlayType calls. |
| 392 | + if( navigator.userAgent.indexOf('BlackBerry') != -1 ){ |
| 393 | + return false ; |
| 394 | + } |
| 395 | + var dummyvid = document.createElement( "video" ); |
| 396 | + if( dummyvid.canPlayType ) { |
| 397 | + return true; |
| 398 | + } |
| 399 | + return false; |
| 400 | + } |
| 401 | + |
| 402 | + mw.supportsFlash = function(){ |
| 403 | + // Check if the client does not have flash and has the video tag |
| 404 | + if ( navigator.mimeTypes && navigator.mimeTypes.length > 0 ) { |
| 405 | + for ( var i = 0; i < navigator.mimeTypes.length; i++ ) { |
| 406 | + var type = navigator.mimeTypes[i].type; |
| 407 | + var semicolonPos = type.indexOf( ';' ); |
| 408 | + if ( semicolonPos > -1 ) { |
| 409 | + type = type.substr( 0, semicolonPos ); |
| 410 | + } |
| 411 | + if (type == 'application/x-shockwave-flash' ) { |
| 412 | + // flash is installed |
| 413 | + return true; |
| 414 | + } |
| 415 | + } |
| 416 | + } |
| 417 | + |
| 418 | + // for IE: |
| 419 | + var hasObj = true; |
| 420 | + if( typeof ActiveXObject != 'undefined' ){ |
| 421 | + try { |
| 422 | + var obj = new ActiveXObject( 'ShockwaveFlash.ShockwaveFlash' ); |
| 423 | + } catch ( e ) { |
| 424 | + hasObj = false; |
| 425 | + } |
| 426 | + if( hasObj ){ |
| 427 | + return true; |
| 428 | + } |
| 429 | + } |
| 430 | + return false; |
| 431 | + }; |
| 432 | + |
| 433 | + |
| 434 | +} )( mediaWiki, jQuery ); |
\ No newline at end of file |
Property changes on: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MwEmbedSupport/mwEmbed.core.js |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 435 | + text/plain |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MwEmbedSupport/MwEmbedSupport.php |
— | — | @@ -0,0 +1,8 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +return array( |
| 5 | + |
| 6 | +) |
| 7 | + |
| 8 | +?> |
| 9 | + |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MwEmbedSupport/mwEmbed.old.js |
— | — | @@ -0,0 +1,2698 @@ |
| 2 | +// Add support for html5 / mwEmbed elements to browsers that do not support the elements natively |
| 3 | +// For discussion and comments, see: http://ejohn.org/blog/html5-shiv/ |
| 4 | +'video audio source track'.replace(/\w+/g, function(n){ document.createElement(n); }); |
| 5 | + |
| 6 | +/** |
| 7 | + * @license mwEmbed Dual licensed under the MIT or GPL Version 2 licenses. |
| 8 | + * |
| 9 | + * @copyright (C) 2010 Kaltura |
| 10 | + * @author Michael Dale ( michael.dale at kaltura.com ) |
| 11 | + * |
| 12 | + * @url http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library |
| 13 | + * |
| 14 | + * Libraries used include code license in headers |
| 15 | + */ |
| 16 | + |
| 17 | +/** |
| 18 | + * Setup the "mw" global: |
| 19 | + */ |
| 20 | +if ( typeof window.mw == 'undefined' ) { |
| 21 | + window.mw = { }; |
| 22 | +} |
| 23 | +/** |
| 24 | + * Set the mwEmbedVersion |
| 25 | + */ |
| 26 | +var MW_EMBED_VERSION = '1.1h'; |
| 27 | + |
| 28 | +// Globals to pre-set ready functions in dynamic loading of mwEmbed |
| 29 | +if( typeof preMwEmbedReady == 'undefined'){ |
| 30 | + var preMwEmbedReady = []; |
| 31 | +} |
| 32 | +// Globals to pre-set config values in dynamic loading of mwEmbed |
| 33 | +if( typeof preMwEmbedConfig == 'undefined') { |
| 34 | + var preMwEmbedConfig = []; |
| 35 | +} |
| 36 | + |
| 37 | +/** |
| 38 | + * The global mw object: |
| 39 | + */ |
| 40 | +( function( mw ) { |
| 41 | + // The version of mwEmbed |
| 42 | + mw.version = MW_EMBED_VERSION; |
| 43 | + |
| 44 | + // List valid skins here: |
| 45 | + mw.validSkins = [ 'mvpcf', 'kskin' ]; |
| 46 | + |
| 47 | + // Storage variable for loaded style sheet keys |
| 48 | + if( ! mw.style ){ |
| 49 | + mw.style = { }; |
| 50 | + } |
| 51 | + |
| 52 | + /** |
| 53 | + * Configuration System: |
| 54 | + */ |
| 55 | + |
| 56 | + // Local scope configuration var: |
| 57 | + if( !mwConfig ){ |
| 58 | + var mwConfig = { }; |
| 59 | + } |
| 60 | + |
| 61 | + if( !mwNonDefaultConfigList ){ |
| 62 | + var mwNonDefaultConfigList = []; |
| 63 | + } |
| 64 | + |
| 65 | + // mw scope mwUserConfig var. Stores user configuration |
| 66 | + var mwUserConfig = { }; |
| 67 | + |
| 68 | + /** |
| 69 | + * Setter for configuration values |
| 70 | + * |
| 71 | + * @param [Mixed] |
| 72 | + * name Name of configuration value {Object} Will iderate through |
| 73 | + * each key and call setConfig {String} Will set configuration by |
| 74 | + * string name to value |
| 75 | + * @param {String} |
| 76 | + * value Value of configuration name {Object} value Set of values |
| 77 | + * to be merged |
| 78 | + */ |
| 79 | + mw.setConfig = function ( name, value ) { |
| 80 | + if( typeof name == 'object' ) { |
| 81 | + for( var i in name ) { |
| 82 | + mw.setConfig( i, name[ i ] ); |
| 83 | + } |
| 84 | + return ; |
| 85 | + } |
| 86 | + mwConfig[ name ] = value; |
| 87 | + mwNonDefaultConfigList.push( name ); |
| 88 | + }; |
| 89 | + |
| 90 | + // Apply any pre-setup config: |
| 91 | + mw.setConfig( preMwEmbedConfig ); |
| 92 | + |
| 93 | + /** |
| 94 | + * Merge in a configuration value: |
| 95 | + */ |
| 96 | + mw.mergeConfig = function( name, value ){ |
| 97 | + if( typeof name == 'object' ) { |
| 98 | + $j.each( name, function( inx, val) { |
| 99 | + mw.setConfig( inx, val ); |
| 100 | + }); |
| 101 | + return ; |
| 102 | + } |
| 103 | + // Check if we should "merge" the config |
| 104 | + if( typeof value == 'object' && typeof mwConfig[ name ] == 'object' ) { |
| 105 | + if ( value.constructor.toString().indexOf("Array") != -1 && |
| 106 | + mwConfig[ name ].constructor.toString().indexOf("Array") != -1 ){ |
| 107 | + // merge in the array |
| 108 | + mwConfig[ name ] = $j.merge( mwConfig[ name ], value ); |
| 109 | + } else { |
| 110 | + for( var i in value ){ |
| 111 | + mwConfig[ name ][ i ] = value[ i ]; |
| 112 | + } |
| 113 | + } |
| 114 | + return ; |
| 115 | + } |
| 116 | + // else do a normal setConfig |
| 117 | + mwConfig[ name ] = value; |
| 118 | + mwNonDefaultConfigList.push( name ); |
| 119 | + }; |
| 120 | + |
| 121 | + /** |
| 122 | + * Set a default config value Will only update configuration if no value is |
| 123 | + * present |
| 124 | + * |
| 125 | + * @param [Mixed] |
| 126 | + * value Set configuration name to value {Object} Will idorate |
| 127 | + * through each key and call setDefaultConfig {String} Will set |
| 128 | + * configuration by string name to value |
| 129 | + */ |
| 130 | + mw.setDefaultConfig = function( name, value ) { |
| 131 | + if( typeof name == 'object' ) { |
| 132 | + for( var i in name ) { |
| 133 | + mw.setDefaultConfig( i, name[ i ] ); |
| 134 | + } |
| 135 | + return ; |
| 136 | + } |
| 137 | + if( typeof mwConfig[ name ] == 'undefined' ) { |
| 138 | + mwConfig[ name ] = value; |
| 139 | + return ; |
| 140 | + } |
| 141 | + }; |
| 142 | + |
| 143 | + /** |
| 144 | + * Getter for configuration values |
| 145 | + * |
| 146 | + * @param {String} |
| 147 | + * name of configuration value to get |
| 148 | + * @return {Mixed} value of configuration key returns "false" if key not |
| 149 | + * found |
| 150 | + */ |
| 151 | + mw.getConfig = function ( name ) { |
| 152 | + if( mwConfig[ name ] ) |
| 153 | + return mwConfig[ name ]; |
| 154 | + return false; |
| 155 | + }; |
| 156 | + /** |
| 157 | + * Get all the non-default configuration ( useful for passing state to |
| 158 | + * iframes in limited hash url length of a few K ) |
| 159 | + */ |
| 160 | + mw.getNonDefaultConfigObject = function(){ |
| 161 | + var nonDefaultConfig = {}; |
| 162 | + for( var i =0 ; i < mwNonDefaultConfigList.length; i ++){ |
| 163 | + var configKey = mwNonDefaultConfigList[i]; |
| 164 | + nonDefaultConfig[ configKey ] = mw.getConfig( configKey ); |
| 165 | + } |
| 166 | + return nonDefaultConfig; |
| 167 | + } |
| 168 | + |
| 169 | + /** |
| 170 | + * Loads the mwUserConfig from a cookie. |
| 171 | + * |
| 172 | + * Modules that want to use "User Config" should call this setup function in |
| 173 | + * their moduleLoader code. |
| 174 | + * |
| 175 | + * For performance interfaces using "user config" should load '$j.cookie' & |
| 176 | + * 'JSON' in their module loader |
| 177 | + * |
| 178 | + * By abstracting user preference we could eventually integrate a persistent |
| 179 | + * per-account preference system on the server. |
| 180 | + * |
| 181 | + * @parma {Function} callback Function to be called once userPrefrences are |
| 182 | + * loaded |
| 183 | + */ |
| 184 | + var setupUserConfigFlag = false; |
| 185 | + mw.setupUserConfig = function( callback ) { |
| 186 | + if( setupUserConfigFlag ) { |
| 187 | + if( callback ) { |
| 188 | + callback(); |
| 189 | + } |
| 190 | + return ; |
| 191 | + } |
| 192 | + // Do Setup user config: |
| 193 | + mw.load( [ '$j.cookie', 'JSON' ], function() { |
| 194 | + if( $j.cookie( 'mwUserConfig' ) ) { |
| 195 | + mwUserConfig = JSON.parse( $j.cookie( 'mwUserConfig' ) ); |
| 196 | + } |
| 197 | + setupUserConfigFlag = true; |
| 198 | + if( callback ) { |
| 199 | + callback(); |
| 200 | + } |
| 201 | + }); |
| 202 | + }; |
| 203 | + |
| 204 | + /** |
| 205 | + * Save a user configuration var to a cookie & local global variable Loads |
| 206 | + * the cookie plugin if not already loaded |
| 207 | + * |
| 208 | + * @param {String} |
| 209 | + * name Name of user configuration value |
| 210 | + * @param {String} |
| 211 | + * value Value of configuration name |
| 212 | + */ |
| 213 | + mw.setUserConfig = function ( name, value, cookieOptions ) { |
| 214 | + if( ! setupUserConfigFlag ) { |
| 215 | + mw.log( "Error: userConfig not setup" ); |
| 216 | + return false; |
| 217 | + } |
| 218 | + // Update local value |
| 219 | + mwUserConfig[ name ] = value; |
| 220 | + |
| 221 | + // Update the cookie ( '$j.cookie' & 'JSON' should already be loaded ) |
| 222 | + $j.cookie( 'mwUserConfig', JSON.stringify( mwUserConfig ) ); |
| 223 | + }; |
| 224 | + |
| 225 | + /** |
| 226 | + * Save a user configuration var to a cookie & local global variable |
| 227 | + * |
| 228 | + * @param {String} |
| 229 | + * name Name of user configuration value |
| 230 | + * @return value of the configuration name false if the configuration name |
| 231 | + * could not be found |
| 232 | + */ |
| 233 | + mw.getUserConfig = function ( name ) { |
| 234 | + if( mwUserConfig[ name ] ) |
| 235 | + return mwUserConfig[ name ]; |
| 236 | + return false; |
| 237 | + }; |
| 238 | + |
| 239 | + /** |
| 240 | + * Add a hook system for a target object / interface |
| 241 | + * |
| 242 | + * depricated you should instead use jQuery's bind and trigger |
| 243 | + * |
| 244 | + * @param {Object} |
| 245 | + * targetObj Interface Object to add hook system to. |
| 246 | + */ |
| 247 | + mw.addHookSystem = function( targetObj ) { |
| 248 | + |
| 249 | + // Setup the target object hook holder: |
| 250 | + targetObj[ 'hooks' ] = { }; |
| 251 | + |
| 252 | + /** |
| 253 | + * Adds a hook to the target object |
| 254 | + * |
| 255 | + * Should be called by clients to setup named hooks |
| 256 | + * |
| 257 | + * @param {String} |
| 258 | + * hookName Name of hook to be added |
| 259 | + * @param {Function} |
| 260 | + * hookFunction Function to be called at hook time |
| 261 | + */ |
| 262 | + targetObj.addHook = function( hookName, hookFunction ) { |
| 263 | + if( ! this.hooks[ hookName ] ) { |
| 264 | + this.hooks[ hookName ] = [ ]; |
| 265 | + } |
| 266 | + this.hooks[ hookName ].push( hookFunction ); |
| 267 | + }; |
| 268 | + |
| 269 | + /** |
| 270 | + * Runs all the hooks by a given name with reference to the host object |
| 271 | + * |
| 272 | + * Should be called by the host object at named execution points |
| 273 | + * |
| 274 | + * @param {String} |
| 275 | + * hookName Name of hook to be called |
| 276 | + * @return Value of hook result true interface should continue function |
| 277 | + * execution false interface should stop or return from method |
| 278 | + */ |
| 279 | + targetObj.runHook = function( hookName, options ) { |
| 280 | + if( this.hooks[ hookName ] ) { |
| 281 | + for( var i =0; i < this.hooks[ hookName ].length; i ++ ) { |
| 282 | + if( typeof( this.hooks[ hookName ][ i ] ) == 'function' ) { |
| 283 | + this.hooks[ hookName ][ i ]( options ); |
| 284 | + } |
| 285 | + } |
| 286 | + } |
| 287 | + }; |
| 288 | + }; |
| 289 | + |
| 290 | + // Add hooks system to the core "mw" object |
| 291 | + mw.addHookSystem( mw ); |
| 292 | + |
| 293 | + // Stores callbacks for resource loader loading |
| 294 | + var mwLoadDoneCB = { }; |
| 295 | + |
| 296 | + |
| 297 | + /** |
| 298 | + * Top level loader prototype: |
| 299 | + */ |
| 300 | + mw.loader = { |
| 301 | + /** |
| 302 | + * Javascript Module Loader functions |
| 303 | + * |
| 304 | + * @key Name of Module |
| 305 | + * @value function code to load module |
| 306 | + */ |
| 307 | + moduleLoaders : [], |
| 308 | + |
| 309 | + /** |
| 310 | + * Module resource list queue. |
| 311 | + * |
| 312 | + * @key Name of Module |
| 313 | + * @value .resourceList list of resources to be loaded .functionQueue |
| 314 | + * list of functions to be run once module is ready |
| 315 | + */ |
| 316 | + moduleLoadQueue: { }, |
| 317 | + |
| 318 | + /** |
| 319 | + * Javascript Class Paths |
| 320 | + * |
| 321 | + * @key Name of resource |
| 322 | + * @value Class file path |
| 323 | + */ |
| 324 | + resourcePaths : { }, |
| 325 | + |
| 326 | + /** |
| 327 | + * Stores resources that have been requested ( to avoid re-requesting |
| 328 | + * the same resources ) in concurrent requests ) |
| 329 | + */ |
| 330 | + requestedResourceQueue: { }, |
| 331 | + |
| 332 | + /** |
| 333 | + * javascript Resource Paths |
| 334 | + * |
| 335 | + * @key Name of resource |
| 336 | + * @value Name of depenent style sheet |
| 337 | + */ |
| 338 | + resourceStyleDependency: { }, |
| 339 | + |
| 340 | + /** |
| 341 | + * Core load function: |
| 342 | + * |
| 343 | + * @param {Mixed} |
| 344 | + * loadRequest: |
| 345 | + * |
| 346 | + * {String} Name of a module to be loaded Modules are added via |
| 347 | + * addModuleLoader and can define custom code needed to check config and |
| 348 | + * return a list of resources to be loaded |
| 349 | + * |
| 350 | + * {String} Name of a resource to loaded. Resources are added via |
| 351 | + * addResourcePaths function Using defined resource names avoids loading |
| 352 | + * the same resource twice by first checking if the named resource is |
| 353 | + * defined in the global javascript scope variable |
| 354 | + * |
| 355 | + * {String} Absolute or relative to url path The same file won't be |
| 356 | + * loaded twice |
| 357 | + * |
| 358 | + * {Array} can be an array of any combination of the above strings. Will |
| 359 | + * be loaded in-order or in a single resource loader request if |
| 360 | + * scriptLoader is available. |
| 361 | + * |
| 362 | + * {Array} {Array} Can be a set of Arrays for loading. Some browsers |
| 363 | + * execute included scripts out of order. This lets you chain sets of |
| 364 | + * request for those browsers. If using the server side resource loader |
| 365 | + * order is preserved in output and a single request will be used. |
| 366 | + * |
| 367 | + * @param {Function} |
| 368 | + * callback Function called once loading is complete |
| 369 | + * |
| 370 | + */ |
| 371 | + load: function( loadRequest, instanceCallback ) { |
| 372 | + // mw.log("mw.load:: " + loadRequest ); |
| 373 | + var _this = this; |
| 374 | + |
| 375 | + // Throw out any loadRequests that are not strings |
| 376 | + loadRequest = this.cleanLoadRequest( loadRequest ); |
| 377 | + |
| 378 | + // Ensure the callback is only called once per load instance |
| 379 | + var callback = function(){ |
| 380 | + // mw.log( 'instanceCallback::running callback: ' + |
| 381 | + // instanceCallback ); |
| 382 | + if( instanceCallback ){ |
| 383 | + // We pass the loadRequest back to the callback for easy |
| 384 | + // debugging of concurrency issues. |
| 385 | + // ( normally its not used ) |
| 386 | + instanceCallback( loadRequest ); |
| 387 | + instanceCallback = null; |
| 388 | + } |
| 389 | + }; |
| 390 | + |
| 391 | + // Check for empty loadRequest ( directly return the callback ) |
| 392 | + if( mw.isEmpty( loadRequest ) ) { |
| 393 | + mw.log( 'Empty load request: ( ' + loadRequest + ' ) ' ); |
| 394 | + callback( loadRequest ); |
| 395 | + return ; |
| 396 | + } |
| 397 | + |
| 398 | + |
| 399 | + // Check if its a multi-part request: |
| 400 | + if( typeof loadRequest == 'object' ) { |
| 401 | + if( loadRequest.length > 1 ) { |
| 402 | + this.loadMany ( loadRequest, callback ); |
| 403 | + return ; |
| 404 | + }else{ |
| 405 | + // If an array of length 1 set as first element |
| 406 | + loadRequest = loadRequest[0]; |
| 407 | + } |
| 408 | + } |
| 409 | + |
| 410 | + // Check for the module name loader function |
| 411 | + if( this.moduleLoaders[ loadRequest ] ) { |
| 412 | + var resourceSet = this.getModuleResourceSet( loadRequest ); |
| 413 | + if( !resourceSet ){ |
| 414 | + mw.log( "mw.load:: Error with module loader: " + loadRequest + ' ( no resource set defined )' ); |
| 415 | + return ; |
| 416 | + } |
| 417 | + |
| 418 | + // xxx should use refactor "ready" stuff into a "domReady" class |
| 419 | + // So we would not have local scope globals like this: |
| 420 | + // if ( mwReadyFlag ) { |
| 421 | + // Load the module directly if load request is after |
| 422 | + // mw.ready has run |
| 423 | + this.load( resourceSet, callback ); |
| 424 | + // } else { |
| 425 | + // this.addToModuleLoaderQueue( |
| 426 | + // loadRequest, |
| 427 | + // resourceSet, |
| 428 | + // callback |
| 429 | + // ); |
| 430 | + // } |
| 431 | + return ; |
| 432 | + } |
| 433 | + |
| 434 | + // Check for javascript resource |
| 435 | + if( this.getResourcePath( loadRequest ) ) { |
| 436 | + this.loadResource( loadRequest, callback ); |
| 437 | + return ; |
| 438 | + } |
| 439 | + |
| 440 | + // Try loading as a "file" or via ScriptLoader |
| 441 | + if( loadRequest ) { |
| 442 | + // Check if this resource was already requested |
| 443 | + if( typeof this.requestedResourceQueue[ loadRequest ] == 'object' ){ |
| 444 | + this.requestedResourceQueue[ loadRequest ].push( callback ); |
| 445 | + return ; |
| 446 | + } else { |
| 447 | + this.requestedResourceQueue[ loadRequest ] = []; |
| 448 | + } |
| 449 | + |
| 450 | + if( loadRequest.indexOf( '.js' ) == -1 && !mw.getResourceLoaderPath() ) { |
| 451 | + mw.log( 'Error: are you sure ' + loadRequest + ' is a file ( is it missing a resource path? ) ' ); |
| 452 | + } |
| 453 | + mw.getScript( loadRequest, function(){ |
| 454 | + // Check if we have requestedResources queue items: |
| 455 | + while( _this.requestedResourceQueue[ loadRequest ].length ){ |
| 456 | + _this.requestedResourceQueue[ loadRequest ].shift()( loadRequest ); |
| 457 | + } |
| 458 | + callback( loadRequest ); |
| 459 | + // empty the load request queue: |
| 460 | + _this.requestedResourceQueue[ loadRequest ] = []; |
| 461 | + }); |
| 462 | + return ; |
| 463 | + } |
| 464 | + |
| 465 | + // Possible error? |
| 466 | + mw.log( "Error could not handle load request: " + loadRequest ); |
| 467 | + }, |
| 468 | + |
| 469 | + getModuleResourceSet: function( moduleName ){ |
| 470 | + // Check if the module loader is a function ~run that function~ |
| 471 | + if( typeof ( this.moduleLoaders[ moduleName ] ) == 'function' ) { |
| 472 | + // Add the result of the module loader function |
| 473 | + return this.moduleLoaders[ moduleName ](); |
| 474 | + } else if( typeof ( this.moduleLoaders[ moduleName ] ) == 'object' ){ |
| 475 | + // set resourceSet directly |
| 476 | + return this.moduleLoaders[ moduleName ]; |
| 477 | + } |
| 478 | + return false; |
| 479 | + }, |
| 480 | + |
| 481 | + /** |
| 482 | + * Clean the loadRequest ( throw out any non-string items ) |
| 483 | + */ |
| 484 | + cleanLoadRequest: function( loadRequest ){ |
| 485 | + var cleanRequest = []; |
| 486 | + if( ! loadRequest ){ |
| 487 | + return []; |
| 488 | + } |
| 489 | + if( typeof loadRequest == 'string' ) |
| 490 | + return loadRequest; |
| 491 | + for( var i =0;i < loadRequest.length; i++ ){ |
| 492 | + if( typeof loadRequest[i] == 'object' ) { |
| 493 | + cleanRequest[i] = this.cleanLoadRequest( loadRequest[i] ); |
| 494 | + } else if( typeof loadRequest[i] == 'string' ){ |
| 495 | + cleanRequest[i] = $j.trim( loadRequest[i] ); |
| 496 | + } else{ |
| 497 | + // bad request type skip |
| 498 | + } |
| 499 | + } |
| 500 | + return cleanRequest; |
| 501 | + }, |
| 502 | + |
| 503 | + /** |
| 504 | + * Load a set of scripts. Will issue many load requests or package the |
| 505 | + * request for the resource loader |
| 506 | + * |
| 507 | + * @param {Object} |
| 508 | + * loadSet Set of scripts to be loaded |
| 509 | + * @param {Function} |
| 510 | + * callback Function to call once all scripts are loaded. |
| 511 | + */ |
| 512 | + loadMany: function( loadSet, callback ) { |
| 513 | + var _this = this; |
| 514 | + // Setup up the local "loadStates" |
| 515 | + var loadStates = { }; |
| 516 | + |
| 517 | + // Check if we can load via the "resource loader" ( mwEmbed was |
| 518 | + // included via scriptLoader ) |
| 519 | + if( mw.getResourceLoaderPath() ) { |
| 520 | + // Get the grouped loadStates variable |
| 521 | + loadStates = this.getGroupLoadState( loadSet ); |
| 522 | + if( mw.isEmpty( loadStates ) ) { |
| 523 | + // mw.log( 'loadMany:all resources already loaded'); |
| 524 | + callback(); |
| 525 | + return ; |
| 526 | + } |
| 527 | + }else{ |
| 528 | + // Check if its a dependency set ( nested objects ) |
| 529 | + if( typeof loadSet [ 0 ] == 'object' ) { |
| 530 | + _this.dependencyChainCallFlag[ loadSet ] = false; |
| 531 | + // Load sets of resources ( to preserver order for some |
| 532 | + // browsers ) |
| 533 | + _this.loadDependencyChain( loadSet, callback ); |
| 534 | + return ; |
| 535 | + } |
| 536 | + |
| 537 | + // Set the initial load state for every item in the loadSet |
| 538 | + for( var i = 0; i < loadSet.length ; i++ ) { |
| 539 | + var loadName = loadSet[ i ]; |
| 540 | + loadStates[ loadName ] = 0; |
| 541 | + } |
| 542 | + } |
| 543 | + |
| 544 | + // We are infact loading many: |
| 545 | + // mw.log("mw.load: LoadMany:: " + loadSet ); |
| 546 | + |
| 547 | + // Issue the load request check check loadStates to see if we are |
| 548 | + // "done" |
| 549 | + for( var loadName in loadStates ) { |
| 550 | + // mw.log("loadMany: load: " + loadName ); |
| 551 | + this.load( loadName, function ( loadName ) { |
| 552 | + loadStates[ loadName ] = 1; |
| 553 | + |
| 554 | + /* |
| 555 | + * for( var i in loadStates ) { mw.log( loadName + ' |
| 556 | + * finished of: ' + i + ' : ' + loadStates[i] ); } |
| 557 | + */ |
| 558 | + |
| 559 | + // Check if all load request states are set 1 |
| 560 | + var loadDone = true; |
| 561 | + for( var j in loadStates ) { |
| 562 | + if( loadStates[ j ] === 0 ) |
| 563 | + loadDone = false; |
| 564 | + } |
| 565 | + // Run the parent scope callback for "loadMany" |
| 566 | + if( loadDone ) { |
| 567 | + callback( loadName ); |
| 568 | + } |
| 569 | + } ); |
| 570 | + } |
| 571 | + }, |
| 572 | + |
| 573 | + /** |
| 574 | + * Get grouped load state for script loader |
| 575 | + * |
| 576 | + * Groups the scriptRequest where possible: Modules include "loader |
| 577 | + * code" so they are separated into pre-condition code to be run for |
| 578 | + * subsequent requests |
| 579 | + * |
| 580 | + * @param {Object} |
| 581 | + * loadSet Loadset to return grouped |
| 582 | + * @return {Object} grouped loadSet |
| 583 | + */ |
| 584 | + getGroupLoadState: function( loadSet ) { |
| 585 | + var groupedLoadSet = []; |
| 586 | + var loadStates = { }; |
| 587 | + // Merge load set into new groupedLoadSet |
| 588 | + if( typeof loadSet[0] == 'object' ) { |
| 589 | + for( var i = 0; i < loadSet.length ; i++ ) { |
| 590 | + for( var j = 0; j < loadSet[i].length ; j++ ) { |
| 591 | + // Make sure we have not already included it: |
| 592 | + groupedLoadSet.push( loadSet[i][j] ); |
| 593 | + } |
| 594 | + } |
| 595 | + } else { |
| 596 | + // Use the loadSet directly: |
| 597 | + groupedLoadSet = loadSet; |
| 598 | + } |
| 599 | + |
| 600 | + // Setup grouped loadStates Set: |
| 601 | + var groupClassKey = ''; |
| 602 | + var coma = ''; |
| 603 | + var uniqueResourceName = {}; |
| 604 | + for( var i=0; i < groupedLoadSet.length; i++ ) { |
| 605 | + var loadName = groupedLoadSet[ i ]; |
| 606 | + if( this.getResourcePath( loadName ) ) { |
| 607 | + // Check if not already in request queue and not defined in |
| 608 | + // global namespace |
| 609 | + if( !mw.isset( loadName ) && ! uniqueResourceName[ loadName] ){ |
| 610 | + groupClassKey += coma + loadName; |
| 611 | + coma = ','; |
| 612 | + |
| 613 | + // Check for style sheet dependencies |
| 614 | + if( this.resourceStyleDependency[ loadName ] ){ |
| 615 | + groupClassKey += coma + this.resourceStyleDependency[ loadName ]; |
| 616 | + } |
| 617 | + } |
| 618 | + } else if ( this.moduleLoaders[ loadName ] ) { |
| 619 | + |
| 620 | + // Module loaders break up grouped script requests ( add the |
| 621 | + // current groupClassKey ) |
| 622 | + if( groupClassKey != '' ) { |
| 623 | + loadStates[ groupClassKey ] = 0; |
| 624 | + groupClassKey = coma = ''; |
| 625 | + } |
| 626 | + if( ! uniqueResourceName[ loadName] ){ |
| 627 | + // Add the module to the loadSate |
| 628 | + loadStates[ loadName ] = 0; |
| 629 | + } |
| 630 | + } |
| 631 | + uniqueResourceName[ loadName] = true; |
| 632 | + } |
| 633 | + |
| 634 | + // Add groupClassKey if set: |
| 635 | + if( groupClassKey != '' ) { |
| 636 | + loadStates [ groupClassKey ] = 0; |
| 637 | + } |
| 638 | + |
| 639 | + return loadStates; |
| 640 | + }, |
| 641 | + |
| 642 | + // Array to register that a callback has been called |
| 643 | + dependencyChainCallFlag: { }, |
| 644 | + |
| 645 | + /** |
| 646 | + * Load a sets of scripts satisfy dependency order for browsers that |
| 647 | + * execute dynamically included scripts out of order |
| 648 | + * |
| 649 | + * @param {Object} |
| 650 | + * loadChain A set of javascript arrays to be loaded. Sets |
| 651 | + * are requested in array order. |
| 652 | + */ |
| 653 | + loadDependencyChain: function( loadChain, callback ) { |
| 654 | + var _this = this; |
| 655 | + // Load with dependency checks |
| 656 | + var callSet = loadChain.shift(); |
| 657 | + this.load( callSet, function( cbname ) { |
| 658 | + if ( loadChain.length != 0 ) { |
| 659 | + _this.loadDependencyChain( loadChain, callback ); |
| 660 | + } else { |
| 661 | + // NOTE: IE gets called twice so we have check the |
| 662 | + // dependencyChainCallFlag before calling the callback |
| 663 | + if( _this.dependencyChainCallFlag[ callSet ] == callback ) { |
| 664 | + mw.log("... already called this callback for " + callSet ); |
| 665 | + return ; |
| 666 | + } |
| 667 | + _this.dependencyChainCallFlag[ callSet ] = callback; |
| 668 | + callback( ); |
| 669 | + } |
| 670 | + } ); |
| 671 | + }, |
| 672 | + |
| 673 | + /** |
| 674 | + * Add to the module loader queue |
| 675 | + */ |
| 676 | + addToModuleLoaderQueue: function( moduleName, resourceSet, callback ) { |
| 677 | + mw.log(" addToModuleLoaderQueue:: " + moduleName + ' resourceSet: ' + resourceSet ); |
| 678 | + if( this.moduleLoadQueue[ moduleName ] ){ |
| 679 | + // If the module is already in the queue just add its callback: |
| 680 | + this.moduleLoadQueue[ moduleName ].functionQueue.push( callback ); |
| 681 | + } else { |
| 682 | + // create the moduleLoadQueue item |
| 683 | + this.moduleLoadQueue[ moduleName ] = { |
| 684 | + 'resourceSet' : resourceSet, |
| 685 | + 'functionQueue' : [ callback ], |
| 686 | + 'loaded' : false |
| 687 | + }; |
| 688 | + } |
| 689 | + }, |
| 690 | + |
| 691 | + /** |
| 692 | + * Loops over all modules in queue, builds request sets based on config |
| 693 | + * request type |
| 694 | + */ |
| 695 | + runModuleLoadQueue: function(){ |
| 696 | + var _this = this; |
| 697 | + mw.log( "mw.runModuleLoadQueue:: " ); |
| 698 | + var runModuleFunctionQueue = function(){ |
| 699 | + // Run all the callbacks |
| 700 | + for( var moduleName in _this.moduleLoadQueue ){ |
| 701 | + while( _this.moduleLoadQueue[moduleName].functionQueue.length ) { |
| 702 | + _this.moduleLoadQueue[moduleName].functionQueue.shift()(); |
| 703 | + } |
| 704 | + } |
| 705 | + }; |
| 706 | + |
| 707 | + // Check for single request or javascript debug based loading: |
| 708 | + if( !mw.getResourceLoaderPath() || mw.getConfig( 'loader.groupStrategy' ) == 'single' ){ |
| 709 | + // if not using the resource load just do a normal array merge |
| 710 | + // ( for browsers like IE that don't follow first append first |
| 711 | + // execute rule ) |
| 712 | + var fullResourceList = []; |
| 713 | + for( var moduleName in this.moduleLoadQueue ) { |
| 714 | + var resourceSet = this.moduleLoadQueue[ moduleName ].resourceSet; |
| 715 | + // Lets try a global merge |
| 716 | + fullResourceList = $j.merge( fullResourceList, resourceSet ); |
| 717 | + } |
| 718 | + mw.load( fullResourceList, function(){ |
| 719 | + runModuleFunctionQueue(); |
| 720 | + }); |
| 721 | + return ; |
| 722 | + } |
| 723 | + |
| 724 | + // Else do per module group loading |
| 725 | + if( mw.getConfig( 'loader.groupStrategy' ) == 'module' ) { |
| 726 | + var fullResourceList = []; |
| 727 | + var sharedResourceList = []; |
| 728 | + |
| 729 | + for( var moduleName in this.moduleLoadQueue ) { |
| 730 | + // Build a shared dependencies list and load that separately |
| 731 | + // "first" |
| 732 | + // ( in IE we have to wait until its "ready" since it does |
| 733 | + // not follow dom order ) |
| 734 | + var moduleResourceList = this.getFlatModuleResourceList( moduleName ); |
| 735 | + // Build the sharedResourceList |
| 736 | + for( var i=0; i < moduleResourceList.length; i++ ){ |
| 737 | + var moduleResource = moduleResourceList[i]; |
| 738 | + // Check if already in the full resource list if so add |
| 739 | + // to shared. |
| 740 | + if( fullResourceList[ moduleResource ] ){ |
| 741 | + if( $j.inArray( moduleResource, sharedResourceList ) == -1 ){ |
| 742 | + sharedResourceList.push( moduleResource ); |
| 743 | + } |
| 744 | + } |
| 745 | + // Add to the fullResourceList |
| 746 | + fullResourceList[ moduleResource ] = true; |
| 747 | + } |
| 748 | + } |
| 749 | + |
| 750 | + // Local module request set ( stores the actual request we will |
| 751 | + // make after grouping shared resources |
| 752 | + var moduleRequestSet = {}; |
| 753 | + |
| 754 | + // Only add non-shared to respective modules load requests |
| 755 | + for( var moduleName in this.moduleLoadQueue ) { |
| 756 | + moduleRequestSet[ moduleName ] = []; |
| 757 | + var moduleResourceList = this.getFlatModuleResourceList( moduleName ); |
| 758 | + for( var i =0; i < moduleResourceList.length; i++ ){ |
| 759 | + var moduleResource = moduleResourceList[i]; |
| 760 | + if( $j.inArray( moduleResource, sharedResourceList ) == -1 ){ |
| 761 | + moduleRequestSet[ moduleName ].push( moduleResource ); |
| 762 | + } |
| 763 | + } |
| 764 | + } |
| 765 | + var sharedResourceLoadDone = false; |
| 766 | + // Check if modules are done |
| 767 | + var checkModulesDone = function(){ |
| 768 | + if( !sharedResourceLoadDone ){ |
| 769 | + return false; |
| 770 | + } |
| 771 | + for( var moduleName in _this.moduleLoadQueue ) { |
| 772 | + if( ! _this.moduleLoadQueue[ moduleName ].loaded ){ |
| 773 | + return false; |
| 774 | + } |
| 775 | + } |
| 776 | + runModuleFunctionQueue(); |
| 777 | + }; |
| 778 | + // Local instance of load requests to retain resourceSet |
| 779 | + // context: |
| 780 | + var localLoadCallInstance = function( moduleName, resourceSet ){ |
| 781 | + mw.load( resourceSet, function(){ |
| 782 | + _this.moduleLoadQueue[ moduleName ].loaded = true; |
| 783 | + checkModulesDone(); |
| 784 | + }); |
| 785 | + }; |
| 786 | + |
| 787 | + // Load the shared resources |
| 788 | + mw.load( sharedResourceList, function(){ |
| 789 | + // mw.log("Shared Resources loaded"); |
| 790 | + // xxx check if we are in "IE" and dependencies need to be |
| 791 | + // loaded "first" |
| 792 | + sharedResourceLoadDone = true; |
| 793 | + checkModulesDone(); |
| 794 | + }); |
| 795 | + // Load all module Request Set |
| 796 | + for( var moduleName in moduleRequestSet ){ |
| 797 | + localLoadCallInstance( moduleName, moduleRequestSet[ moduleName ] ); |
| 798 | + } |
| 799 | + } |
| 800 | + // xxx Here we could also do some "intelligent" grouping |
| 801 | + }, |
| 802 | + |
| 803 | + getFlatModuleResourceList: function( moduleName ){ |
| 804 | + var moduleList = []; |
| 805 | + for( var j in this.moduleLoadQueue[moduleName].resourceSet ){ |
| 806 | + // Check if we have a multi-set array: |
| 807 | + if( typeof this.moduleLoadQueue[moduleName].resourceSet[j] == 'object' ){ |
| 808 | + moduleList = $j.merge( moduleList, this.moduleLoadQueue[moduleName].resourceSet[j] ); |
| 809 | + } else { |
| 810 | + moduleList = $j.merge( moduleList, [ this.moduleLoadQueue[moduleName].resourceSet[j] ] ); |
| 811 | + } |
| 812 | + } |
| 813 | + return moduleList; |
| 814 | + }, |
| 815 | + |
| 816 | + /** |
| 817 | + * Loads javascript or css associated with a resourceName |
| 818 | + * |
| 819 | + * @param {String} |
| 820 | + * resourceName Name of resource to load |
| 821 | + * @param {Function} |
| 822 | + * callback Function to run once resource is loaded |
| 823 | + */ |
| 824 | + loadResource: function( resourceName , callback) { |
| 825 | + // mw.log("LoadResource:" + resourceName ); |
| 826 | + var _this = this; |
| 827 | + |
| 828 | + // Check for css dependency on resource name |
| 829 | + if( this.resourceStyleDependency[ resourceName ] ) { |
| 830 | + if( ! mw.isset( this.resourceStyleDependency[ resourceName ] )){ |
| 831 | + mw.log("loadResource:: dependent css resource: " + this.resourceStyleDependency[ resourceName ] ); |
| 832 | + _this.loadResource( this.resourceStyleDependency[ resourceName ] , function() { |
| 833 | + // Continue the original loadResource request. |
| 834 | + _this.loadResource( resourceName, callback ); |
| 835 | + }); |
| 836 | + return ; |
| 837 | + } |
| 838 | + } |
| 839 | + |
| 840 | + // Make sure the resource is not already defined: |
| 841 | + if ( mw.isset( resourceName ) ) { |
| 842 | + // mw.log( 'Class ( ' + resourceName + ' ) already defined ' ); |
| 843 | + callback( resourceName ); |
| 844 | + return ; |
| 845 | + } |
| 846 | + |
| 847 | + // Setup the Script Request var: |
| 848 | + var scriptRequest = null; |
| 849 | + |
| 850 | + |
| 851 | + // If the scriptloader is enabled use the resourceName as the |
| 852 | + // scriptRequest: |
| 853 | + if( mw.getResourceLoaderPath() ) { |
| 854 | + scriptRequest = resourceName; |
| 855 | + }else{ |
| 856 | + // Get the resource url: |
| 857 | + var baseClassPath = this.getResourcePath( resourceName ); |
| 858 | + // Add the mwEmbed path if not a root path or a full url |
| 859 | + if( baseClassPath.indexOf( '/' ) !== 0 && |
| 860 | + baseClassPath.indexOf( '://' ) === -1 ) { |
| 861 | + scriptRequest = mw.getMwEmbedPath() + baseClassPath; |
| 862 | + }else{ |
| 863 | + scriptRequest = baseClassPath; |
| 864 | + } |
| 865 | + if( ! scriptRequest ) { |
| 866 | + mw.log( "Error Could not get url for resource " + resourceName ); |
| 867 | + return false; |
| 868 | + } |
| 869 | + } |
| 870 | + // Include resource defined check for older browsers |
| 871 | + var resourceDone = false; |
| 872 | + |
| 873 | + // Set the loadDone callback per the provided resourceName |
| 874 | + mw.setLoadDoneCB( resourceName, callback ); |
| 875 | + // Issue the request to load the resource (include resource name in |
| 876 | + // result callback: |
| 877 | + mw.getScript( scriptRequest, function( scriptRequest ) { |
| 878 | + // If its a "style sheet" manually set its resource to true |
| 879 | + var ext = scriptRequest.substr( scriptRequest.split('?')[0].lastIndexOf( '.' ), 4 ).toLowerCase(); |
| 880 | + if( ext == '.css' && resourceName.substr(0,8) == 'mw.style' ){ |
| 881 | + mw.style[ resourceName.substr( 9 ) ] = true; |
| 882 | + } |
| 883 | + |
| 884 | + // Send warning if resourceName is not defined |
| 885 | + if(! mw.isset( resourceName ) |
| 886 | + && mwLoadDoneCB[ resourceName ] != 'done' ) { |
| 887 | + // mw.log( 'Possible Error: ' + resourceName +' not set in |
| 888 | + // time, or not defined in:' + "\n" |
| 889 | + // + _this.getResourcePath( resourceName ) ); |
| 890 | + } |
| 891 | + |
| 892 | + // If ( debug mode ) and the script include is missing resource |
| 893 | + // messages |
| 894 | + // do a separate request to retrieve the msgs |
| 895 | + if( mw.currentClassMissingMessages ) { |
| 896 | + mw.log( " resourceName " + resourceName + " is missing messages" ); |
| 897 | + // Reset the currentClassMissingMessages flag |
| 898 | + mw.currentClassMissingMessages = false; |
| 899 | + |
| 900 | + // Load msgs for this resource: |
| 901 | + mw.loadResourceMessages( resourceName, function() { |
| 902 | + // Run the onDone callback |
| 903 | + mw.loadDone( resourceName ); |
| 904 | + } ); |
| 905 | + } else { |
| 906 | + // If not using the resource loader make sure the |
| 907 | + // resourceName is available before firing the loadDone |
| 908 | + if( !mw.getResourceLoaderPath() ) { |
| 909 | + mw.waitForObject( resourceName, function( resourceName ) { |
| 910 | + // Once object is ready run loadDone |
| 911 | + mw.loadDone( resourceName ); |
| 912 | + } ); |
| 913 | + } else { |
| 914 | + // loadDone should be appended to the bottom of the |
| 915 | + // resource loader response |
| 916 | + // mw.loadDone( resourceName ); |
| 917 | + } |
| 918 | + } |
| 919 | + } ); |
| 920 | + }, |
| 921 | + |
| 922 | + /** |
| 923 | + * Adds a module to the mwLoader object |
| 924 | + * |
| 925 | + * @param {String} |
| 926 | + * name Name of module |
| 927 | + * @param {Function} |
| 928 | + * moduleLoader Function that loads dependencies for a module |
| 929 | + */ |
| 930 | + addModuleLoader: function( name, moduleLoader ) { |
| 931 | + this.moduleLoaders [ name ] = moduleLoader; |
| 932 | + }, |
| 933 | + |
| 934 | + /** |
| 935 | + * Adds resource file path key value pairs |
| 936 | + * |
| 937 | + * @param {Object} |
| 938 | + * resourceSet JSON formated list of resource name file path |
| 939 | + * pairs. |
| 940 | + * |
| 941 | + * resourceSet must be strict JSON to allow the php scriptLoader to |
| 942 | + * parse the file paths. |
| 943 | + */ |
| 944 | + addResourcePaths: function( resourceSet ) { |
| 945 | + var prefix = ( mw.getConfig( 'loaderContext' ) )? |
| 946 | + mw.getConfig( 'loaderContext' ): ''; |
| 947 | + |
| 948 | + for( var i in resourceSet ) { |
| 949 | + this.resourcePaths[ i ] = prefix + resourceSet[ i ]; |
| 950 | + } |
| 951 | + }, |
| 952 | + |
| 953 | + /* |
| 954 | + * Adds a named style sheet dependency to a named resource |
| 955 | + * |
| 956 | + * @parma {Object} resourceSet JSON formated list of resource names and |
| 957 | + * associated style sheet names |
| 958 | + */ |
| 959 | + addStyleResourceDependency: function( resourceSet ){ |
| 960 | + for( var i in resourceSet ){ |
| 961 | + this.resourceStyleDependency[ i ] = resourceSet[i]; |
| 962 | + } |
| 963 | + }, |
| 964 | + |
| 965 | + /** |
| 966 | + * Get a resource path from a resourceName if no resource found return |
| 967 | + * false |
| 968 | + */ |
| 969 | + getResourcePath: function( resourceName ) { |
| 970 | + if( this.resourcePaths[ resourceName ] ) |
| 971 | + return this.resourcePaths[ resourceName ]; |
| 972 | + return false; |
| 973 | + } |
| 974 | + }; |
| 975 | + |
| 976 | + /** |
| 977 | + * Load done callback for script loader |
| 978 | + * |
| 979 | + * @param {String} |
| 980 | + * requestName Name of the load request |
| 981 | + */ |
| 982 | + mw.loadDone = function( requestName ) { |
| 983 | + if( !mwLoadDoneCB[ requestName ] ) { |
| 984 | + return true; |
| 985 | + } |
| 986 | + while( mwLoadDoneCB[ requestName ].length ) { |
| 987 | + // check if mwLoadDoneCB is already "done" |
| 988 | + // the function list is not an object |
| 989 | + if( typeof mwLoadDoneCB[ requestName ] != 'object' ) |
| 990 | + { |
| 991 | + break; |
| 992 | + } |
| 993 | + var func = mwLoadDoneCB[ requestName ].pop(); |
| 994 | + if( typeof func == 'function' ) { |
| 995 | + // mw.log( "LoadDone: " + requestName + ' run callback::' + |
| 996 | + // func); |
| 997 | + func( requestName ); |
| 998 | + }else{ |
| 999 | + mw.log('mwLoadDoneCB: Error non callback function on stack'); |
| 1000 | + } |
| 1001 | + } |
| 1002 | + // Set the load request name to done |
| 1003 | + mwLoadDoneCB[ requestName ] = 'done'; |
| 1004 | + }; |
| 1005 | + |
| 1006 | + /** |
| 1007 | + * Set a load done callback |
| 1008 | + * |
| 1009 | + * @param {String} |
| 1010 | + * requestName Name of resource or request set |
| 1011 | + * @param {Function} |
| 1012 | + * callback Function called once requestName is ready |
| 1013 | + */ |
| 1014 | + mw.setLoadDoneCB = function( requestName, callback ) { |
| 1015 | + // If the requestName is already done loading just callback |
| 1016 | + if( mwLoadDoneCB[ requestName ] == 'done' ) { |
| 1017 | + callback( requestName ); |
| 1018 | + } |
| 1019 | + // Setup the function queue if unset |
| 1020 | + if( typeof mwLoadDoneCB[ requestName ] != 'object' ) { |
| 1021 | + mwLoadDoneCB[ requestName ] = []; |
| 1022 | + } |
| 1023 | + mwLoadDoneCB[ requestName ].push( callback ); |
| 1024 | + }; |
| 1025 | + |
| 1026 | + /** |
| 1027 | + * Shortcut entry points / convenience functions: Lets you write mw.load() |
| 1028 | + * instead of mw.loader.load() only these entry points should be used. |
| 1029 | + * |
| 1030 | + * future closure optimizations could minify internal function names |
| 1031 | + */ |
| 1032 | + |
| 1033 | + /** |
| 1034 | + * Load Object entry point: Loads a requested set of javascript |
| 1035 | + */ |
| 1036 | + mw.load = function( loadRequest, callback ) { |
| 1037 | + return mw.loader.load( loadRequest, callback ); |
| 1038 | + }; |
| 1039 | + |
| 1040 | + /** |
| 1041 | + * Add module entry point: Adds a module to the mwLoader object |
| 1042 | + */ |
| 1043 | + mw.addModuleLoader = function ( name, loaderFunction ) { |
| 1044 | + return mw.loader.addModuleLoader( name, loaderFunction ); |
| 1045 | + }; |
| 1046 | + |
| 1047 | + /** |
| 1048 | + * Add Class File Paths entry point: |
| 1049 | + */ |
| 1050 | + mw.addResourcePaths = function ( resourceSet ) { |
| 1051 | + return mw.loader.addResourcePaths( resourceSet ); |
| 1052 | + }; |
| 1053 | + |
| 1054 | + mw.addStyleResourceDependency = function ( resourceSet ) { |
| 1055 | + return mw.loader.addStyleResourceDependency( resourceSet ); |
| 1056 | + }; |
| 1057 | + |
| 1058 | + /** |
| 1059 | + * Get Class File Path entry point: |
| 1060 | + */ |
| 1061 | + mw.getResourcePath = function( resourceName ) { |
| 1062 | + return mw.loader.getResourcePath( resourceName ); |
| 1063 | + }; |
| 1064 | + |
| 1065 | + |
| 1066 | + /** |
| 1067 | + * Utility Functions |
| 1068 | + */ |
| 1069 | + |
| 1070 | + /** |
| 1071 | + * addLoaderDialog small helper for displaying a loading dialog |
| 1072 | + * |
| 1073 | + * @param {String} |
| 1074 | + * dialogHtml text Html of the loader msg |
| 1075 | + */ |
| 1076 | + mw.addLoaderDialog = function( dialogHtml ) { |
| 1077 | + if( typeof dialogHtml == 'undefined'){ |
| 1078 | + dialogHtml =''; |
| 1079 | + } |
| 1080 | + var $dialog = mw.addDialog( { |
| 1081 | + 'title' : dialogHtml, |
| 1082 | + 'content' : dialogHtml + '<br>' + |
| 1083 | + $j('<div />') |
| 1084 | + .loadingSpinner() |
| 1085 | + .html() |
| 1086 | + }); |
| 1087 | + return $dialog; |
| 1088 | + }; |
| 1089 | + |
| 1090 | + /** |
| 1091 | + * Close the loader dialog created with addLoaderDialog |
| 1092 | + */ |
| 1093 | + mw.closeLoaderDialog = function() { |
| 1094 | + // Make sure the dialog resource is present |
| 1095 | + if( !mw.isset( '$j.ui.dialog' ) ) { |
| 1096 | + return false; |
| 1097 | + } |
| 1098 | + // Close with timeout since jquery ui binds with timeout: |
| 1099 | + // ui dialog line 530 |
| 1100 | + setTimeout( function(){ |
| 1101 | + $j( '#mwTempLoaderDialog' ) |
| 1102 | + .dialog( 'destroy' ); |
| 1103 | + } , 10); |
| 1104 | + }; |
| 1105 | + |
| 1106 | + /** |
| 1107 | + * Add a (temporary) dialog window: |
| 1108 | + * |
| 1109 | + * @param {Object} |
| 1110 | + * with following keys: title: {String} Title string for the |
| 1111 | + * dialog content: {String} to be inserted in msg box buttons: |
| 1112 | + * {Object} A button object for the dialog Can be a string for |
| 1113 | + * the close button any jquery.ui.dialog option |
| 1114 | + */ |
| 1115 | + mw.addDialog = function ( options ) { |
| 1116 | + // Remove any other dialog |
| 1117 | + $j( '#mwTempLoaderDialog' ).remove(); |
| 1118 | + |
| 1119 | + if( !options){ |
| 1120 | + options = {}; |
| 1121 | + } |
| 1122 | + |
| 1123 | + // Extend the default options with provided options |
| 1124 | + var options = $j.extend({ |
| 1125 | + 'bgiframe': true, |
| 1126 | + 'draggable': true, |
| 1127 | + 'resizable': false, |
| 1128 | + 'modal': true, |
| 1129 | + 'position' : ['center', 'center'] |
| 1130 | + }, options ); |
| 1131 | + |
| 1132 | + if( ! options.title || ! options.content ){ |
| 1133 | + mw.log("Error: mwEmbed addDialog missing required options ( title, content ) "); |
| 1134 | + return ; |
| 1135 | + } |
| 1136 | + |
| 1137 | + // Append the dialog div on top: |
| 1138 | + $j( 'body' ).append( |
| 1139 | + $j('<div />') |
| 1140 | + .attr( { |
| 1141 | + 'id' : "mwTempLoaderDialog", |
| 1142 | + 'title' : options.title |
| 1143 | + }) |
| 1144 | + .hide() |
| 1145 | + .append( options.content ) |
| 1146 | + ); |
| 1147 | + |
| 1148 | + // Build the uiRequest |
| 1149 | + var uiRequest = [ '$j.ui.dialog' ]; |
| 1150 | + if( options.draggable ){ |
| 1151 | + uiRequest.push( '$j.ui.mouse' ); |
| 1152 | + uiRequest.push( '$j.ui.draggable' ); |
| 1153 | + } |
| 1154 | + if( options.resizable ){ |
| 1155 | + uiRequest.push( '$j.ui.resizable' ); |
| 1156 | + } |
| 1157 | + |
| 1158 | + // Special button string |
| 1159 | + if ( typeof options.buttons == 'string' ) { |
| 1160 | + var buttonMsg = options.buttons; |
| 1161 | + buttons = { }; |
| 1162 | + options.buttons[ buttonMsg ] = function() { |
| 1163 | + $j( this ).dialog( 'close' ); |
| 1164 | + }; |
| 1165 | + } |
| 1166 | + |
| 1167 | + // Load the dialog resources |
| 1168 | + mw.load([ |
| 1169 | + [ |
| 1170 | + '$j.ui', |
| 1171 | + '$j.widget', |
| 1172 | + '$j.ui.mouse', |
| 1173 | + '$j.ui.position' |
| 1174 | + ], |
| 1175 | + uiRequest |
| 1176 | + ], function() { |
| 1177 | + var $dialog = $j( '#mwTempLoaderDialog' ).show().dialog( options ); |
| 1178 | + } ); |
| 1179 | + return $j( '#mwTempLoaderDialog' ); |
| 1180 | + }; |
| 1181 | + |
| 1182 | + /** |
| 1183 | + * Similar to php isset function checks if the variable exists. Does a safe |
| 1184 | + * check of a descendant method or variable |
| 1185 | + * |
| 1186 | + * @param {String} |
| 1187 | + * objectPath |
| 1188 | + * @return {Boolean} true if objectPath exists false if objectPath is |
| 1189 | + * undefined |
| 1190 | + */ |
| 1191 | + mw.isset = function( objectPath ) { |
| 1192 | + if ( !objectPath || typeof objectPath != 'string') { |
| 1193 | + return false; |
| 1194 | + } |
| 1195 | + var pathSet = objectPath.split( '.' ); |
| 1196 | + var cur_path = ''; |
| 1197 | + |
| 1198 | + for ( var p = 0; p < pathSet.length; p++ ) { |
| 1199 | + cur_path = ( cur_path == '' ) ? cur_path + pathSet[p] : cur_path + '.' + pathSet[p]; |
| 1200 | + eval( 'var ptest = typeof ( ' + cur_path + ' ); ' ); |
| 1201 | + if ( ptest == 'undefined' ) { |
| 1202 | + return false; |
| 1203 | + } |
| 1204 | + } |
| 1205 | + return true; |
| 1206 | + }; |
| 1207 | + |
| 1208 | + /** |
| 1209 | + * Wait for a object to be defined and the call the callback |
| 1210 | + * |
| 1211 | + * @param {Object} |
| 1212 | + * objectName Name of object to be defined |
| 1213 | + * @param {Function} |
| 1214 | + * callback Function to call once object is defined |
| 1215 | + * @param {Null} |
| 1216 | + * callNumber Used internally to keep track of number of times |
| 1217 | + * waitForObject has been called |
| 1218 | + */ |
| 1219 | + var waitTime = 1200; // About 30 seconds |
| 1220 | + mw.waitForObject = function( objectName, callback, _callNumber) { |
| 1221 | + // mw.log( 'waitForObject: ' + objectName + ' cn: ' + _callNumber); |
| 1222 | + |
| 1223 | + // Increment callNumber: |
| 1224 | + if( !_callNumber ) { |
| 1225 | + _callNumber = 1; |
| 1226 | + } else { |
| 1227 | + _callNumber++; |
| 1228 | + } |
| 1229 | + |
| 1230 | + if( _callNumber > waitTime ) { |
| 1231 | + mw.log( "Error: waiting for object: " + objectName + ' timeout ' ); |
| 1232 | + callback( false ); |
| 1233 | + return ; |
| 1234 | + } |
| 1235 | + |
| 1236 | + // If the object is defined ( or we are done loading from a callback ) |
| 1237 | + if ( mw.isset( objectName ) || mwLoadDoneCB[ objectName ] == 'done' ) { |
| 1238 | + callback( objectName ); |
| 1239 | + }else{ |
| 1240 | + setTimeout( function( ) { |
| 1241 | + mw.waitForObject( objectName, callback, _callNumber); |
| 1242 | + }, 25); |
| 1243 | + } |
| 1244 | + }; |
| 1245 | + |
| 1246 | + /** |
| 1247 | + * Check if an object is empty or if its an empty string. |
| 1248 | + * |
| 1249 | + * @param {Object} |
| 1250 | + * object Object to be checked |
| 1251 | + */ |
| 1252 | + mw.isEmpty = function( object ) { |
| 1253 | + if( typeof object == 'string' ) { |
| 1254 | + if( object == '' ) return true; |
| 1255 | + // Non empty string: |
| 1256 | + return false; |
| 1257 | + } |
| 1258 | + |
| 1259 | + // If an array check length: |
| 1260 | + if( Object.prototype.toString.call( object ) === "[object Array]" |
| 1261 | + && object.length == 0 ) { |
| 1262 | + return true; |
| 1263 | + } |
| 1264 | + |
| 1265 | + // Else check as an object: |
| 1266 | + for( var i in object ) { return false; } |
| 1267 | + |
| 1268 | + // Else object is empty: |
| 1269 | + return true; |
| 1270 | + }; |
| 1271 | + |
| 1272 | + /** |
| 1273 | + * Log a string msg to the console |
| 1274 | + * |
| 1275 | + * all mw.log statements will be removed on minification so lots of mw.log |
| 1276 | + * calls will not impact performance in non debug mode |
| 1277 | + * |
| 1278 | + * @param {String} |
| 1279 | + * string String to output to console |
| 1280 | + */ |
| 1281 | + mw.log = function( string ) { |
| 1282 | + // Add any prepend debug strings if necessary |
| 1283 | + if ( mw.getConfig( 'Mw.LogPrepend' ) ){ |
| 1284 | + string = mw.getConfig( 'Mw.LogPrepend' ) + string; |
| 1285 | + } |
| 1286 | + // To debug stack size ( useful for iPad / safari that have a 100 call |
| 1287 | + // stack limit |
| 1288 | + // string = mw.getCallStack().length -1 + ' : ' + string; |
| 1289 | + |
| 1290 | + if ( window.console ) { |
| 1291 | + window.console.log( string ); |
| 1292 | + } else { |
| 1293 | + /** |
| 1294 | + * Old IE and non-Firebug debug: ( commented out for now ) |
| 1295 | + */ |
| 1296 | + |
| 1297 | + /* |
| 1298 | + * var log_elm = document.getElementById('mv_js_log'); if(!log_elm) { |
| 1299 | + * document.getElementsByTagName("body")[0].innerHTML += '<div ' + |
| 1300 | + * 'style="position:absolute;z-index:500;bottom:0px;left:0px;right:0px;height:200px;">' + '<textarea |
| 1301 | + * id="mv_js_log" cols="120" rows="12"></textarea>' + '</div>'; } |
| 1302 | + * var log_elm = document.getElementById('mv_js_log'); if(log_elm) { |
| 1303 | + * log_elm.value+=string+"\n"; // scroll to bottom: |
| 1304 | + * log_elm.scrollTop = log_elm.scrollHeight; } |
| 1305 | + */ |
| 1306 | + } |
| 1307 | + }; |
| 1308 | + mw.getCallStack = function(){ |
| 1309 | + var stringifyArguments = function(args) { |
| 1310 | + for (var i = 0; i < args.length; ++i) { |
| 1311 | + var arg = args[i]; |
| 1312 | + if (arg === undefined) { |
| 1313 | + args[i] = 'undefined'; |
| 1314 | + } else if (arg === null) { |
| 1315 | + args[i] = 'null'; |
| 1316 | + } else if (arg.constructor) { |
| 1317 | + if (arg.constructor === Array) { |
| 1318 | + if (arg.length < 3) { |
| 1319 | + args[i] = '[' + stringifyArguments(arg) + ']'; |
| 1320 | + } else { |
| 1321 | + args[i] = '[' + stringifyArguments(Array.prototype.slice.call(arg, 0, 1)) + '...' + stringifyArguments(Array.prototype.slice.call(arg, -1)) + ']'; |
| 1322 | + } |
| 1323 | + } else if (arg.constructor === Object) { |
| 1324 | + args[i] = '#object'; |
| 1325 | + } else if (arg.constructor === Function) { |
| 1326 | + args[i] = '#function'; |
| 1327 | + } else if (arg.constructor === String) { |
| 1328 | + args[i] = '"' + arg + '"'; |
| 1329 | + } |
| 1330 | + } |
| 1331 | + } |
| 1332 | + return args.join(','); |
| 1333 | + }; |
| 1334 | + var getStack = function(curr){ |
| 1335 | + var ANON = '{anonymous}', fnRE = /function\s*([\w\-$]+)?\s*\(/i, |
| 1336 | + stack = [], fn, args, maxStackSize = 100; |
| 1337 | + |
| 1338 | + while (curr && stack.length < maxStackSize) { |
| 1339 | + fn = fnRE.test(curr.toString()) ? RegExp.$1 || ANON : ANON; |
| 1340 | + args = Array.prototype.slice.call(curr['arguments']); |
| 1341 | + stack[stack.length] = fn + '(' + stringifyArguments(args) + ')'; |
| 1342 | + curr = curr.caller; |
| 1343 | + } |
| 1344 | + return stack; |
| 1345 | + } |
| 1346 | + // Add stack size ( iPad has 100 stack size limit ) |
| 1347 | + var stack = getStack( arguments.callee ); |
| 1348 | + return stack; |
| 1349 | + } |
| 1350 | + |
| 1351 | + // Setup the local mwOnLoadFunctions array: |
| 1352 | + var mwOnLoadFunctions = []; |
| 1353 | + |
| 1354 | + // mw Ready flag ( set once mwEmbed is ready ) |
| 1355 | + var mwReadyFlag = false; |
| 1356 | + |
| 1357 | + /** |
| 1358 | + * Enables load hooks to run once mwEmbeed is "ready" Will ensure jQuery is |
| 1359 | + * available, is in the $j namespace and mw interfaces and configuration has |
| 1360 | + * been loaded and applied |
| 1361 | + * |
| 1362 | + * This is different from jQuery(document).ready() ( jQuery ready is not |
| 1363 | + * friendly with dynamic includes and not friendly with core interface |
| 1364 | + * asynchronous build out. ) |
| 1365 | + * |
| 1366 | + * @param {Function} |
| 1367 | + * callback Function to run once DOM and jQuery are ready |
| 1368 | + */ |
| 1369 | + mw.ready = function( callback ) { |
| 1370 | + if( mwReadyFlag === false ) { |
| 1371 | + // Add the callbcak to the onLoad function stack |
| 1372 | + mwOnLoadFunctions.push ( callback ); |
| 1373 | + } else { |
| 1374 | + // If mwReadyFlag is already "true" issue the callback directly: |
| 1375 | + callback(); |
| 1376 | + } |
| 1377 | + }; |
| 1378 | + |
| 1379 | + /** |
| 1380 | + * Runs all the queued functions called by mwEmbedSetup |
| 1381 | + */ |
| 1382 | + mw.runReadyFunctions = function ( ) { |
| 1383 | + mw.log('mw.runReadyFunctions: ' + mwOnLoadFunctions.length ); |
| 1384 | + // Run any pre-setup ready functions |
| 1385 | + while( preMwEmbedReady.length ){ |
| 1386 | + preMwEmbedReady.shift()(); |
| 1387 | + } |
| 1388 | + // Run all the queued functions: |
| 1389 | + while( mwOnLoadFunctions.length ) { |
| 1390 | + mwOnLoadFunctions.shift()(); |
| 1391 | + } |
| 1392 | + // Sets mwReadyFlag to true so that future mw.ready run the |
| 1393 | + // callback directly |
| 1394 | + mwReadyFlag = true; |
| 1395 | + |
| 1396 | + // Once we have run all the queued functions |
| 1397 | + setTimeout(function(){ |
| 1398 | + mw.loader.runModuleLoadQueue(); |
| 1399 | + },1); |
| 1400 | + }; |
| 1401 | + |
| 1402 | + |
| 1403 | + /** |
| 1404 | + * Wrapper for jQuery getScript, Uses the scriptLoader if enabled |
| 1405 | + * |
| 1406 | + * |
| 1407 | + * @param {String} |
| 1408 | + * scriptRequest The requested path or resourceNames for the |
| 1409 | + * scriptLoader |
| 1410 | + * @param {Function} |
| 1411 | + * callback Function to call once script is loaded |
| 1412 | + */ |
| 1413 | + mw.getScript = function( scriptRequest, callback ) { |
| 1414 | + // mw.log( "mw.getScript::" + scriptRequest ); |
| 1415 | + // Setup the local scope callback instace |
| 1416 | + var myCallback = function(){ |
| 1417 | + if( callback ) { |
| 1418 | + callback( scriptRequest ); |
| 1419 | + } |
| 1420 | + }; |
| 1421 | + // Set the base url based scriptLoader availability & type of |
| 1422 | + // scriptRequest |
| 1423 | + // ( presently script loader only handles "classes" not relative urls: |
| 1424 | + var scriptLoaderPath = mw.getResourceLoaderPath(); |
| 1425 | + |
| 1426 | + // Check if its a resource name, ( ie does not start with "/" and does |
| 1427 | + // not include :// |
| 1428 | + var isResourceName = ( scriptRequest.indexOf('://') == -1 && scriptRequest.indexOf('/') !== 0 )? true : false; |
| 1429 | + |
| 1430 | + var ext = scriptRequest.substr( scriptRequest.lastIndexOf( '.' ), 4 ).toLowerCase(); |
| 1431 | + var isCssFile = ( ext == '.css') ? true : false ; |
| 1432 | + |
| 1433 | + if( scriptLoaderPath && isResourceName ) { |
| 1434 | + url = scriptLoaderPath + '?class=' + scriptRequest ; |
| 1435 | + } else { |
| 1436 | + // Add the mwEmbed path if a relative path request |
| 1437 | + url = ( isResourceName ) ? mw.getMwEmbedPath() : ''; |
| 1438 | + url+= scriptRequest; |
| 1439 | + } |
| 1440 | + |
| 1441 | + // Add on the request parameters to the url: |
| 1442 | + url += ( url.indexOf( '?' ) == -1 )? '?' : '&'; |
| 1443 | + url += mw.getUrlParam(); |
| 1444 | + |
| 1445 | + // Only log sciprts ( Css is logged via "add css" ) |
| 1446 | + if( !isCssFile ){ |
| 1447 | + mw.log( 'mw.getScript: ' + url ); |
| 1448 | + } |
| 1449 | + |
| 1450 | + // If jQuery is available and debug is off load the script via jQuery |
| 1451 | + // ( will use XHR if on same domain ) |
| 1452 | + if( mw.isset( 'window.jQuery' ) |
| 1453 | + && mw.getConfig( 'debug' ) === false |
| 1454 | + && typeof $j != 'undefined' |
| 1455 | + && mw.parseUri( url ).protocal != 'file' |
| 1456 | + && !isCssFile ) |
| 1457 | + { |
| 1458 | + $j.getScript( url, myCallback); |
| 1459 | + return ; |
| 1460 | + } |
| 1461 | + |
| 1462 | + /** |
| 1463 | + * No jQuery OR In debug mode OR Is css file :: inject the script |
| 1464 | + * instead of doing an XHR eval |
| 1465 | + */ |
| 1466 | + |
| 1467 | + // load style sheet directly if requested loading css |
| 1468 | + if( isCssFile ){ |
| 1469 | + mw.getStyleSheet( url, myCallback); |
| 1470 | + return ; |
| 1471 | + } |
| 1472 | + |
| 1473 | + // Load and bind manually: ( copied from jQuery ajax function ) |
| 1474 | + var head = document.getElementsByTagName("head")[ 0 ]; |
| 1475 | + var script = document.createElement("script"); |
| 1476 | + script.setAttribute( 'src', url ); |
| 1477 | + |
| 1478 | + // Attach handlers ( if using script loader it issues onDone callback as |
| 1479 | + // well ) |
| 1480 | + script.onload = script.onreadystatechange = function() { |
| 1481 | + if (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") { |
| 1482 | + myCallback(); |
| 1483 | + } |
| 1484 | + }; |
| 1485 | + // mw.log(" append script: " + script.src ); |
| 1486 | + // Append the script to the DOM: |
| 1487 | + head.appendChild( script ); |
| 1488 | + }; |
| 1489 | + |
| 1490 | + /** |
| 1491 | + * Add a style sheet string to the document head |
| 1492 | + * |
| 1493 | + * @param {String} |
| 1494 | + * cssResourceName Name of style sheet that has been defined |
| 1495 | + * @param {String} |
| 1496 | + * cssString Css Payload to be added to head of document |
| 1497 | + */ |
| 1498 | + mw.addStyleString = function( cssResourceName, cssString ) { |
| 1499 | + if( mw.style[ cssResourceName ] ) { |
| 1500 | + mw.log(" Style: ( " + cssResourceName + ' ) already set' ); |
| 1501 | + return true; |
| 1502 | + } |
| 1503 | + // Set the style to true ( to not request it again ) |
| 1504 | + mw.style[ cssResourceName ] = true; |
| 1505 | + // Add the spinner directly ( without jQuery in case we have to |
| 1506 | + // dynamically load jQuery ) |
| 1507 | + mw.log( 'Adding style:' + cssResourceName + " to dom " ); |
| 1508 | + var styleNode = document.createElement('style'); |
| 1509 | + styleNode.type = "text/css"; |
| 1510 | + // Use cssText or createTextNode depending on browser: |
| 1511 | + if( ( window.attachEvent && !window.opera ) ) { |
| 1512 | + styleNode.styleSheet.cssText = cssString; |
| 1513 | + } else { |
| 1514 | + var styleText = document.createTextNode( cssString ); |
| 1515 | + styleNode.appendChild( styleText ); |
| 1516 | + } |
| 1517 | + var head = document.getElementsByTagName("head")[0]; |
| 1518 | + head.appendChild( styleNode ); |
| 1519 | + }; |
| 1520 | + |
| 1521 | + /** |
| 1522 | + * Get a style sheet and append the style sheet to the DOM |
| 1523 | + * |
| 1524 | + * @param {Mixed} |
| 1525 | + * {String} url Url of the style sheet to be loaded {Function} |
| 1526 | + * callback Function called once sheet is ready |
| 1527 | + */ |
| 1528 | + mw.getStyleSheet = function( url , callback) { |
| 1529 | + // Add URL params ( if not already included ) |
| 1530 | + if ( url.indexOf( '?' ) == -1 ) { |
| 1531 | + url += '?' + mw.getUrlParam(); |
| 1532 | + } |
| 1533 | + |
| 1534 | + // Check if style sheet is already included: |
| 1535 | + var foundSheet = false; |
| 1536 | + $j( 'link' ).each( function() { |
| 1537 | + var currentSheet = $j( this) .attr( 'href' ); |
| 1538 | + var sheetParts = currentSheet.split('?'); |
| 1539 | + var urlParts = url.split('?'); |
| 1540 | + // if the base url's match check the parameters: |
| 1541 | + if( sheetParts[0] == urlParts[0] && sheetParts[1]) { |
| 1542 | + // Check if url params match ( sort to do string compare ) |
| 1543 | + if( sheetParts[1].split( '&' ).sort().join('') == |
| 1544 | + urlParts[1].split('&').sort().join('') ) { |
| 1545 | + foundSheet = true; |
| 1546 | + } |
| 1547 | + } |
| 1548 | + } ); |
| 1549 | + if( foundSheet ) { |
| 1550 | + mw.log( 'skiped sheet: ' + url); |
| 1551 | + if( callback) { |
| 1552 | + callback(); |
| 1553 | + } |
| 1554 | + return ; |
| 1555 | + } |
| 1556 | + |
| 1557 | + mw.log( ' add css: ' + url ); |
| 1558 | + $j( 'head' ).append( |
| 1559 | + $j('<link />').attr( { |
| 1560 | + 'rel' : 'stylesheet', |
| 1561 | + 'type' : 'text/css', |
| 1562 | + 'href' : url |
| 1563 | + } ) |
| 1564 | + ); |
| 1565 | + // No easy way to check css "onLoad" attribute |
| 1566 | + // In production sheets are loaded via resource loader and fire the |
| 1567 | + // onDone function call. |
| 1568 | + if( callback ) { |
| 1569 | + callback(); |
| 1570 | + } |
| 1571 | + }; |
| 1572 | + |
| 1573 | + mw.getRelativeMwEmbedPath = function(){ |
| 1574 | + return mw.getMwEmbedPath(true); |
| 1575 | + }; |
| 1576 | + /** |
| 1577 | + * Get the path to the mwEmbed folder |
| 1578 | + */ |
| 1579 | + mw.getMwEmbedPath = function( relativePath ) { |
| 1580 | + // Get mwEmbed src: |
| 1581 | + var src = mw.getMwEmbedSrc(); |
| 1582 | + var mwpath = null; |
| 1583 | + |
| 1584 | + // Check for direct include of the mwEmbed.js |
| 1585 | + if ( src.indexOf( 'mwEmbed.js' ) !== -1 ) { |
| 1586 | + alert( 'Direct Refrece to mwEmbed is no longer suported, please update to ResourceLoader.php?class=window.jQuery,mwEmbed& instead'); |
| 1587 | + mwpath = src.substr( 0, src.indexOf( 'mwEmbed.js' ) ); |
| 1588 | + } |
| 1589 | + |
| 1590 | + // Check for scriptLoader include of mwEmbed: |
| 1591 | + if ( src.indexOf( 'mwResourceLoader.php' ) !== -1 ) { |
| 1592 | + // Script loader is in the root of MediaWiki, Include the default |
| 1593 | + // mwEmbed extension path: |
| 1594 | + mwpath = src.substr( 0, src.indexOf( 'mwResourceLoader.php' ) ) + mw.getConfig( 'mediaWikiEmbedPath' ); |
| 1595 | + } |
| 1596 | + |
| 1597 | + // resource loader has ResourceLoader name when local: |
| 1598 | + if( src.indexOf( 'ResourceLoader.php' ) !== -1 ) { |
| 1599 | + mwpath = src.substr( 0, src.indexOf( 'ResourceLoader.php' ) ); |
| 1600 | + } |
| 1601 | + |
| 1602 | + // For static packages mwEmbed packages start with: "mwEmbed-" |
| 1603 | + if( src.indexOf( 'mwEmbed-' ) !== -1 && src.indexOf( '-static' ) !== -1 ) { |
| 1604 | + mwpath = src.substr( 0, src.indexOf( 'mwEmbed-' ) ); |
| 1605 | + } |
| 1606 | + |
| 1607 | + // Error out if we could not get the path: |
| 1608 | + if( mwpath === null ) { |
| 1609 | + mw.log( "Error could not get mwEmbed path " ); |
| 1610 | + return ; |
| 1611 | + } |
| 1612 | + |
| 1613 | + // Update the cached var with the absolute path: |
| 1614 | + if( !relativePath ){ |
| 1615 | + mwpath = mw.absoluteUrl( mwpath ) ; |
| 1616 | + } |
| 1617 | + return mwpath; |
| 1618 | + }; |
| 1619 | + |
| 1620 | + /** |
| 1621 | + * Get Script loader path |
| 1622 | + * |
| 1623 | + * @returns {String}|{Boolean} Url of the scriptLodaer false if the |
| 1624 | + * scriptLoader is not used |
| 1625 | + */ |
| 1626 | + mw.getResourceLoaderPath = function( ) { |
| 1627 | + var src = mw.getMwEmbedSrc(); |
| 1628 | + if ( src.indexOf( 'mwResourceLoader.php' ) !== -1 || |
| 1629 | + src.indexOf( 'ResourceLoader.php' ) !== -1 ) |
| 1630 | + { |
| 1631 | + // Return just the script part of the url |
| 1632 | + return src.split('?')[0]; |
| 1633 | + } |
| 1634 | + return false; |
| 1635 | + }; |
| 1636 | + /** |
| 1637 | + * Given a float number of seconds, returns npt format response. ( ignore |
| 1638 | + * days for now ) |
| 1639 | + * |
| 1640 | + * @param {Float} |
| 1641 | + * sec Seconds |
| 1642 | + * @param {Boolean} |
| 1643 | + * verbose If hours and milliseconds should padded be displayed. |
| 1644 | + * @return {Float} String npt format |
| 1645 | + */ |
| 1646 | + mw.seconds2npt = function( sec, verbose ) { |
| 1647 | + if ( isNaN( sec ) ) { |
| 1648 | + mw.log("Warning: trying to get npt time on NaN:" + sec); |
| 1649 | + return '0:00:00'; |
| 1650 | + } |
| 1651 | + |
| 1652 | + var tm = mw.seconds2Measurements( sec ); |
| 1653 | + |
| 1654 | + // Round the number of seconds to the required number of significant |
| 1655 | + // digits |
| 1656 | + if ( verbose ) { |
| 1657 | + tm.seconds = Math.round( tm.seconds * 1000 ) / 1000; |
| 1658 | + } else { |
| 1659 | + tm.seconds = Math.round( tm.seconds ); |
| 1660 | + } |
| 1661 | + if ( tm.seconds < 10 ){ |
| 1662 | + tm.seconds = '0' + tm.seconds; |
| 1663 | + } |
| 1664 | + if( tm.hours == 0 && !verbose ){ |
| 1665 | + hoursStr = ''; |
| 1666 | + } else { |
| 1667 | + if ( tm.minutes < 10 && verbose) { |
| 1668 | + tm.minutes = '0' + tm.minutes; |
| 1669 | + } |
| 1670 | + |
| 1671 | + if( tm.hours < 10 && verbose){ |
| 1672 | + tm.hours = '0' + tm.hours; |
| 1673 | + } |
| 1674 | + |
| 1675 | + hoursStr = tm.hours + ':'; |
| 1676 | + } |
| 1677 | + return hoursStr + tm.minutes + ":" + tm.seconds; |
| 1678 | + }; |
| 1679 | + /** |
| 1680 | + * Given seconds return array with 'days', 'hours', 'min', 'seconds' |
| 1681 | + * |
| 1682 | + * @param {float} |
| 1683 | + * sec Seconds to be converted into time measurements |
| 1684 | + */ |
| 1685 | + mw.seconds2Measurements = function ( sec ){ |
| 1686 | + var tm = {}; |
| 1687 | + tm.days = Math.floor( sec / ( 3600 * 24 ) ); |
| 1688 | + tm.hours = Math.floor( sec / 3600 ); |
| 1689 | + tm.minutes = Math.floor( ( sec / 60 ) % 60 ); |
| 1690 | + tm.seconds = sec % 60; |
| 1691 | + return tm; |
| 1692 | + }; |
| 1693 | + |
| 1694 | + /** |
| 1695 | + * Given a float number of seconds, returns npt format response. ( ignore |
| 1696 | + * days for now ) |
| 1697 | + * |
| 1698 | + * @param {Float} |
| 1699 | + * sec Seconds |
| 1700 | + * @param {Boolean} |
| 1701 | + * verbose If hours and milliseconds should padded be displayed. |
| 1702 | + * @return {Float} String npt format |
| 1703 | + */ |
| 1704 | + mw.npt2seconds = function ( npt_str ) { |
| 1705 | + if ( !npt_str ) { |
| 1706 | + // mw.log('npt2seconds:not valid ntp:'+ntp); |
| 1707 | + return false; |
| 1708 | + } |
| 1709 | + // Strip {npt:}01:02:20 or 32{s} from time if present |
| 1710 | + npt_str = npt_str.replace( /npt:|s/g, '' ); |
| 1711 | + |
| 1712 | + var hour = 0; |
| 1713 | + var min = 0; |
| 1714 | + var sec = 0; |
| 1715 | + |
| 1716 | + times = npt_str.split( ':' ); |
| 1717 | + if ( times.length == 3 ) { |
| 1718 | + sec = times[2]; |
| 1719 | + min = times[1]; |
| 1720 | + hour = times[0]; |
| 1721 | + } else if ( times.length == 2 ) { |
| 1722 | + sec = times[1]; |
| 1723 | + min = times[0]; |
| 1724 | + } else { |
| 1725 | + sec = times[0]; |
| 1726 | + } |
| 1727 | + // Sometimes a comma is used instead of period for ms |
| 1728 | + sec = sec.replace( /,\s?/, '.' ); |
| 1729 | + // Return seconds float |
| 1730 | + return parseInt( hour * 3600 ) + parseInt( min * 60 ) + parseFloat( sec ); |
| 1731 | + }; |
| 1732 | + |
| 1733 | + // Local mwEmbedSrc variable ( for cache of mw.getMwEmbedSrc ) |
| 1734 | + var mwEmbedSrc = null; |
| 1735 | + |
| 1736 | + /** |
| 1737 | + * Gets the mwEmbed script src attribute |
| 1738 | + */ |
| 1739 | + mw.getMwEmbedSrc = function() { |
| 1740 | + if ( mwEmbedSrc ) { |
| 1741 | + return mwEmbedSrc; |
| 1742 | + } |
| 1743 | + |
| 1744 | + // Get all the javascript includes: |
| 1745 | + var js_elements = document.getElementsByTagName( "script" ); |
| 1746 | + for ( var i = 0; i < js_elements.length; i++ ) { |
| 1747 | + // Check for mwEmbed.js and/or script loader |
| 1748 | + var src = js_elements[i].getAttribute( "src" ); |
| 1749 | + if ( src ) { |
| 1750 | + if ( // Check for mwEmbed.js ( debug mode ) |
| 1751 | + ( src.indexOf( 'mwEmbed.js' ) !== -1 && src.indexOf( 'MediaWiki:Gadget') == -1 ) |
| 1752 | + || // Check for resource loader |
| 1753 | + ( |
| 1754 | + ( src.indexOf( 'mwResourceLoader.php' ) !== -1 || src.indexOf( 'ResourceLoader.php' ) !== -1 ) |
| 1755 | + && |
| 1756 | + src.indexOf( 'mwEmbed' ) !== -1 |
| 1757 | + ) |
| 1758 | + || // Check for static mwEmbed package |
| 1759 | + ( src.indexOf( 'mwEmbed' ) !== -1 && src.indexOf( 'static' ) !== -1 ) |
| 1760 | + ) { |
| 1761 | + mwEmbedSrc = src; |
| 1762 | + return mwEmbedSrc; |
| 1763 | + } |
| 1764 | + } |
| 1765 | + } |
| 1766 | + mw.log( 'Error: getMwEmbedSrc failed to get script path' ); |
| 1767 | + return false; |
| 1768 | + }; |
| 1769 | + |
| 1770 | + // Local mwUrlParam variable ( for cache of mw.getUrlParam ) |
| 1771 | + var mwUrlParam = null; |
| 1772 | + |
| 1773 | + /** |
| 1774 | + * Get URL Parameters per parameters in the host script include |
| 1775 | + */ |
| 1776 | + mw.getUrlParam = function() { |
| 1777 | + if ( mwUrlParam ) { |
| 1778 | + return mwUrlParam; |
| 1779 | + } |
| 1780 | + |
| 1781 | + var mwEmbedSrc = mw.getMwEmbedSrc(); |
| 1782 | + var req_param = ''; |
| 1783 | + |
| 1784 | + // If we already have a URI, add it to the param request: |
| 1785 | + var urid = mw.parseUri( mwEmbedSrc ).queryKey['urid']; |
| 1786 | + |
| 1787 | + // If we're in debug mode, get a fresh unique request key and pass on |
| 1788 | + // "debug" param |
| 1789 | + if ( mw.parseUri( mwEmbedSrc ).queryKey['debug'] == 'true' ) { |
| 1790 | + mw.setConfig( 'debug', true ); |
| 1791 | + var d = new Date(); |
| 1792 | + req_param += 'urid=' + d.getTime() + '&debug=true'; |
| 1793 | + |
| 1794 | + } else if ( urid ) { |
| 1795 | + // Just pass on the existing urid: |
| 1796 | + req_param += 'urid=' + urid; |
| 1797 | + } else { |
| 1798 | + // Otherwise, Use the mwEmbed version |
| 1799 | + req_param += 'urid=' + mw.version; |
| 1800 | + } |
| 1801 | + |
| 1802 | + // Add the language param if present: |
| 1803 | + var langKey = mw.parseUri( mwEmbedSrc ).queryKey['uselang']; |
| 1804 | + if ( langKey ) |
| 1805 | + req_param += '&uselang=' + langKey; |
| 1806 | + |
| 1807 | + // Update the local cache and return the value |
| 1808 | + mwUrlParam = req_param; |
| 1809 | + return mwUrlParam; |
| 1810 | + }; |
| 1811 | + |
| 1812 | + /** |
| 1813 | + * Replace url parameters via newParams key value pairs |
| 1814 | + * |
| 1815 | + * @param {String} |
| 1816 | + * url Source url to be updated |
| 1817 | + * @param {Object} |
| 1818 | + * newParams key, value paris to swap in |
| 1819 | + * @return {String} the updated url |
| 1820 | + */ |
| 1821 | + mw.replaceUrlParams = function( url, newParams ) { |
| 1822 | + var parsedUrl = mw.parseUri( url ); |
| 1823 | + |
| 1824 | + if ( parsedUrl.protocol != '' ) { |
| 1825 | + var new_url = parsedUrl.protocol + '://' + parsedUrl.authority + parsedUrl.path + '?'; |
| 1826 | + } else { |
| 1827 | + var new_url = parsedUrl.path + '?'; |
| 1828 | + } |
| 1829 | + |
| 1830 | + // Merge new params: |
| 1831 | + for( var key in newParams ) { |
| 1832 | + parsedUrl.queryKey[ key ] = newParams[ key ]; |
| 1833 | + } |
| 1834 | + |
| 1835 | + // Output to new_url |
| 1836 | + var amp = ''; |
| 1837 | + for ( var key in parsedUrl.queryKey ) { |
| 1838 | + var val = parsedUrl.queryKey[ key ]; |
| 1839 | + new_url += amp + key + '=' + val; |
| 1840 | + amp = '&'; |
| 1841 | + } |
| 1842 | + return new_url; |
| 1843 | + }; |
| 1844 | + |
| 1845 | + /** |
| 1846 | + * parseUri 1.2.2 (c) Steven Levithan <stevenlevithan.com> MIT License |
| 1847 | + */ |
| 1848 | + mw.parseUri = function (str) { |
| 1849 | + var o = mw.parseUri.options, |
| 1850 | + m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), |
| 1851 | + uri = {}, |
| 1852 | + i = 14; |
| 1853 | + |
| 1854 | + while (i--) uri[o.key[i]] = m[i] || ""; |
| 1855 | + |
| 1856 | + uri[o.q.name] = {}; |
| 1857 | + uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { |
| 1858 | + if ($1) uri[o.q.name][$1] = $2; |
| 1859 | + }); |
| 1860 | + |
| 1861 | + return uri; |
| 1862 | + }; |
| 1863 | + |
| 1864 | + /** |
| 1865 | + * Parse URI function |
| 1866 | + * |
| 1867 | + * For documentation on its usage see: |
| 1868 | + * http://stevenlevithan.com/demo/parseuri/js/ |
| 1869 | + */ |
| 1870 | + mw.parseUri.options = { |
| 1871 | + strictMode: false, |
| 1872 | + key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", |
| 1873 | + "port", "relative", "path", "directory", "file", "query", "anchor"], |
| 1874 | + q: { |
| 1875 | + name: "queryKey", |
| 1876 | + parser: /(?:^|&)([^&=]*)=?([^&]*)/g |
| 1877 | + }, |
| 1878 | + parser: { |
| 1879 | + strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, |
| 1880 | + loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ |
| 1881 | + } |
| 1882 | + }; |
| 1883 | + |
| 1884 | + /** |
| 1885 | + * getAbsoluteUrl takes a src and returns the absolute location given the |
| 1886 | + * document.URL or a contextUrl param |
| 1887 | + * |
| 1888 | + * @param {String} |
| 1889 | + * src path or url |
| 1890 | + * @param {String} |
| 1891 | + * contextUrl The domain / context for creating an absolute url |
| 1892 | + * from a relative path |
| 1893 | + * @return {String} absolute url |
| 1894 | + */ |
| 1895 | +mw.absoluteUrl = function( src, contextUrl ) { |
| 1896 | + |
| 1897 | + var parsedSrc = mw.parseUri( src ); |
| 1898 | + |
| 1899 | + // Source is already absolute return: |
| 1900 | + if( parsedSrc.protocol != '') { |
| 1901 | + return src; |
| 1902 | + } |
| 1903 | + |
| 1904 | + // Get parent Url location the context URL |
| 1905 | + if( !contextUrl ) { |
| 1906 | + contextUrl = document.URL; |
| 1907 | + } |
| 1908 | + var parsedUrl = mw.parseUri( contextUrl ); |
| 1909 | + |
| 1910 | + // Check for IE local file that does not flip the slashes |
| 1911 | + if( parsedUrl.directory == '' && parsedUrl.protocol == 'file' ){ |
| 1912 | + // pop off the file |
| 1913 | + var fileUrl = contextUrl.split( '\\'); |
| 1914 | + fileUrl.pop(); |
| 1915 | + return fileUrl.join('\\') + '\\' + src; |
| 1916 | + } |
| 1917 | + |
| 1918 | + // Check for leading slash: |
| 1919 | + if( src.indexOf( '/' ) === 0 ) { |
| 1920 | + return parsedUrl.protocol + '://' + parsedUrl.authority + src; |
| 1921 | + }else{ |
| 1922 | + return parsedUrl.protocol + '://' + parsedUrl.authority + parsedUrl.directory + src; |
| 1923 | + } |
| 1924 | + }; |
| 1925 | + /** |
| 1926 | + * Check if a given source string is likely a url |
| 1927 | + * |
| 1928 | + * @return {boolean} true if a url false if a string |
| 1929 | + */ |
| 1930 | + mw.isUrl = function( src ){ |
| 1931 | + var parsedSrc = mw.parseUri( src ); |
| 1932 | + // if the url is just a string source and host will match |
| 1933 | + return ( parsedSrc.host != parsedSrc.source ); |
| 1934 | + }; |
| 1935 | + |
| 1936 | + /** |
| 1937 | + * Escape quotes in a text string |
| 1938 | + * |
| 1939 | + * @param {String} |
| 1940 | + * text String to be escaped |
| 1941 | + * @return {string} escaped text string |
| 1942 | + */ |
| 1943 | + mw.escapeQuotes = function( text ) { |
| 1944 | + var re = new RegExp("'","g"); |
| 1945 | + text = text.replace(re,"\\'"); |
| 1946 | + re = new RegExp("\\n","g"); |
| 1947 | + text = text.replace(re,"\\n"); |
| 1948 | + return mw.escapeQuotesHTML(text); |
| 1949 | + }; |
| 1950 | + |
| 1951 | + /** |
| 1952 | + * Escape an HTML text string |
| 1953 | + * |
| 1954 | + * @param {String} |
| 1955 | + * text String to be escaped |
| 1956 | + * @return {string} escaped text html string |
| 1957 | + */ |
| 1958 | + mw.escapeQuotesHTML = function( text ) { |
| 1959 | + var replaceMap = { |
| 1960 | + "&" : "&", |
| 1961 | + '"' : """, |
| 1962 | + '<' : "<", |
| 1963 | + '>' : ">" |
| 1964 | + }; |
| 1965 | + for( var i in replaceMap ){ |
| 1966 | + text = text.split(i).join( replaceMap[i]); |
| 1967 | + } |
| 1968 | + return text; |
| 1969 | + }; |
| 1970 | + |
| 1971 | + |
| 1972 | + // Array of setup functions |
| 1973 | + var mwSetupFunctions = []; |
| 1974 | + |
| 1975 | + /** |
| 1976 | + * Add a function to be run during setup ( prior to mw.ready) this is useful |
| 1977 | + * for building out interfaces that should be ready before mw.ready is |
| 1978 | + * called. |
| 1979 | + * |
| 1980 | + * @param {callback} |
| 1981 | + * Function Callback function must accept a ready function |
| 1982 | + * callback to be called once setup is done |
| 1983 | + */ |
| 1984 | + mw.addSetupHook = function( callback ) { |
| 1985 | + mwSetupFunctions.push ( callback ) ; |
| 1986 | + }; |
| 1987 | + |
| 1988 | + /** |
| 1989 | + * One time "setup" for mwEmbed run onDomReady ( so calls to setConfg apply |
| 1990 | + * to setup ) |
| 1991 | + */ |
| 1992 | + // Flag to ensure setup is only run once: |
| 1993 | + var mwSetupFlag = false; |
| 1994 | + mw.setupMwEmbed = function ( ) { |
| 1995 | + // Only run the setup once: |
| 1996 | + if( mwSetupFlag ) { |
| 1997 | + return ; |
| 1998 | + } |
| 1999 | + mwSetupFlag = true; |
| 2000 | + |
| 2001 | + mw.log( 'mw:setupMwEmbed SRC:: ' + mw.getMwEmbedSrc() ); |
| 2002 | + |
| 2003 | + // Check core mwEmbed loader.js file ( to get configuration and paths ) |
| 2004 | + mw.checkCoreLoaderFile( function(){ |
| 2005 | + // Make sure we have jQuery |
| 2006 | + mw.load( 'window.jQuery', function() { |
| 2007 | + |
| 2008 | + // Add jQuery to $j var. |
| 2009 | + if ( ! window[ '$j' ] ) { |
| 2010 | + window[ '$j' ] = jQuery.noConflict(); |
| 2011 | + } |
| 2012 | + |
| 2013 | + // Set up mvEmbed utility jQuery bindings |
| 2014 | + mw.dojQueryBindings(); |
| 2015 | + |
| 2016 | + // Setup user config: |
| 2017 | + mw.setupUserConfig( function(){ |
| 2018 | + // Get module loader.js, and language files |
| 2019 | + // ( will hit callback directly if set via resource loader ) |
| 2020 | + mw.checkModuleLoaderFiles( function() { |
| 2021 | + |
| 2022 | + // Set the User language |
| 2023 | + if( typeof wgUserLanguage != 'undefined' && mw.isValidLang( wgUserLanguage) ) { |
| 2024 | + mw.setConfig( 'userLanguage', wgUserLanguage ); |
| 2025 | + }else{ |
| 2026 | + // Grab it from the included url |
| 2027 | + var langKey = mw.parseUri( mw.getMwEmbedSrc() ).queryKey['uselang']; |
| 2028 | + if ( langKey && mw.isValidLang( langKey ) ) { |
| 2029 | + mw.setConfig( 'userLanguage', langKey); |
| 2030 | + } |
| 2031 | + } |
| 2032 | + |
| 2033 | + // Update the image path |
| 2034 | + mw.setConfig( 'imagesPath', mw.getMwEmbedPath() + 'skins/common/images/' ); |
| 2035 | + |
| 2036 | + // Set up AJAX to not send dynamic URLs for loading |
| 2037 | + // scripts |
| 2038 | + $j.ajaxSetup( { |
| 2039 | + cache: true |
| 2040 | + } ); |
| 2041 | + |
| 2042 | + // Update the magic keywords |
| 2043 | + mw.Language.magicSetup(); |
| 2044 | + |
| 2045 | + |
| 2046 | + // Special Hack for conditional jquery ui inclusion ( |
| 2047 | + // once |
| 2048 | + // Usability extension |
| 2049 | + // registers the jquery.ui skin in mw.style |
| 2050 | + if( mw.hasJQueryUiCss() ){ |
| 2051 | + mw.style[ 'ui_' + mw.getConfig( 'jQueryUISkin' ) ] = true; |
| 2052 | + } |
| 2053 | + |
| 2054 | + |
| 2055 | + // Make sure style sheets are loaded: |
| 2056 | + mw.load( ['mw.style.mwCommon'] , function(){ |
| 2057 | + // Run all the setup function hooks |
| 2058 | + // NOTE: setup functions are added via addSetupHook |
| 2059 | + // calls |
| 2060 | + // and must include a callback. |
| 2061 | + // |
| 2062 | + // Once complete we can run .ready() queued |
| 2063 | + // functions |
| 2064 | + function runSetupFunctions() { |
| 2065 | + if( mwSetupFunctions.length ) { |
| 2066 | + mwSetupFunctions.shift()( function() { |
| 2067 | + runSetupFunctions(); |
| 2068 | + } ); |
| 2069 | + }else{ |
| 2070 | + mw.runReadyFunctions(); |
| 2071 | + } |
| 2072 | + } |
| 2073 | + runSetupFunctions(); |
| 2074 | + } ); |
| 2075 | + |
| 2076 | + } ); |
| 2077 | + }); |
| 2078 | + }); |
| 2079 | + }); |
| 2080 | + }; |
| 2081 | + |
| 2082 | + /** |
| 2083 | + * Checks for jquery ui css by name jquery-ui-1.7.2.css NOTE: this is a hack |
| 2084 | + * for usability jquery-ui in the future usability should register a |
| 2085 | + * resource in mw.skin |
| 2086 | + * |
| 2087 | + * @return true if found, return false if not found |
| 2088 | + */ |
| 2089 | + mw.hasJQueryUiCss = function(){ |
| 2090 | + var hasUiCss = false; |
| 2091 | + var cssStyleSheetNames = ['jquery-ui-1.7.2.css', 'jquery-ui.css']; |
| 2092 | + // Load the jQuery ui skin if usability skin not set |
| 2093 | + $j( 'link' ).each( function( na, linkNode ){ |
| 2094 | + $j.each( cssStyleSheetNames, function(inx, sheetName ){ |
| 2095 | + if( $j( linkNode ).attr( 'href' ).indexOf( sheetName ) != -1 ){ |
| 2096 | + hasUiCss = true; |
| 2097 | + return true; |
| 2098 | + } |
| 2099 | + }); |
| 2100 | + } ); |
| 2101 | + // Check all the "style" nodes for @import for sheet name |
| 2102 | + // xxx Note: we could do this a bit cleaner with regEx |
| 2103 | + $j( 'style' ).each( function( na, styleNode ){ |
| 2104 | + $j.each( cssStyleSheetNames, function(inx, sheetName ){ |
| 2105 | + if( $j( styleNode ).text().indexOf( '@import' ) != -1 |
| 2106 | + && |
| 2107 | + $j( styleNode ).text().indexOf( sheetName ) != -1 ) |
| 2108 | + { |
| 2109 | + hasUiCss=true; |
| 2110 | + return true; |
| 2111 | + } |
| 2112 | + }); |
| 2113 | + }); |
| 2114 | + return hasUiCss; |
| 2115 | + }; |
| 2116 | + |
| 2117 | + /** |
| 2118 | + * Loads the core mwEmbed "loader.js" file config |
| 2119 | + * |
| 2120 | + * NOTE: if using the ScriptLoader all the loaders and localization |
| 2121 | + * converters are included automatically |
| 2122 | + * |
| 2123 | + * @param {Function} |
| 2124 | + * callback Function called once core loader file is loaded |
| 2125 | + */ |
| 2126 | + mw.checkCoreLoaderFile = function( callback ) { |
| 2127 | + // Check if we are using scriptloader ( handles loader include |
| 2128 | + // automatically ) |
| 2129 | + if( mw.getResourceLoaderPath() ) { |
| 2130 | + callback(); |
| 2131 | + return ; |
| 2132 | + } |
| 2133 | + |
| 2134 | + // Check if we are using a static package ( mwEmbed path includes |
| 2135 | + // -static ) |
| 2136 | + if( mw.isStaticPackge() ){ |
| 2137 | + callback(); |
| 2138 | + return ; |
| 2139 | + } |
| 2140 | + |
| 2141 | + // Add the Core loader to the request |
| 2142 | + // The follow code is ONLY RUN in debug / raw file mode |
| 2143 | + mw.load( 'loader.js', callback ); |
| 2144 | + }; |
| 2145 | + |
| 2146 | + /** |
| 2147 | + * Checks if the javascript is a static package ( not using resource loader ) |
| 2148 | + * |
| 2149 | + * @return {boolean} true the included script is static false the included |
| 2150 | + * script |
| 2151 | + */ |
| 2152 | + mw.isStaticPackge = function(){ |
| 2153 | + var src = mw.getMwEmbedSrc(); |
| 2154 | + if( src.indexOf('-static') !== -1 ){ |
| 2155 | + return true; |
| 2156 | + } |
| 2157 | + return false; |
| 2158 | + }; |
| 2159 | + |
| 2160 | + /** |
| 2161 | + * Check for resource loader module loaders, and localization files |
| 2162 | + * |
| 2163 | + * NOTE: if using the ScriptLoader all the loaders and localization |
| 2164 | + * converters are included automatically. |
| 2165 | + */ |
| 2166 | + mw.checkModuleLoaderFiles = function( callback ) { |
| 2167 | + mw.log( 'doLoaderCheck::' ); |
| 2168 | + |
| 2169 | + // Check if we are using scriptloader ( handles loader include |
| 2170 | + // automatically ) |
| 2171 | + // Or if mwEmbed is a static package ( all resources are already loaded |
| 2172 | + // ) |
| 2173 | + if( mw.getResourceLoaderPath() || mw.isStaticPackge() ) { |
| 2174 | + callback(); |
| 2175 | + return ; |
| 2176 | + } |
| 2177 | + |
| 2178 | + // Load the configured modules / components |
| 2179 | + // The follow code is ONLY RUN in debug / raw file mode |
| 2180 | + var loaderRequest = []; |
| 2181 | + |
| 2182 | + // Load enabled components |
| 2183 | + var enabledComponents = mw.getConfig( 'coreComponents' ); |
| 2184 | + function loadEnabledComponents( enabledComponents ){ |
| 2185 | + if( ! enabledComponents.length ){ |
| 2186 | + // If no more components load modules:: |
| 2187 | + |
| 2188 | + // Add the enabledModules loaders: |
| 2189 | + var enabledModules = mw.getConfig( 'enabledModules' ); |
| 2190 | + loadEnabledModules( enabledModules ); |
| 2191 | + return ; |
| 2192 | + } |
| 2193 | + var componentName = enabledComponents.shift(); |
| 2194 | + componentName = componentName.replace(/"/g,''); |
| 2195 | + mw.load( componentName, function(){ |
| 2196 | + loadEnabledComponents( enabledComponents ); |
| 2197 | + } ); |
| 2198 | + } |
| 2199 | + loadEnabledComponents( enabledComponents ); |
| 2200 | + |
| 2201 | + |
| 2202 | + // Set the loader context and get each loader individually |
| 2203 | + function loadEnabledModules( enabledModules ){ |
| 2204 | + if( ! enabledModules.length ){ |
| 2205 | + // If no more modules left load the LanguageFile |
| 2206 | + addLanguageFile(); |
| 2207 | + return ; |
| 2208 | + } |
| 2209 | + var moduleName = enabledModules.shift(); |
| 2210 | + moduleName = moduleName.replace(/"/g,''); |
| 2211 | + mw.setConfig( 'loaderContext', 'modules/' + moduleName + '/' ); |
| 2212 | + mw.load( 'modules/' + moduleName + '/loader.js', function(){ |
| 2213 | + loadEnabledModules( enabledModules ); |
| 2214 | + } ); |
| 2215 | + } |
| 2216 | + |
| 2217 | + function addLanguageFile(){ |
| 2218 | + // Add the language file |
| 2219 | + var langLoaderRequest = []; |
| 2220 | + |
| 2221 | + if( mw.getConfig( 'userLanguage' ) ) { |
| 2222 | + var langCode = mw.getConfig( 'userLanguage' ); |
| 2223 | + |
| 2224 | + // Load the language resource if not default 'en' |
| 2225 | + var transformKey = mw.getLangTransformKey( langCode ); |
| 2226 | + if( transformKey != 'en' ){ |
| 2227 | + // Upper case the first letter: |
| 2228 | + langCode = langCode.substr(0,1).toUpperCase() + langCode.substr( 1, langCode.length ); |
| 2229 | + langLoaderRequest.push( 'languages/classes/Language' + |
| 2230 | + langCode + '.js' ); |
| 2231 | + } |
| 2232 | + |
| 2233 | + } |
| 2234 | + if ( ! langLoaderRequest.length ) { |
| 2235 | + addLocalSettings(); |
| 2236 | + return ; |
| 2237 | + } |
| 2238 | + |
| 2239 | + // Load the language if set |
| 2240 | + mw.load( langLoaderRequest, function(){ |
| 2241 | + mw.log( 'Done moduleLoaderCheck request' ); |
| 2242 | + addLocalSettings(); |
| 2243 | + } ); |
| 2244 | + } |
| 2245 | + function addLocalSettings(){ |
| 2246 | + var continueCallback = function(){ |
| 2247 | + // Set the mwModuleLoaderCheckFlag flag to true |
| 2248 | + mwModuleLoaderCheckFlag = true; |
| 2249 | + callback(); |
| 2250 | + }; |
| 2251 | + if( mw.getConfig( 'LoadLocalSettings') != true ){ |
| 2252 | + continueCallback(); |
| 2253 | + return; |
| 2254 | + } |
| 2255 | + mw.log("Load loacal settings"); |
| 2256 | + mw.load( 'localSettings.js', function(){ |
| 2257 | + continueCallback(); |
| 2258 | + }); |
| 2259 | + } |
| 2260 | + |
| 2261 | + }; |
| 2262 | + |
| 2263 | + /** |
| 2264 | + * Checks if a css style rule exists |
| 2265 | + * |
| 2266 | + * On a page with lots of rules it can take some time so avoid calling this |
| 2267 | + * function where possible and cache its result |
| 2268 | + * |
| 2269 | + * NOTE: this only works for style sheets on the same domain :( |
| 2270 | + * |
| 2271 | + * @param {String} |
| 2272 | + * styleRule Style rule name to check |
| 2273 | + * @return {Boolean} true if the rule exists false if the rule does not |
| 2274 | + * exist |
| 2275 | + */ |
| 2276 | + mw.styleRuleExists = function ( styleRule ) { |
| 2277 | + // Set up the skin paths configuration |
| 2278 | + for( var i=0 ; i < document.styleSheets.length ; i++ ) { |
| 2279 | + var rules = null; |
| 2280 | + try{ |
| 2281 | + if ( document.styleSheets[i].cssRules ) |
| 2282 | + rules = document.styleSheets[i].cssRules; |
| 2283 | + else if (document.styleSheets[0].rules) |
| 2284 | + rules = document.styleSheets[i].rules; |
| 2285 | + for(var j=0 ; j < rules.length ; j++ ) { |
| 2286 | + var rule = rules[j].selectorText; |
| 2287 | + if( rule && rule.indexOf( styleRule ) != -1 ) { |
| 2288 | + return true; |
| 2289 | + } |
| 2290 | + } |
| 2291 | + }catch ( e ) { |
| 2292 | + mw.log( 'Error: cant check rule on cross domain style sheet:' + document.styleSheets[i].href ); |
| 2293 | + } |
| 2294 | + } |
| 2295 | + return false; |
| 2296 | + }; |
| 2297 | + |
| 2298 | + // Flag to register the domReady has been called |
| 2299 | + var mwDomReadyFlag = false; |
| 2300 | + |
| 2301 | + // Flag to register if the domreadyHooks have been called |
| 2302 | + var mwModuleLoaderCheckFlag = false; |
| 2303 | + |
| 2304 | + /** |
| 2305 | + * This will get called when the DOM is ready Will check configuration and |
| 2306 | + * issue a mw.setupMwEmbed call if needed |
| 2307 | + */ |
| 2308 | + mw.domReady = function ( ) { |
| 2309 | + if( mwDomReadyFlag ) { |
| 2310 | + return ; |
| 2311 | + } |
| 2312 | + mw.log( 'run:domReady:: ' + document.getElementsByTagName('video').length ); |
| 2313 | + // Set the onDomReady Flag |
| 2314 | + mwDomReadyFlag = true; |
| 2315 | + |
| 2316 | + // Give us a chance to get to the bottom of the script. |
| 2317 | + // When loading mwEmbed asynchronously the dom ready gets called |
| 2318 | + // directly and in some browsers beets the $j = jQuery.noConflict(); |
| 2319 | + // call |
| 2320 | + // and causes symbol undefined errors. |
| 2321 | + setTimeout(function(){ |
| 2322 | + mw.setupMwEmbed(); |
| 2323 | + },1); |
| 2324 | + }; |
| 2325 | + |
| 2326 | + /** |
| 2327 | + * A version comparison utility function Handles version of types |
| 2328 | + * {Major}.{MinorN}.{Patch} |
| 2329 | + * |
| 2330 | + * Note this just handles version numbers not patch letters. |
| 2331 | + * |
| 2332 | + * @param {String} |
| 2333 | + * minVersion Minnium version needed |
| 2334 | + * @param {String} |
| 2335 | + * clientVersion Client version to be checked |
| 2336 | + * |
| 2337 | + * @return true if the version is at least of minVersion false if the |
| 2338 | + * version is less than minVersion |
| 2339 | + */ |
| 2340 | + mw.versionIsAtLeast = function( minVersion, clientVersion ) { |
| 2341 | + var minVersionParts = minVersion.split('.'); |
| 2342 | + var clientVersionParts = clientVersion.split('.'); |
| 2343 | + for( var i =0; i < minVersionParts.length; i++ ) { |
| 2344 | + if( parseInt( clientVersionParts[i] ) > parseInt( minVersionParts[i] ) ) { |
| 2345 | + return true; |
| 2346 | + } |
| 2347 | + if( parseInt( clientVersionParts[i] ) < parseInt( minVersionParts[i] ) ) { |
| 2348 | + return false; |
| 2349 | + } |
| 2350 | + } |
| 2351 | + // Same version: |
| 2352 | + return true; |
| 2353 | + }; |
| 2354 | + |
| 2355 | + /** |
| 2356 | + * Utility jQuery bindings Setup after jQuery is available ). |
| 2357 | + */ |
| 2358 | + mw.dojQueryBindings = function() { |
| 2359 | + mw.log( 'mw.dojQueryBindings' ); |
| 2360 | + ( function( $ ) { |
| 2361 | + |
| 2362 | + /** |
| 2363 | + * Runs all the triggers on all the named bindings of an object with |
| 2364 | + * a single callback |
| 2365 | + * |
| 2366 | + * NOTE THIS REQUIRES JQUERY 1.4.2 and above |
| 2367 | + * |
| 2368 | + * Normal jQuery tirgger calls will run the callback directly |
| 2369 | + * multiple times for every binded function. |
| 2370 | + * |
| 2371 | + * With triggerQueueCallback() callback is not called until all the |
| 2372 | + * binded events have been run. |
| 2373 | + * |
| 2374 | + * @param {string} |
| 2375 | + * triggerName Name of trigger to be run |
| 2376 | + * @param {object=} |
| 2377 | + * arguments Optional arguments object to be passed to |
| 2378 | + * the callback |
| 2379 | + * @param {function} |
| 2380 | + * callback Function called once all triggers have been |
| 2381 | + * run |
| 2382 | + * |
| 2383 | + */ |
| 2384 | + $.fn.triggerQueueCallback = function( triggerName, triggerParam, callback ){ |
| 2385 | + var targetObject = this; |
| 2386 | + // Support optional triggerParam data |
| 2387 | + if( !callback && typeof triggerParam == 'function' ){ |
| 2388 | + callback = triggerParam; |
| 2389 | + triggerParam = null; |
| 2390 | + } |
| 2391 | + // Support namespaced event segmentation ( jQuery |
| 2392 | + var triggerBaseName = triggerName.split(".")[0]; |
| 2393 | + var triggerNamespace = triggerName.split(".")[1]; |
| 2394 | + // Get the callback set |
| 2395 | + var callbackSet = []; |
| 2396 | + if( ! triggerNamespace ){ |
| 2397 | + callbackSet = $j( targetObject ).data( 'events' )[ triggerBaseName ]; |
| 2398 | + } else{ |
| 2399 | + $j.each( $j( targetObject ).data( 'events' )[ triggerBaseName ], function( inx, bindObject ){ |
| 2400 | + if( bindObject.namespace == triggerNamespace ){ |
| 2401 | + callbackSet.push( bindObject ); |
| 2402 | + } |
| 2403 | + }); |
| 2404 | + } |
| 2405 | + |
| 2406 | + if( !callbackSet || callbackSet.length === 0 ){ |
| 2407 | + mw.log( '"mwEmbed::jQuery.triggerQueueCallback: No events run the callback directly: ' + triggerName ); |
| 2408 | + // No events run the callback directly |
| 2409 | + callback(); |
| 2410 | + return ; |
| 2411 | + } |
| 2412 | + |
| 2413 | + // Set the callbackCount |
| 2414 | + var callbackCount = ( callbackSet.length )? callbackSet.length : 1; |
| 2415 | + // mw.log("mwEmbed::jQuery.triggerQueueCallback: " + triggerName |
| 2416 | + // + ' number of queued functions:' + callbackCount ); |
| 2417 | + var callInx = 0; |
| 2418 | + var doCallbackCheck = function() { |
| 2419 | + // mw.log( 'callback for: ' + mw.getCallStack()[0] + |
| 2420 | + // callInx); |
| 2421 | + callInx++; |
| 2422 | + if( callInx == callbackCount ){ |
| 2423 | + callback(); |
| 2424 | + } |
| 2425 | + }; |
| 2426 | + if( triggerParam ){ |
| 2427 | + $( this ).trigger( triggerName, [ triggerParam, doCallbackCheck ]); |
| 2428 | + } else { |
| 2429 | + $( this ).trigger( triggerName, [ doCallbackCheck ] ); |
| 2430 | + } |
| 2431 | + }; |
| 2432 | + |
| 2433 | + /** |
| 2434 | + * Set a given selector html to the loading spinner: |
| 2435 | + */ |
| 2436 | + $.fn.loadingSpinner = function( ) { |
| 2437 | + if ( this ) { |
| 2438 | + $( this ).html( |
| 2439 | + $( '<div />' ) |
| 2440 | + .addClass( "loadingSpinner" ) |
| 2441 | + ); |
| 2442 | + } |
| 2443 | + return this; |
| 2444 | + }; |
| 2445 | + |
| 2446 | + /** |
| 2447 | + * Add an absolute overlay spinner useful for cases where the |
| 2448 | + * element does not display child elements, ( images, video ) |
| 2449 | + */ |
| 2450 | + $.fn.getAbsoluteOverlaySpinner = function(){ |
| 2451 | + var pos = $j( this ).offset(); |
| 2452 | + var posLeft = ( $j( this ).width() ) ? |
| 2453 | + parseInt( pos.left + ( .5 * $j( this ).width() ) -16 ) : |
| 2454 | + pos.left + 30; |
| 2455 | + |
| 2456 | + var posTop = ( $j( this ).height() ) ? |
| 2457 | + parseInt( pos.top + ( .5 * $j( this ).height() ) -16 ) : |
| 2458 | + pos.top + 30; |
| 2459 | + |
| 2460 | + var $spinner = $j('<div />') |
| 2461 | + .loadingSpinner() |
| 2462 | + .css({ |
| 2463 | + 'width' : 32, |
| 2464 | + 'height' : 32, |
| 2465 | + 'position': 'absolute', |
| 2466 | + 'top' : posTop + 'px', |
| 2467 | + 'left' : posLeft + 'px' |
| 2468 | + }); |
| 2469 | + $j('body').append( $spinner ); |
| 2470 | + return $spinner; |
| 2471 | + }; |
| 2472 | + |
| 2473 | + /** |
| 2474 | + * dragDrop file loader |
| 2475 | + */ |
| 2476 | + $.fn.dragFileUpload = function ( conf ) { |
| 2477 | + if ( this.selector ) { |
| 2478 | + var _this = this; |
| 2479 | + // load the dragger and "setup" |
| 2480 | + mw.load( ['$j.fn.dragDropFile'], function() { |
| 2481 | + $j( _this.selector ).dragDropFile(); |
| 2482 | + } ); |
| 2483 | + } |
| 2484 | + }; |
| 2485 | + |
| 2486 | + /** |
| 2487 | + * Shortcut to a themed button Should be depreciated for $.button |
| 2488 | + * bellow |
| 2489 | + */ |
| 2490 | + $.btnHtml = function( msg, styleClass, iconId, opt ) { |
| 2491 | + if ( !opt ) |
| 2492 | + opt = { }; |
| 2493 | + var href = ( opt.href ) ? opt.href : '#'; |
| 2494 | + var target_attr = ( opt.target ) ? ' target="' + opt.target + '" ' : ''; |
| 2495 | + var style_attr = ( opt.style ) ? ' style="' + opt.style + '" ' : ''; |
| 2496 | + return '<a href="' + href + '" ' + target_attr + style_attr + |
| 2497 | + ' class="ui-state-default ui-corner-all ui-icon_link ' + |
| 2498 | + styleClass + '"><span class="ui-icon ui-icon-' + iconId + '" ></span>' + |
| 2499 | + '<span class="btnText">' + msg + '</span></a>'; |
| 2500 | + }; |
| 2501 | + |
| 2502 | + // Shortcut to jQuery button ( should replace all btnHtml with |
| 2503 | + // button ) |
| 2504 | + var mw_default_button_options = { |
| 2505 | + // The class name for the button link |
| 2506 | + 'class' : '', |
| 2507 | + |
| 2508 | + // The style properties for the button link |
| 2509 | + 'style' : { }, |
| 2510 | + |
| 2511 | + // The text of the button link |
| 2512 | + 'text' : '', |
| 2513 | + |
| 2514 | + // The icon id that precedes the button link: |
| 2515 | + 'icon' : 'carat-1-n' |
| 2516 | + }; |
| 2517 | + |
| 2518 | + $.button = function( options ) { |
| 2519 | + var options = $j.extend( {}, mw_default_button_options, options); |
| 2520 | + |
| 2521 | + // Button: |
| 2522 | + var $button = $j('<a />') |
| 2523 | + .attr('href', '#') |
| 2524 | + .addClass( 'ui-state-default ui-corner-all ui-icon_link' ); |
| 2525 | + // Add css if set: |
| 2526 | + if( options.css ) { |
| 2527 | + $button.css( options.css ); |
| 2528 | + } |
| 2529 | + |
| 2530 | + if( options['class'] ) { |
| 2531 | + $button.addClass( options['class'] ); |
| 2532 | + } |
| 2533 | + |
| 2534 | + // return the button: |
| 2535 | + $button.append( |
| 2536 | + $j('<span />').addClass( 'ui-icon ui-icon-' + options.icon ), |
| 2537 | + $j('<span />').addClass( 'btnText' ) |
| 2538 | + ) |
| 2539 | + .buttonHover(); // add buttonHover binding; |
| 2540 | + |
| 2541 | + if( options.text ){ |
| 2542 | + $button.find('.btnText').text( options.text ); |
| 2543 | + } else { |
| 2544 | + $button.css('padding', '1em'); |
| 2545 | + } |
| 2546 | + return $button; |
| 2547 | + }; |
| 2548 | + |
| 2549 | + // Shortcut to bind hover state |
| 2550 | + $.fn.buttonHover = function() { |
| 2551 | + $j( this ).hover( |
| 2552 | + function() { |
| 2553 | + $j( this ).addClass( 'ui-state-hover' ); |
| 2554 | + }, |
| 2555 | + function() { |
| 2556 | + $j( this ).removeClass( 'ui-state-hover' ); |
| 2557 | + } |
| 2558 | + ); |
| 2559 | + return this; |
| 2560 | + }; |
| 2561 | + |
| 2562 | + /** |
| 2563 | + * Resize a dialog to fit the window |
| 2564 | + * |
| 2565 | + * @param {Object} |
| 2566 | + * options horizontal and vertical space ( default 50 ) |
| 2567 | + */ |
| 2568 | + $.fn.dialogFitWindow = function( options ) { |
| 2569 | + var opt_default = { 'hspace':50, 'vspace':50 }; |
| 2570 | + if ( !options ) |
| 2571 | + var options = { }; |
| 2572 | + options = $j.extend( opt_default, options ); |
| 2573 | + $j( this.selector ).dialog( 'option', 'width', $j( window ).width() - options.hspace ); |
| 2574 | + $j( this.selector ).dialog( 'option', 'height', $j( window ).height() - options.vspace ); |
| 2575 | + $j( this.selector ).dialog( 'option', 'position', 'center' ); |
| 2576 | + // update the child position: (some of this should be pushed |
| 2577 | + // up-stream via dialog config options |
| 2578 | + $j( this.selector + '~ .ui-dialog-buttonpane' ).css( { |
| 2579 | + 'position':'absolute', |
| 2580 | + 'left':'0px', |
| 2581 | + 'right':'0px', |
| 2582 | + 'bottom':'0px' |
| 2583 | + } ); |
| 2584 | + }; |
| 2585 | + |
| 2586 | + } )( jQuery ); |
| 2587 | + }; |
| 2588 | + |
| 2589 | +} )( window.mw ); |
| 2590 | + |
| 2591 | + |
| 2592 | +/** |
| 2593 | + * Set DOM-ready call We copy jQuery( document ).ready here since sometimes |
| 2594 | + * mwEmbed.js is included without jQuery and we need our own "ready" system so |
| 2595 | + * that mwEmbed interfaces can support async built out and the include of |
| 2596 | + * jQuery. |
| 2597 | + */ |
| 2598 | +// Check if already ready: |
| 2599 | +if ( document.readyState === "complete" ) { |
| 2600 | + mw.domReady(); |
| 2601 | +} |
| 2602 | + |
| 2603 | +// Cleanup functions for the document ready method |
| 2604 | +if ( document.addEventListener ) { |
| 2605 | + DOMContentLoaded = function() { |
| 2606 | + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); |
| 2607 | + mw.domReady(); |
| 2608 | + }; |
| 2609 | + |
| 2610 | +} else if ( document.attachEvent ) { |
| 2611 | + DOMContentLoaded = function() { |
| 2612 | + // Make sure body exists, at least, in case IE gets a little overzealous |
| 2613 | + // (ticket #5443). |
| 2614 | + if ( document.readyState === "complete" ) { |
| 2615 | + document.detachEvent( "onreadystatechange", DOMContentLoaded ); |
| 2616 | + mw.domReady(); |
| 2617 | + } |
| 2618 | + }; |
| 2619 | +} |
| 2620 | +// Mozilla, Opera and webkit nightlies currently support this event |
| 2621 | +if ( document.addEventListener ) { |
| 2622 | + // Use the handy event callback |
| 2623 | + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); |
| 2624 | + |
| 2625 | + // A fallback to window.onload, that will always work |
| 2626 | + window.addEventListener( "load", mw.domReady, false ); |
| 2627 | + |
| 2628 | +// If IE event model is used |
| 2629 | +} else if ( document.attachEvent ) { |
| 2630 | + // ensure firing before onload, |
| 2631 | + // maybe late but safe also for iframes |
| 2632 | + document.attachEvent("onreadystatechange", DOMContentLoaded); |
| 2633 | + |
| 2634 | + // A fallback to window.onload, that will always work |
| 2635 | + window.attachEvent( "onload", mw.domReady ); |
| 2636 | + |
| 2637 | + // If IE and not a frame |
| 2638 | + // continually check to see if the document is ready |
| 2639 | + var toplevel = false; |
| 2640 | + |
| 2641 | + try { |
| 2642 | + toplevel = window.frameElement == null; |
| 2643 | + } catch(e) {} |
| 2644 | + |
| 2645 | + if ( document.documentElement.doScroll && toplevel ) { |
| 2646 | + doScrollCheck(); |
| 2647 | + } |
| 2648 | +} |
| 2649 | +// The DOM ready check for Internet Explorer |
| 2650 | +function doScrollCheck() { |
| 2651 | + try { |
| 2652 | + // If IE is used, use the trick by Diego Perini |
| 2653 | + // http://javascript.nwbox.com/IEContentLoaded/ |
| 2654 | + document.documentElement.doScroll("left"); |
| 2655 | + } catch( error ) { |
| 2656 | + setTimeout( doScrollCheck, 1 ); |
| 2657 | + return; |
| 2658 | + } |
| 2659 | + mw.domReady(); |
| 2660 | +} |
| 2661 | + |
| 2662 | +// If using the resource loader and jQuery has not been set give a warning to |
| 2663 | +// the user: |
| 2664 | +// (this is needed because packaged loader.js files could refrence jQuery ) |
| 2665 | +if( mw.getResourceLoaderPath() && !window.jQuery ) { |
| 2666 | + mw.log( 'Error: jQuery is required for mwEmbed, please update your resource loader request' ); |
| 2667 | +} |
| 2668 | + |
| 2669 | +if( mw.isStaticPackge() && !window.jQuery ){ |
| 2670 | + alert( 'Error: jQuery is required for mwEmbed '); |
| 2671 | +} |
| 2672 | + |
| 2673 | +/** |
| 2674 | + * Hack to keep jQuery in $ when its already there, but also use noConflict to |
| 2675 | + * get $j = jQuery |
| 2676 | + * |
| 2677 | + * This way sites that use $ for jQuery continue to work after including mwEmbed |
| 2678 | + * javascript. |
| 2679 | + * |
| 2680 | + * Also if jQuery is included prior to mwEmbed we ensure $j is set |
| 2681 | + */ |
| 2682 | + |
| 2683 | +if( window.jQuery ){ |
| 2684 | + if( ! mw.versionIsAtLeast( '1.4.2', jQuery.fn.jquery ) ){ |
| 2685 | + if( window.console && window.console.log ) { |
| 2686 | + console.log( 'Error mwEmbed requires jQuery 1.4 or above' ); |
| 2687 | + } |
| 2688 | + } |
| 2689 | + var dollarFlag = false; |
| 2690 | + if( $ && $.fn && $.fn.jquery ) { |
| 2691 | + // NOTE we could check the version of |
| 2692 | + // jQuery and do a removal call if too old |
| 2693 | + dollarFlag = true; |
| 2694 | + } |
| 2695 | + window[ '$j' ] = jQuery.noConflict(); |
| 2696 | + if( dollarFlag ) { |
| 2697 | + window[ '$' ] = jQuery.noConflict(); |
| 2698 | + } |
| 2699 | +} |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/modules/MwEmbedSupport/README |
— | — | @@ -0,0 +1,3 @@ |
| 2 | +This is the mwEmbed Support module it supplies common functionality that other mwEmbed modules depend on. |
| 3 | + |
| 4 | +Modules can express the dependency as 'mwembed.support' |
\ No newline at end of file |
Index: branches/MwEmbedStandAloneRL1_17/MwEmbedStandAlone/resources/README |
— | — | @@ -0,0 +1,4 @@ |
| 2 | +This is almost a direct copy of MediaWiki/resources |
| 3 | + |
| 4 | +Some mediaWiki specific code is removed and we rename the resource define file ( to not assume it |
| 5 | +stays in sync with mediaWiki ) |
\ No newline at end of file |