r84943 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r84942‎ | r84943 | r84944 >
Date:01:09, 29 March 2011
Author:dale
Status:deferred
Tags:
Comment:
* improved credits parsing
* updated mediawiki.api to work with mw.uri class
Modified paths:
  • /trunk/extensions/MwEmbedSupport/MwEmbedModules/MediaWikiSupport/MediaWikiSupport.loader.js (modified) (history)
  • /trunk/extensions/MwEmbedSupport/MwEmbedModules/MediaWikiSupport/resources/MediaWikiPlayerSupport.js (modified) (history)
  • /trunk/extensions/MwEmbedSupport/MwEmbedModules/MwEmbedSupport/MwEmbedSupport.php (modified) (history)
  • /trunk/extensions/MwEmbedSupport/MwEmbedModules/MwEmbedSupport/mediawiki/mediawiki.absoluteUrl.js (modified) (history)
  • /trunk/extensions/MwEmbedSupport/MwEmbedModules/MwEmbedSupport/mwEmbed.old.js (deleted) (history)
  • /trunk/extensions/MwEmbedSupport/MwEmbedModules/MwEmbedSupport/mwEmbedSupport.js (modified) (history)
  • /trunk/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.i18n.php (modified) (history)
  • /trunk/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.loader.js (modified) (history)
  • /trunk/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.php (modified) (history)
  • /trunk/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/iframeApi/mw.IFramePlayerApiClient.js (modified) (history)
  • /trunk/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/iframeApi/mw.IFramePlayerApiServer.js (modified) (history)

Diff [purge]

Index: trunk/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.php
@@ -25,6 +25,7 @@
2626 'mediawiki.client',
2727 'mediawiki.UtilitiesTime',
2828 'mediawiki.Uri',
 29+ 'mediawiki.absoluteUrl',
2930
3031 // Sub classes:
3132 'MediaElement',
Index: trunk/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.loader.js
@@ -43,7 +43,6 @@
4444 // Hide videonojs class
4545 $( '.videonojs' ).hide();
4646
47 -
4847 // Set up the embed video player class request: (include the skin js as well)
4948 var dependencySet = [
5049 'mw.EmbedPlayer'
@@ -107,7 +106,7 @@
108107 $( mw ).trigger( 'EmbedPlayerUpdateDependencies',
109108 [ playerElement, dependencySet ] );
110109 });
111 - // Remove duplicates in the dependencySet
 110+ // Remove any duplicates in the dependencySet:
112111 dependencySet = $.unique( dependencySet );
113112 // Do the request and process the playerElements with updated dependency set
114113 mediaWiki.loader.using( dependencySet, function(){
Index: trunk/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/iframeApi/mw.IFramePlayerApiClient.js
@@ -5,7 +5,7 @@
66 */
77
88 ( function( mw ) {
9 -
 9+
1010 mw.IFramePlayerApiClient = function( iframe, playerProxy ){
1111 return this.init( iframe , playerProxy );
1212 }
@@ -119,7 +119,7 @@
120120 for( var attrName in playerAttributes ){
121121 if( attrName != 'id' ){
122122 if( _this._prevPlayerProxy[ attrName ] != _this.playerProxy[ attrName ] ){
123 - //mw.log( "IFramePlayerApiClient:: User js update:" + attrName + ' set to: ' + this.playerProxy[ attrName ] + ' != old: ' + _this._prevPlayerProxy[ attrName ] );
 123+ // mw.log( "IFramePlayerApiClient:: User js update:" + attrName + ' set to: ' + this.playerProxy[ attrName ] + ' != old: ' + _this._prevPlayerProxy[ attrName ] );
124124 // Send the updated attribute back to the iframe:
125125 _this.postMessage({
126126 'attrName' : attrName,
Index: trunk/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/resources/iframeApi/mw.IFramePlayerApiServer.js
@@ -16,7 +16,6 @@
1717
1818 ( function( mw ) {
1919
20 -
2120 // Bind apiServer to EmbedPlayerNewPlayer:
2221 $( mw ).bind( 'EmbedPlayerNewPlayer', function( event, embedPlayer ) {
2322 // Check if the iFrame player api is enabled and we have a parent iframe url:
Index: trunk/extensions/TimedMediaHandler/MwEmbedModules/EmbedPlayer/EmbedPlayer.i18n.php
@@ -9,6 +9,8 @@
1010 $messages = array();
1111 $messages['en'] = array(
1212 'mwe-embedplayer-credit-title' => 'Title: $1',
 13+ 'mwe-embedplayer-credit-date' => 'Date: $1',
 14+ 'mwe-embedplayer-credit-author' => 'Author: $1',
1315 'mwe-embedplayer-loading_plugin' => 'Loading plugin ...',
1416 'mwe-embedplayer-select_playback' => 'Set playback preference',
1517 'mwe-embedplayer-link_back' => 'Link back',
Index: trunk/extensions/MwEmbedSupport/MwEmbedModules/MwEmbedSupport/mwEmbed.old.js
@@ -1,2698 +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 - $('<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 - $( '#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 - $( '#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 - $( 'body' ).append(
1139 - $('<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 - $( 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 = $( '#mwTempLoaderDialog' ).show().dialog( options );
1178 - } );
1179 - return $( '#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 - $( 'link' ).each( function() {
1537 - var currentSheet = $( 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 - $( 'head' ).append(
1559 - $('<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.html.escape(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 - "&" : "&amp;",
1961 - '"' : "&quot;",
1962 - '<' : "&lt;",
1963 - '>' : "&gt;"
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 - $( 'link' ).each( function( na, linkNode ){
2094 - $j.each( cssStyleSheetNames, function(inx, sheetName ){
2095 - if( $( 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 - $( 'style' ).each( function( na, styleNode ){
2104 - $j.each( cssStyleSheetNames, function(inx, sheetName ){
2105 - if( $( styleNode ).text().indexOf( '@import' ) != -1
2106 - &&
2107 - $( 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 = $( targetObject ).data( 'events' )[ triggerBaseName ];
2398 - } else{
2399 - $j.each( $( 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 = $( this ).offset();
2452 - var posLeft = ( $( this ).width() ) ?
2453 - parseInt( pos.left + ( .5 * $( this ).width() ) -16 ) :
2454 - pos.left + 30;
2455 -
2456 - var posTop = ( $( this ).height() ) ?
2457 - parseInt( pos.top + ( .5 * $( this ).height() ) -16 ) :
2458 - pos.top + 30;
2459 -
2460 - var $spinner = $('<div />')
2461 - .loadingSpinner()
2462 - .css({
2463 - 'width' : 32,
2464 - 'height' : 32,
2465 - 'position': 'absolute',
2466 - 'top' : posTop + 'px',
2467 - 'left' : posLeft + 'px'
2468 - });
2469 - $('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 - $( _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 = $('<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 - $('<span />').addClass( 'ui-icon ui-icon-' + options.icon ),
2537 - $('<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 - $( this ).hover(
2552 - function() {
2553 - $( this ).addClass( 'ui-state-hover' );
2554 - },
2555 - function() {
2556 - $( 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 - $( this.selector ).dialog( 'option', 'width', $( window ).width() - options.hspace );
2574 - $( this.selector ).dialog( 'option', 'height', $( window ).height() - options.vspace );
2575 - $( 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 - $( 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: trunk/extensions/MwEmbedSupport/MwEmbedModules/MwEmbedSupport/mwEmbedSupport.js
@@ -87,13 +87,17 @@
8888 return mediaWiki.config.get( name, value );
8989 };
9090 mw.setDefaultConfig = function( name, value ){
91 - if( ! mediaWiki.config.get( name ) ){
 91+ if( mediaWiki.config.get( name ) === null ){
9292 mediaWiki.config.set( name, value );
9393 }
9494 };
 95+ /**
 96+ * Aliased load function
 97+ */
9598 mw.load = function( resources, callback ){
9699 mediaWiki.loader.using( resources, callback, function(){
97100 // failed to load
 101+ mw.log("Failed to load resources:" + resources );
98102 });
99103 };
100104
@@ -193,7 +197,7 @@
194198
195199 /**
196200 * gM ( get Message ) in js2 conflated jQuery return type with string return type
197 - * Do a legacy check for input paramaters and call the correct function.
 201+ * Do a legacy check for input parameters and call the correct function.
198202 *
199203 * TODO Replace with new Neil's new parser functions
200204 */
@@ -409,6 +413,7 @@
410414 mw.load(uiRequest, function() {
411415 $( '#mweDialog' ).dialog( options );
412416 } );
 417+
413418 return $( '#mweDialog' );
414419 };
415420
Index: trunk/extensions/MwEmbedSupport/MwEmbedModules/MwEmbedSupport/MwEmbedSupport.php
@@ -37,6 +37,7 @@
3838 'mediawiki.UtilitiesTime' => array( 'scripts' => 'mediawiki/mediawiki.UtilitiesTime.js' ),
3939 'mediawiki.client' => array( 'scripts' => 'mediawiki/mediawiki.client.js' ),
4040 'mediawiki.Uri' => array( 'scripts' => 'mediawiki/mediawiki.Uri.js' ),
 41+ 'mediawiki.absoluteUrl' => array( 'scripts' => 'mediawiki/mediawiki.absoluteUrl.js' ),
4142
4243 'mediawiki.language.parser' => array(
4344 'scripts'=> 'mediawiki/mediawiki.language.parser.js',
Index: trunk/extensions/MwEmbedSupport/MwEmbedModules/MwEmbedSupport/mediawiki/mediawiki.absoluteUrl.js
@@ -12,35 +12,32 @@
1313 * @return {=String} absolute url
1414 */
1515 mw.absoluteUrl = function( source, contextUrl ) {
16 - var isAlreadyAbsolute = true;
1716 try{
1817 var parsedSrc = new mw.Uri( source );
 18+ if( parsedSrc.protocol )
 19+ return source;
1920 } catch(e){
20 - isAlreadyAbsolute = false;
 21+ // not already absolute
2122 };
22 - // If source was parsed successfully return ( already absolute )
23 - if( isAlreadyAbsolute ){
24 - return source;
25 - }
26 -
 23+
2724 // Get parent Url location the context URL
2825 if( !contextUrl ) {
2926 contextUrl = document.URL;
3027 }
31 - var parsedUrl = new mw.Uri( contextUrl );
 28+ var contextUrl = new mw.Uri( contextUrl );
3229
3330 // Check for local windows file that does not flip the slashes:
34 - if( parsedUrl.directory == '' && parsedUrl.protocol == 'file' ){
 31+ if( contextUrl.directory == '' && contextUrl.protocol == 'file' ){
3532 // pop off the file
3633 var fileUrl = contextUrl.split( '\\');
3734 fileUrl.pop();
38 - return fileUrl.join('\\') + '\\' + src;
 35+ return fileUrl.join('\\') + '\\' + src;
3936 }
4037 // Check for leading slash:
41 - if( src.indexOf( '/' ) === 0 ) {
42 - return parsedUrl.protocol + '://' + parsedUrl.authority + src;
 38+ if( source.indexOf( '/' ) === 0 ) {
 39+ return contextUrl.protocol + '://' + contextUrl.getAuthority() + source;
4340 }else{
44 - return parsedUrl.protocol + '://' + parsedUrl.authority + parsedUrl.directory + src;
 41+ return contextUrl.protocol + '://' + contextUrl.getAuthority() + contextUrl.path + source;
4542 }
4643 };
4744
Index: trunk/extensions/MwEmbedSupport/MwEmbedModules/MediaWikiSupport/MediaWikiSupport.loader.js
@@ -1,7 +1,7 @@
22
33 // Wrap in mediaWiki
44 ( function( mw ) {
5 - // Add MediaWikiSupportPlayer dependency on players with mwtitle
 5+ // Add MediaWikiSupportPlayer dependency on players with a mediaWiki title
66 $( mw ).bind( 'EmbedPlayerUpdateDependencies', function( event, embedPlayer, dependencySet ){
77 if( $( embedPlayer ).attr( 'data-mwtitle' ) ){
88 $.merge( dependencySet, ['MediaWikiPlayerSupport'] );
Index: trunk/extensions/MwEmbedSupport/MwEmbedModules/MediaWikiSupport/resources/MediaWikiPlayerSupport.js
@@ -113,9 +113,63 @@
114114 function doCreditLine( resourceHTML, articleUrl ){
115115 // Get the title string ( again a "Title" like js object could help out here. )
116116 var titleStr = embedPlayer.apiTitleKey.replace(/_/g, ' ');
 117+
 118+ // Setup the initial credits line:
 119+ var $creditLine = $( '<div />');
 120+
 121+ // Add the title:
 122+ $creditLine.append(
 123+ $('<span>').html(
 124+ gM( 'mwe-embedplayer-credit-title' ,
 125+ // We use a div container to easily get at the built out link
 126+ $('<div>').append(
 127+ $('<a/>').attr({
 128+ 'href' : articleUrl,
 129+ 'title' : titleStr
 130+ }).text( titleStr )
 131+ ).html()
 132+ )
 133+ )
 134+ );
 135+
 136+ // Parse some data from the page info template if possible:
 137+ var $page = $( resourceHTML );
 138+
 139+ // Look for author:
 140+ var $author = $page.find('#fileinfotpl_aut');
 141+ if( $author.length ){
 142+ // Get the real author sibling of fileinfotpl_aut
 143+ $author = $author.next().find('p');
 144+ // Remove white space:
 145+ $author.find('br').remove();
 146+
 147+ // Update link to be absolute per page url context:
 148+ var authUrl = $author.find('a').attr('href');
 149+ authUrl = mw.absoluteUrl( authUrl, articleUrl );
 150+ $author.find('a').attr('href',
 151+ authUrl
 152+ )
 153+ $creditLine.append( $( '<br />' ),
 154+ gM('mwe-embedplayer-credit-author', $author.html() )
 155+ )
 156+ }
 157+
 158+ // Look for date:
 159+ var $date =$page.find('#fileinfotpl_date');
 160+ if( $date.length ){
 161+ // Get the real date sibling of fileinfotpl_date
 162+ $date = $date.next().find('p');
 163+
 164+ // remove white space:
 165+ $date.find('br').remove();
 166+ $creditLine.append( $( '<br />' ),
 167+ gM('mwe-embedplayer-credit-date', $date.html() )
 168+ )
 169+ }
 170+
117171
 172+ // Build out the image and credit line
118173 var imgWidth = ( embedPlayer.controlBuilder.getOverlayWidth() < 250 )? 45 : 120;
119 -
120174 return $( '<div/>' ).addClass( 'creditline' )
121175 .append(
122176 $('<a/>').attr({
@@ -132,17 +186,7 @@
133187 )
134188 )
135189 .append(
136 - $('<span>').html(
137 - gM( 'mwe-embedplayer-credit-title' ,
138 - // We use a div container to easily get at the built out link
139 - $('<div>').html(
140 - $('<a/>').attr({
141 - 'href' : articleUrl,
142 - 'title' : titleStr
143 - }).text( titleStr )
144 - ).html()
145 - )
146 - )
 190+ $creditLine
147191 );
148192 };
149193

Status & tagging log