Index: trunk/extensions/MwEmbed/MwEmbedResourceManager.php |
— | — | @@ -31,10 +31,10 @@ |
32 | 32 | } |
33 | 33 | |
34 | 34 | // Add the messages to the extension messages set: |
35 | | - $wgExtensionMessagesFiles[ 'MwEmbed.' . $moduleName ] = $fullResourcePath . '/' . $moduleName . '.i18n.php'; |
| 35 | + $wgExtensionMessagesFiles[ 'MwEmbed.' . $moduleName ] = $fullResourcePath . '/' . $moduleName . '.i18n.php'; |
36 | 36 | |
37 | 37 | // Get the mwEmbed module resource list |
38 | | - $resourceList = include( $fullResourcePath . '/' . $moduleName . '.resourceList.php' ); |
| 38 | + $resourceList = include( $fullResourcePath . '/' . $moduleName . '.resources.php' ); |
39 | 39 | |
40 | 40 | // Look for special 'messages' => 'moduleFile' key and load all modules file messages: |
41 | 41 | foreach( $resourceList as $name => $resources ){ |
— | — | @@ -46,6 +46,9 @@ |
47 | 47 | } |
48 | 48 | } |
49 | 49 | }; |
| 50 | + |
| 51 | + // Add the moduleLoader to the resource list: |
| 52 | + $resourceList[$moduleName. '.loader'] = array( 'loader' => $moduleName . '.loader.js' ); |
50 | 53 | |
51 | 54 | // Add the resource list into the module set with its provided path |
52 | 55 | self::$moduleSet[ $mwEmbedResourcePath ] = $resourceList; |
Index: trunk/extensions/MwEmbed/MwEmbed/MwEmbed.resourceList.php |
— | — | @@ -1,69 +0,0 @@ |
2 | | -<?php |
3 | | - |
4 | | -/** |
5 | | - * MwEmebed module resource list array |
6 | | - */ |
7 | | - |
8 | | -return array( |
9 | | - 'mw.Language' => array ( 'scripts' => 'components/mw.Language.js' ), |
10 | | - 'mw.Parser' => array ( 'scripts' => 'components/mw.Parser.js' ), |
11 | | - 'mw.Api' => array ( 'scripts' => 'components/mw.Api.js' ), |
12 | | - 'mwEmbed' => array( |
13 | | - 'scripts' => 'mwEmbed.js', |
14 | | - 'skinStyles' => array( |
15 | | - 'default' => 'skins/common/mw.style.mwCommon.css' |
16 | | - ), |
17 | | - 'group' => 'ext.mwEmbed', |
18 | | - 'dependencies' => array( |
19 | | - 'jquery' |
20 | | - ), |
21 | | - 'messages' => 'moduleFile', |
22 | | - 'languageScripts' => array( |
23 | | - 'am' => 'languages/classes/LanuageAm.js', |
24 | | - 'ar' => 'languages/classes/LanuageAr.js', |
25 | | - 'bat_smg' => 'languages/classes/LanuageBat_smg.js', |
26 | | - 'be' => 'languages/classes/LanuageBe.js', |
27 | | - 'be_tarask' => 'languages/classes/LanuageBe_tarask.js', |
28 | | - 'bh' => 'languages/classes/LanuageBh.js', |
29 | | - 'bs' => 'languages/classes/LanuageBs.js', |
30 | | - 'cs' => 'languages/classes/LanuageCs.js', |
31 | | - 'cu' => 'languages/classes/LanuageCu.js', |
32 | | - 'cy' => 'languages/classes/LanuageCy.js', |
33 | | - 'dsb' => 'languages/classes/LanuageDsb.js', |
34 | | - 'fr' => 'languages/classes/LanuageFr.js', |
35 | | - 'ga' => 'languages/classes/LanuageGa.js', |
36 | | - 'gd' => 'languages/classes/LanuageGd.js', |
37 | | - 'gv' => 'languages/classes/LanuageGv.js', |
38 | | - 'he' => 'languages/classes/LanuageHe.js', |
39 | | - 'hi' => 'languages/classes/LanuageHi.js', |
40 | | - 'hr' => 'languages/classes/LanuageHr.js', |
41 | | - 'hsb' => 'languages/classes/LanuageHsb.js', |
42 | | - 'hy' => 'languages/classes/LanuageHy.js', |
43 | | - 'ksh' => 'languages/classes/LanuageKsh.js', |
44 | | - 'ln' => 'languages/classes/LanuageLn.js', |
45 | | - 'lt' => 'languages/classes/LanuageLt.js', |
46 | | - 'lv' => 'languages/classes/LanuageLv.js', |
47 | | - 'mg' => 'languages/classes/LanuageMg.js', |
48 | | - 'mk' => 'languages/classes/LanuageMk.js', |
49 | | - 'mo' => 'languages/classes/LanuageMo.js', |
50 | | - 'mt' => 'languages/classes/LanuageMt.js', |
51 | | - 'nso' => 'languages/classes/LanuageNso.js', |
52 | | - 'pl' => 'languages/classes/LanuagePl.js', |
53 | | - 'pt_br' => 'languages/classes/LanuagePt_br.js', |
54 | | - 'ro' => 'languages/classes/LanuageRo.js', |
55 | | - 'ru' => 'languages/classes/LanuageRu.js', |
56 | | - 'se' => 'languages/classes/LanuageSe.js', |
57 | | - 'sh' => 'languages/classes/LanuageSh.js', |
58 | | - 'sk' => 'languages/classes/LanuageSk.js', |
59 | | - 'sl' => 'languages/classes/LanuageSl.js', |
60 | | - 'sma' => 'languages/classes/LanuageSma.js', |
61 | | - 'sr_ec' => 'languages/classes/LanuageSr_ec.js', |
62 | | - 'sr_el' => 'languages/classes/LanuageSr_el.js', |
63 | | - 'sr' => 'languages/classes/LanuageSr.js', |
64 | | - 'ti' => 'languages/classes/LanuageTi.js', |
65 | | - 'tl' => 'languages/classes/LanuageTl.js', |
66 | | - 'uk' => 'languages/classes/LanuageUk.js', |
67 | | - 'wa' => 'languages/classes/LanuageWa.js', |
68 | | - ) |
69 | | - ) |
70 | | -); |
\ No newline at end of file |
Index: trunk/extensions/MwEmbed/MwEmbed/MwEmbed.resources.php |
— | — | @@ -0,0 +1,19 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * MwEmebed module resource list array |
| 6 | + */ |
| 7 | + |
| 8 | +return array( |
| 9 | + 'mw.jQueryUtil' => array( 'scripts' => 'components/mw.jQueryUtil.js' ), |
| 10 | + 'mwEmbed' => array( |
| 11 | + 'scripts' => 'mwEmbed.core.js', |
| 12 | + 'dependencies' => array( |
| 13 | + 'mediaWiki.messageParser', |
| 14 | + 'mw.jQueryUtil' |
| 15 | + ), |
| 16 | + 'styles' => 'skins/common/mw.style.mwCommon.css', |
| 17 | + 'group' => 'ext.mwEmbed', |
| 18 | + 'messages' => 'moduleFile', |
| 19 | + ) |
| 20 | +); |
\ No newline at end of file |
Index: trunk/extensions/MwEmbed/MwEmbed/mwEmbed.core.js |
— | — | @@ -0,0 +1,678 @@ |
| 2 | +// Add support for html5 / mwEmbed elements to IE |
| 3 | +// For discussion and comments, see: http://remysharp.com/2009/01/07/html5-enabling-script/ |
| 4 | +'video audio source track'.replace(/\w+/g,function( n ){ document.createElement( n ) } ); |
| 5 | + |
| 6 | +/** |
| 7 | + * mwEmbed.core includes shared mwEmbed utilities |
| 8 | + * |
| 9 | + * @license |
| 10 | + * mwEmbed |
| 11 | + * Dual licensed under the MIT or GPL Version 2 licenses. |
| 12 | + * |
| 13 | + * @copyright (C) 2010 Kaltura |
| 14 | + * @author Michael Dale ( michael.dale at kaltura.com ) |
| 15 | + * |
| 16 | + * @url http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library |
| 17 | + * |
| 18 | + * Libraries used include code license in headers |
| 19 | + */ |
| 20 | + |
| 21 | + |
| 22 | +/** |
| 23 | + * Setup the "mw" global: |
| 24 | + */ |
| 25 | +if ( typeof window.mw == 'undefined' ) { |
| 26 | + window.mw = { }; |
| 27 | +} |
| 28 | + |
| 29 | +/** |
| 30 | + * Set the mwEmbedVersion |
| 31 | + */ |
| 32 | +var MW_EMBED_VERSION = '1.1g'; |
| 33 | + |
| 34 | +// Globals to pre-set ready functions in dynamic loading of mwEmbed |
| 35 | +if( typeof preMwEmbedReady == 'undefined'){ |
| 36 | + var preMwEmbedReady = []; |
| 37 | +} |
| 38 | +// Globals to pre-set config values in dynamic loading of mwEmbed |
| 39 | +if( typeof preMwEmbedConfig == 'undefined') { |
| 40 | + var preMwEmbedConfig = []; |
| 41 | +} |
| 42 | + |
| 43 | +/** |
| 44 | + * Global mw object: |
| 45 | + */ |
| 46 | +( function( mw ) { |
| 47 | + |
| 48 | + /** |
| 49 | + * Add a function to be run during setup ( prior to mw.ready) this is useful |
| 50 | + * for building out interfaces that should be ready before mw.ready is |
| 51 | + * called. |
| 52 | + * |
| 53 | + * @param {callback} |
| 54 | + * Function Callback function must accept a ready function |
| 55 | + * callback to be called once setup is done |
| 56 | + */ |
| 57 | + var mwSetupFunctions = []; // Array of setup functions |
| 58 | + mw.addSetupHook = function( callback ) { |
| 59 | + mwSetupFunctions.push ( callback ) ; |
| 60 | + }; |
| 61 | + |
| 62 | + // flag for mwSetup being run: |
| 63 | + mwSetupFlag = false; |
| 64 | + mw.setupMwEmbed = function(){ |
| 65 | + mw.log( 'mw.setupMwEmbed' ); |
| 66 | + // Only run the setup once: |
| 67 | + if( mwSetupFlag ) { |
| 68 | + return ; |
| 69 | + } |
| 70 | + mwSetupFlag = true; |
| 71 | + // check if mediaWiki has already been setup. |
| 72 | + if (! window.mediaWiki ) { |
| 73 | + // @@todo load mediaWiki from load.php |
| 74 | + |
| 75 | + // Issue a call to load.php to get the set of modules in a way that 'mediaWiki' understands. |
| 76 | + } else { |
| 77 | + mw.setupWithmediaWikiJS(); |
| 78 | + } |
| 79 | + }; |
| 80 | + mw.setupWithmediaWikiJS = function(){ |
| 81 | + // Update mediaWiki object with mwEmbed tools / helpers |
| 82 | + |
| 83 | + // Now with window.mediaWiki we can run all the calls and trigger the mw.ready |
| 84 | + |
| 85 | + // run setup callbacks |
| 86 | + function runSetupFunctions() { |
| 87 | + if( mwSetupFunctions.length ) { |
| 88 | + mwSetupFunctions.shift()( function() { |
| 89 | + runSetupFunctions(); |
| 90 | + } ); |
| 91 | + }else{ |
| 92 | + mw.runReadyFunctions(); |
| 93 | + } |
| 94 | + } |
| 95 | + runSetupFunctions(); |
| 96 | + }; |
| 97 | + |
| 98 | + |
| 99 | + /** |
| 100 | + * Enables load hooks to run once mwEmbeed is "ready" Will ensure jQuery is |
| 101 | + * available, is in the $j namespace and mw interfaces and configuration has |
| 102 | + * been loaded and applied |
| 103 | + * |
| 104 | + * This is different from jQuery(document).ready() ( jQuery ready is not |
| 105 | + * friendly with dynamic includes and not friendly with core interface |
| 106 | + * asynchronous build out. ) |
| 107 | + * |
| 108 | + * @param {Function} |
| 109 | + * callback Function to run once DOM and jQuery are ready |
| 110 | + */ |
| 111 | + var mwOnLoadFunctions = []; // Setup the local mwOnLoadFunctions array: |
| 112 | + var mwReadyFlag = false; // mw Ready flag ( set once mwEmbed is ready ) |
| 113 | + mw.ready = function( callback ) { |
| 114 | + if( mwReadyFlag === false ) { |
| 115 | + // Add the callbcak to the onLoad function stack |
| 116 | + mwOnLoadFunctions.push ( callback ); |
| 117 | + } else { |
| 118 | + // If mwReadyFlag is already "true" issue the callback directly: |
| 119 | + callback(); |
| 120 | + } |
| 121 | + } |
| 122 | + |
| 123 | + /** |
| 124 | + * Runs all the queued functions called by mwEmbedSetup |
| 125 | + */ |
| 126 | + mw.runReadyFunctions = function ( ) { |
| 127 | + mw.log('mw.runReadyFunctions: ' + mwOnLoadFunctions.length ); |
| 128 | + // Run any pre-setup ready functions |
| 129 | + while( preMwEmbedReady.length ){ |
| 130 | + preMwEmbedReady.shift()(); |
| 131 | + } |
| 132 | + // Run all the queued functions: |
| 133 | + while( mwOnLoadFunctions.length ) { |
| 134 | + mwOnLoadFunctions.shift()(); |
| 135 | + } |
| 136 | + // Sets mwReadyFlag to true so that future mw.ready run the |
| 137 | + // callback directly |
| 138 | + mwReadyFlag = true; |
| 139 | + |
| 140 | + } |
| 141 | + |
| 142 | + |
| 143 | + /* User config */ |
| 144 | + |
| 145 | + var setupUserConfigFlag = false; |
| 146 | + mw.setupUserConfig = function( callback ) { |
| 147 | + if( setupUserConfigFlag ) { |
| 148 | + if( callback ) { |
| 149 | + callback(); |
| 150 | + } |
| 151 | + return ; |
| 152 | + } |
| 153 | + // Do Setup user config: |
| 154 | + mw.load( [ '$j.cookie', 'JSON' ], function() { |
| 155 | + if( $j.cookie( 'mwUserConfig' ) ) { |
| 156 | + mwUserConfig = JSON.parse( $j.cookie( 'mwUserConfig' ) ); |
| 157 | + } |
| 158 | + setupUserConfigFlag = true; |
| 159 | + if( callback ) { |
| 160 | + callback(); |
| 161 | + } |
| 162 | + }); |
| 163 | + } |
| 164 | + |
| 165 | + /** |
| 166 | + * Save a user configuration var to a cookie & local global variable Loads |
| 167 | + * the cookie plugin if not already loaded |
| 168 | + * |
| 169 | + * @param {String} |
| 170 | + * name Name of user configuration value |
| 171 | + * @param {String} |
| 172 | + * value Value of configuration name |
| 173 | + */ |
| 174 | + mw.setUserConfig = function ( name, value, cookieOptions ) { |
| 175 | + if( ! setupUserConfigFlag ) { |
| 176 | + mw.log( "Error: userConfig not setup" ); |
| 177 | + return false; |
| 178 | + } |
| 179 | + // Update local value |
| 180 | + mwUserConfig[ name ] = value; |
| 181 | + |
| 182 | + // Update the cookie ( '$j.cookie' & 'JSON' should already be loaded ) |
| 183 | + $j.cookie( 'mwUserConfig', JSON.stringify( mwUserConfig ) ); |
| 184 | + } |
| 185 | + |
| 186 | + /** |
| 187 | + * Save a user configuration var to a cookie & local global variable |
| 188 | + * |
| 189 | + * @param {String} |
| 190 | + * name Name of user configuration value |
| 191 | + * @return value of the configuration name false if the configuration name |
| 192 | + * could not be found |
| 193 | + */ |
| 194 | + mw.getUserConfig = function ( name ) { |
| 195 | + if( mwUserConfig[ name ] ) |
| 196 | + return mwUserConfig[ name ]; |
| 197 | + return false; |
| 198 | + } |
| 199 | + |
| 200 | + |
| 201 | + /** |
| 202 | + * Aliased functions |
| 203 | + * |
| 204 | + * Wrap mediaWiki functionality while we port over the libraries |
| 205 | + */ |
| 206 | + mw.setConfig = function( name, value ){ |
| 207 | + mediaWiki.config.set( name, value ); |
| 208 | + }; |
| 209 | + mw.getConfig = function( name, value ){ |
| 210 | + mediaWiki.config.get( name, value ); |
| 211 | + }; |
| 212 | + mw.setDefaultConfig = function( name, value ){ |
| 213 | + //@@ FIXME only set if not already present: |
| 214 | + mediaWiki.config.set( name, value ); |
| 215 | + }; |
| 216 | + mw.load = function( resources, callback ){ |
| 217 | + mediaWiki.using( resources, callback, function(){ |
| 218 | + // failed to load |
| 219 | + }) |
| 220 | + }; |
| 221 | + mw.addModuleLoader = function ( name, loaderFunction ) { |
| 222 | + mediaWiki.register( name, 0, loaderFunction ); |
| 223 | + } |
| 224 | + |
| 225 | + |
| 226 | + /** |
| 227 | + * Utility Functions |
| 228 | + */ |
| 229 | + |
| 230 | + /** |
| 231 | + * Given a float number of seconds, returns npt format response. ( ignore |
| 232 | + * days for now ) |
| 233 | + * |
| 234 | + * @param {Float} |
| 235 | + * sec Seconds |
| 236 | + * @param {Boolean} |
| 237 | + * show_ms If milliseconds should be displayed. |
| 238 | + * @return {Float} String npt format |
| 239 | + */ |
| 240 | + mw.seconds2npt = function( sec, show_ms ) { |
| 241 | + if ( isNaN( sec ) ) { |
| 242 | + mw.log("Warning: trying to get npt time on NaN:" + sec); |
| 243 | + return '0:00:00'; |
| 244 | + } |
| 245 | + |
| 246 | + var tm = mw.seconds2Measurements( sec ) |
| 247 | + |
| 248 | + // Round the number of seconds to the required number of significant |
| 249 | + // digits |
| 250 | + if ( show_ms ) { |
| 251 | + tm.seconds = Math.round( tm.seconds * 1000 ) / 1000; |
| 252 | + } else { |
| 253 | + tm.seconds = Math.round( tm.seconds ); |
| 254 | + } |
| 255 | + if ( tm.seconds < 10 ){ |
| 256 | + tm.seconds = '0' + tm.seconds; |
| 257 | + } |
| 258 | + if( tm.hours == 0 ){ |
| 259 | + hoursStr = '' |
| 260 | + } else { |
| 261 | + if ( tm.minutes < 10 ) |
| 262 | + tm.minutes = '0' + tm.minutes; |
| 263 | + |
| 264 | + hoursStr = tm.hours + ":"; |
| 265 | + } |
| 266 | + return hoursStr + tm.minutes + ":" + tm.seconds; |
| 267 | + } |
| 268 | + |
| 269 | + /** |
| 270 | + * Given seconds return array with 'days', 'hours', 'min', 'seconds' |
| 271 | + * |
| 272 | + * @param {float} |
| 273 | + * sec Seconds to be converted into time measurements |
| 274 | + */ |
| 275 | + mw.seconds2Measurements = function ( sec ){ |
| 276 | + var tm = {}; |
| 277 | + tm.days = Math.floor( sec / ( 3600 * 24 ) ) |
| 278 | + tm.hours = Math.floor( sec / 3600 ); |
| 279 | + tm.minutes = Math.floor( ( sec / 60 ) % 60 ); |
| 280 | + tm.seconds = sec % 60; |
| 281 | + return tm; |
| 282 | + } |
| 283 | + |
| 284 | + /** |
| 285 | + * Take hh:mm:ss,ms or hh:mm:ss.ms input, return the number of seconds |
| 286 | + * |
| 287 | + * @param {String} |
| 288 | + * npt_str NPT time string |
| 289 | + * @return {Float} Number of seconds |
| 290 | + */ |
| 291 | + mw.npt2seconds = function ( npt_str ) { |
| 292 | + if ( !npt_str ) { |
| 293 | + // mw.log('npt2seconds:not valid ntp:'+ntp); |
| 294 | + return false; |
| 295 | + } |
| 296 | + // Strip {npt:}01:02:20 or 32{s} from time if present |
| 297 | + npt_str = npt_str.replace( /npt:|s/g, '' ); |
| 298 | + |
| 299 | + var hour = 0; |
| 300 | + var min = 0; |
| 301 | + var sec = 0; |
| 302 | + |
| 303 | + times = npt_str.split( ':' ); |
| 304 | + if ( times.length == 3 ) { |
| 305 | + sec = times[2]; |
| 306 | + min = times[1]; |
| 307 | + hour = times[0]; |
| 308 | + } else if ( times.length == 2 ) { |
| 309 | + sec = times[1]; |
| 310 | + min = times[0]; |
| 311 | + } else { |
| 312 | + sec = times[0]; |
| 313 | + } |
| 314 | + // Sometimes a comma is used instead of period for ms |
| 315 | + sec = sec.replace( /,\s?/, '.' ); |
| 316 | + // Return seconds float |
| 317 | + return parseInt( hour * 3600 ) + parseInt( min * 60 ) + parseFloat( sec ); |
| 318 | + } |
| 319 | + |
| 320 | + /** |
| 321 | + * addLoaderDialog small helper for displaying a loading dialog |
| 322 | + * |
| 323 | + * @param {String} |
| 324 | + * dialogHtml text Html of the loader msg |
| 325 | + */ |
| 326 | + mw.addLoaderDialog = function( dialogHtml ) { |
| 327 | + $dialog = mw.addDialog( { |
| 328 | + 'title' : dialogHtml, |
| 329 | + 'content' : dialogHtml + '<br>' + |
| 330 | + $j('<div />') |
| 331 | + .loadingSpinner() |
| 332 | + .html() |
| 333 | + }); |
| 334 | + return $dialog; |
| 335 | + } |
| 336 | + |
| 337 | + /** |
| 338 | + * Mobile HTML5 has special properties for html5 video:: |
| 339 | + * |
| 340 | + * NOTE: should be phased out in favor of browser feature detection where possible |
| 341 | + */ |
| 342 | + mw.isMobileHTML5 = function() { |
| 343 | + // check mobile safari foce ( for debug ) |
| 344 | + if( mw.getConfig( 'forceMobileHTML5' ) || document.URL.indexOf('forceMobileHTML5') != -1 ){ |
| 345 | + return true; |
| 346 | + } |
| 347 | + if (( navigator.userAgent.indexOf('iPhone') != -1) || |
| 348 | + ( navigator.userAgent.indexOf('iPod') != -1) || |
| 349 | + ( navigator.userAgent.indexOf('iPad') != -1) || |
| 350 | + ( mw.isAndroid2() ) |
| 351 | + ) { |
| 352 | + return true; |
| 353 | + } |
| 354 | + return false; |
| 355 | + }; |
| 356 | + // Android 2 has some restrictions vs other mobile platforms |
| 357 | + mw.isAndroid2 = function(){ |
| 358 | + if ( navigator.userAgent.indexOf('Android 2.') != -1) { |
| 359 | + return true; |
| 360 | + } |
| 361 | + return false; |
| 362 | + }; |
| 363 | + |
| 364 | + /** |
| 365 | + * Add a (temporary) dialog window: |
| 366 | + * |
| 367 | + * @param {Object} with following keys: |
| 368 | + * title: {String} Title string for the dialog |
| 369 | + * content: {String} to be inserted in msg box |
| 370 | + * buttons: {Object} A button object for the dialog Can be a string |
| 371 | + * for the close button |
| 372 | + * any jquery.ui.dialog option |
| 373 | + */ |
| 374 | + mw.addDialog = function ( options ) { |
| 375 | + // Remove any other dialog |
| 376 | + $j( '#mwTempLoaderDialog' ).remove(); |
| 377 | + |
| 378 | + if( !options){ |
| 379 | + options = {}; |
| 380 | + } |
| 381 | + |
| 382 | + // Extend the default options with provided options |
| 383 | + var options = $j.extend({ |
| 384 | + 'bgiframe': true, |
| 385 | + 'draggable': true, |
| 386 | + 'resizable': false, |
| 387 | + 'modal': true |
| 388 | + }, options ); |
| 389 | + |
| 390 | + if( ! options.title || ! options.content ){ |
| 391 | + mw.log("Error: mwEmbed addDialog missing required options ( title, content ) ") |
| 392 | + return ; |
| 393 | + } |
| 394 | + |
| 395 | + // Append the dialog div on top: |
| 396 | + $j( 'body' ).append( |
| 397 | + $j('<div />') |
| 398 | + .attr( { |
| 399 | + 'id' : "mwTempLoaderDialog", |
| 400 | + 'title' : options.title |
| 401 | + }) |
| 402 | + .css({ |
| 403 | + 'display': 'none' |
| 404 | + }) |
| 405 | + .append( options.content ) |
| 406 | + ); |
| 407 | + |
| 408 | + // Build the uiRequest |
| 409 | + var uiRequest = [ '$j.ui.dialog' ]; |
| 410 | + if( options.draggable ){ |
| 411 | + uiRequest.push( '$j.ui.draggable' ) |
| 412 | + } |
| 413 | + if( options.resizable ){ |
| 414 | + uiRequest.push( '$j.ui.resizable' ); |
| 415 | + } |
| 416 | + |
| 417 | + // Special button string |
| 418 | + if ( typeof options.buttons == 'string' ) { |
| 419 | + var buttonMsg = options.buttons; |
| 420 | + buttons = { }; |
| 421 | + options.buttons[ buttonMsg ] = function() { |
| 422 | + $j( this ).dialog( 'close' ); |
| 423 | + } |
| 424 | + } |
| 425 | + |
| 426 | + // Load the dialog resources |
| 427 | + mw.load([ |
| 428 | + [ |
| 429 | + '$j.ui' |
| 430 | + ], |
| 431 | + uiRequest |
| 432 | + ], function() { |
| 433 | + $j( '#mwTempLoaderDialog' ).dialog( options ); |
| 434 | + } ); |
| 435 | + return $j( '#mwTempLoaderDialog' ); |
| 436 | + } |
| 437 | + |
| 438 | + /** |
| 439 | + * Close the loader dialog created with addLoaderDialog |
| 440 | + */ |
| 441 | + mw.closeLoaderDialog = function() { |
| 442 | + // Make sure the dialog resource is present |
| 443 | + if( !mw.isset( '$j.ui.dialog' ) ) { |
| 444 | + return false; |
| 445 | + } |
| 446 | + $j( '#mwTempLoaderDialog' ).dialog( 'destroy' ).remove(); |
| 447 | + } |
| 448 | + |
| 449 | + |
| 450 | + /** |
| 451 | + * Similar to php isset function checks if the variable exists. Does a safe |
| 452 | + * check of a descendant method or variable |
| 453 | + * |
| 454 | + * @param {String} |
| 455 | + * objectPath |
| 456 | + * @return {Boolean} true if objectPath exists false if objectPath is |
| 457 | + * undefined |
| 458 | + */ |
| 459 | + mw.isset = function( objectPath ) { |
| 460 | + if ( !objectPath ) { |
| 461 | + return false; |
| 462 | + } |
| 463 | + var pathSet = objectPath.split( '.' ); |
| 464 | + var cur_path = ''; |
| 465 | + |
| 466 | + for ( var p = 0; p < pathSet.length; p++ ) { |
| 467 | + cur_path = ( cur_path == '' ) ? cur_path + pathSet[p] : cur_path + '.' + pathSet[p]; |
| 468 | + eval( 'var ptest = typeof ( ' + cur_path + ' ); ' ); |
| 469 | + if ( ptest == 'undefined' ) { |
| 470 | + return false; |
| 471 | + } |
| 472 | + } |
| 473 | + return true; |
| 474 | + } |
| 475 | + |
| 476 | + /** |
| 477 | + * Wait for a object to be defined and the call the callback |
| 478 | + * |
| 479 | + * @param {Object} |
| 480 | + * objectName Name of object to be defined |
| 481 | + * @param {Function} |
| 482 | + * callback Function to call once object is defined |
| 483 | + * @param {Null} |
| 484 | + * callNumber Used internally to keep track of number of times |
| 485 | + * waitForObject has been called |
| 486 | + */ |
| 487 | + var waitTime = 1200; // About 30 seconds |
| 488 | + mw.waitForObject = function( objectName, callback, _callNumber) { |
| 489 | + // mw.log( 'waitForObject: ' + objectName + ' cn: ' + _callNumber); |
| 490 | + |
| 491 | + // Increment callNumber: |
| 492 | + if( !_callNumber ) { |
| 493 | + _callNumber = 1; |
| 494 | + } else { |
| 495 | + _callNumber++; |
| 496 | + } |
| 497 | + |
| 498 | + if( _callNumber > waitTime ) { |
| 499 | + mw.log( "Error: waiting for object: " + objectName + ' timeout ' ); |
| 500 | + callback( false ); |
| 501 | + return ; |
| 502 | + } |
| 503 | + |
| 504 | + // If the object is defined ( or we are done loading from a callback ) |
| 505 | + if ( mw.isset( objectName ) || mwLoadDoneCB[ objectName ] == 'done' ) { |
| 506 | + callback( objectName ) |
| 507 | + }else{ |
| 508 | + setTimeout( function( ) { |
| 509 | + mw.waitForObject( objectName, callback, _callNumber); |
| 510 | + }, 25); |
| 511 | + } |
| 512 | + } |
| 513 | + |
| 514 | + /** |
| 515 | + * Check if an object is empty or if its an empty string. |
| 516 | + * |
| 517 | + * @param {Object} |
| 518 | + * object Object to be checked |
| 519 | + */ |
| 520 | + mw.isEmpty = function( object ) { |
| 521 | + if( typeof object == 'string' ) { |
| 522 | + if( object == '' ) return true; |
| 523 | + // Non empty string: |
| 524 | + return false; |
| 525 | + } |
| 526 | + |
| 527 | + // If an array check length: |
| 528 | + if( Object.prototype.toString.call( object ) === "[object Array]" |
| 529 | + && object.length == 0 ) { |
| 530 | + return true; |
| 531 | + } |
| 532 | + |
| 533 | + // Else check as an object: |
| 534 | + for( var i in object ) { return false; } |
| 535 | + |
| 536 | + // Else object is empty: |
| 537 | + return true; |
| 538 | + } |
| 539 | + |
| 540 | + /** |
| 541 | + * Log a string msg to the console |
| 542 | + * |
| 543 | + * all mw.log statements will be removed on minification so lots of mw.log |
| 544 | + * calls will not impact performance in non debug mode |
| 545 | + * |
| 546 | + * @param {String} |
| 547 | + * string String to output to console |
| 548 | + */ |
| 549 | + mw.log = function( string ) { |
| 550 | + // Add any prepend debug strings if necessary |
| 551 | + if ( mw.getConfig( 'pre-append-log' ) ){ |
| 552 | + string = mw.getConfig( 'pre-append-log' ) + string; |
| 553 | + } |
| 554 | + |
| 555 | + if ( window.console ) { |
| 556 | + window.console.log( string ); |
| 557 | + } else { |
| 558 | + /** |
| 559 | + * Old IE and non-Firebug debug: ( commented out for now ) |
| 560 | + */ |
| 561 | + /*var log_elm = document.getElementById('mv_js_log'); |
| 562 | + if(!log_elm) { |
| 563 | + document.getElementsByTagName("body")[0].innerHTML += '<div ' + |
| 564 | + 'style="position:absolute;z-index:500;bottom:0px;left:0px;right:0px;height:200px;">' + |
| 565 | + '<textarea id="mv_js_log" cols="120" rows="12"></textarea>' + |
| 566 | + '</div>'; |
| 567 | + } |
| 568 | + var log_elm = document.getElementById('mv_js_log'); |
| 569 | + if(log_elm) { |
| 570 | + log_elm.value+=string+"\n"; |
| 571 | + }*/ |
| 572 | + } |
| 573 | + } |
| 574 | + |
| 575 | + |
| 576 | + /** |
| 577 | + * This will get called when the DOM is ready Will check configuration and |
| 578 | + * issue a mw.setupMwEmbed call if needed |
| 579 | + */ |
| 580 | + // Flag to register the domReady has been called |
| 581 | + var mwDomReadyFlag = false; |
| 582 | + mw.domReady = function ( ) { |
| 583 | + if( mwDomReadyFlag ) { |
| 584 | + return ; |
| 585 | + } |
| 586 | + // Set the onDomReady Flag |
| 587 | + mwDomReadyFlag = true; |
| 588 | + mw.setupMwEmbed(); |
| 589 | + } |
| 590 | + |
| 591 | + /** |
| 592 | + * Set DOM-ready call We copy jQuery( document ).ready here since sometimes |
| 593 | + * mwEmbed.js is included without jQuery and we need our own "ready" system so |
| 594 | + * that mwEmbed interfaces can support async built out and the include of |
| 595 | + * jQuery. |
| 596 | + */ |
| 597 | + var mwDomIsReady = false; |
| 598 | + function runMwDomReady(){ |
| 599 | + mwDomIsReady = true; |
| 600 | + if( mw.domReady ){ |
| 601 | + mw.domReady() |
| 602 | + } |
| 603 | + } |
| 604 | + // Check if already ready: |
| 605 | + if ( document.readyState === "complete" ) { |
| 606 | + runMwDomReady(); |
| 607 | + } |
| 608 | + |
| 609 | + // Cleanup functions for the document ready method |
| 610 | + if ( document.addEventListener ) { |
| 611 | + DOMContentLoaded = function() { |
| 612 | + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); |
| 613 | + runMwDomReady(); |
| 614 | + }; |
| 615 | + |
| 616 | + } else if ( document.attachEvent ) { |
| 617 | + DOMContentLoaded = function() { |
| 618 | + // Make sure body exists, at least, in case IE gets a little overzealous |
| 619 | + // (ticket #5443). |
| 620 | + if ( document.readyState === "complete" ) { |
| 621 | + document.detachEvent( "onreadystatechange", DOMContentLoaded ); |
| 622 | + runMwDomReady(); |
| 623 | + } |
| 624 | + }; |
| 625 | + } |
| 626 | + // Mozilla, Opera and webkit currently support this event |
| 627 | + if ( document.addEventListener ) { |
| 628 | + // Use the handy event callback |
| 629 | + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); |
| 630 | + |
| 631 | + // A fallback to window.onload, that will always work |
| 632 | + window.addEventListener( "load", mw.domReady, false ); |
| 633 | + |
| 634 | + // If IE event model is used |
| 635 | + } else if ( document.attachEvent ) { |
| 636 | + // ensure firing before onload, |
| 637 | + // maybe late but safe also for iframes |
| 638 | + document.attachEvent("onreadystatechange", DOMContentLoaded); |
| 639 | + |
| 640 | + // A fallback to window.onload, that will always work |
| 641 | + window.attachEvent( "onload", runMwDomReady ); |
| 642 | + |
| 643 | + // If IE and not a frame |
| 644 | + // continually check to see if the document is ready |
| 645 | + var toplevel = false; |
| 646 | + |
| 647 | + try { |
| 648 | + toplevel = window.frameElement == null; |
| 649 | + } catch(e) {} |
| 650 | + |
| 651 | + if ( document.documentElement.doScroll && toplevel ) { |
| 652 | + doScrollCheck(); |
| 653 | + } |
| 654 | + } |
| 655 | + // The DOM ready check for Internet Explorer |
| 656 | + function doScrollCheck() { |
| 657 | + if ( mwDomIsReady ) { |
| 658 | + return; |
| 659 | + } |
| 660 | + |
| 661 | + try { |
| 662 | + // If IE is used, use the trick by Diego Perini |
| 663 | + // http://javascript.nwbox.com/IEContentLoaded/ |
| 664 | + document.documentElement.doScroll("left"); |
| 665 | + } catch( error ) { |
| 666 | + setTimeout( doScrollCheck, 1 ); |
| 667 | + return; |
| 668 | + } |
| 669 | + |
| 670 | + // and execute any waiting functions |
| 671 | + runMwDomReady(); |
| 672 | + } |
| 673 | + |
| 674 | + |
| 675 | +} )( window.mw ); |
| 676 | + |
| 677 | + |
| 678 | + |
| 679 | + |
Property changes on: trunk/extensions/MwEmbed/MwEmbed/mwEmbed.core.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 680 | + native |
Index: trunk/extensions/MwEmbed/MwEmbed/components/mw.Parser.js |
— | — | @@ -1,323 +0,0 @@ |
2 | | -/** |
3 | | -* Mediawiki language text parser |
4 | | -*/ |
5 | | - |
6 | | -// Setup swap string constants |
7 | | -var JQUERY_SWAP_STRING = 'ZjQuerySwapZ'; |
8 | | -var LINK_SWAP_STRING = 'ZreplaceZ'; |
9 | | - |
10 | | -( function( mw ) { |
11 | | - |
12 | | - // The parser magic global |
13 | | - var pMagicSet = { }; |
14 | | - |
15 | | - /** |
16 | | - * addTemplateTransform to the parser |
17 | | - * |
18 | | - * Lets you add a set template key to be transformed by a callback function |
19 | | - * |
20 | | - * @param {Object} magicSet key:callback |
21 | | - */ |
22 | | - mw.addTemplateTransform = function( magicSet ) { |
23 | | - for ( var i in magicSet ) { |
24 | | - pMagicSet[ i ] = magicSet[i]; |
25 | | - } |
26 | | - }; |
27 | | - |
28 | | - /** |
29 | | - * MediaWiki wikitext "Parser" constructor |
30 | | - * |
31 | | - * @param {String} wikiText the wikitext to be parsed |
32 | | - * @return {Object} parserObj returns a parser object that has methods for getting at |
33 | | - * things you would want |
34 | | - */ |
35 | | - mw.Parser = function( wikiText, options) { |
36 | | - // return the parserObj |
37 | | - this.init( wikiText, options ) ; |
38 | | - }; |
39 | | - |
40 | | - mw.Parser.prototype = { |
41 | | - |
42 | | - // the parser output string container |
43 | | - pOut: false, |
44 | | - |
45 | | - init: function( wikiText, parserOptions ) { |
46 | | - this.wikiText = wikiText; |
47 | | - }, |
48 | | - |
49 | | - // Update the text value |
50 | | - updateText : function( wikiText ) { |
51 | | - this.wikiText = wikiText; |
52 | | - |
53 | | - // invalidate the output ( will force a re-parse ) |
54 | | - this.pOut = false; |
55 | | - }, |
56 | | - |
57 | | - /** |
58 | | - * Quickly recursive / parse out templates: |
59 | | - */ |
60 | | - parse: function() { |
61 | | - function recurseTokenizeNodes ( text ) { |
62 | | - var node = { }; |
63 | | - // Inspect each char |
64 | | - for ( var a = 0; a < text.length; a++ ) { |
65 | | - if ( text[a] == '{' && text[a + 1] == '{' ) { |
66 | | - a = a + 2; |
67 | | - node['parent'] = node; |
68 | | - if ( !node['child'] ) { |
69 | | - node['child'] = new Array(); |
70 | | - } |
71 | | - |
72 | | - node['child'].push( recurseTokenizeNodes( text.substr( a ) ) ); |
73 | | - } else if ( text[a] == '}' && text[a + 1] == '}' ) { |
74 | | - a++; |
75 | | - if ( !node['parent'] ) { |
76 | | - return node; |
77 | | - } |
78 | | - node = node['parent']; |
79 | | - } |
80 | | - if ( !node['text'] ) { |
81 | | - node['text'] = ''; |
82 | | - } |
83 | | - // Don't put }} closures into output: |
84 | | - if ( text[a] && text[a] != '}' ) { |
85 | | - node['text'] += text[a]; |
86 | | - } |
87 | | - } |
88 | | - return node; |
89 | | - } |
90 | | - |
91 | | - /** |
92 | | - * Parse template text as template name and named params |
93 | | - * @param {String} templateString Template String to be parsed |
94 | | - */ |
95 | | - function parseTmplTxt( templateString ) { |
96 | | - var templateObject = { }; |
97 | | - |
98 | | - // Get template name: |
99 | | - templateName = templateString.split( '\|' ).shift() ; |
100 | | - templateName = templateName.split( '\{' ).shift() ; |
101 | | - templateName = templateName.replace( /^\s+|\s+$/g, "" ); //trim |
102 | | - |
103 | | - // Check for arguments: |
104 | | - if ( templateName.split( ':' ).length == 1 ) { |
105 | | - templateObject["name"] = templateName; |
106 | | - } else { |
107 | | - templateObject["name"] = templateName.split( ':' ).shift(); |
108 | | - templateObject["arg"] = templateName.split( ':' ).pop(); |
109 | | - } |
110 | | - |
111 | | - var paramSet = templateString.split( '\|' ); |
112 | | - paramSet.splice( 0, 1 ); |
113 | | - if ( paramSet.length ) { |
114 | | - templateObject.param = new Array(); |
115 | | - for ( var pInx in paramSet ) { |
116 | | - var paramString = paramSet[ pInx ]; |
117 | | - // check for empty param |
118 | | - if ( paramString == '' ) { |
119 | | - templateObject.param[ pInx ] = ''; |
120 | | - continue; |
121 | | - } |
122 | | - for ( var b = 0 ; b < paramString.length ; b++ ) { |
123 | | - if ( paramString[b] == '=' && b > 0 && b < paramString.length && paramString[b - 1] != '\\' ) { |
124 | | - // named param |
125 | | - templateObject.param[ paramString.split( '=' ).shift() ] = paramString.split( '=' ).pop(); |
126 | | - } else { |
127 | | - // indexed param |
128 | | - templateObject.param[ pInx ] = paramString; |
129 | | - } |
130 | | - } |
131 | | - } |
132 | | - } |
133 | | - return templateObject; |
134 | | - } |
135 | | - |
136 | | - /** |
137 | | - * Get the Magic text from a template node |
138 | | - */ |
139 | | - function getMagicTxtFromTempNode( node ) { |
140 | | - node.templateObject = parseTmplTxt ( node.text ); |
141 | | - // Do magic swap if template key found in pMagicSet |
142 | | - if ( node.templateObject.name in pMagicSet ) { |
143 | | - var nodeText = pMagicSet[ node.templateObject.name ]( node.templateObject ); |
144 | | - return nodeText; |
145 | | - } else { |
146 | | - // don't swap just return text |
147 | | - return node.text; |
148 | | - } |
149 | | - } |
150 | | - |
151 | | - /** |
152 | | - * swap links of form [ ] for html a links or jquery helper spans |
153 | | - * NOTE: this could be integrated into the tokenizer but for now |
154 | | - * is a staged process. |
155 | | - * |
156 | | - * @param text to swapped |
157 | | - */ |
158 | | - function linkSwapText( text ) { |
159 | | - //mw.log( "linkSwapText::" + text ); |
160 | | - var re = new RegExp( /\[([^\s]+[\s]+[^\]]*)\]/g ); |
161 | | - var matchSet = text.match( re ); |
162 | | - |
163 | | - if( !matchSet ){ |
164 | | - return text; |
165 | | - } |
166 | | - |
167 | | - text = text.replace( re , LINK_SWAP_STRING ); |
168 | | - |
169 | | - for( var i=0; i < matchSet.length; i++ ) { |
170 | | - // Strip the leading [ and trailing ] |
171 | | - var matchParts = matchSet[i].substr(1, matchSet[i].length-2); |
172 | | - |
173 | | - // Check for special jQuery type swap and replace inner JQUERY_SWAP_STRING not value |
174 | | - if( matchParts.indexOf( JQUERY_SWAP_STRING ) !== -1 ) { |
175 | | - // parse the link as html |
176 | | - var $matchParts = $j('<span>' + matchParts + '</span>' ); |
177 | | - |
178 | | - $jQuerySpan = $matchParts.find('#' +JQUERY_SWAP_STRING + i ); |
179 | | - |
180 | | - var linkText = $matchParts.text(); |
181 | | - //mw.log(" going to swap in linktext: " + linkText ); |
182 | | - $jQuerySpan.text( linkText ); |
183 | | - |
184 | | - text = text.replace( LINK_SWAP_STRING, $j('<span />' ).append( $jQuerySpan ).html() ); |
185 | | - } else { |
186 | | - // do text string replace |
187 | | - matchParts = matchParts.split(/ /); |
188 | | - var link = matchParts[0]; |
189 | | - matchParts.shift(); |
190 | | - var linkText = matchParts.join(' '); |
191 | | - |
192 | | - text = text.replace( LINK_SWAP_STRING, '<a href="' + link + '">' + linkText + '</a>' ); |
193 | | - } |
194 | | - } |
195 | | - return text; |
196 | | - } |
197 | | - |
198 | | - /** |
199 | | - * recurse_magic_swap |
200 | | - * |
201 | | - * Go last child first swap upward: |
202 | | - */ |
203 | | - var pNode = null; |
204 | | - function recurse_magic_swap( node ) { |
205 | | - if ( !pNode ) |
206 | | - pNode = node; |
207 | | - |
208 | | - if ( node['child'] ) { |
209 | | - // swap all the kids: |
210 | | - for ( var i in node['child'] ) { |
211 | | - var nodeText = recurse_magic_swap( node['child'][i] ); |
212 | | - // swap it into current |
213 | | - if ( node.text ) { |
214 | | - node.text = node.text.replace( node['child'][i].text, nodeText ); |
215 | | - } |
216 | | - // swap into parent |
217 | | - pNode.text = pNode.text.replace( node['child'][i].text, nodeText ); |
218 | | - } |
219 | | - // Get the updated node text |
220 | | - var nodeText = getMagicTxtFromTempNode( node ); |
221 | | - pNode.text = pNode.text.replace( node.text , nodeText ); |
222 | | - // return the node text |
223 | | - return node.text; |
224 | | - } else { |
225 | | - return getMagicTxtFromTempNode( node ); |
226 | | - } |
227 | | - } |
228 | | - |
229 | | - // Parse out the template node structure: |
230 | | - this.pNode = recurseTokenizeNodes ( this.wikiText ); |
231 | | - |
232 | | - // Strip out the parent from the root |
233 | | - this.pNode['parent'] = null; |
234 | | - |
235 | | - // Do the recursive magic swap text: |
236 | | - this.pOut = recurse_magic_swap( this.pNode ); |
237 | | - |
238 | | - // Do link swap |
239 | | - this.pOut = linkSwapText( this.pOut ); |
240 | | - }, |
241 | | - |
242 | | - /** |
243 | | - * templates |
244 | | - * |
245 | | - * Get a requested template from the wikitext (if available) |
246 | | - * @param templateName |
247 | | - */ |
248 | | - templates: function( templateName ) { |
249 | | - this.parse(); |
250 | | - var tmplSet = new Array(); |
251 | | - function getMatchingTmpl( node ) { |
252 | | - if ( node['child'] ) { |
253 | | - for ( var i in node['child'] ) { |
254 | | - getMatchingTmpl( node['child'] ); |
255 | | - } |
256 | | - } |
257 | | - if ( templateName && node.templateObject ) { |
258 | | - if ( node.templateObject['name'] == templateName ) |
259 | | - tmplSet.push( node.templateObject ); |
260 | | - } else if ( node.templateObject ) { |
261 | | - tmplSet.push( node.templateObject ); |
262 | | - } |
263 | | - } |
264 | | - getMatchingTmpl( this.pNode ); |
265 | | - return tmplSet; |
266 | | - }, |
267 | | - |
268 | | - /** |
269 | | - * getTemplateVars |
270 | | - * returns a set of template values in a given wikitext page |
271 | | - * |
272 | | - * NOTE: should be integrated with the usability wikitext parser |
273 | | - */ |
274 | | - getTemplateVars: function() { |
275 | | - //mw.log('matching against: ' + wikiText); |
276 | | - templateVars = new Array(); |
277 | | - var tempVars = wikiText.match(/\{\{\{([^\}]*)\}\}\}/gi); |
278 | | - |
279 | | - // Clean up results: |
280 | | - for(var i=0; i < tempVars.length; i++) { |
281 | | - //match |
282 | | - var tvar = tempVars[i].replace('{{{','').replace('}}}',''); |
283 | | - |
284 | | - // Strip anything after a | |
285 | | - if(tvar.indexOf('|') != -1) { |
286 | | - tvar = tvar.substr(0, tvar.indexOf('|')); |
287 | | - } |
288 | | - |
289 | | - // Check for duplicates: |
290 | | - var do_add=true; |
291 | | - for(var j=0; j < templateVars.length; j++) { |
292 | | - if( templateVars[j] == tvar) |
293 | | - do_add=false; |
294 | | - } |
295 | | - |
296 | | - // Add the template vars to the output obj |
297 | | - if(do_add) |
298 | | - templateVars.push( tvar ); |
299 | | - } |
300 | | - return templateVars; |
301 | | - }, |
302 | | - |
303 | | - /** |
304 | | - * Returns the transformed wikitext |
305 | | - * |
306 | | - * Build output from swappable index |
307 | | - * (all transforms must be expanded in parse stage and linearly rebuilt) |
308 | | - * Alternatively we could build output using a place-holder & replace system |
309 | | - * (this lets us be slightly more sloppy with ordering and indexes, but probably slower) |
310 | | - * |
311 | | - * Ideal: we build a 'wiki DOM' |
312 | | - * When editing you update the data structure directly |
313 | | - * Then in output time you just go DOM->html-ish output without re-parsing anything |
314 | | - */ |
315 | | - getHTML: function() { |
316 | | - // wikiText updates should invalidate pOut |
317 | | - if ( ! this.pOut ) { |
318 | | - this.parse(); |
319 | | - } |
320 | | - return this.pOut; |
321 | | - } |
322 | | - }; |
323 | | - |
324 | | -}) ( window.mw ); |
\ No newline at end of file |
Index: trunk/extensions/MwEmbed/MwEmbed/components/mw.Language.js |
— | — | @@ -1,1131 +0,0 @@ |
2 | | -/** |
3 | | -* Core Language mw.Language object |
4 | | -* |
5 | | -* Localized Language support attempts to mirror some of the functionality of Language.php in MediaWiki |
6 | | -* It contains methods for loading and transforming msg text |
7 | | - |
8 | | -*/ |
9 | | - |
10 | | -( function( mw ) { |
11 | | - |
12 | | - // Setup the global mw.Language var: |
13 | | - mw.Language = { }; |
14 | | - |
15 | | - /** |
16 | | - * Setup the lang object |
17 | | - */ |
18 | | - var messageCache = { }; |
19 | | - var gRuleSet = { }; |
20 | | - |
21 | | - /** |
22 | | - * mw.addMessages function |
23 | | - * Loads a set of json messages into the messegeCache object. |
24 | | - * |
25 | | - * @param {JSON} msgSet The set of msgs to be loaded |
26 | | - */ |
27 | | - mw.addMessages = function( msgSet ) { |
28 | | - for ( var i in msgSet ) { |
29 | | - messageCache[ i ] = msgSet[i]; |
30 | | - } |
31 | | - } |
32 | | - // By default set the current class missing messages flag to default. |
33 | | - mw.currentClassMissingMessages = false; |
34 | | - |
35 | | - /** |
36 | | - * mw.addMessagesKey function |
37 | | - * Adds a messageKey to be pulled in remotely. |
38 | | - * |
39 | | - * NOTE the script-loader should replace addMessageKeys with localized addMessages calls |
40 | | - * |
41 | | - * If addMessagesKey is called then we are running in raw file debug mode. |
42 | | - * it populates the messegeKeyQueue and loads the values in a separate request callback |
43 | | - * |
44 | | - * @param {Array} msgSet The set of msgs to be loaded |
45 | | - */ |
46 | | - mw.addMessageKeys = function( msgSet ) { |
47 | | - // Check if any msg key from this class is missing |
48 | | - for( i=0; i < msgSet.length; i++ ){ |
49 | | - msgKey = msgSet[i]; |
50 | | - if( ! messageCache[ msgKey ] ) { |
51 | | - // Set the missing messages flag |
52 | | - mw.currentClassMissingMessages = true; |
53 | | - return false; |
54 | | - } |
55 | | - } |
56 | | - return true; |
57 | | - } |
58 | | - |
59 | | - /** |
60 | | - * Special function to register that all of the module messages need to be loaded. |
61 | | - */ |
62 | | - mw.includeAllModuleMessages = function (){ |
63 | | - mw.currentClassMissingMessages = true; |
64 | | - } |
65 | | - |
66 | | - /** |
67 | | - * Load messages for a given named javascript class. |
68 | | - * This worked in conjunction with the scriptLoader |
69 | | - * @param {string} className Name of class file to be loaded |
70 | | - * @param {function} callback Function to be called once class messages are loaded. |
71 | | - */ |
72 | | - mw.loadResourceMessages = function( className, callback ) { |
73 | | - // Check if wgScriptLoaderPath is set ( else guess the path relative to mwEmbed) |
74 | | - if ( typeof wgScriptLoaderLocation == 'undefined' || ! wgScriptLoaderLocation ){ |
75 | | - wgScriptLoaderLocation = mw.getMwEmbedPath() + 'ResourceLoader.php'; |
76 | | - } |
77 | | - // Run the addMessages script-loader call |
78 | | - mw.getScript( wgScriptLoaderLocation + '?class=' + className + '&format=messages', callback); |
79 | | - } |
80 | | - |
81 | | - |
82 | | - /** |
83 | | - * Returns a transformed msg string |
84 | | - * |
85 | | - * it take a msg key and array of replacement values of form |
86 | | - * $1, $2 and does relevant messageKey transformation returning |
87 | | - * the user msg. |
88 | | - * |
89 | | - * @param {String} messageKey The msg key as set by mw.addMessages |
90 | | - * @param {Mixed} args A string|jQuery Object or array of string|jQuery Objects |
91 | | - * |
92 | | - * extra parameters are appended to the args array as numbered replacements |
93 | | - * |
94 | | - * @return string |
95 | | - */ |
96 | | - mw.getMsg = function( messageKey , args ) { |
97 | | - |
98 | | - // Check for missing message key |
99 | | - if ( ! messageCache[ messageKey ] ){ |
100 | | - return '[' + messageKey + ']'; |
101 | | - } |
102 | | - // Check if we need to do args replacements: |
103 | | - if( typeof args != 'undefined' ) { |
104 | | - |
105 | | - // Make arg into an array if its not already an array |
106 | | - if ( typeof args == 'string' |
107 | | - || typeof args == 'number' |
108 | | - || args instanceof jQuery ) |
109 | | - { |
110 | | - args = [ args ]; |
111 | | - } |
112 | | - |
113 | | - // Put any extra arguments into the args array |
114 | | - var extraArgs = $j.makeArray( arguments ); |
115 | | - for(var i=2; i < extraArgs.length; i ++ ) { |
116 | | - args.push( extraArgs[ i ] ); |
117 | | - } |
118 | | - } |
119 | | - // Fast check message text return ( no arguments and no parsing needed ) |
120 | | - if( ( !args || args.length == 0 ) |
121 | | - && messageCache[ messageKey ].indexOf( '{{' ) === -1 |
122 | | - && messageCache[ messageKey ].indexOf( '[' ) === -1 |
123 | | - ) { |
124 | | - return messageCache[ messageKey ]; |
125 | | - } |
126 | | - |
127 | | - // Else Setup the messageSwap object: |
128 | | - var messageSwap = new mw.Language.messageSwapObject( messageCache[ messageKey ], args ); |
129 | | - |
130 | | - // Return the jQuery object or message string |
131 | | - return messageSwap.getMsg(); |
132 | | - } |
133 | | - |
134 | | - /** |
135 | | - * A message Swap Object |
136 | | - * Swap object manages message type swapping and returns jQuery or text output |
137 | | - * |
138 | | - * @param {String} message The text of the message |
139 | | - * @param {array} arguments A set of swap arguments |
140 | | - */ |
141 | | - |
142 | | - mw.Language.messageSwapObject = function( message, arguments ){ |
143 | | - this.init( message, arguments ); |
144 | | - } |
145 | | - |
146 | | - mw.Language.messageSwapObject.prototype= { |
147 | | - /* constructor */ |
148 | | - init: function( message, arguments ){ |
149 | | - this.message = message; |
150 | | - this.arguments = arguments; |
151 | | - |
152 | | - // Set the includesjQueryArgs flag to false |
153 | | - includesjQueryArgs: false; |
154 | | - }, |
155 | | - |
156 | | - // Return the transformed message text or jQuery object |
157 | | - getMsg: function(){ |
158 | | - // Get message with string swap |
159 | | - this.replaceStringArgs(); |
160 | | - |
161 | | - // Check if we need to parse the string |
162 | | - if( this.message.indexOf( '{{' ) === -1 |
163 | | - && this.message.indexOf( '[' ) === -1 |
164 | | - && ! this.includesjQueryArgs ) |
165 | | - { |
166 | | - // replaceStringArgs is all we need, return the msg |
167 | | - return this.message |
168 | | - } |
169 | | - |
170 | | - // Else Send the messageText through the parser |
171 | | - var pObj = new mw.Parser( this.message ); |
172 | | - |
173 | | - // Get template and link transformed text: |
174 | | - this.message = pObj.getHTML(); |
175 | | - |
176 | | - // if jQuery arguments is false return message string |
177 | | - if(! this.includesjQueryArgs ){ |
178 | | - //Do string link substitution |
179 | | - return this.message; |
180 | | - } |
181 | | - |
182 | | - // jQuery arguments exist swap and return jQuery object |
183 | | - return this.getJQueryArgsReplace(); |
184 | | - |
185 | | - }, |
186 | | - |
187 | | - /** |
188 | | - * Swap in an array of values for $1, $2, $n for a given msg key |
189 | | - * |
190 | | - * @param string messageKey The msg key to lookup |
191 | | - * @param {Array} args An array of string or jQuery objects to be swapped in |
192 | | - * @return string |
193 | | - */ |
194 | | - replaceStringArgs : function() { |
195 | | - if( ! this.arguments ) { |
196 | | - return ; |
197 | | - } |
198 | | - // Replace Values |
199 | | - for ( var v = 0; v < this.arguments.length; v++ ) { |
200 | | - if( typeof this.arguments[v] == 'undefined' ) { |
201 | | - continue; |
202 | | - } |
203 | | - var replaceValue = this.arguments[ v ]; |
204 | | - |
205 | | - // Convert number if applicable |
206 | | - if( parseInt( replaceValue ) == replaceValue ) { |
207 | | - replaceValue = mw.Language.convertNumber( replaceValue ); |
208 | | - } |
209 | | - |
210 | | - // Message test replace arguments start at 1 instead of zero: |
211 | | - var argumentRegExp = new RegExp( '\\$' + ( parseInt( v ) + 1 ), 'g' ); |
212 | | - |
213 | | - // Check if we got passed in a jQuery object: |
214 | | - if( replaceValue instanceof jQuery) { |
215 | | - // Set the jQuery msg flag |
216 | | - this.includesjQueryArgs = true; |
217 | | - // Swap in a jQuery span place holder: |
218 | | - this.message = this.message.replace( argumentRegExp, |
219 | | - '<span id="' + JQUERY_SWAP_STRING + v +'"></span>' ); |
220 | | - } else { |
221 | | - // Assume replaceValue is a string |
222 | | - this.message = this.message.replace( argumentRegExp, replaceValue ); |
223 | | - } |
224 | | - } |
225 | | - }, |
226 | | - |
227 | | - /** |
228 | | - * Return a jquery element with resolved swapped arguments. |
229 | | - * return {Element} |
230 | | - */ |
231 | | - getJQueryArgsReplace: function() { |
232 | | - var $jQueryMessage = false; |
233 | | - mw.log( 'msgReplaceJQueryArgs' ); |
234 | | - for ( var v = 0; v < this.arguments.length; v++ ) { |
235 | | - if( typeof this.arguments[v] == 'undefined' ) { |
236 | | - continue; |
237 | | - } |
238 | | - var $replaceValue = this.arguments[ v ]; |
239 | | - // Only look for jQuery replacements |
240 | | - if( $replaceValue instanceof jQuery) { |
241 | | - // Setup the jqueryMessage if not set |
242 | | - if( !$jQueryMessage ){ |
243 | | - // Setup the message as html to search for jquery swap points |
244 | | - $jQueryMessage = $j( '<span />' ).html( this.message ); |
245 | | - } |
246 | | - mw.log(" current jQueryMessage::: " + $jQueryMessage.html() ); |
247 | | - // Find swap target |
248 | | - var $swapTarget = $jQueryMessage.find( '#' + JQUERY_SWAP_STRING + v ); |
249 | | - // Now we try and find the jQuerySwap points and replace with jQuery object preserving bindings. |
250 | | - if( ! $swapTarget.length ){ |
251 | | - mw.log( "Error could not find jQuery Swap target: " + v + ' by id: '+ JQUERY_SWAP_STRING + v |
252 | | - + ' In string: ' + this.message ) ; |
253 | | - continue; |
254 | | - } |
255 | | - |
256 | | - if( $swapTarget.html() != '' ) { |
257 | | - $replaceValue.html( $swapTarget.html() ); |
258 | | - } |
259 | | - |
260 | | - // Swap for $swapTarget for $replaceValue swap target * preserving the jQuery binding ) |
261 | | - $swapTarget.replaceWith( $replaceValue ); |
262 | | - } |
263 | | - } |
264 | | - // Return the jQuery object ( if no jQuery substitution occurred we return false ) |
265 | | - return $jQueryMessage; |
266 | | - } |
267 | | - } |
268 | | - |
269 | | - /** |
270 | | - * Get msg content without transformation |
271 | | - * |
272 | | - * @returns string The msg key without transforming it |
273 | | - */ |
274 | | - mw.Language.msgNoTrans = function( key ) { |
275 | | - if ( messageCache[ key ] ) |
276 | | - return messageCache[ key ] |
277 | | - |
278 | | - // Missing key placeholder |
279 | | - return '<' + key + '>'; |
280 | | - } |
281 | | - /** |
282 | | - * Check if a message key is defined |
283 | | - * @return {Boolean} true if msg is defined, false if msg is not set |
284 | | - */ |
285 | | - mw.Language.isMsgKeyDefined = function( msgKey ){ |
286 | | - if( messageCache[ msgKey ] ){ |
287 | | - return true |
288 | | - } |
289 | | - return false; |
290 | | - } |
291 | | - |
292 | | - /** |
293 | | - * Add Supported Magic Words to parser |
294 | | - */ |
295 | | - // Set the setupflag to false: |
296 | | - mw.Language.doneSetup = false; |
297 | | - mw.Language.magicSetup = function() { |
298 | | - if ( !mw.Language.doneSetup ) { |
299 | | - mw.addTemplateTransform ( { |
300 | | - 'PLURAL' : mw.Language.procPLURAL, |
301 | | - 'GENDER' : mw.Language.procGENDER |
302 | | - } ) |
303 | | - |
304 | | - mw.Language.doneSetup = true; |
305 | | - } |
306 | | - |
307 | | - } |
308 | | - |
309 | | - /** |
310 | | - * Plural form transformations, needed for some languages. |
311 | | - * For example, there are 3 form of plural in Russian and Polish, |
312 | | - * depending on "count mod 10". See [[w:Plural]] |
313 | | - * For English it is pretty simple. |
314 | | - * |
315 | | - * Invoked by putting {{plural:count|wordform1|wordform2}} |
316 | | - * or {{plural:count|wordform1|wordform2|wordform3}} |
317 | | - * |
318 | | - * Example: {{plural:{{NUMBEROFARTICLES}}|article|articles}} |
319 | | - * |
320 | | - * @param count Integer: non-localized number |
321 | | - * @param forms Array: different plural forms |
322 | | - * @return string Correct form of plural for count in this language |
323 | | - */ |
324 | | - |
325 | | - /** |
326 | | - * Base gender transform function |
327 | | - */ |
328 | | - mw.Language.gender = function( gender, forms ) { |
329 | | - if ( ! forms.length ) { |
330 | | - return ''; |
331 | | - } |
332 | | - forms = mw.Language.preConvertPlural( forms, 2 ); |
333 | | - if ( gender === 'male' ) return forms[0]; |
334 | | - if ( gender === 'female' ) return forms[1]; |
335 | | - return ( forms[2] ) ? forms[2] : forms[0]; |
336 | | - }; |
337 | | - |
338 | | - /** |
339 | | - * Process the PLURAL template substitution |
340 | | - * @param {Object} template Template object |
341 | | - * |
342 | | - * {{Template:argument|params}} |
343 | | - * |
344 | | - * Template object should include: |
345 | | - * [arg] The argument sent to the template |
346 | | - * [params] The template parameters |
347 | | - */ |
348 | | - mw.Language.procPLURAL = function( templateObject ) { |
349 | | - // Setup shortcuts |
350 | | - // ( gRuleSet is loaded from script-loader to contains local ruleset ) |
351 | | - var rs = gRuleSet[ 'PLURAL' ]; |
352 | | - |
353 | | - if( templateObject.arg && templateObject.param && mw.Language.convertPlural) { |
354 | | - // Check if we have forms to replace |
355 | | - if ( templateObject.param.length == 0 ) { |
356 | | - return ''; |
357 | | - } |
358 | | - // Restore the count into a Number ( if it got converted earlier ) |
359 | | - var count = mw.Language.convertNumber( templateObject.arg, true ); |
360 | | - |
361 | | - // Do convertPlural call |
362 | | - return mw.Language.convertPlural( parseInt( count ), templateObject.param ); |
363 | | - |
364 | | - } |
365 | | - // Could not process plural return first form or nothing |
366 | | - if( templateObject.param[0] ) { |
367 | | - return templateObject.param[0]; |
368 | | - } |
369 | | - return ''; |
370 | | - }; |
371 | | - |
372 | | - // NOTE:: add gender support here |
373 | | - mw.Language.procGENDER = function( templateObject ){ |
374 | | - return 'gender-not-supported-in-js-yet'; |
375 | | - } |
376 | | - /* |
377 | | - * Base convertPlural function: |
378 | | - */ |
379 | | - mw.Language.convertPlural = function( count, forms ){ |
380 | | - if ( !forms || forms.length == 0 ) { |
381 | | - return ''; |
382 | | - } |
383 | | - return ( parseInt( count ) == 1 ) ? forms[0] : forms[1]; |
384 | | - }; |
385 | | - /** |
386 | | - * Checks that convertPlural was given an array and pads it to requested |
387 | | - * amount of forms by copying the last one. |
388 | | - * |
389 | | - * @param {Array} forms Forms given to convertPlural |
390 | | - * @param {Integer} count How many forms should there be at least |
391 | | - * @return {Array} Padded array of forms or an exception if not an array |
392 | | - */ |
393 | | - mw.Language.preConvertPlural = function( forms, count ) { |
394 | | - while ( forms.length < count ) { |
395 | | - forms.push( forms[ forms.length-1 ] ); |
396 | | - } |
397 | | - return forms; |
398 | | - }; |
399 | | - |
400 | | - /** |
401 | | - * Init the digitTransformTable ( populated by language classes where applicable ) |
402 | | - */ |
403 | | - mw.Language.digitTransformTable = null; |
404 | | - |
405 | | - /** |
406 | | - * Convert a number using the digitTransformTable |
407 | | - * @param Number number to be converted |
408 | | - * @param Bollean typeInt if we should return a number of type int |
409 | | - */ |
410 | | - mw.Language.convertNumber = function( number, typeInt ) { |
411 | | - if( !mw.Language.digitTransformTable ) |
412 | | - return number; |
413 | | - |
414 | | - // Set the target Transform table: |
415 | | - var transformTable = mw.Language.digitTransformTable; |
416 | | - |
417 | | - // Check if the "restore" to latin number flag is set: |
418 | | - if( typeInt ) { |
419 | | - if( parseInt( number ) == number ) |
420 | | - return number; |
421 | | - var tmp = []; |
422 | | - for( var i in transformTable ) { |
423 | | - tmp[ transformTable[ i ] ] = i; |
424 | | - } |
425 | | - transformTable = tmp; |
426 | | - } |
427 | | - |
428 | | - var numberString = '' + number; |
429 | | - var convertedNumber = ''; |
430 | | - for( var i =0; i < numberString.length; i++) { |
431 | | - if( transformTable[ numberString[i] ] ) { |
432 | | - convertedNumber += transformTable[ numberString[i] ]; |
433 | | - }else{ |
434 | | - convertedNumber += numberString[i]; |
435 | | - } |
436 | | - } |
437 | | - return ( typeInt )? parseInt( convertedNumber) : convertedNumber; |
438 | | - } |
439 | | - |
440 | | - /** |
441 | | - * Checks if a language key is valid ( is part of languageCodeList ) |
442 | | - * @param {String} langKey Language key to be checked |
443 | | - * @return true if valid language, false if not |
444 | | - */ |
445 | | - mw.isValidLang = function( langKey ) { |
446 | | - return ( mw.Language.names[ langKey ] )? true : false; |
447 | | - } |
448 | | - |
449 | | - /** |
450 | | - * Get a language transform key |
451 | | - * returns default "en" fallback if none found |
452 | | - * @param String langKey The language key to be checked |
453 | | - */ |
454 | | - mw.getLangTransformKey = function( langKey ) { |
455 | | - if( mw.Language.fallbackTransformMap[ langKey ] ) { |
456 | | - langKey = mw.Language.fallbackTransformMap[ langKey ]; |
457 | | - } |
458 | | - // Make sure the langKey has a transformClass: |
459 | | - for( var i = 0; i < mw.Language.transformClass.length ; i++ ) { |
460 | | - if( langKey == mw.Language.transformClass[i] ){ |
461 | | - return langKey |
462 | | - } |
463 | | - } |
464 | | - // By default return the base 'en' class |
465 | | - return 'en'; |
466 | | - } |
467 | | - |
468 | | - /** |
469 | | - * getRemoteMsg loads remote msg strings |
470 | | - * |
471 | | - * @param {Mixed} msgSet the set of msg to load remotely |
472 | | - * @param function callback the callback to issue once string is ready |
473 | | - */ |
474 | | - mw.getRemoteMsg = function( msgSet, callback ) { |
475 | | - var ammessages = ''; |
476 | | - if ( typeof msgSet == 'object' ) { |
477 | | - for ( var i in msgSet ) { |
478 | | - if( !messageCache[ i ] ) { |
479 | | - ammessages += msgSet[i] + '|'; |
480 | | - } |
481 | | - } |
482 | | - } else if ( typeof msgSet == 'string' ) { |
483 | | - if( !messageCache[ i ] ) { |
484 | | - ammessages += msgSet; |
485 | | - } |
486 | | - } |
487 | | - if ( ammessages == '' ) { |
488 | | - mw.log( 'no remote msgs to get' ); |
489 | | - callback(); |
490 | | - return false; |
491 | | - } |
492 | | - var request = { |
493 | | - 'meta': 'allmessages', |
494 | | - 'ammessages': ammessages |
495 | | - } |
496 | | - mw.getJSON( request, function( data ) { |
497 | | - if ( data.query.allmessages ) { |
498 | | - var msgs = data.query.allmessages; |
499 | | - for ( var i in msgs ) { |
500 | | - var ld = { }; |
501 | | - ld[ msgs[i]['name'] ] = msgs[i]['*']; |
502 | | - mw.addMessages( ld ); |
503 | | - } |
504 | | - } |
505 | | - callback(); |
506 | | - } ); |
507 | | - } |
508 | | - |
509 | | - /** |
510 | | - * Format a size in bytes for output, using an appropriate |
511 | | - * unit (B, KB, MB or GB) according to the magnitude in question |
512 | | - * |
513 | | - * @param size Size to format |
514 | | - * @return string Plain text (not HTML) |
515 | | - */ |
516 | | - mw.Language.formatSize = function ( size ) { |
517 | | - // For small sizes no decimal places are necessary |
518 | | - var round = 0; |
519 | | - var msg = ''; |
520 | | - if ( size > 1024 ) { |
521 | | - size = size / 1024; |
522 | | - if ( size > 1024 ) { |
523 | | - size = size / 1024; |
524 | | - // For MB and bigger two decimal places are smarter |
525 | | - round = 2; |
526 | | - if ( size > 1024 ) { |
527 | | - size = size / 1024; |
528 | | - msg = 'mwe-size-gigabytes'; |
529 | | - } else { |
530 | | - msg = 'mwe-size-megabytes'; |
531 | | - } |
532 | | - } else { |
533 | | - msg = 'mwe-size-kilobytes'; |
534 | | - } |
535 | | - } else { |
536 | | - msg = 'mwe-size-bytes'; |
537 | | - } |
538 | | - // JavaScript does not let you choose the precision when rounding |
539 | | - var p = Math.pow( 10, round ); |
540 | | - size = Math.round( size * p ) / p; |
541 | | - return gM( msg , size ); |
542 | | - }; |
543 | | - |
544 | | - /** |
545 | | - * Format a number |
546 | | - * @param {Number} num Number to be formated |
547 | | - * NOTE: add il8n support to lanuages/class/Language{langCode}.js |
548 | | - */ |
549 | | - mw.Language.formatNumber = function( num ) { |
550 | | - /* |
551 | | - * addSeparatorsNF |
552 | | - * @param Str: The number to be formatted, as a string or number. |
553 | | - * @param outD: The decimal character for the output, such as ',' for the number 100,2 |
554 | | - * @param sep: The separator character for the output, such as ',' for the number 1,000.2 |
555 | | - */ |
556 | | - function addSeparatorsNF( nStr, outD, sep ) { |
557 | | - nStr += ''; |
558 | | - var dpos = nStr.indexOf( '.' ); |
559 | | - var nStrEnd = ''; |
560 | | - if ( dpos != -1 ) { |
561 | | - nStrEnd = outD + nStr.substring( dpos + 1, nStr.length ); |
562 | | - nStr = nStr.substring( 0, dpos ); |
563 | | - } |
564 | | - var rgx = /(\d+)(\d{3})/; |
565 | | - while ( rgx.test( nStr ) ) { |
566 | | - nStr = nStr.replace( rgx, '$1' + sep + '$2' ); |
567 | | - } |
568 | | - return nStr + nStrEnd; |
569 | | - } |
570 | | - // @@todo read language code and give periods or comas: |
571 | | - return addSeparatorsNF( num, '.', ',' ); |
572 | | - } |
573 | | - |
574 | | - |
575 | | - /** |
576 | | - * List of all languages mediaWiki supports ( Avoid an api call to get this same info ) |
577 | | - * http://commons.wikimedia.org/w/api.php?action=query&meta=siteinfo&siprop=languages&format=jsonfm |
578 | | - */ |
579 | | - mw.Language.names = { |
580 | | - "aa" : "Qaf\u00e1r af", |
581 | | - "ab" : "\u0410\u04a7\u0441\u0443\u0430", |
582 | | - "ace" : "Ac\u00e8h", |
583 | | - "af" : "Afrikaans", |
584 | | - "ak" : "Akan", |
585 | | - "aln" : "Geg\u00eb", |
586 | | - "als" : "Alemannisch", |
587 | | - "am" : "\u12a0\u121b\u122d\u129b", |
588 | | - "an" : "Aragon\u00e9s", |
589 | | - "ang" : "Anglo-Saxon", |
590 | | - "ar" : "\u0627\u0644\u0639\u0631\u0628\u064a\u0629", |
591 | | - "arc" : "\u0710\u072a\u0721\u071d\u0710", |
592 | | - "arn" : "Mapudungun", |
593 | | - "arz" : "\u0645\u0635\u0631\u0649", |
594 | | - "as" : "\u0985\u09b8\u09ae\u09c0\u09af\u09bc\u09be", |
595 | | - "ast" : "Asturianu", |
596 | | - "av" : "\u0410\u0432\u0430\u0440", |
597 | | - "avk" : "Kotava", |
598 | | - "ay" : "Aymar aru", |
599 | | - "az" : "Az\u0259rbaycan", |
600 | | - "ba" : "\u0411\u0430\u0448\u04a1\u043e\u0440\u0442", |
601 | | - "bar" : "Boarisch", |
602 | | - "bat-smg" : "\u017demait\u0117\u0161ka", |
603 | | - "bcc" : "\u0628\u0644\u0648\u0686\u06cc \u0645\u06a9\u0631\u0627\u0646\u06cc", |
604 | | - "bcl" : "Bikol Central", |
605 | | - "be" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f", |
606 | | - "be-tarask" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)", |
607 | | - "be-x-old" : "\u0411\u0435\u043b\u0430\u0440\u0443\u0441\u043a\u0430\u044f (\u0442\u0430\u0440\u0430\u0448\u043a\u0435\u0432\u0456\u0446\u0430)", |
608 | | - "bg" : "\u0411\u044a\u043b\u0433\u0430\u0440\u0441\u043a\u0438", |
609 | | - "bh" : "\u092d\u094b\u091c\u092a\u0941\u0930\u0940", |
610 | | - "bi" : "Bislama", |
611 | | - "bm" : "Bamanankan", |
612 | | - "bn" : "\u09ac\u09be\u0982\u09b2\u09be", |
613 | | - "bo" : "\u0f56\u0f7c\u0f51\u0f0b\u0f61\u0f72\u0f42", |
614 | | - "bpy" : "\u0987\u09ae\u09be\u09b0 \u09a0\u09be\u09b0\/\u09ac\u09bf\u09b7\u09cd\u09a3\u09c1\u09aa\u09cd\u09b0\u09bf\u09af\u09bc\u09be \u09ae\u09a3\u09bf\u09aa\u09c1\u09b0\u09c0", |
615 | | - "bqi" : "\u0628\u062e\u062a\u064a\u0627\u0631\u064a", |
616 | | - "br" : "Brezhoneg", |
617 | | - "bs" : "Bosanski", |
618 | | - "bug" : "\u1a05\u1a14 \u1a15\u1a18\u1a01\u1a17", |
619 | | - "bxr" : "\u0411\u0443\u0440\u044f\u0430\u0434", |
620 | | - "ca" : "Catal\u00e0", |
621 | | - "cbk-zam" : "Chavacano de Zamboanga", |
622 | | - "cdo" : "M\u00ecng-d\u0115\u0324ng-ng\u1e73\u0304", |
623 | | - "ce" : "\u041d\u043e\u0445\u0447\u0438\u0439\u043d", |
624 | | - "ceb" : "Cebuano", |
625 | | - "ch" : "Chamoru", |
626 | | - "cho" : "Choctaw", |
627 | | - "chr" : "\u13e3\u13b3\u13a9", |
628 | | - "chy" : "Tsets\u00eahest\u00e2hese", |
629 | | - "ckb" : "Soran\u00ee \/ \u06a9\u0648\u0631\u062f\u06cc", |
630 | | - "ckb-latn" : "\u202aSoran\u00ee (lat\u00een\u00ee)\u202c", |
631 | | - "ckb-arab" : "\u202b\u06a9\u0648\u0631\u062f\u06cc (\u0639\u06d5\u0631\u06d5\u0628\u06cc)\u202c", |
632 | | - "co" : "Corsu", |
633 | | - "cr" : "N\u0113hiyaw\u0113win \/ \u14c0\u1426\u1403\u152d\u140d\u140f\u1423", |
634 | | - "crh" : "Q\u0131r\u0131mtatarca", |
635 | | - "crh-latn" : "\u202aQ\u0131r\u0131mtatarca (Latin)\u202c", |
636 | | - "crh-cyrl" : "\u202a\u041a\u044a\u044b\u0440\u044b\u043c\u0442\u0430\u0442\u0430\u0440\u0434\u0436\u0430 (\u041a\u0438\u0440\u0438\u043b\u043b)\u202c", |
637 | | - "cs" : "\u010cesky", |
638 | | - "csb" : "Kasz\u00ebbsczi", |
639 | | - "cu" : "\u0421\u043b\u043e\u0432\u0463\u0301\u043d\u044c\u0441\u043a\u044a \/ \u2c14\u2c0e\u2c11\u2c02\u2c21\u2c10\u2c20\u2c14\u2c0d\u2c1f", |
640 | | - "cv" : "\u0427\u04d1\u0432\u0430\u0448\u043b\u0430", |
641 | | - "cy" : "Cymraeg", |
642 | | - "da" : "Dansk", |
643 | | - "de" : "Deutsch", |
644 | | - "de-at" : "\u00d6sterreichisches Deutsch", |
645 | | - "de-ch" : "Schweizer Hochdeutsch", |
646 | | - "de-formal" : "Deutsch (Sie-Form)", |
647 | | - "diq" : "Zazaki", |
648 | | - "dk" : "Dansk (deprecated:da)", |
649 | | - "dsb" : "Dolnoserbski", |
650 | | - "dv" : "\u078b\u07a8\u0788\u07ac\u0780\u07a8\u0784\u07a6\u0790\u07b0", |
651 | | - "dz" : "\u0f47\u0f7c\u0f44\u0f0b\u0f41", |
652 | | - "ee" : "E\u028begbe", |
653 | | - "el" : "\u0395\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u03ac", |
654 | | - "eml" : "Emili\u00e0n e rumagn\u00f2l", |
655 | | - "en" : "English", |
656 | | - "en-gb" : "British English", |
657 | | - "eo" : "Esperanto", |
658 | | - "es" : "Espa\u00f1ol", |
659 | | - "et" : "Eesti", |
660 | | - "eu" : "Euskara", |
661 | | - "ext" : "Estreme\u00f1u", |
662 | | - "fa" : "\u0641\u0627\u0631\u0633\u06cc", |
663 | | - "ff" : "Fulfulde", |
664 | | - "fi" : "Suomi", |
665 | | - "fiu-vro" : "V\u00f5ro", |
666 | | - "fj" : "Na Vosa Vakaviti", |
667 | | - "fo" : "F\u00f8royskt", |
668 | | - "fr" : "Fran\u00e7ais", |
669 | | - "frc" : "Fran\u00e7ais cadien", |
670 | | - "frp" : "Arpetan", |
671 | | - "fur" : "Furlan", |
672 | | - "fy" : "Frysk", |
673 | | - "ga" : "Gaeilge", |
674 | | - "gag" : "Gagauz", |
675 | | - "gan" : "\u8d1b\u8a9e", |
676 | | - "gan-hans" : "\u8d63\u8bed(\u7b80\u4f53)", |
677 | | - "gan-hant" : "\u8d1b\u8a9e(\u7e41\u9ad4)", |
678 | | - "gd" : "G\u00e0idhlig", |
679 | | - "gl" : "Galego", |
680 | | - "glk" : "\u06af\u06cc\u0644\u06a9\u06cc", |
681 | | - "gn" : "Ava\u00f1e'\u1ebd", |
682 | | - "got" : "\ud800\udf32\ud800\udf3f\ud800\udf44\ud800\udf39\ud800\udf43\ud800\udf3a", |
683 | | - "grc" : "\u1f08\u03c1\u03c7\u03b1\u03af\u03b1 \u1f11\u03bb\u03bb\u03b7\u03bd\u03b9\u03ba\u1f74", |
684 | | - "gsw" : "Alemannisch", |
685 | | - "gu" : "\u0a97\u0ac1\u0a9c\u0ab0\u0abe\u0aa4\u0ac0", |
686 | | - "gv" : "Gaelg", |
687 | | - "ha" : "\u0647\u064e\u0648\u064f\u0633\u064e", |
688 | | - "hak" : "Hak-k\u00e2-fa", |
689 | | - "haw" : "Hawai`i", |
690 | | - "he" : "\u05e2\u05d1\u05e8\u05d9\u05ea", |
691 | | - "hi" : "\u0939\u093f\u0928\u094d\u0926\u0940", |
692 | | - "hif" : "Fiji Hindi", |
693 | | - "hif-deva" : "\u092b\u093c\u0940\u091c\u0940 \u0939\u093f\u0928\u094d\u0926\u0940", |
694 | | - "hif-latn" : "Fiji Hindi", |
695 | | - "hil" : "Ilonggo", |
696 | | - "ho" : "Hiri Motu", |
697 | | - "hr" : "Hrvatski", |
698 | | - "hsb" : "Hornjoserbsce", |
699 | | - "ht" : "Krey\u00f2l ayisyen", |
700 | | - "hu" : "Magyar", |
701 | | - "hy" : "\u0540\u0561\u0575\u0565\u0580\u0565\u0576", |
702 | | - "hz" : "Otsiherero", |
703 | | - "ia" : "Interlingua", |
704 | | - "id" : "Bahasa Indonesia", |
705 | | - "ie" : "Interlingue", |
706 | | - "ig" : "Igbo", |
707 | | - "ii" : "\ua187\ua259", |
708 | | - "ik" : "I\u00f1upiak", |
709 | | - "ike-cans" : "\u1403\u14c4\u1483\u144e\u1450\u1466", |
710 | | - "ike-latn" : "inuktitut", |
711 | | - "ilo" : "Ilokano", |
712 | | - "inh" : "\u0413\u0406\u0430\u043b\u0433\u0406\u0430\u0439 \u011eal\u011faj", |
713 | | - "io" : "Ido", |
714 | | - "is" : "\u00cdslenska", |
715 | | - "it" : "Italiano", |
716 | | - "iu" : "\u1403\u14c4\u1483\u144e\u1450\u1466\/inuktitut", |
717 | | - "ja" : "\u65e5\u672c\u8a9e", |
718 | | - "jbo" : "Lojban", |
719 | | - "jut" : "Jysk", |
720 | | - "jv" : "Basa Jawa", |
721 | | - "ka" : "\u10e5\u10d0\u10e0\u10d7\u10e3\u10da\u10d8", |
722 | | - "kaa" : "Qaraqalpaqsha", |
723 | | - "kab" : "Taqbaylit", |
724 | | - "kg" : "Kongo", |
725 | | - "ki" : "G\u0129k\u0169y\u0169", |
726 | | - "kiu" : "Kurmanc\u00ee", |
727 | | - "kj" : "Kwanyama", |
728 | | - "kk" : "\u049a\u0430\u0437\u0430\u049b\u0448\u0430", |
729 | | - "kk-arab" : "\u202b\u0642\u0627\u0632\u0627\u0642\u0634\u0627 (\u062a\u0674\u0648\u062a\u06d5)\u202c", |
730 | | - "kk-cyrl" : "\u202a\u049a\u0430\u0437\u0430\u049b\u0448\u0430 (\u043a\u0438\u0440\u0438\u043b)\u202c", |
731 | | - "kk-latn" : "\u202aQazaq\u015fa (lat\u0131n)\u202c", |
732 | | - "kk-cn" : "\u202b\u0642\u0627\u0632\u0627\u0642\u0634\u0627 (\u062c\u06c7\u0646\u06af\u0648)\u202c", |
733 | | - "kk-kz" : "\u202a\u049a\u0430\u0437\u0430\u049b\u0448\u0430 (\u049a\u0430\u0437\u0430\u049b\u0441\u0442\u0430\u043d)\u202c", |
734 | | - "kk-tr" : "\u202aQazaq\u015fa (T\u00fcrk\u00efya)\u202c", |
735 | | - "kl" : "Kalaallisut", |
736 | | - "km" : "\u1797\u17b6\u179f\u17b6\u1781\u17d2\u1798\u17c2\u179a", |
737 | | - "kn" : "\u0c95\u0ca8\u0ccd\u0ca8\u0ca1", |
738 | | - "ko" : "\ud55c\uad6d\uc5b4", |
739 | | - "ko-kp" : "\ud55c\uad6d\uc5b4 (\uc870\uc120)", |
740 | | - "kr" : "Kanuri", |
741 | | - "kri" : "Krio", |
742 | | - "krj" : "Kinaray-a", |
743 | | - "ks" : "\u0915\u0936\u094d\u092e\u0940\u0930\u0940 - (\u0643\u0634\u0645\u064a\u0631\u064a)", |
744 | | - "ksh" : "Ripoarisch", |
745 | | - "ku" : "Kurd\u00ee \/ \u0643\u0648\u0631\u062f\u06cc", |
746 | | - "ku-latn" : "\u202aKurd\u00ee (lat\u00een\u00ee)\u202c", |
747 | | - "ku-arab" : "\u202b\u0643\u0648\u0631\u062f\u064a (\u0639\u06d5\u0631\u06d5\u0628\u06cc)\u202c", |
748 | | - "kv" : "\u041a\u043e\u043c\u0438", |
749 | | - "kw" : "Kernowek", |
750 | | - "ky" : "\u041a\u044b\u0440\u0433\u044b\u0437\u0447\u0430", |
751 | | - "la" : "Latina", |
752 | | - "lad" : "Ladino", |
753 | | - "lb" : "L\u00ebtzebuergesch", |
754 | | - "lbe" : "\u041b\u0430\u043a\u043a\u0443", |
755 | | - "lez" : "\u041b\u0435\u0437\u0433\u0438", |
756 | | - "lfn" : "Lingua Franca Nova", |
757 | | - "lg" : "Luganda", |
758 | | - "li" : "Limburgs", |
759 | | - "lij" : "L\u00edguru", |
760 | | - "lmo" : "Lumbaart", |
761 | | - "ln" : "Ling\u00e1la", |
762 | | - "lo" : "\u0ea5\u0eb2\u0ea7", |
763 | | - "loz" : "Silozi", |
764 | | - "lt" : "Lietuvi\u0173", |
765 | | - "lv" : "Latvie\u0161u", |
766 | | - "lzh" : "\u6587\u8a00", |
767 | | - "mai" : "\u092e\u0948\u0925\u093f\u0932\u0940", |
768 | | - "map-bms" : "Basa Banyumasan", |
769 | | - "mdf" : "\u041c\u043e\u043a\u0448\u0435\u043d\u044c", |
770 | | - "mg" : "Malagasy", |
771 | | - "mh" : "Ebon", |
772 | | - "mhr" : "\u041e\u043b\u044b\u043a \u041c\u0430\u0440\u0438\u0439", |
773 | | - "mi" : "M\u0101ori", |
774 | | - "mk" : "\u041c\u0430\u043a\u0435\u0434\u043e\u043d\u0441\u043a\u0438", |
775 | | - "ml" : "\u0d2e\u0d32\u0d2f\u0d3e\u0d33\u0d02", |
776 | | - "mn" : "\u041c\u043e\u043d\u0433\u043e\u043b", |
777 | | - "mo" : "\u041c\u043e\u043b\u0434\u043e\u0432\u0435\u043d\u044f\u0441\u043a\u044d", |
778 | | - "mr" : "\u092e\u0930\u093e\u0920\u0940", |
779 | | - "ms" : "Bahasa Melayu", |
780 | | - "mt" : "Malti", |
781 | | - "mus" : "Mvskoke", |
782 | | - "mwl" : "Mirand\u00e9s", |
783 | | - "my" : "\u1019\u103c\u1014\u103a\u1019\u102c\u1018\u102c\u101e\u102c", |
784 | | - "myv" : "\u042d\u0440\u0437\u044f\u043d\u044c", |
785 | | - "mzn" : "\u0645\u064e\u0632\u0650\u0631\u0648\u0646\u064a", |
786 | | - "na" : "Dorerin Naoero", |
787 | | - "nah" : "N\u0101huatl", |
788 | | - "nan" : "B\u00e2n-l\u00e2m-g\u00fa", |
789 | | - "nap" : "Nnapulitano", |
790 | | - "nb" : "\u202aNorsk (bokm\u00e5l)\u202c", |
791 | | - "nds" : "Plattd\u00fc\u00fctsch", |
792 | | - "nds-nl" : "Nedersaksisch", |
793 | | - "ne" : "\u0928\u0947\u092a\u093e\u0932\u0940", |
794 | | - "new" : "\u0928\u0947\u092a\u093e\u0932 \u092d\u093e\u0937\u093e", |
795 | | - "ng" : "Oshiwambo", |
796 | | - "niu" : "Niu\u0113", |
797 | | - "nl" : "Nederlands", |
798 | | - "nn" : "\u202aNorsk (nynorsk)\u202c", |
799 | | - "no" : "\u202aNorsk (bokm\u00e5l)\u202c", |
800 | | - "nov" : "Novial", |
801 | | - "nrm" : "Nouormand", |
802 | | - "nso" : "Sesotho sa Leboa", |
803 | | - "nv" : "Din\u00e9 bizaad", |
804 | | - "ny" : "Chi-Chewa", |
805 | | - "oc" : "Occitan", |
806 | | - "om" : "Oromoo", |
807 | | - "or" : "\u0b13\u0b21\u0b3c\u0b3f\u0b06", |
808 | | - "os" : "\u0418\u0440\u043e\u043d\u0430\u0443", |
809 | | - "pa" : "\u0a2a\u0a70\u0a1c\u0a3e\u0a2c\u0a40", |
810 | | - "pag" : "Pangasinan", |
811 | | - "pam" : "Kapampangan", |
812 | | - "pap" : "Papiamentu", |
813 | | - "pcd" : "Picard", |
814 | | - "pdc" : "Deitsch", |
815 | | - "pdt" : "Plautdietsch", |
816 | | - "pfl" : "Pf\u00e4lzisch", |
817 | | - "pi" : "\u092a\u093e\u093f\u0934", |
818 | | - "pih" : "Norfuk \/ Pitkern", |
819 | | - "pl" : "Polski", |
820 | | - "pms" : "Piemont\u00e8is", |
821 | | - "pnb" : "\u067e\u0646\u062c\u0627\u0628\u06cc", |
822 | | - "pnt" : "\u03a0\u03bf\u03bd\u03c4\u03b9\u03b1\u03ba\u03ac", |
823 | | - "ps" : "\u067e\u069a\u062a\u0648", |
824 | | - "pt" : "Portugu\u00eas", |
825 | | - "pt-br" : "Portugu\u00eas do Brasil", |
826 | | - "qu" : "Runa Simi", |
827 | | - "rif" : "Tarifit", |
828 | | - "rm" : "Rumantsch", |
829 | | - "rmy" : "Romani", |
830 | | - "rn" : "Kirundi", |
831 | | - "ro" : "Rom\u00e2n\u0103", |
832 | | - "roa-rup" : "Arm\u00e3neashce", |
833 | | - "roa-tara" : "Tarand\u00edne", |
834 | | - "ru" : "\u0420\u0443\u0441\u0441\u043a\u0438\u0439", |
835 | | - "ruq" : "Vl\u0103he\u015fte", |
836 | | - "ruq-cyrl" : "\u0412\u043b\u0430\u0445\u0435\u0441\u0442\u0435", |
837 | | - "ruq-latn" : "Vl\u0103he\u015fte", |
838 | | - "rw" : "Kinyarwanda", |
839 | | - "sa" : "\u0938\u0902\u0938\u094d\u0915\u0943\u0924", |
840 | | - "sah" : "\u0421\u0430\u0445\u0430 \u0442\u044b\u043b\u0430", |
841 | | - "sc" : "Sardu", |
842 | | - "scn" : "Sicilianu", |
843 | | - "sco" : "Scots", |
844 | | - "sd" : "\u0633\u0646\u068c\u064a", |
845 | | - "sdc" : "Sassaresu", |
846 | | - "se" : "S\u00e1megiella", |
847 | | - "sei" : "Cmique Itom", |
848 | | - "sg" : "S\u00e4ng\u00f6", |
849 | | - "sh" : "Srpskohrvatski \/ \u0421\u0440\u043f\u0441\u043a\u043e\u0445\u0440\u0432\u0430\u0442\u0441\u043a\u0438", |
850 | | - "shi" : "Ta\u0161l\u1e25iyt", |
851 | | - "si" : "\u0dc3\u0dd2\u0d82\u0dc4\u0dbd", |
852 | | - "simple" : "Simple English", |
853 | | - "sk" : "Sloven\u010dina", |
854 | | - "sl" : "Sloven\u0161\u010dina", |
855 | | - "sli" : "Schl\u00e4sch", |
856 | | - "sm" : "Gagana Samoa", |
857 | | - "sma" : "\u00c5arjelsaemien", |
858 | | - "sn" : "chiShona", |
859 | | - "so" : "Soomaaliga", |
860 | | - "sq" : "Shqip", |
861 | | - "sr" : "\u0421\u0440\u043f\u0441\u043a\u0438 \/ Srpski", |
862 | | - "sr-ec" : "\u0421\u0440\u043f\u0441\u043a\u0438 (\u045b\u0438\u0440\u0438\u043b\u0438\u0446\u0430)", |
863 | | - "sr-el" : "Srpski (latinica)", |
864 | | - "srn" : "Sranantongo", |
865 | | - "ss" : "SiSwati", |
866 | | - "st" : "Sesotho", |
867 | | - "stq" : "Seeltersk", |
868 | | - "su" : "Basa Sunda", |
869 | | - "sv" : "Svenska", |
870 | | - "sw" : "Kiswahili", |
871 | | - "szl" : "\u015al\u016fnski", |
872 | | - "ta" : "\u0ba4\u0bae\u0bbf\u0bb4\u0bcd", |
873 | | - "tcy" : "\u0ca4\u0cc1\u0cb3\u0cc1", |
874 | | - "te" : "\u0c24\u0c46\u0c32\u0c41\u0c17\u0c41", |
875 | | - "tet" : "Tetun", |
876 | | - "tg" : "\u0422\u043e\u04b7\u0438\u043a\u04e3", |
877 | | - "tg-cyrl" : "\u0422\u043e\u04b7\u0438\u043a\u04e3", |
878 | | - "tg-latn" : "tojik\u012b", |
879 | | - "th" : "\u0e44\u0e17\u0e22", |
880 | | - "ti" : "\u1275\u130d\u122d\u129b", |
881 | | - "tk" : "T\u00fcrkmen\u00e7e", |
882 | | - "tl" : "Tagalog", |
883 | | - "tn" : "Setswana", |
884 | | - "to" : "lea faka-Tonga", |
885 | | - "tokipona" : "Toki Pona", |
886 | | - "tp" : "Toki Pona (deprecated:tokipona)", |
887 | | - "tpi" : "Tok Pisin", |
888 | | - "tr" : "T\u00fcrk\u00e7e", |
889 | | - "ts" : "Xitsonga", |
890 | | - "tt" : "\u0422\u0430\u0442\u0430\u0440\u0447\u0430\/Tatar\u00e7a", |
891 | | - "tt-cyrl" : "\u0422\u0430\u0442\u0430\u0440\u0447\u0430", |
892 | | - "tt-latn" : "Tatar\u00e7a", |
893 | | - "tum" : "chiTumbuka", |
894 | | - "tw" : "Twi", |
895 | | - "ty" : "Reo M\u0101`ohi", |
896 | | - "tyv" : "\u0422\u044b\u0432\u0430 \u0434\u044b\u043b", |
897 | | - "udm" : "\u0423\u0434\u043c\u0443\u0440\u0442", |
898 | | - "ug" : "Uyghurche\u200e \/ \u0626\u06c7\u064a\u063a\u06c7\u0631\u0686\u06d5", |
899 | | - "ug-arab" : "\u0626\u06c7\u064a\u063a\u06c7\u0631\u0686\u06d5", |
900 | | - "ug-latn" : "Uyghurche\u200e", |
901 | | - "uk" : "\u0423\u043a\u0440\u0430\u0457\u043d\u0441\u044c\u043a\u0430", |
902 | | - "ur" : "\u0627\u0631\u062f\u0648", |
903 | | - "uz" : "O'zbek", |
904 | | - "ve" : "Tshivenda", |
905 | | - "vec" : "V\u00e8neto", |
906 | | - "vep" : "Vepsan kel'", |
907 | | - "vi" : "Ti\u1ebfng Vi\u1ec7t", |
908 | | - "vls" : "West-Vlams", |
909 | | - "vo" : "Volap\u00fck", |
910 | | - "vro" : "V\u00f5ro", |
911 | | - "wa" : "Walon", |
912 | | - "war" : "Winaray", |
913 | | - "wo" : "Wolof", |
914 | | - "wuu" : "\u5434\u8bed", |
915 | | - "xal" : "\u0425\u0430\u043b\u044c\u043c\u0433", |
916 | | - "xh" : "isiXhosa", |
917 | | - "xmf" : "\u10db\u10d0\u10e0\u10d2\u10d0\u10da\u10e3\u10e0\u10d8", |
918 | | - "yi" : "\u05d9\u05d9\u05b4\u05d3\u05d9\u05e9", |
919 | | - "yo" : "Yor\u00f9b\u00e1", |
920 | | - "yue" : "\u7cb5\u8a9e", |
921 | | - "za" : "Vahcuengh", |
922 | | - "zea" : "Ze\u00eauws", |
923 | | - "zh" : "\u4e2d\u6587", |
924 | | - "zh-classical" : "\u6587\u8a00", |
925 | | - "zh-cn" : "\u202a\u4e2d\u6587(\u4e2d\u56fd\u5927\u9646)\u202c", |
926 | | - "zh-hans" : "\u202a\u4e2d\u6587(\u7b80\u4f53)\u202c", |
927 | | - "zh-hant" : "\u202a\u4e2d\u6587(\u7e41\u9ad4)\u202c", |
928 | | - "zh-hk" : "\u202a\u4e2d\u6587(\u9999\u6e2f)\u202c", |
929 | | - "zh-min-nan" : "B\u00e2n-l\u00e2m-g\u00fa", |
930 | | - "zh-mo" : "\u202a\u4e2d\u6587(\u6fb3\u9580)\u202c", |
931 | | - "zh-my" : "\u202a\u4e2d\u6587(\u9a6c\u6765\u897f\u4e9a)\u202c", |
932 | | - "zh-sg" : "\u202a\u4e2d\u6587(\u65b0\u52a0\u5761)\u202c", |
933 | | - "zh-tw" : "\u202a\u4e2d\u6587(\u53f0\u7063)\u202c", |
934 | | - "zh-yue" : "\u7cb5\u8a9e", |
935 | | - "zu" : "isiZulu" |
936 | | - }; |
937 | | - |
938 | | - // Language classes ( has a file in /languages/classes/Language{code}.js ) |
939 | | - // ( for languages that override default transforms ) |
940 | | - mw.Language.transformClass = ['am', 'ar', 'bat_smg', 'be_tarak', 'be', 'bh', |
941 | | - 'bs', 'cs', 'cu', 'cy', 'dsb', 'fr', 'ga', 'gd', 'gv', 'he', 'hi', |
942 | | - 'hr', 'hsb', 'hy', 'ksh', 'ln', 'lt', 'lv', 'mg', 'mk', 'mo', 'mt', |
943 | | - 'nso', 'pl', 'pt_br', 'ro', 'ru', 'se', 'sh', 'sk', 'sl', 'sma', |
944 | | - 'sr_ec', 'sr_el', 'sr', 'ti', 'tl', 'uk', 'wa' |
945 | | - ]; |
946 | | - |
947 | | - // Language fallbacks listed from language -> fallback language |
948 | | - mw.Language.fallbackTransformMap = { |
949 | | - 'mwl' : 'pt', |
950 | | - 'ace' : 'id', |
951 | | - 'hsb' : 'de', |
952 | | - 'frr' : 'de', |
953 | | - 'pms' : 'it', |
954 | | - 'dsb' : 'de', |
955 | | - 'gan' : 'gan-hant', |
956 | | - 'lzz' : 'tr', |
957 | | - 'ksh' : 'de', |
958 | | - 'kl' : 'da', |
959 | | - 'fur' : 'it', |
960 | | - 'zh-hk' : 'zh-hant', |
961 | | - 'kk' : 'kk-cyrl', |
962 | | - 'zh-my' : 'zh-sg', |
963 | | - 'nah' : 'es', |
964 | | - 'sr' : 'sr-ec', |
965 | | - 'ckb-latn' : 'ckb-arab', |
966 | | - 'mo' : 'ro', |
967 | | - 'ay' : 'es', |
968 | | - 'gl' : 'pt', |
969 | | - 'gag' : 'tr', |
970 | | - 'mzn' : 'fa', |
971 | | - 'ruq-cyrl' : 'mk', |
972 | | - 'kk-arab' : 'kk-cyrl', |
973 | | - 'pfl' : 'de', |
974 | | - 'zh-yue' : 'yue', |
975 | | - 'ug' : 'ug-latn', |
976 | | - 'ltg' : 'lv', |
977 | | - 'nds' : 'de', |
978 | | - 'sli' : 'de', |
979 | | - 'mhr' : 'ru', |
980 | | - 'sah' : 'ru', |
981 | | - 'ff' : 'fr', |
982 | | - 'ab' : 'ru', |
983 | | - 'ko-kp' : 'ko', |
984 | | - 'sg' : 'fr', |
985 | | - 'zh-tw' : 'zh-hant', |
986 | | - 'map-bms' : 'jv', |
987 | | - 'av' : 'ru', |
988 | | - 'nds-nl' : 'nl', |
989 | | - 'pt-br' : 'pt', |
990 | | - 'ce' : 'ru', |
991 | | - 'vep' : 'et', |
992 | | - 'wuu' : 'zh-hans', |
993 | | - 'pdt' : 'de', |
994 | | - 'krc' : 'ru', |
995 | | - 'gan-hant' : 'zh-hant', |
996 | | - 'bqi' : 'fa', |
997 | | - 'as' : 'bn', |
998 | | - 'bm' : 'fr', |
999 | | - 'gn' : 'es', |
1000 | | - 'tt' : 'ru', |
1001 | | - 'zh-hant' : 'zh-hans', |
1002 | | - 'hif' : 'hif-latn', |
1003 | | - 'zh' : 'zh-hans', |
1004 | | - 'kaa' : 'kk-latn', |
1005 | | - 'lij' : 'it', |
1006 | | - 'vot' : 'fi', |
1007 | | - 'ii' : 'zh-cn', |
1008 | | - 'ku-arab' : 'ckb-arab', |
1009 | | - 'xmf' : 'ka', |
1010 | | - 'vmf' : 'de', |
1011 | | - 'zh-min-nan' : 'nan', |
1012 | | - 'bcc' : 'fa', |
1013 | | - 'an' : 'es', |
1014 | | - 'rgn' : 'it', |
1015 | | - 'qu' : 'es', |
1016 | | - 'nb' : 'no', |
1017 | | - 'bar' : 'de', |
1018 | | - 'lbe' : 'ru', |
1019 | | - 'su' : 'id', |
1020 | | - 'pcd' : 'fr', |
1021 | | - 'glk' : 'fa', |
1022 | | - 'lb' : 'de', |
1023 | | - 'kk-kz' : 'kk-cyrl', |
1024 | | - 'kk-tr' : 'kk-latn', |
1025 | | - 'inh' : 'ru', |
1026 | | - 'mai' : 'hi', |
1027 | | - 'tp' : 'tokipona', |
1028 | | - 'kk-latn' : 'kk-cyrl', |
1029 | | - 'ba' : 'ru', |
1030 | | - 'nap' : 'it', |
1031 | | - 'ruq' : 'ruq-latn', |
1032 | | - 'tt-cyrl' : 'ru', |
1033 | | - 'lad' : 'es', |
1034 | | - 'dk' : 'da', |
1035 | | - 'de-ch' : 'de', |
1036 | | - 'be-x-old' : 'be-tarask', |
1037 | | - 'za' : 'zh-hans', |
1038 | | - 'kk-cn' : 'kk-arab', |
1039 | | - 'shi' : 'ar', |
1040 | | - 'crh' : 'crh-latn', |
1041 | | - 'yi' : 'he', |
1042 | | - 'pdc' : 'de', |
1043 | | - 'eml' : 'it', |
1044 | | - 'uk' : 'ru', |
1045 | | - 'kv' : 'ru', |
1046 | | - 'koi' : 'ru', |
1047 | | - 'cv' : 'ru', |
1048 | | - 'zh-cn' : 'zh-hans', |
1049 | | - 'de-at' : 'de', |
1050 | | - 'jut' : 'da', |
1051 | | - 'vec' : 'it', |
1052 | | - 'zh-mo' : 'zh-hk', |
1053 | | - 'fiu-vro' : 'vro', |
1054 | | - 'frp' : 'fr', |
1055 | | - 'mg' : 'fr', |
1056 | | - 'ruq-latn' : 'ro', |
1057 | | - 'sa' : 'hi', |
1058 | | - 'lmo' : 'it', |
1059 | | - 'kiu' : 'tr', |
1060 | | - 'tcy' : 'kn', |
1061 | | - 'srn' : 'nl', |
1062 | | - 'jv' : 'id', |
1063 | | - 'vls' : 'nl', |
1064 | | - 'zea' : 'nl', |
1065 | | - 'ty' : 'fr', |
1066 | | - 'szl' : 'pl', |
1067 | | - 'rmy' : 'ro', |
1068 | | - 'wo' : 'fr', |
1069 | | - 'vro' : 'et', |
1070 | | - 'udm' : 'ru', |
1071 | | - 'bpy' : 'bn', |
1072 | | - 'mrj' : 'ru', |
1073 | | - 'ckb' : 'ckb-arab', |
1074 | | - 'xal' : 'ru', |
1075 | | - 'de-formal' : 'de', |
1076 | | - 'myv' : 'ru', |
1077 | | - 'ku' : 'ku-latn', |
1078 | | - 'crh-cyrl' : 'ru', |
1079 | | - 'gsw' : 'de', |
1080 | | - 'rue' : 'uk', |
1081 | | - 'iu' : 'ike-cans', |
1082 | | - 'stq' : 'de', |
1083 | | - 'gan-hans' : 'zh-hans', |
1084 | | - 'scn' : 'it', |
1085 | | - 'arn' : 'es', |
1086 | | - 'ht' : 'fr', |
1087 | | - 'zh-sg' : 'zh-hans', |
1088 | | - 'bat-smg' : 'lt', |
1089 | | - 'aln' : 'sq', |
1090 | | - 'tg' : 'tg-cyrl', |
1091 | | - 'li' : 'nl', |
1092 | | - 'simple' : 'en', |
1093 | | - 'os' : 'ru', |
1094 | | - 'ln' : 'fr', |
1095 | | - 'als' : 'gsw', |
1096 | | - 'zh-classical' : 'lzh', |
1097 | | - 'arz' : 'ar', |
1098 | | - 'wa' : 'fr' |
1099 | | - }; |
1100 | | - |
1101 | | - |
1102 | | -}) ( window.mw ); |
1103 | | - |
1104 | | - |
1105 | | -// Load in js2 stopgap global msgs into proper location: |
1106 | | -if ( typeof gMsg != 'undefined' ) { |
1107 | | - mw.addMessages( gMsg ) |
1108 | | -} |
1109 | | - |
1110 | | -// Set global gM shortcut: |
1111 | | -window[ 'gM' ] = mw.getMsg; |
1112 | | - |
1113 | | - |
1114 | | -/** |
1115 | | -* Add the core mvEmbed Messages ( will be localized by script server ) |
1116 | | -*/ |
1117 | | -mw.addMessages( { |
1118 | | - "mwe-loading_txt" : "Loading ...", |
1119 | | - "mwe-size-gigabytes" : "$1 GB", |
1120 | | - "mwe-size-megabytes" : "$1 MB", |
1121 | | - "mwe-size-kilobytes" : "$1 K", |
1122 | | - "mwe-size-bytes" : "$1 B", |
1123 | | - "mwe-error_load_lib" : "Error: JavaScript $1 was not retrievable or does not define $2", |
1124 | | - "mwe-apiproxy-setup" : "Setting up API proxy", |
1125 | | - "mwe-load-drag-item" : "Loading dragged item", |
1126 | | - "mwe-ok" : "OK", |
1127 | | - "mwe-cancel" : "Cancel", |
1128 | | - "mwe-enable-gadget" : "Enable multimedia beta ( mwEmbed ) for all pages", |
1129 | | - "mwe-enable-gadget-done" : "multimedia beta gadget has been enabled", |
1130 | | - "mwe-must-login-gadget" : "To enable gadget you must <a target=\"_new\" href=\"$1\">login</a>", |
1131 | | - "mwe-test-plural" : "I ran {{PLURAL:$1|$1 test|$1 tests}}" |
1132 | | -} ); |
\ No newline at end of file |
Index: trunk/extensions/MwEmbed/MwEmbed/components/mw.jQueryUtil.js |
— | — | @@ -0,0 +1,158 @@ |
| 2 | +/** |
| 3 | + * mwEmbed jQuery utility function |
| 4 | + */ |
| 5 | + |
| 6 | +( function( $ ) { |
| 7 | + |
| 8 | + /** |
| 9 | + * Set a given selector html to the loading spinner: |
| 10 | + */ |
| 11 | + $.fn.loadingSpinner = function( ) { |
| 12 | + if ( this ) { |
| 13 | + $j( this ).html( |
| 14 | + $j( '<div />' ) |
| 15 | + .addClass( "loadingSpinner" ) |
| 16 | + ); |
| 17 | + } |
| 18 | + return this; |
| 19 | + }; |
| 20 | + /** |
| 21 | + * Add an absolute overlay spinner useful for cases where the |
| 22 | + * element does not display child elements, ( images, video ) |
| 23 | + */ |
| 24 | + $.fn.getAbsoluteOverlaySpinner = function(){ |
| 25 | + var pos = $j( this ).offset(); |
| 26 | + var posLeft = ( $j( this ).width() ) ? |
| 27 | + parseInt( pos.left + ( .5 * $j( this ).width() ) -16 ) : |
| 28 | + pos.left + 30; |
| 29 | + |
| 30 | + var posTop = ( $j( this ).height() ) ? |
| 31 | + parseInt( pos.top + ( .5 * $j( this ).height() ) -16 ) : |
| 32 | + pos.top + 30; |
| 33 | + |
| 34 | + var $spinner = $j('<div />') |
| 35 | + .loadingSpinner() |
| 36 | + .css({ |
| 37 | + 'width' : 32, |
| 38 | + 'height' : 32, |
| 39 | + 'position': 'absolute', |
| 40 | + 'top' : posTop + 'px', |
| 41 | + 'left' : posLeft + 'px' |
| 42 | + }); |
| 43 | + $j('body').append( $spinner ); |
| 44 | + return $spinner; |
| 45 | + }; |
| 46 | + |
| 47 | + /** |
| 48 | + * dragDrop file loader |
| 49 | + */ |
| 50 | + $.fn.dragFileUpload = function ( conf ) { |
| 51 | + if ( this.selector ) { |
| 52 | + var _this = this; |
| 53 | + // load the dragger and "setup" |
| 54 | + mw.load( ['$j.fn.dragDropFile'], function() { |
| 55 | + $j( _this.selector ).dragDropFile(); |
| 56 | + } ); |
| 57 | + } |
| 58 | + }; |
| 59 | + |
| 60 | + /** |
| 61 | + * Shortcut to a themed button Should be depreciated for $.button |
| 62 | + * bellow |
| 63 | + */ |
| 64 | + $.btnHtml = function( msg, styleClass, iconId, opt ) { |
| 65 | + if ( !opt ) |
| 66 | + opt = { }; |
| 67 | + var href = ( opt.href ) ? opt.href : '#'; |
| 68 | + var target_attr = ( opt.target ) ? ' target="' + opt.target + '" ' : ''; |
| 69 | + var style_attr = ( opt.style ) ? ' style="' + opt.style + '" ' : ''; |
| 70 | + return '<a href="' + href + '" ' + target_attr + style_attr + |
| 71 | + ' class="ui-state-default ui-corner-all ui-icon_link ' + |
| 72 | + styleClass + '"><span class="ui-icon ui-icon-' + iconId + '" ></span>' + |
| 73 | + '<span class="btnText">' + msg + '</span></a>'; |
| 74 | + }; |
| 75 | + |
| 76 | + // Shortcut to jQuery button ( should replace all btnHtml with |
| 77 | + // button ) |
| 78 | + var mw_default_button_options = { |
| 79 | + // The class name for the button link |
| 80 | + 'class' : '', |
| 81 | + |
| 82 | + // The style properties for the button link |
| 83 | + 'style' : { }, |
| 84 | + |
| 85 | + // The text of the button link |
| 86 | + 'text' : '', |
| 87 | + |
| 88 | + // The icon id that precedes the button link: |
| 89 | + 'icon' : 'carat-1-n' |
| 90 | + }; |
| 91 | + |
| 92 | + $.button = function( options ) { |
| 93 | + var options = $j.extend( {}, mw_default_button_options, options); |
| 94 | + |
| 95 | + // Button: |
| 96 | + var $button = $j('<a />') |
| 97 | + .attr('href', '#') |
| 98 | + .addClass( 'ui-state-default ui-corner-all ui-icon_link' ); |
| 99 | + // Add css if set: |
| 100 | + if( options.css ) { |
| 101 | + $button.css( options.css ); |
| 102 | + } |
| 103 | + |
| 104 | + if( options['class'] ) { |
| 105 | + $button.addClass( options['class'] ); |
| 106 | + } |
| 107 | + |
| 108 | + |
| 109 | + // return the button: |
| 110 | + $button.append( |
| 111 | + $j('<span />').addClass( 'ui-icon ui-icon-' + options.icon ), |
| 112 | + $j('<span />').addClass( 'btnText' ) |
| 113 | + .text( options.text ) |
| 114 | + ) |
| 115 | + .buttonHover(); // add buttonHover binding; |
| 116 | + if( !options.text ){ |
| 117 | + $button.css('padding', '1em'); |
| 118 | + } |
| 119 | + return $button; |
| 120 | + }; |
| 121 | + |
| 122 | + // Shortcut to bind hover state |
| 123 | + $.fn.buttonHover = function() { |
| 124 | + $j( this ).hover( |
| 125 | + function() { |
| 126 | + $j( this ).addClass( 'ui-state-hover' ); |
| 127 | + }, |
| 128 | + function() { |
| 129 | + $j( this ).removeClass( 'ui-state-hover' ); |
| 130 | + } |
| 131 | + ); |
| 132 | + return this; |
| 133 | + }; |
| 134 | + |
| 135 | + /** |
| 136 | + * Resize a dialog to fit the window |
| 137 | + * |
| 138 | + * @param {Object} |
| 139 | + * options horizontal and vertical space ( default 50 ) |
| 140 | + */ |
| 141 | + $.fn.dialogFitWindow = function( options ) { |
| 142 | + var opt_default = { 'hspace':50, 'vspace':50 }; |
| 143 | + if ( !options ) |
| 144 | + var options = { }; |
| 145 | + options = $j.extend( opt_default, options ); |
| 146 | + $j( this.selector ).dialog( 'option', 'width', $j( window ).width() - options.hspace ); |
| 147 | + $j( this.selector ).dialog( 'option', 'height', $j( window ).height() - options.vspace ); |
| 148 | + $j( this.selector ).dialog( 'option', 'position', 'center' ); |
| 149 | + // update the child position: (some of this should be pushed |
| 150 | + // up-stream via dialog config options |
| 151 | + $j( this.selector + '~ .ui-dialog-buttonpane' ).css( { |
| 152 | + 'position':'absolute', |
| 153 | + 'left':'0px', |
| 154 | + 'right':'0px', |
| 155 | + 'bottom':'0px' |
| 156 | + } ); |
| 157 | + }; |
| 158 | + |
| 159 | +} )( jQuery ); |
\ No newline at end of file |
Property changes on: trunk/extensions/MwEmbed/MwEmbed/components/mw.jQueryUtil.js |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 160 | + text/plain |
Index: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/mw.ApiProxy.js |
— | — | @@ -0,0 +1,1024 @@ |
| 2 | +/** |
| 3 | +* |
| 4 | +* Api proxy system |
| 5 | +* |
| 6 | +* Supports cross domain uploading, and api actions for a approved set of domains. |
| 7 | +* |
| 8 | +* All cross domain communication is done with iframe children ( Avoids polling |
| 9 | +* which is resource intensive and can lose messages ) |
| 10 | +* |
| 11 | +* The framework ~will eventually~ support a request approval system for per-user domain approval |
| 12 | +* and a central blacklisting of domains controlled by the site |
| 13 | +* |
| 14 | +* NOTE: If the browser supports it we should pass msgs with postMessage API |
| 15 | +* http://ejohn.org/blog/cross-window-messaging/ ( rather than using these iframes ) |
| 16 | +* |
| 17 | +* NOTE: refactor efforts will include separating out "core" proxy functions and |
| 18 | +* having a separate class for "server" and "client" api usage |
| 19 | +* |
| 20 | +*/ |
| 21 | + |
| 22 | +mw.includeAllModuleMessages(); |
| 23 | + |
| 24 | +/** |
| 25 | + * apiProxy jQuery binding |
| 26 | + * |
| 27 | + * Note: probably should split up "server" and "client" binding |
| 28 | + * |
| 29 | + * @param {String} mode Mode is either 'server' or 'client' |
| 30 | + * @param {Object} proxyConfig Proxy configuration |
| 31 | + * @param {Function} callback The function called once proxy request is done |
| 32 | + */ |
| 33 | + |
| 34 | + /** |
| 35 | + * Set the base API Proxy object |
| 36 | + * |
| 37 | + */ |
| 38 | +mw.ApiProxy = { }; |
| 39 | + |
| 40 | +// ApiProxy scoped functions: |
| 41 | +( function( $ ) { |
| 42 | + |
| 43 | + // Proxy Context stores an array of proxy context requests |
| 44 | + // this enables multiple simultaneous requests to be processed. |
| 45 | + var proxyContext = []; |
| 46 | + |
| 47 | + /** |
| 48 | + * Takes a requestQuery, executes the query and then calls the callback |
| 49 | + * sets the local callback to be called once requestQuery completes |
| 50 | + * |
| 51 | + * @param {String} apiUrl Url to the api we want to do the request on. |
| 52 | + * @param {Object} requestQuery Api request object |
| 53 | + * @param {Function} callback Function called once the request is complete |
| 54 | + * @param {Function} [callbackTimeout] Optional Function called on api timeout |
| 55 | + */ |
| 56 | + $.doRequest = function( apiUrl, requestQuery, callback , callbackTimeout ) { |
| 57 | + // Sanity check: |
| 58 | + if ( mw.isLocalDomain( apiUrl ) ) { |
| 59 | + mw.log( "Error: trying to proxy local domain? " ); |
| 60 | + return false; |
| 61 | + } |
| 62 | + |
| 63 | + // Generate a new context object: (its oky that optional arguments are null ) |
| 64 | + var context = createContext({ |
| 65 | + 'apiUrl' : apiUrl, // currentServerApiUrl |
| 66 | + 'apiReq' : requestQuery, |
| 67 | + 'callback' : callback, |
| 68 | + 'timeoutCb' : callbackTimeout |
| 69 | + } ); |
| 70 | + |
| 71 | + mw.log( "doRequest:: " + JSON.stringify( requestQuery ) ); |
| 72 | + |
| 73 | + // Do the proxy req: |
| 74 | + doFrameProxy( context ); |
| 75 | + }; |
| 76 | + |
| 77 | + /** |
| 78 | + * Generates a remote browse file iframe window |
| 79 | + * usefull for "uploading" cross domain |
| 80 | + * |
| 81 | + * @param {Function} callback Function to host the |
| 82 | + */ |
| 83 | + $.browseFile = function( options ) { |
| 84 | + if( ! options ) { |
| 85 | + options = {}; |
| 86 | + } |
| 87 | + |
| 88 | + if( ! options.target ) { |
| 89 | + mw.log( "Error: no target for file browse iframe" ) ; |
| 90 | + return false; |
| 91 | + } |
| 92 | + |
| 93 | + if( !options.token ){ |
| 94 | + mw.log( "Error: no token for file browse "); |
| 95 | + return false; |
| 96 | + } |
| 97 | + |
| 98 | + if( ! options.apiUrl ) { |
| 99 | + mw.log( "Error: no api url to target" ); |
| 100 | + return false; |
| 101 | + } |
| 102 | + mw.log( 'Setup uploadDialogInterface' ); |
| 103 | + |
| 104 | + // Make sure we have the dialog interface: |
| 105 | + var uploadDialogInterface = new mw.UploadDialogInterface( { |
| 106 | + 'uploadHandlerAction' : function( action ){ |
| 107 | + mw.log( 'apiProxy uploadActionHandler:: ' + action ); |
| 108 | + |
| 109 | + // Handle actions that don't need to go to the iframe: |
| 110 | + switch ( action ){ |
| 111 | + case 'returnToFormCb': |
| 112 | + if( options.returnToFormCb ){ |
| 113 | + options.returnToFormCb(); |
| 114 | + } |
| 115 | + return ; |
| 116 | + break; |
| 117 | + } |
| 118 | + |
| 119 | + // Handle actions that get sent to the remote frame |
| 120 | + mw.ApiProxy.sendServerMsg( { |
| 121 | + 'apiUrl' : options.apiUrl, |
| 122 | + 'frameName' : iFrameName, |
| 123 | + 'frameMsg' : { |
| 124 | + 'action' : 'uploadHandlerAction', |
| 125 | + 'uiAction' : action |
| 126 | + } |
| 127 | + } ); |
| 128 | + } |
| 129 | + } ); |
| 130 | + |
| 131 | + // Setup the context with the callback in the current closure |
| 132 | + var context = createContext( { |
| 133 | + 'apiUrl' : options.apiUrl, |
| 134 | + // Setup the callback to process iframeData |
| 135 | + 'callback' : function( iframeData ) { |
| 136 | + // Process fileBrowse callbacks :: |
| 137 | + |
| 138 | + // check for basic status "ok" |
| 139 | + if( iframeData['status'] == 'ok' ) { |
| 140 | + // Hide the loading spinner |
| 141 | + $j( options.target ).find('.loadingSpinner').fadeOut('fast'); |
| 142 | + mw.log("iframe ready callback"); |
| 143 | + $j( '#' + iFrameName ).fadeIn( 'fast' ); |
| 144 | + return ; |
| 145 | + } |
| 146 | + mw.log( '~browseFile Callback~ event type: ' + iframeData['event'] ); |
| 147 | + |
| 148 | + // Handle events: |
| 149 | + if( iframeData['event'] ) { |
| 150 | + switch( iframeData['event'] ) { |
| 151 | + case 'selectFileCb': |
| 152 | + if( options.selectFileCb ) { |
| 153 | + options.selectFileCb( iframeData[ 'fileName' ] ); |
| 154 | + } |
| 155 | + break; |
| 156 | + // Set the doneUploadCb if set in the browseFile options |
| 157 | + case 'doneUploadCb': |
| 158 | + mw.log( "should call cb: " + options.doneUploadCb ); |
| 159 | + if( options.doneUploadCb ) { |
| 160 | + options.doneUploadCb( iframeData[ 'apiResult' ] ); |
| 161 | + return true; |
| 162 | + }else{ |
| 163 | + return false; |
| 164 | + } |
| 165 | + break; |
| 166 | + case 'uploadUI': |
| 167 | + if( uploadDialogInterface[ iframeData[ 'method' ] ] ){ |
| 168 | + var args = iframeData['arguments']; |
| 169 | + mw.log( "Do dialog interface: " + iframeData['method'] + ' args: ' + args[0] + ', ' + args[1] + ', ' + args[2] ); |
| 170 | + uploadDialogInterface[ iframeData['method'] ]( |
| 171 | + args[0], args[1], args[2] |
| 172 | + ); |
| 173 | + } |
| 174 | + break; |
| 175 | + default: |
| 176 | + mw.log(" Error unreconginzed event " + iframeData['event'] ); |
| 177 | + } |
| 178 | + } |
| 179 | + } |
| 180 | + }); |
| 181 | + |
| 182 | + // Setup the default width and height: |
| 183 | + if( ! options.width ) { |
| 184 | + options.width = 270; |
| 185 | + } |
| 186 | + if( ! options.height ) { |
| 187 | + options.height = 27; |
| 188 | + } |
| 189 | + |
| 190 | + var iFrameName = ( options.iframeName ) ? options.iframeName : 'fileBrowse_' + $j('iframe').length; |
| 191 | + // Setup an object to be packaged into the frame |
| 192 | + var iFrameRequest = { |
| 193 | + 'clientFrame' : getClientFrame( context ), |
| 194 | + 'action' : 'browseFile', |
| 195 | + 'token' : options.token |
| 196 | + }; |
| 197 | + |
| 198 | + var frameStyle = 'display:none;border:none;overflow:hidden;' |
| 199 | + + 'width:'+ parseInt( options.width ) + 'px;' |
| 200 | + + 'height:' + parseInt( options.height ) +'px'; |
| 201 | + |
| 202 | + // Empty the target ( so that the iframe can be put there ) |
| 203 | + $j( options.target ).empty(); |
| 204 | + |
| 205 | + mw.log( 'append spinner'); |
| 206 | + // Add a loading spinner to the target |
| 207 | + $j( options.target ).append( |
| 208 | + $j( '<div />' ).loadingSpinner() |
| 209 | + ); |
| 210 | + |
| 211 | + // Append the browseFile iframe to the target: |
| 212 | + appendIframe( { |
| 213 | + 'context' : context, |
| 214 | + 'persist' : true, |
| 215 | + 'style' : frameStyle, |
| 216 | + 'name' : iFrameName, |
| 217 | + 'request' : iFrameRequest, |
| 218 | + 'target' : options.target |
| 219 | + } ); |
| 220 | + |
| 221 | + // Return the name of the browseFile frame |
| 222 | + return iFrameName; |
| 223 | + }; |
| 224 | + |
| 225 | + /** |
| 226 | + * Output a server msg to a server iFrame |
| 227 | + * ( such as a hosted browse file or dialog prompt ) |
| 228 | + * |
| 229 | + * @param {Object} options Arguments to setup send server msg |
| 230 | + * apiUrl The api url of the server to send the frame msg to |
| 231 | + * frameName The frame name to send the msg to |
| 232 | + * frameMsg The msg object to send to frame |
| 233 | + */ |
| 234 | + $.sendServerMsg = function( options ){ |
| 235 | + if( !options.apiUrl || ! options.frameMsg || !options.frameName ){ |
| 236 | + mw.log( "Error missing required option"); |
| 237 | + return false; |
| 238 | + } |
| 239 | + |
| 240 | + //Setup a new context |
| 241 | + var context = createContext( { |
| 242 | + 'apiUrl' : options.apiUrl |
| 243 | + } ); |
| 244 | + |
| 245 | + // Send a msg to the server frameName from the server domain |
| 246 | + // Setup an object to be packaged into the frame |
| 247 | + var iFrameRequest = { |
| 248 | + 'clientFrame' : getClientFrame( context ), |
| 249 | + 'action' : 'sendFrameMsg', |
| 250 | + 'frameName' : options.frameName, |
| 251 | + 'frameMsg' : options.frameMsg |
| 252 | + }; |
| 253 | + |
| 254 | + // Send the iframe request: |
| 255 | + appendIframe( { |
| 256 | + 'persist' : true, |
| 257 | + 'context' : context, |
| 258 | + 'request' : iFrameRequest, |
| 259 | + 'target' : options.target |
| 260 | + }, function( ) { |
| 261 | + mw.log( "sendServerMsg iframe done loading" ); |
| 262 | + } ); |
| 263 | + }; |
| 264 | + |
| 265 | + /** |
| 266 | + * The nested iframe action that passes its result back up to the top frame instance |
| 267 | + * |
| 268 | + * Entry point for hashResult from nested iframe |
| 269 | + * |
| 270 | + * @param {Object} hashResult Value to be sent to parent frame |
| 271 | + */ |
| 272 | + $.nested = function( hashResult ) { |
| 273 | + // Close the loader if present: |
| 274 | + //mw.closeLoaderDialog(); |
| 275 | + |
| 276 | + mw.log( '$.proxy.nested callback :: ' + decodeURIComponent( hashResult ) ); |
| 277 | + |
| 278 | + // Try to parse the hash result |
| 279 | + try { |
| 280 | + var resultObject = JSON.parse( decodeURIComponent( hashResult ) ); |
| 281 | + } catch ( e ) { |
| 282 | + mw.log( "Error could not parse hashResult" ); |
| 283 | + } |
| 284 | + |
| 285 | + // Check for the contextKey |
| 286 | + if ( ! resultObject.contextKey ) { |
| 287 | + mw.log( "Error missing context key in nested callback" ); |
| 288 | + return false; |
| 289 | + } |
| 290 | + |
| 291 | + // Get the context via contextKey |
| 292 | + var context = getContext( resultObject.contextKey ); |
| 293 | + |
| 294 | + // Set the loaded flag to true. ( avoids timeout calls ) |
| 295 | + context[ 'proxyLoaded' ] = true; |
| 296 | + |
| 297 | + // Special callback to quickly establish a valid proxy connection. |
| 298 | + // If the proxyed "request" takes more time it does not |
| 299 | + // count against the proxy connection being established. |
| 300 | + if ( resultObject.state == 'ok' ) { |
| 301 | + return ; |
| 302 | + } |
| 303 | + |
| 304 | + // Check for the context callback: |
| 305 | + if( context.callback ){ |
| 306 | + context.callback( resultObject ); |
| 307 | + } |
| 308 | + }; |
| 309 | + |
| 310 | + |
| 311 | + /** |
| 312 | + * Handle a server msg |
| 313 | + * |
| 314 | + * @param {Object} frameMsg |
| 315 | + */ |
| 316 | + $.handleServerMsg = function( frameMsg ){ |
| 317 | + mw.log( "handleServerMsg:: " + JSON.stringify( frameMsg ) ); |
| 318 | + if( ! frameMsg.action ) { |
| 319 | + mw.log(" missing frameMsg action " ); |
| 320 | + return false; |
| 321 | + } |
| 322 | + switch( frameMsg.action ) { |
| 323 | + case 'fileSubmit': |
| 324 | + serverSubmitFile( frameMsg.formData ); |
| 325 | + break; |
| 326 | + case 'uploadHandlerAction': |
| 327 | + serverSendUploadHandlerAction( frameMsg.uiAction ); |
| 328 | + break; |
| 329 | + } |
| 330 | + }; |
| 331 | + |
| 332 | + /** |
| 333 | + * Api server proxy entry point: |
| 334 | + * validates the server frame request |
| 335 | + * and process the request type |
| 336 | + */ |
| 337 | + $.server = function() { |
| 338 | + // Validate the server request: |
| 339 | + if( ! validateIframeRequest() ) { |
| 340 | + mw.log( "Not a valid iframe request"); |
| 341 | + return false; |
| 342 | + } |
| 343 | + // Inform the client frame that we passed validation |
| 344 | + sendClientMsg( { 'state':'ok' } ); |
| 345 | + |
| 346 | + return serverHandleRequest(); |
| 347 | + } |
| 348 | + |
| 349 | + /** |
| 350 | + * Local scoped helper functions: |
| 351 | + */ |
| 352 | + |
| 353 | + /** |
| 354 | + * Creates a new context stored in the proxyContext local global |
| 355 | + * @param {Object} contextVars Initial contextVars |
| 356 | + */ |
| 357 | + function createContext ( contextVars ) { |
| 358 | + // Create a ~ sufficiently ~ unique context key |
| 359 | + var contextKey = new Date().getTime() * Math.random(); |
| 360 | + proxyContext [ contextKey ] = contextVars; |
| 361 | + |
| 362 | + // Setup the proxy loaded flag for this context: |
| 363 | + proxyContext[ contextKey ][ 'proxyLoaded' ] = false; |
| 364 | + |
| 365 | + // Set a local pointer to the contextKey |
| 366 | + proxyContext[ contextKey ]['contextKey' ] = contextKey; |
| 367 | + |
| 368 | + mw.log( "created context with key:" + contextKey ); |
| 369 | + |
| 370 | + // Return the proxy context |
| 371 | + return proxyContext [ contextKey ]; |
| 372 | + }; |
| 373 | + |
| 374 | + /** |
| 375 | + * Get a context from a contextKey |
| 376 | + * @param {String} [optional] contextKey Key of the context object to be returned |
| 377 | + * @return context object |
| 378 | + * false if context object can not be found |
| 379 | + */ |
| 380 | + function getContext ( contextKey ) { |
| 381 | + if( ! proxyContext [ contextKey ] ){ |
| 382 | + mw.log( "Error: contextKey not found:: " + contextKey ); |
| 383 | + return false; |
| 384 | + } |
| 385 | + return proxyContext [ contextKey ];; |
| 386 | + }; |
| 387 | + |
| 388 | + /** |
| 389 | + * Get the client frame path |
| 390 | + */ |
| 391 | + function getClientFrame( context ) { |
| 392 | + // Check if the mwEmbed is on the same server as we are |
| 393 | + if( mw.isLocalDomain( mw.getMwEmbedPath() ) ){ |
| 394 | + return mw.getMwEmbedPath() + 'modules/ApiProxy/NestedCallbackIframe.html'; |
| 395 | + } else { |
| 396 | + // Use the nested callback function ( server frame point back ) |
| 397 | + nestedServerFrame = getServerFrame( { |
| 398 | + 'apiUrl' : mw.getLocalApiUrl(), |
| 399 | + 'pageName' : 'ApiProxyNestedCb' |
| 400 | + } ); |
| 401 | + // Update the context to include the nestedCallbackFlag flag in the request |
| 402 | + return nestedServerFrame; |
| 403 | + } |
| 404 | + }; |
| 405 | + |
| 406 | + /** |
| 407 | + * Get the server Frame path per requested Api url |
| 408 | + * (presently hard coded to MediaWiki:ApiProxy per /remotes/medaiWiki.js ) |
| 409 | + * |
| 410 | + * NOTE: we should have a Hosted page once we deploy mwEmbed on the servers. |
| 411 | + * A hosted page would be much faster since it would not have to load all the |
| 412 | + * normal page view assets prior to being rewrite for api proxy usage. |
| 413 | + * |
| 414 | + * NOTE: We add the gadget incase the user has not enabled the gadget on the |
| 415 | + * domain they want to iframe to. There is no cost if they already have the |
| 416 | + * gadget on. This can be removed once deployed as well. |
| 417 | + * |
| 418 | + * @param {URL} apiUrl The url of the api server |
| 419 | + */ |
| 420 | + // Include gadget js ( in case the user has not enabled the gadget on that domain ) |
| 421 | + |
| 422 | + //var gadgetWithJS = ''; |
| 423 | + |
| 424 | + function getServerFrame( context ) { |
| 425 | + if( ! context || ! context.apiUrl ){ |
| 426 | + mw.log( "Error no context api url " ); |
| 427 | + return false; |
| 428 | + } |
| 429 | + var parsedUrl = mw.parseUri( context.apiUrl ); |
| 430 | + |
| 431 | + var pageName = ( context.pageName ) ? context.pageName : 'ApiProxy'; |
| 432 | + |
| 433 | + var pageUrl = parsedUrl.protocol + '://' + parsedUrl.authority |
| 434 | + + '/w/index.php/MediaWiki:' + pageName; |
| 435 | + |
| 436 | + if( mw.getConfig( 'Mw.AppendWithJS' ) ){ |
| 437 | + pageUrl+= '?' + mw.getConfig( 'Mw.AppendWithJS' ); |
| 438 | + } |
| 439 | + return pageUrl; |
| 440 | + } |
| 441 | + |
| 442 | + /** |
| 443 | + * Do the frame proxy |
| 444 | + * Sets up a frame proxy request |
| 445 | + * |
| 446 | + * @param {Object} context ( the context of the current doFrameProxy call ) |
| 447 | + * @param {Object} requestQuery The api request object |
| 448 | + */ |
| 449 | + function doFrameProxy ( context ) { |
| 450 | + |
| 451 | + var iframeRequest = { |
| 452 | + // Client domain frame ( will be approved by the server before sending and receiving msgs ) |
| 453 | + 'clientFrame' : getClientFrame( context ), |
| 454 | + 'action' : 'apiRequest', |
| 455 | + 'request' : context[ 'apiReq' ] |
| 456 | + } |
| 457 | + |
| 458 | + mw.log( "Do frame proxy request on src: \n" + getServerFrame( context ) + "\n" + JSON.stringify( context[ 'apiReq' ] ) ); |
| 459 | + appendIframe( { |
| 460 | + 'persist' : true, |
| 461 | + 'request' : iframeRequest, |
| 462 | + 'context' : context |
| 463 | + } ) |
| 464 | + } |
| 465 | + |
| 466 | + /** |
| 467 | + * Validate an iframe request |
| 468 | + * checks the url hash for required parameters |
| 469 | + * checks master_blacklist |
| 470 | + * checks master_whitelist |
| 471 | + */ |
| 472 | + function validateIframeRequest() { |
| 473 | + var clientRequest = getClientRequest(); |
| 474 | + |
| 475 | + if ( !clientRequest || !clientRequest.clientFrame ) { |
| 476 | + mw.log( "Error: no client domain provided " ); |
| 477 | + $j( 'body' ).append( "no client frame provided" ); |
| 478 | + return false; |
| 479 | + } |
| 480 | + |
| 481 | + // Make sure we are logged in |
| 482 | + // (its a normal mediaWiki page so all site vars should be defined) |
| 483 | + if ( typeof wgUserName != 'undefined' && !wgUserName ) { |
| 484 | + mw.log( 'Error Not logged in' ); |
| 485 | + return false; |
| 486 | + } |
| 487 | + |
| 488 | + mw.log( "Setup server on: " + mw.parseUri( document.URL ).host ); |
| 489 | + mw.log('Client frame: ' + clientRequest.clientFrame ); |
| 490 | + |
| 491 | + /** |
| 492 | + * CHECK IF THE DOMAIN IS ALLOWED per the ApiProxy config: |
| 493 | + */ |
| 494 | + return isAllowedClientFrame( clientRequest.clientFrame );; |
| 495 | + } |
| 496 | + |
| 497 | + /** |
| 498 | + * Check if a domain is allowed. |
| 499 | + * @param {Object} clientFrame |
| 500 | + */ |
| 501 | + function isAllowedClientFrame( clientFrame ) { |
| 502 | + var clientDomain = mw.parseUri( clientFrame ).host ; |
| 503 | + // Get the proxy config |
| 504 | + |
| 505 | + // Check master blacklist |
| 506 | + if( mw.getConfig('ApiProxy.DomainBlackList') && mw.getConfig('ApiProxy.DomainBlackList').length ){ |
| 507 | + var domainBlackList = mw.getConfig('ApiProxy.DomainBlackList'); |
| 508 | + for ( var i =0; i < domainBlackList.length; i++ ) { |
| 509 | + var blackDomain = domainBlackList[i]; |
| 510 | + // Check if domain check is a RegEx: |
| 511 | + if( typeof blackDomain == 'object' ){ |
| 512 | + if( clientDomain.match( blackDomain ) ){ |
| 513 | + return false; |
| 514 | + } |
| 515 | + } else { |
| 516 | + // just do a direct domain check: |
| 517 | + if( clientDomain == blackDomain ){ |
| 518 | + return false; |
| 519 | + } |
| 520 | + } |
| 521 | + } |
| 522 | + } |
| 523 | + |
| 524 | + // Check the master whitelist: |
| 525 | + if( mw.getConfig('ApiProxy.DomainWhiteList') && mw.getConfig('ApiProxy.DomainWhiteList').length ){ |
| 526 | + var domainWhiteList = mw.getConfig('ApiProxy.DomainWhiteList'); |
| 527 | + for ( var i =0; i < domainWhiteList.length; i++ ) { |
| 528 | + whiteDomain = domainWhiteList[i]; |
| 529 | + // Check if domain check is a RegEx: |
| 530 | + if( typeof whiteDomain == 'object' ){ |
| 531 | + if( clientDomain.match( whiteDomain ) ) { |
| 532 | + return true; |
| 533 | + } |
| 534 | + } else { |
| 535 | + if( clientDomain == whiteDomain ){ |
| 536 | + return true; |
| 537 | + } |
| 538 | + } |
| 539 | + } |
| 540 | + } |
| 541 | + |
| 542 | + // FIXME Add in user based approval :: |
| 543 | + |
| 544 | + // FIXME offer the user the ability to "approve" requested domain save to |
| 545 | + // their user preference setup ) |
| 546 | + |
| 547 | + // FIXME grab and check domain against the users whitelist and permissions |
| 548 | + |
| 549 | + // for now just return false if the domain is not in the approved list |
| 550 | + return false; |
| 551 | + }; |
| 552 | + |
| 553 | + /** |
| 554 | + * Get the client request from the document hash |
| 555 | + * @return {Object} the object result of parsing the document anchor msg |
| 556 | + */ |
| 557 | + function getClientRequest() { |
| 558 | + // Read the anchor data package from the requesting url |
| 559 | + var hashMsg = unescape( mw.parseUri( document.URL ).anchor ); |
| 560 | + try { |
| 561 | + return JSON.parse( hashMsg ); |
| 562 | + } catch ( e ) { |
| 563 | + mw.log( "ProxyServer:: could not parse anchor" ); |
| 564 | + return false; |
| 565 | + } |
| 566 | + }; |
| 567 | + |
| 568 | + /** |
| 569 | + * Dialog to send the user if a proxy to the remote server could not be created |
| 570 | + * @param {Object} context |
| 571 | + */ |
| 572 | + function proxyNotReadyTimeout( context ) { |
| 573 | + mw.log( "Error:: api proxy timeout " + context.contextKey ); |
| 574 | + |
| 575 | + // See if we have a callback function to call ( do not display the dialog ) |
| 576 | + if( context[ 'timeoutCb' ] && typeof context[ 'timeoutCb' ] == 'function' ) { |
| 577 | + context[ 'timeoutCb' ] ( ); |
| 578 | + return true; |
| 579 | + } |
| 580 | + |
| 581 | + var buttons = { }; |
| 582 | + buttons[ gM( 'mwe-re-try' ) ] = function() { |
| 583 | + mw.addLoaderDialog( gM( 'mwe-re-trying' ) ); |
| 584 | + // Re try the same context request: |
| 585 | + doFrameProxy( context ); |
| 586 | + }; |
| 587 | + buttons[ gM( 'mwe-cancel' ) ] = function() { |
| 588 | + mw.closeLoaderDialog ( ); |
| 589 | + }; |
| 590 | + |
| 591 | + // Setup the login link: |
| 592 | + var pUri = mw.parseUri( getServerFrame( context ) ); |
| 593 | + var login_url = pUri.protocol + '://' + pUri.host; |
| 594 | + login_url += pUri.path.replace( 'MediaWiki:ApiProxy', 'Special:UserLogin' ); |
| 595 | + |
| 596 | + var $dialogMsg = $j('<p />'); |
| 597 | + $dialogMsg.append( |
| 598 | + gM( 'mwe-please-login', |
| 599 | + pUri.host, |
| 600 | + |
| 601 | + // Add log-in link: |
| 602 | + $j( '<a />') |
| 603 | + .attr( { |
| 604 | + 'href' : login_url, |
| 605 | + 'target' : '_new' |
| 606 | + } ) |
| 607 | + .text( gM('mwe-log-in-link') ) |
| 608 | + ) |
| 609 | + ) |
| 610 | + // Add the security note as well: |
| 611 | + $dialogMsg.append( |
| 612 | + $j('<br />'), |
| 613 | + gM( 'mwe-remember-loging' ) |
| 614 | + ) |
| 615 | + |
| 616 | + mw.addDialog( { |
| 617 | + 'title' : gM( 'mwe-proxy-not-ready' ), |
| 618 | + 'content' : $dialogMsg, |
| 619 | + 'buttons' : buttons |
| 620 | + }) |
| 621 | + }; |
| 622 | + |
| 623 | + /** |
| 624 | + * API iFrame Server:: |
| 625 | + * |
| 626 | + * Handles the server side proxy of requests |
| 627 | + * it adds child frames pointing to the parent "blank" frames |
| 628 | + */ |
| 629 | + |
| 630 | + /** |
| 631 | + * serverHandleRequest handle a given request from the client |
| 632 | + * maps the request to serverBrowseFile or serverApiRequest |
| 633 | + * |
| 634 | + * NOTE: mw.ApiProxy.server entry point validates the request |
| 635 | + */ |
| 636 | + function serverHandleRequest( ) { |
| 637 | + var clientRequest = getClientRequest(); |
| 638 | + mw.log(" Handle client request :: " + JSON.stringify( clientRequest ) ); |
| 639 | + // Process request type: |
| 640 | + switch( clientRequest[ 'action' ] ){ |
| 641 | + case 'browseFile': |
| 642 | + return serverBrowseFile(); |
| 643 | + break; |
| 644 | + case 'apiRequest': |
| 645 | + return serverApiRequest(); |
| 646 | + break; |
| 647 | + case 'sendFrameMsg': |
| 648 | + return serverSendFrameMsg(); |
| 649 | + break; |
| 650 | + } |
| 651 | + mw.log( "Error could not handle client request" ); |
| 652 | + return false; |
| 653 | + }; |
| 654 | + |
| 655 | + /** |
| 656 | + * Api iFrame request: |
| 657 | + */ |
| 658 | + function serverApiRequest( ) { |
| 659 | + // Get the client request |
| 660 | + var clientRequest = getClientRequest(); |
| 661 | + |
| 662 | + // Make sure its a json format |
| 663 | + clientRequest.request[ 'format' ] = 'json'; |
| 664 | + |
| 665 | + mw.log(" do post request to: " + wgScriptPath + '/api' + wgScriptExtension ); |
| 666 | + |
| 667 | + // Process the API request. We don't use mw.getJSON since we need to "post" |
| 668 | + $j.post( wgScriptPath + '/api' + wgScriptExtension, |
| 669 | + clientRequest.request, |
| 670 | + function( data ) { |
| 671 | + // Make sure data is in JSON data format ( not a string ) |
| 672 | + if( typeof data != 'object' ){ |
| 673 | + data = JSON.parse( data ); |
| 674 | + } |
| 675 | + mw.log(" server api request got data: " + JSON.stringify( data ) ); |
| 676 | + // Send the result data to the client |
| 677 | + sendClientMsg( data ); |
| 678 | + } |
| 679 | + ); |
| 680 | + } |
| 681 | + |
| 682 | + /** |
| 683 | + * Send a msg to a server frame |
| 684 | + * |
| 685 | + * Server frame instances that handle msgs |
| 686 | + * should accept processMsg calls |
| 687 | + */ |
| 688 | + function serverSendFrameMsg( ){ |
| 689 | + var clientRequest = getClientRequest(); |
| 690 | + |
| 691 | + // Make sure the requested frame exists: |
| 692 | + if( ! clientRequest.frameMsg || ! clientRequest.frameName ) { |
| 693 | + mw.log("Error serverSendFrameMsg without frame msg or frameName" ); |
| 694 | + return false; |
| 695 | + } |
| 696 | + |
| 697 | + // Send the message to the target frame |
| 698 | + top[ clientRequest.frameName ].mw.ApiProxy.handleServerMsg( clientRequest.frameMsg ); |
| 699 | + } |
| 700 | + |
| 701 | + /** |
| 702 | + * Setup the browse file proxy on the "server" |
| 703 | + * |
| 704 | + * Sets the page content to browser file |
| 705 | + */ |
| 706 | + function serverBrowseFile( ) { |
| 707 | + |
| 708 | + // If wgEnableFirefogg is not boolean false, set to true |
| 709 | + if ( typeof wgEnableFirefogg == 'undefined' ) { |
| 710 | + wgEnableFirefogg = true; |
| 711 | + } |
| 712 | + |
| 713 | + // Setup the browse file html |
| 714 | + serverBrowseFileSetup(); |
| 715 | + |
| 716 | + // Load the mw.upload library with iframe interface (similar to uploadPage.js) |
| 717 | + // Check if firefogg is enabled: |
| 718 | + // NOTE: the binding function should be made identical. |
| 719 | + if( wgEnableFirefogg ) { |
| 720 | + mw.load( 'AddMedia.firefogg', function() { |
| 721 | + $j( '#wpUploadFile' ).firefogg( getUploadFileConfig() ); |
| 722 | + |
| 723 | + // Update status |
| 724 | + sendClientMsg( {'status':'ok'} ); |
| 725 | + }); |
| 726 | + } else { |
| 727 | + mw.load( 'AddMedia.UploadHandler', function() { |
| 728 | + var uploadConfig = getUploadFileConfig(); |
| 729 | + |
| 730 | + $j( '#mw-upload-form' ).uploadHandler( getUploadFileConfig() ); |
| 731 | + |
| 732 | + // Update status |
| 733 | + sendClientMsg( {'status':'ok'} ); |
| 734 | + }); |
| 735 | + } |
| 736 | + }; |
| 737 | + |
| 738 | + /** |
| 739 | + * Setup the browse file html |
| 740 | + * @return browse file config |
| 741 | + */ |
| 742 | + function serverBrowseFileSetup( ){ |
| 743 | + // Get the client request config |
| 744 | + var clientRequest = getClientRequest(); |
| 745 | + |
| 746 | + // Check for fw ( file width ) |
| 747 | + if( ! clientRequest.fileWidth ) { |
| 748 | + clientRequest.fileWidth = 130; |
| 749 | + } |
| 750 | + // Check for the token |
| 751 | + if( ! clientRequest.token ){ |
| 752 | + mw.log("Error server browse file setup without token") |
| 753 | + return false; |
| 754 | + } |
| 755 | + |
| 756 | + //Build a form with bindings similar to uploadPage.js ( but only the browse button ) |
| 757 | + $j('body').html( |
| 758 | + $j('<form />') |
| 759 | + .attr( { |
| 760 | + 'name' : "mw-upload-form", |
| 761 | + 'id' : "mw-upload-form", |
| 762 | + 'enctype' : "multipart/form-data", |
| 763 | + 'method' : "post", |
| 764 | + // Submit to the local domain |
| 765 | + 'action' : mw.getLocalApiUrl() |
| 766 | + } ) |
| 767 | + .append( |
| 768 | + //Add the "browse for file" button |
| 769 | + $j('<input />') |
| 770 | + .attr({ |
| 771 | + 'type' : "file", |
| 772 | + 'name' : "wpUploadFile", |
| 773 | + 'id' : "wpUploadFile" |
| 774 | + }) |
| 775 | + .css({ |
| 776 | + 'width' : clientRequest.fileWidth |
| 777 | + }), |
| 778 | + |
| 779 | + // Append the token |
| 780 | + $j('<input />') |
| 781 | + .attr({ |
| 782 | + 'type' : 'hidden', |
| 783 | + 'id' : "wpEditToken", |
| 784 | + 'name' : 'token' |
| 785 | + }) |
| 786 | + .val( clientRequest.token ) |
| 787 | + ) |
| 788 | + ); |
| 789 | + } |
| 790 | + |
| 791 | + /** |
| 792 | + * Browse file upload config generator |
| 793 | + */ |
| 794 | + function getUploadFileConfig(){ |
| 795 | + |
| 796 | + // Setup the upload iframeUI |
| 797 | + var uploadIframeUI = new mw.UploadIframeUI( function( method ){ |
| 798 | + // Get all the arguments after the "method" |
| 799 | + var args = $j.makeArray( arguments ).splice( 1 ); |
| 800 | + // Send the client the msg: |
| 801 | + sendClientMsg( { |
| 802 | + 'event' : 'uploadUI', |
| 803 | + 'method' : method, |
| 804 | + // Get all the arguments after the "method" |
| 805 | + 'arguments' : args |
| 806 | + } ); |
| 807 | + } ); |
| 808 | + |
| 809 | + var uploadConfig = { |
| 810 | + // Set the interface type |
| 811 | + 'ui' : uploadIframeUI, |
| 812 | + |
| 813 | + // Set the select file callback to update clientFrame |
| 814 | + 'selectFileCb' : function( fileName ) { |
| 815 | + sendClientMsg( { |
| 816 | + 'event': 'selectFileCb', |
| 817 | + 'fileName' : fileName |
| 818 | + } ); |
| 819 | + }, |
| 820 | + // The return to form cb: |
| 821 | + 'returnToFormCb' : function (){ |
| 822 | + sendClientMsg( { |
| 823 | + 'event': 'returnToFormCb' |
| 824 | + } ); |
| 825 | + }, |
| 826 | + // Api proxy does not handle descriptionText rewrite |
| 827 | + 'rewriteDescriptionText' : false, |
| 828 | + |
| 829 | + // Don't show firefogg upload warning |
| 830 | + 'showFoggWarningFlag' : false, |
| 831 | + |
| 832 | + // Set the doneUploadCb if set in the browseFile options |
| 833 | + 'doneUploadCb' : function ( apiResult ){ |
| 834 | + sendClientMsg( { |
| 835 | + 'event': 'doneUploadCb', |
| 836 | + 'apiResult' : apiResult |
| 837 | + } ); |
| 838 | + } |
| 839 | + } |
| 840 | + |
| 841 | + return uploadConfig; |
| 842 | + } |
| 843 | + |
| 844 | + /** |
| 845 | + * Server send interface action |
| 846 | + */ |
| 847 | + function serverSendUploadHandlerAction( action ) { |
| 848 | + // Get a refrence to the uploadHandler: |
| 849 | + // NOTE: both firefogg and upload form should save upload target in a similar way |
| 850 | + var selector = ( wgEnableFirefogg ) ? '#wpUploadFile' : '#mw-upload-form'; |
| 851 | + var uploadHandler = $j( selector ).get(0).uploadHandler; |
| 852 | + if( uploadHandler ){ |
| 853 | + uploadHandler.uploadHandlerAction( action ); |
| 854 | + } else { |
| 855 | + mw.log( "Error: could not find upload handler" ); |
| 856 | + } |
| 857 | + } |
| 858 | + |
| 859 | + /** |
| 860 | + * Server submit file |
| 861 | + * @param {Object} options Options for submiting file |
| 862 | + */ |
| 863 | + function serverSubmitFile( formData ){ |
| 864 | + mw.log("Submit form with fname:" + formData.filename + "\n :: " + formData.comment) |
| 865 | + // Add the FileName and and the description to the form |
| 866 | + var $form = $j('#mw-upload-form'); |
| 867 | + var formApiFields = [ 'filename', 'comment', 'watch', 'ignorewarnings', 'token' ]; |
| 868 | + |
| 869 | + for( var i=0; i < formApiFields.length ; i++ ){ |
| 870 | + var fieldName = formApiFields[ i ]; |
| 871 | + if( typeof formData[ fieldName ] == 'string' ) { |
| 872 | + // Add the input field if not already there: |
| 873 | + if( ! $form.find("[name='" + fieldName + "']" ).length ){ |
| 874 | + $form.append( |
| 875 | + $j( '<input />' ) |
| 876 | + .attr( { |
| 877 | + 'name' : fieldName, |
| 878 | + 'type' : 'hidden' |
| 879 | + } ) |
| 880 | + ) |
| 881 | + } |
| 882 | + // Add the value if set: |
| 883 | + $form.find("[name='" + fieldName + "']" ).val( formData[ fieldName ] ); |
| 884 | + } |
| 885 | + } |
| 886 | + // Do submit the form |
| 887 | + $form.submit(); |
| 888 | + }; |
| 889 | + |
| 890 | + /** |
| 891 | + * Outputs the result object to the client domain |
| 892 | + * |
| 893 | + * @param {msgObj} msgObj Msg to send to client domain |
| 894 | + */ |
| 895 | + function sendClientMsg( msgObj ) { |
| 896 | + |
| 897 | + // Get the client Request: |
| 898 | + var clientRequest = getClientRequest(); |
| 899 | + |
| 900 | + // Get a local reference to the client request |
| 901 | + var clientFrame = clientRequest[ 'clientFrame' ]; |
| 902 | + |
| 903 | + // Double check that the client is an approved domain before outputting the iframe |
| 904 | + if( ! isAllowedClientFrame ( clientFrame ) ) { |
| 905 | + mw.log( "Cant send msg to " + clientFrame ); |
| 906 | + return false; |
| 907 | + } |
| 908 | + |
| 909 | + // Double check we have a context key: |
| 910 | + if( ! clientRequest.contextKey ) { |
| 911 | + mw.log( "Error: missing context key " ); |
| 912 | + return false; |
| 913 | + } |
| 914 | + |
| 915 | + var nestName = 'NestedFrame_' + $j( 'iframe' ).length; |
| 916 | + |
| 917 | + // Append the iframe to body |
| 918 | + appendIframe( { |
| 919 | + 'src' : clientFrame, |
| 920 | + 'request' : msgObj, |
| 921 | + // Client msgs just have the contextKey ( not the full context ) |
| 922 | + 'context' : { |
| 923 | + 'contextKey' : clientRequest.contextKey |
| 924 | + } |
| 925 | + } ); |
| 926 | + }; |
| 927 | + |
| 928 | + /** |
| 929 | + * Appends an iframe to the body from a given set of options |
| 930 | + * |
| 931 | + * NOTE: this uses string html building instead of jquery build-out |
| 932 | + * because IE does not allow setting of iframe attributes |
| 933 | + * |
| 934 | + * @param {Object} options Iframe attribute options |
| 935 | + * name - the name of the iframe |
| 936 | + * src - the url for the iframe |
| 937 | + * request - the request object to be packaged into the hash url |
| 938 | + * persist - set to true if the iframe should not |
| 939 | + * be removed from the dom after its done loading |
| 940 | + */ |
| 941 | + function appendIframe( options ){ |
| 942 | + |
| 943 | + // Build out iframe in string since IE throws away attributes of |
| 944 | + // jQuery iframe buildout |
| 945 | + var s = '<iframe '; |
| 946 | + |
| 947 | + // Check for context |
| 948 | + if( ! options[ 'context' ] ) { |
| 949 | + mw.log("Error missing context"); |
| 950 | + return false; |
| 951 | + }else{ |
| 952 | + var context = options[ 'context' ]; |
| 953 | + } |
| 954 | + |
| 955 | + if( ! options[ 'src' ] ) { |
| 956 | + options[ 'src' ] = getServerFrame( context ); |
| 957 | + } |
| 958 | + |
| 959 | + // Check for frame name: |
| 960 | + if( ! options[ 'name' ] ) { |
| 961 | + options[ 'name' ] = 'mwApiProxyFrame_' + $j( 'iframe' ).length; |
| 962 | + } |
| 963 | + |
| 964 | + // Add the frame name / id: |
| 965 | + s += 'name="' + mw.escapeQuotes( options[ 'name' ] ) + '" '; |
| 966 | + s += 'id="' + mw.escapeQuotes( options[ 'name' ] ) + '" '; |
| 967 | + |
| 968 | + // Check for style: |
| 969 | + if( ! options['style'] ) { |
| 970 | + options['style'] = 'display:none'; |
| 971 | + } |
| 972 | + |
| 973 | + // Add style attribute: |
| 974 | + s += 'style="' + mw.escapeQuotes( options[ 'style' ] ) + '" '; |
| 975 | + |
| 976 | + // Special handler for src and packaged hash request: |
| 977 | + if( options.src ) { |
| 978 | + s += 'src="' + mw.escapeQuotes( options.src ); |
| 979 | + if( options.request ) { |
| 980 | + |
| 981 | + // Add the contextKey to the request |
| 982 | + options.request[ 'contextKey' ] = context.contextKey; |
| 983 | + |
| 984 | + // Add the escaped version of the request: |
| 985 | + s += '#' + encodeURIComponent( JSON.stringify( options.request ) ); |
| 986 | + } |
| 987 | + s += '" '; |
| 988 | + } |
| 989 | + |
| 990 | + // Close up the iframe: |
| 991 | + s += '></iframe>'; |
| 992 | + |
| 993 | + // Check for the iframe append target ( default "body" tag ) |
| 994 | + if( ! options[ 'target' ] ){ |
| 995 | + options[ 'target' ] = 'body'; |
| 996 | + } |
| 997 | + var targetName = ( typeof options[ 'target' ] == 'string') ? options[ 'target' ] : $j( options[ 'target' ]).length ; |
| 998 | + |
| 999 | + mw.log( "Append iframe:" + options[ 'src' ] + ' to: ' + targetName + " \n with data: " + JSON.stringify( options.request ) ); |
| 1000 | + |
| 1001 | + // Append to target |
| 1002 | + $j( options[ 'target' ] ).append( s ); |
| 1003 | + |
| 1004 | + // Setup the onload callback |
| 1005 | + $j( '#' + options[ 'name' ] ).get( 0 ).onload = function() { |
| 1006 | + if( ! options.persist ){ |
| 1007 | + // Schedule the removal of the iframe |
| 1008 | + // We don't call remove directly since some browsers seem to call "ready" |
| 1009 | + // before blocking javascript code is done running |
| 1010 | + setTimeout( function() { |
| 1011 | + $j('#' + options[ 'name' ] ).remove(); |
| 1012 | + }, 10 ); |
| 1013 | + } |
| 1014 | + }; |
| 1015 | + |
| 1016 | + // Setupt the timeout check: |
| 1017 | + setTimeout( function() { |
| 1018 | + if ( context[ 'proxyLoaded' ] === false ) { |
| 1019 | + // We timed out no api proxy (should make sure the user is "logged in") |
| 1020 | + proxyNotReadyTimeout( context ); |
| 1021 | + } |
| 1022 | + }, mw.getConfig( 'defaultRequestTimeout') * 1000 ); |
| 1023 | + } |
| 1024 | + |
| 1025 | +} )( window.mw.ApiProxy ); |
Property changes on: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/mw.ApiProxy.js |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 1026 | + text/plain |
Index: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/README |
— | — | @@ -0,0 +1 @@ |
| 2 | +Probably have to move this to an extension |
\ No newline at end of file |
Index: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/ApiEmbed.resourceList.php |
— | — | @@ -0,0 +1,10 @@ |
| 2 | +<?php |
| 3 | +/** |
| 4 | + * MwEmebed ApiEmbed resource list array |
| 5 | + */ |
| 6 | + |
| 7 | +return array( |
| 8 | + 'ApiEmbed' => array( |
| 9 | + 'loader' => array() // @@FIXME add in apiSupport |
| 10 | + ) |
| 11 | +) |
\ No newline at end of file |
Index: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/ApiProxy.i18n.php |
— | — | @@ -0,0 +1,195 @@ |
| 2 | +<?php |
| 3 | +/* |
| 4 | + * Internationalisation for ApiProxy |
| 5 | + * |
| 6 | + * @file |
| 7 | + * @ingroup Extensions |
| 8 | + */ |
| 9 | + |
| 10 | +$messages = array(); |
| 11 | +$messages['en'] = array( |
| 12 | + 'mwe-setting-up-proxy' => 'Setting up proxy...', |
| 13 | + 'mwe-re-try' => 'Retry API request', |
| 14 | + 'mwe-re-trying' => 'Retrying API request...', |
| 15 | + 'mwe-proxy-not-ready' => 'Proxy is not configured', |
| 16 | + 'mwe-please-login' => 'The request failed. Are you logged in on $1 ? Please $2 and try again', |
| 17 | + 'mwe-log-in-link' => 'log in', |
| 18 | + 'mwe-remember-loging' => 'General security reminder: Only login to web sites when your address bar displays that site\'s address.', |
| 19 | +); |
| 20 | +$messages['ar'] = array( |
| 21 | + 'mwe-re-try' => 'أعد طلب الواجهة البرمجية', |
| 22 | + 'mwe-re-trying' => 'يعيد طلب الواجهة البرمجية...', |
| 23 | +); |
| 24 | +$messages['be-tarask'] = array( |
| 25 | + 'mwe-setting-up-proxy' => 'Наладка проксі...', |
| 26 | + 'mwe-re-try' => 'Паўтарыць API-запыт', |
| 27 | + 'mwe-re-trying' => 'Паўторны API-запыт…', |
| 28 | + 'mwe-proxy-not-ready' => 'Проксі не сканфігураваны', |
| 29 | + 'mwe-please-login' => 'Вы не <a target="_new" href="$1">ўвайшлі ў сыстэму</a> $2 альбо mwEmbed ня быў уключаны. Вырашыце гэтую праблему і потым паўтарыце запыт.', |
| 30 | + 'mwe-remember-loging' => 'Агульны напамін бясьпекі: Уваходзьце ў сыстэму толькі ў тым выпадку, калі ў радку адраса адлюстроўваецца адрас сайту, які чакаецца.', |
| 31 | +); |
| 32 | +$messages['br'] = array( |
| 33 | + 'mwe-setting-up-proxy' => 'Arventenniñ ar proksi...', |
| 34 | +); |
| 35 | +$messages['bs'] = array( |
| 36 | + 'mwe-re-try' => 'Pokušaj API zahtjev', |
| 37 | +); |
| 38 | +$messages['de'] = array( |
| 39 | + 'mwe-setting-up-proxy' => 'Proxy-Einstellung …', |
| 40 | + 'mwe-re-try' => 'Wiederhole API-Anfrage', |
| 41 | + 'mwe-re-trying' => 'Wiederholung der API-Anfrage …', |
| 42 | + 'mwe-proxy-not-ready' => 'Proxy nicht konfiguriert', |
| 43 | + 'mwe-please-login' => 'Du bist auf $2 nicht <a target="_new" href="$1">angemeldet</a> oder mwEmbed ist nicht aktiviert. Löse das Problem und wiederhole deine Anfrage.', |
| 44 | + 'mwe-remember-loging' => 'Allgemeiner Sicherheitshinweis: Websiteanmeldung nur, wenn deine Adressleiste die Websiteadresse anzeigt.', |
| 45 | +); |
| 46 | +$messages['diq'] = array( |
| 47 | + 'mwe-setting-up-proxy' => 'proxy bar beno...', |
| 48 | + 'mwe-re-try' => 'waştışê Retry API\'yi', |
| 49 | + 'mwe-re-trying' => 'newe ra waştışê Retry API\'yi...', |
| 50 | + 'mwe-proxy-not-ready' => 'proxy nêvıraziyayo/ro nêniyayo', |
| 51 | + 'mwe-please-login' => '<a target="_new" href="$1">logged in</a> on $2 aktif nêbiyo, newe ra tesel bıkerê.', |
| 52 | + 'mwe-remember-loging' => 'virrardışê pawıtışê umumiyi: adresê keyepeli têna wextê cıkewetışi de aseni', |
| 53 | +); |
| 54 | +$messages['dsb'] = array( |
| 55 | + 'mwe-setting-up-proxy' => 'Proksy se pśihotujo...', |
| 56 | + 'mwe-re-try' => 'Napšašowanje API wóspjetowaś', |
| 57 | + 'mwe-re-trying' => 'Napšašowanje API so wóspjetujo...', |
| 58 | + 'mwe-proxy-not-ready' => 'Proksy njejo konfigěrowany', |
| 59 | + 'mwe-please-login' => 'Njejsy na $2 <a target="_new" href="$1">pśizjawjony</a> abo mwEmbed njejo zmóžnjony. Rozwěž tuś ten problem a wóspjetuj pótom napšašowanje.', |
| 60 | + 'mwe-remember-loging' => 'Powšykne wěstotne dopominanje: Pśizjaw se jano na websedłach, gaž twójo adresowe pólo zwobraznjujo adresu togo sedła.', |
| 61 | +); |
| 62 | +$messages['es'] = array( |
| 63 | + 'mwe-re-try' => 'Reintentar solicitud de API', |
| 64 | + 'mwe-re-trying' => 'Reintentando solicitud de API', |
| 65 | + 'mwe-proxy-not-ready' => 'Proxy no configurado', |
| 66 | + 'mwe-remember-loging' => 'Recordatorio general de seguridad: Accede a los sitios web sólo cuando la barra de direcciones muestre esa dirección del sitio.', |
| 67 | +); |
| 68 | +$messages['fr'] = array( |
| 69 | + 'mwe-setting-up-proxy' => 'Paramétrage du proxy...', |
| 70 | + 'mwe-re-try' => 'Réessayer la requête API', |
| 71 | + 'mwe-re-trying' => 'Nouvelle tentative de requête API...', |
| 72 | + 'mwe-proxy-not-ready' => 'Le proxy n’est pas configuré', |
| 73 | + 'mwe-please-login' => 'Vous n’êtes pas <a target="_new" href="$1">connecté</a> sur $2 ou mwEmbed n’a pas été activé. Corrigez le problème, puis retentez votre requête.', |
| 74 | + 'mwe-remember-loging' => 'Rappel de sécurité : ne vous connectez à un site internet que lorsque l’adresse de ce site est affichée dans votre barre d’adresse.', |
| 75 | +); |
| 76 | +$messages['gl'] = array( |
| 77 | + 'mwe-setting-up-proxy' => 'Configurando o proxy...', |
| 78 | + 'mwe-re-try' => 'Reintentar a solicitude API', |
| 79 | + 'mwe-re-trying' => 'Reintentando a solicitude API...', |
| 80 | + 'mwe-proxy-not-ready' => 'O proxy non está configurado', |
| 81 | + 'mwe-please-login' => 'Non <a target="_new" href="$1">accedeu ao sistema</a> de $2 ou o mwEmbed non está activado. Resolva o problema e intente de novo a solicitude.', |
| 82 | + 'mwe-remember-loging' => 'Advertencia de seguridade xeral: non acceda ao sistema de ningunha páxina web cando a súa barra de enderezos mostre outro enderezo que non se corresponda co dese sitio.', |
| 83 | +); |
| 84 | +$messages['gsw'] = array( |
| 85 | + 'mwe-setting-up-proxy' => 'Am Yystelle vun eme Proxy ...', |
| 86 | + 'mwe-re-try' => 'API-Aafrog widerhole', |
| 87 | + 'mwe-re-trying' => 'Am Widerhole vun ere API-Aafrog ...', |
| 88 | + 'mwe-proxy-not-ready' => 'Proxy isch nit konfiguriert', |
| 89 | + 'mwe-please-login' => 'Du bisch nit <a target="_new" href="$1">aagmäldet</a> uf $2 oder mwEmbed isch nit aagschalte. Les s Probläm un versuech d Aafrog derno nonemol.', |
| 90 | + 'mwe-remember-loging' => 'Generälli Sicherheits-Erinnerig: Mäld di numme uf Websyte aa, wänn Dyyni Adrässleischte d Adrässe vu däre Syte aazeigt.', |
| 91 | +); |
| 92 | +$messages['hsb'] = array( |
| 93 | + 'mwe-setting-up-proxy' => 'Proksy so připrawja...', |
| 94 | + 'mwe-re-try' => 'Naprašowanje API wospjetować', |
| 95 | + 'mwe-re-trying' => 'Naprašowanje API so wospjetuje...', |
| 96 | + 'mwe-proxy-not-ready' => 'Proksy njeje konfigurowany', |
| 97 | + 'mwe-please-login' => 'Njejsy na $2 <a target="_new" href="$1">přizjewjeny</a> abo mwEmbed njeje zmóžnjeny. Rozrisaj tutón problem a wospjetuj potom naprašowanje.', |
| 98 | + 'mwe-remember-loging' => 'Powšitkowne wěstotne dopomnjeće: Přizjew so jenož na websydłach, hdyž twoje adresowe polo adresu sydła zwobraznjuje.', |
| 99 | +); |
| 100 | +$messages['hu'] = array( |
| 101 | + 'mwe-setting-up-proxy' => 'Proxy beállítása…', |
| 102 | + 'mwe-re-try' => 'API kérés újrapróbálása', |
| 103 | + 'mwe-re-trying' => 'API kérés újraküldése…', |
| 104 | + 'mwe-proxy-not-ready' => 'A proxy nincs beállítva', |
| 105 | + 'mwe-please-login' => 'Nem vagy <a target="_new" href="$1">bejelentkezve</a> a(z) $2 wikire, vagy az mwEmbed nincs engedélyezve. Orvosold a problémát, majd próbáld újra a kérést.', |
| 106 | + 'mwe-remember-loging' => 'Általános biztonsági emlékeztető: csak akkor jelentkezz be egy weboldalra, ha a böngésződ címsorában annak az oldalnak a címét látod.', |
| 107 | +); |
| 108 | +$messages['ia'] = array( |
| 109 | + 'mwe-setting-up-proxy' => 'Configuration del proxy...', |
| 110 | + 'mwe-re-try' => 'Reprobar requesta API', |
| 111 | + 'mwe-re-trying' => 'Reproba requesta API...', |
| 112 | + 'mwe-proxy-not-ready' => 'Le proxy non es configurate', |
| 113 | + 'mwe-please-login' => 'Tu non es <a target="_new" href="$1">identificate</a> in $2 o mwEmbed non ha essite activate. Resolve le problema, alora reproba le requesta.', |
| 114 | + 'mwe-remember-loging' => 'Promemoria general de securitate: Solmente identifica te a sitos web si tu barra de adresse monstra le adresse del sito in question.', |
| 115 | +); |
| 116 | +$messages['id'] = array( |
| 117 | + 'mwe-setting-up-proxy' => 'Menyiapkan proksi...', |
| 118 | + 'mwe-re-try' => 'Ulangi permintaan API', |
| 119 | + 'mwe-re-trying' => 'Mengulangi permintaan API...', |
| 120 | + 'mwe-proxy-not-ready' => 'Proksi tak dapat dikonfigurasi', |
| 121 | + 'mwe-please-login' => 'Anda tidak <a target="_new" href="$1">masuk log</a> di $2 atau mwEmbed belum diaktifkan. Perbaiki masalah ini, dan ulangi permintaan.', |
| 122 | + 'mwe-remember-loging' => 'Pengingat keamanan umum: Hanya masuk log ke situs web sewaktu bilah alamat Anda menampilkan alamat situs tersebut.', |
| 123 | +); |
| 124 | +$messages['it'] = array( |
| 125 | + 'mwe-setting-up-proxy' => 'Installazione del proxy in corso...', |
| 126 | + 'mwe-proxy-not-ready' => 'Il Proxy non è configurato', |
| 127 | +); |
| 128 | +$messages['ja'] = array( |
| 129 | + 'mwe-setting-up-proxy' => 'プロキシをセットアップ中…', |
| 130 | + 'mwe-re-try' => 'API 要求を再試行', |
| 131 | + 'mwe-re-trying' => 'API 要求を再試行中…', |
| 132 | + 'mwe-proxy-not-ready' => 'プロキシが設定されていません', |
| 133 | + 'mwe-please-login' => 'あなたが $2 へ<a target="_new" href="$1">ログイン</a>していないか、mwEmbed が有効化されていません。この問題を解決し、それから要求を再試行してください。', |
| 134 | + 'mwe-remember-loging' => '一般的に、セキュリティーのためにはアドレスバーにそのサイトのアドレスが表示されるウェブサイトにのみログインしてください。', |
| 135 | +); |
| 136 | +$messages['ksh'] = array( |
| 137 | + 'mwe-remember-loging' => 'Opjepaß: För sescher ze sinn, donn bloß dann ööhnßwoh enlogge,wann Dinge Brauser dä ßait ier Addräß en singem Feld för de Addräß aanzeijsch!', |
| 138 | +); |
| 139 | +$messages['lb'] = array( |
| 140 | + 'mwe-setting-up-proxy' => 'Proxy astellen ...', |
| 141 | + 'mwe-re-try' => 'Api-Ufro widderhuelen', |
| 142 | + 'mwe-re-trying' => 'UPI-Ufro gëtt widderholl.', |
| 143 | + 'mwe-proxy-not-ready' => 'De Proxy ass net agestallt', |
| 144 | +); |
| 145 | +$messages['ml'] = array( |
| 146 | + 'mwe-setting-up-proxy' => 'പ്രോക്സി സജ്ജീകരിക്കുന്നു...', |
| 147 | + 'mwe-proxy-not-ready' => 'പ്രോക്സി ക്രമീകരിക്കപ്പെട്ടിട്ടില്ല.', |
| 148 | + 'mwe-please-login' => 'താങ്കൾ $2 സംരംഭത്തിൽ <a target="_new" href="$1">പ്രവേശിച്ചിട്ടില്ല</a> അല്ലങ്കിൽ mwEmbed സജ്ജമാക്കിയിട്ടില്ല. ഈ പ്രശ്നം പരിഹരിച്ച ശേഷം വീണ്ടും ശ്രമിക്കൂ.', |
| 149 | + 'mwe-remember-loging' => 'പൊതു സുരക്ഷാ ഓർമ്മക്കുറിപ്പ്: സൈറ്റിന്റെ വിലാസം അഡ്രസ് ബാറിൽ കാണുകയാണെങ്കിൽ മാത്രം ലോഗിൻ ചെയ്യുക.', |
| 150 | +); |
| 151 | +$messages['nl'] = array( |
| 152 | + 'mwe-setting-up-proxy' => 'Bezig met het opzetten van een proxy...', |
| 153 | + 'mwe-re-try' => 'API-verzoek opnieuw uitvoeren', |
| 154 | + 'mwe-re-trying' => 'Bezig met het opnieuw uitvoeren van het API-verzoek...', |
| 155 | + 'mwe-proxy-not-ready' => 'De proxy is niet ingesteld', |
| 156 | + 'mwe-please-login' => 'U bent niet <a target="_new" href="$1">aangemeld</a> by $2 of mwEmbed is niet ingeschakeld. Los het probleem op, en voer het verzoek daarna opnieuw uit.', |
| 157 | + 'mwe-remember-loging' => 'Algemene beveiligingswaarschuwing: meld u zich alleen aan bij websites waarvan het adres in de adresbalk overeenkomt met het webadres van de site.', |
| 158 | +); |
| 159 | +$messages['oc'] = array( |
| 160 | + 'mwe-setting-up-proxy' => 'Parametratge del proxy...', |
| 161 | + 'mwe-re-try' => 'Tornar ensajar la requèsta API', |
| 162 | + 'mwe-re-trying' => 'Novèla temptativa de requèsta API...', |
| 163 | + 'mwe-proxy-not-ready' => 'Lo proxy es pas configurat', |
| 164 | + 'mwe-please-login' => 'Sètz pas <a target="_new" href="$1">connectat</a> sus $2 o mwEmbed es pas estat activat. Corregissètz lo problèma, puèi ensajatz tornamai vòstra requèsta.', |
| 165 | + 'mwe-remember-loging' => 'Rapèl de seguretat : vos connectetz pas a un site internet que quand l’adreça d\'aquel site es afichada dins vòstra barra d’adreça.', |
| 166 | +); |
| 167 | +$messages['pt'] = array( |
| 168 | + 'mwe-setting-up-proxy' => 'A preparar o \'\'proxy\'\'...', |
| 169 | + 'mwe-re-try' => 'Repetir pedido API', |
| 170 | + 'mwe-re-trying' => 'A repetir pedido API...', |
| 171 | + 'mwe-proxy-not-ready' => 'O \'\'proxy\'\' não está configurado', |
| 172 | + 'mwe-please-login' => 'Não está <a target="_new" href="$1">autenticado</a> em $2 ou o mwEmbed não foi activado. Resolva o problema e depois repita o pedido.', |
| 173 | + 'mwe-remember-loging' => 'Recomendação geral de segurança: Ao entrar em sítios na internet, certifique-se de que a barra do endereço mostra o endereço do sítio.', |
| 174 | +); |
| 175 | +$messages['ru'] = array( |
| 176 | + 'mwe-setting-up-proxy' => 'Настройка прокси…', |
| 177 | + 'mwe-re-try' => 'Повторить API-запрос', |
| 178 | + 'mwe-re-trying' => 'Повторение API-запроса…', |
| 179 | + 'mwe-proxy-not-ready' => 'Прокси не настроен', |
| 180 | + 'mwe-please-login' => 'Вы не <a target="_new" href="$1">представились системе</a> $2 или mwEmbed не был включён. Решите проблему и затем повторите запрос.', |
| 181 | + 'mwe-remember-loging' => 'Общее напоминание о безопасности. Представляйтесь системе только в том случае, если в строке адреса отображается адрес ожидаемого сайта.', |
| 182 | +); |
| 183 | +$messages['sv'] = array( |
| 184 | + 'mwe-proxy-not-ready' => 'Proxy är inte konfigurerad', |
| 185 | +); |
| 186 | +$messages['tr'] = array( |
| 187 | + 'mwe-setting-up-proxy' => 'Vekil ayarlanıyor...', |
| 188 | + 'mwe-re-try' => 'API isteğini tekrar dene', |
| 189 | + 'mwe-re-trying' => 'API isteği tekrar deneniyor...', |
| 190 | + 'mwe-proxy-not-ready' => 'Vekil ayarlanmadı', |
| 191 | + 'mwe-please-login' => '$2 sitesinde <a target="_new" href="$1">oturum açmadınız</a> ya da mwEmbed henüz etkinleştirilmedi.Sorunu çözün, ve sonra isteği tekrar deneyin.', |
| 192 | + 'mwe-remember-loging' => 'Genel güvenlik hatırlatıcısı: Sadece adres çubuğunuz sitenin adresini gösterirse sitlere giriş yapın.', |
| 193 | +); |
| 194 | +$messages['vec'] = array( |
| 195 | + 'mwe-proxy-not-ready' => 'El proxy no\'l xe mia configurà', |
| 196 | +); |
Property changes on: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/ApiProxy.i18n.php |
___________________________________________________________________ |
Added: svn:executable |
1 | 197 | + * |
Index: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/loader.js |
— | — | @@ -0,0 +1,18 @@ |
| 2 | +/* apiProxy Loader / config */ |
| 3 | + |
| 4 | +// Wrap in mw to not pollute global namespace |
| 5 | +( function( mw ) { |
| 6 | + |
| 7 | + // Set the default allowable domains for api proxy |
| 8 | + mw.setDefaultConfig({ |
| 9 | + // Black list domains |
| 10 | + 'ApiProxy.DomainBlackList' : [], |
| 11 | + |
| 12 | + // White list domains |
| 13 | + 'ApiProxy.DomainWhiteList' : [ |
| 14 | + 'localhost', |
| 15 | + '127.1.1.100' |
| 16 | + ] |
| 17 | + }); |
| 18 | + |
| 19 | +} )( window.mw ); |
\ No newline at end of file |
Property changes on: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/loader.js |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 20 | + text/plain |
Added: svn:executable |
2 | 21 | + * |
Index: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/tests/testApiProxy.html |
— | — | @@ -0,0 +1,190 @@ |
| 2 | +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
| 3 | +<html> |
| 4 | +<head> |
| 5 | +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| 6 | +<title>Api Proxy Test</title> |
| 7 | + <script type="text/javascript" src="../../../mwEmbed.js?debug=true"></script> |
| 8 | + <!-- <script type="text/javascript" src="../../../ResourceLoader.php?class=window.jQuery,mwEmbed"></script> --> |
| 9 | +<script type="text/javascript" > |
| 10 | +//HARD coded local test: |
| 11 | +var remote_wiki_host = 'http://commons.wikimedia.org'; |
| 12 | +var remote_script_path = '/w'; |
| 13 | +var remote_apiUrl = remote_wiki_host + remote_script_path + '/api.php'; |
| 14 | + |
| 15 | +mw.ready( function(){ |
| 16 | + $j('#hostName').text( remote_wiki_host ); |
| 17 | + //callback function here: |
| 18 | + $j('#setupDone').show('slow'); |
| 19 | + $j('#doHello').click( doHello ); |
| 20 | + $j('#doAppend').click( doAppend ); |
| 21 | + $j('#doFileBrowse').click( doFileUpload ); |
| 22 | +}); |
| 23 | + |
| 24 | +function doHello(){ |
| 25 | + mw.log('to a hello user'); |
| 26 | + $j('#helloTarget').loadingSpinner(); |
| 27 | + //first get the user name: |
| 28 | + getUserName( function( user_name ){ |
| 29 | + $j('#helloTarget').addClass('UserNameFound').hide().text( user_name ).fadeIn('slow'); |
| 30 | + } ); |
| 31 | + return false; |
| 32 | +} |
| 33 | +function getUserName( callback ){ |
| 34 | + var rObj = { |
| 35 | + 'action':'query', |
| 36 | + 'meta':'userinfo' |
| 37 | + } |
| 38 | + // Do request ( will automatically invoke proxy because its a proxy action and remote url ) |
| 39 | + mw.getJSON( remote_apiUrl, rObj, function( data ){ |
| 40 | + //now we get the data back for that domain |
| 41 | + if( !data.query || !data.query.userinfo ){ |
| 42 | + mw.log("Error no query.userinfo "); |
| 43 | + return false; |
| 44 | + } |
| 45 | + callback( data.query.userinfo.name ); |
| 46 | + } |
| 47 | + ); |
| 48 | +} |
| 49 | + |
| 50 | +// Simple "hello from api proxy" append on talk page |
| 51 | +function doAppend(){ |
| 52 | + $j('#appendTarget').loadingSpinner(); |
| 53 | + //get user name |
| 54 | + getUserName( function( userName ){ |
| 55 | + var eTitle = 'User_talk:' + userName; |
| 56 | + // Get a edit token |
| 57 | + mw.getToken( remote_apiUrl, eTitle, function( token ) { |
| 58 | + mw.log("got token: " + token) ; |
| 59 | + var request = { |
| 60 | + 'action':'edit', |
| 61 | + 'title': eTitle, |
| 62 | + 'summary': "Api proxy test edit", |
| 63 | + 'appendtext': "\n\n==== Hello from Api proxy At: " + Date() + " ====", |
| 64 | + 'token': token |
| 65 | + } |
| 66 | + mw.getJSON( remote_apiUrl, request, function( result ){ |
| 67 | + if(result.edit && result.edit.newrevid){ |
| 68 | + $j('#appendTarget').html( "success: " + JSON.stringify ( result) ); |
| 69 | + url = remote_wiki_host + remote_script_path + '/index.php/'; |
| 70 | + url+= result.edit.title.replace(' ', '_'); |
| 71 | + $j('#appendTarget').append( '<br><a target="_new" href="' + url + '">visit page</a>' ); |
| 72 | + }else{ |
| 73 | + $j('#appendTarget').html( "falied: " + JSON.stringify ( result) ); |
| 74 | + } |
| 75 | + }); |
| 76 | + |
| 77 | + }); |
| 78 | + }); |
| 79 | +} |
| 80 | + |
| 81 | +function doFileUpload(){ |
| 82 | + $j('#file-upload-container').fadeIn( 'slow' ); |
| 83 | + $j('#browseTarget').loadingSpinner(); |
| 84 | + // Load firefogg lib |
| 85 | + mw.load('AddMedia.firefogg', function( ) { |
| 86 | + // Load proxy lib |
| 87 | + mw.load( 'ApiProxy', function( ) { |
| 88 | + // Get a token for the upload: |
| 89 | + mw.getToken( remote_apiUrl, 'File:MyRandomFileTokenCheck.jpg', function( eToken ) { |
| 90 | + mw.log(" got token :: " + eToken); |
| 91 | + // Add the token to the dom: |
| 92 | + $j( '#file-name' ).append( |
| 93 | + $j('<input />') |
| 94 | + .attr({ |
| 95 | + 'type': 'hidden', |
| 96 | + 'id' : 'wpEditToken', |
| 97 | + 'name' : 'token' |
| 98 | + }) |
| 99 | + .val( eToken ) |
| 100 | + ); |
| 101 | + var fileIframeName = mw.ApiProxy.browseFile( { |
| 102 | + //Target div to put the iframe browser button: |
| 103 | + 'target' : '#browseTarget', |
| 104 | + |
| 105 | + // Set the token |
| 106 | + 'token' : eToken, |
| 107 | + |
| 108 | + // Api url to upload to |
| 109 | + 'apiUrl' : remote_apiUrl, |
| 110 | + |
| 111 | + // File Destination Name change callback: |
| 112 | + 'selectFileCb' : function( fname ){ |
| 113 | + // Update our local target: |
| 114 | + $j('#file-name').val( fname ); |
| 115 | + // Run a destination file name check on the remote target |
| 116 | + $j('#file-name').doDestCheck( { |
| 117 | + 'apiUrl' : remote_apiUrl, |
| 118 | + 'warn_target': '#file-warning' |
| 119 | + } ); |
| 120 | + }, |
| 121 | + 'doneUploadCb' : function( apiResult ){ |
| 122 | + alert(' upload done' ); |
| 123 | + } |
| 124 | + } ); |
| 125 | + |
| 126 | + //Setup submit binding: |
| 127 | + $j('#uploadButton').click( function( ){ |
| 128 | + // Build the output and send upload request to fileProxy |
| 129 | + mw.ApiProxy.sendServerMsg( { |
| 130 | + 'apiUrl' : remote_apiUrl, |
| 131 | + 'frameName' : fileIframeName, |
| 132 | + 'frameMsg' : { |
| 133 | + 'action' : 'fileSubmit', |
| 134 | + 'formData' : { |
| 135 | + 'filename' : $j('#file-name').val(), |
| 136 | + 'comment' : $j('#file-desc').val() |
| 137 | + } |
| 138 | + } |
| 139 | + } ); |
| 140 | + // Maybe set loading to spinner |
| 141 | + } ); |
| 142 | + |
| 143 | + |
| 144 | + // Setup doDestCheck on change |
| 145 | + $j('#file-name').change(function(){ |
| 146 | + $j('#file-name').doDestCheck( { |
| 147 | + 'apiUrl' : remote_apiUrl, |
| 148 | + 'warn_target': '#file-warning' |
| 149 | + } ); |
| 150 | + }); |
| 151 | + }); |
| 152 | + }) |
| 153 | + }); |
| 154 | +}; |
| 155 | + |
| 156 | +</script> |
| 157 | + |
| 158 | +</head> |
| 159 | +<body> |
| 160 | +<h3> Simple API proxy testing system </h3> |
| 161 | + |
| 162 | +<div id="setupProxy">Proxy for: <span id="hostName"></span> <br> |
| 163 | +<span style="font-size:small"> this proxy will only work on a limited set of domains that the gadget allows proxy request from </span></div> |
| 164 | +<div id="setupDone" style="display:none;"> |
| 165 | + <br> <a href="#" id="doHello" >Hello User:</a> <span style="width:200px" id="helloTarget"></span> |
| 166 | + |
| 167 | + <br><br><br> <a href="#" id="doAppend">Append Msg to Talk page:</a> |
| 168 | + <div id="appendTarget"></div> |
| 169 | + |
| 170 | + <br><br><a href="#" id="doFileBrowse">Upload a file to remote:</a> |
| 171 | + <div id="file-upload-container" style="display:none"> |
| 172 | + <div style="background:#FEF;margin:20px;"> |
| 173 | + <h3> Local input </h3> |
| 174 | + Target file name: <input id="file-name" type="text" size="15" /> |
| 175 | + <div id="file-warning"></div> |
| 176 | + <BR> |
| 177 | + Target desc: <input id="file-desc" type="text" size="20" value="test proxy desc"/> |
| 178 | + </div> |
| 179 | + <div style="background:#CEF;margin:20px;"> |
| 180 | + <h3> Browse File Served From Remote: </h3> |
| 181 | + <div id="browseTarget"></div> |
| 182 | + </div> |
| 183 | + <div style="background:#FEF;margin:20px;"> |
| 184 | + <h3> Local submit </h3> |
| 185 | + <input id="uploadButton" type="submit" size="10" value="upload" /> |
| 186 | + </div> |
| 187 | + </div> |
| 188 | +</div> |
| 189 | + |
| 190 | +</body> |
| 191 | +</html> |
\ No newline at end of file |
Property changes on: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/tests/testApiProxy.html |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 192 | + text/plain |
Index: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/ApiProxyPage.js |
— | — | @@ -0,0 +1,22 @@ |
| 2 | +/** |
| 3 | +* mwProxy js2 page system. |
| 4 | +* |
| 5 | +* Invokes the apiProxy system |
| 6 | +*/ |
| 7 | + |
| 8 | +/* |
| 9 | + * Since this is proxy server set a pre-append debug flag to know which debug msgs are coming from where |
| 10 | + */ |
| 11 | + |
| 12 | +mw.setConfig( 'Mw.LogPrepend', 'Proxy:'); |
| 13 | + |
| 14 | +// The default allowable domain list is stored in the loader.js configuration. |
| 15 | + |
| 16 | +mw.ready( function() { |
| 17 | + mw.log( 'load ApiProxy' ); |
| 18 | + mw.load( 'ApiProxy', function() { |
| 19 | + // Clear out the page content ( not needed for iframe proxy ) |
| 20 | + $j( 'body' ).html( '' ); |
| 21 | + mw.ApiProxy.server(); |
| 22 | + } ); |
| 23 | +} ); |
Property changes on: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/ApiProxyPage.js |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 24 | + text/plain |
Added: svn:executable |
2 | 25 | + * |
Index: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/NestedCallbackIframe.html |
— | — | @@ -0,0 +1,16 @@ |
| 2 | +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
| 3 | +<html> |
| 4 | +<head> |
| 5 | +<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> |
| 6 | +<title>Simple nested iframe callback page</title> |
| 7 | +<script type="text/javascript"> |
| 8 | +window.onload = function () { |
| 9 | + //call the nested callback in top most frame: |
| 10 | + top.mw.ApiProxy.nested( window.location.href.split("#")[1] || false ); |
| 11 | +} |
| 12 | +</script> |
| 13 | +</head> |
| 14 | +<body> |
| 15 | +Nested Iframe callback |
| 16 | +</body> |
| 17 | +</html> |
\ No newline at end of file |
Property changes on: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/NestedCallbackIframe.html |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 18 | + text/plain |
Index: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/mw.Api.js |
— | — | @@ -0,0 +1,370 @@ |
| 2 | +/** |
| 3 | +* API Helper functions |
| 4 | +*/ |
| 5 | + |
| 6 | +( function( mw ) { |
| 7 | + // xxx note we should namespace the following helper functions into Api class. |
| 8 | + mw.Api = {}; |
| 9 | + |
| 10 | + /** |
| 11 | + * |
| 12 | + * Helper function to get revision text for a given title |
| 13 | + * |
| 14 | + * Assumes "follow redirects" |
| 15 | + * |
| 16 | + * $j.getTitleText( [apiUrl], title, callback ) |
| 17 | + * |
| 18 | + * @param {String} url or title key |
| 19 | + * @parma {Mixed} title or callback function |
| 20 | + * @param {Function} callback Function or NULL |
| 21 | + * |
| 22 | + * @return callback is called with: |
| 23 | + * {Boolean} false if no page found |
| 24 | + * {String} text of wiki page |
| 25 | + */ |
| 26 | + mw.getTitleText = function( apiUrl, title, callback ) { |
| 27 | + // Check if optional apiURL was not included |
| 28 | + if( !callback ) { |
| 29 | + title = apiUrl; |
| 30 | + callback = title; |
| 31 | + apiUrl = mw.getLocalApiUrl(); |
| 32 | + } |
| 33 | + var request = { |
| 34 | + // Normalize the File NS (ie sometimes its present in apiTitleKey other times not |
| 35 | + 'titles' : title, |
| 36 | + 'prop' : 'revisions', |
| 37 | + 'rvprop' : 'content' |
| 38 | + }; |
| 39 | + |
| 40 | + mw.getJSON( apiUrl , request, function( data ) { |
| 41 | + if( !data || !data.query || !data.query.pages ) { |
| 42 | + callback( false ); |
| 43 | + } |
| 44 | + var pages = data.query.pages; |
| 45 | + for(var i in pages) { |
| 46 | + page = pages[ i ]; |
| 47 | + if( page[ 'revisions' ] && page[ 'revisions' ][0]['*'] ) { |
| 48 | + callback( page[ 'revisions' ][0]['*'] ); |
| 49 | + } |
| 50 | + } |
| 51 | + } ); |
| 52 | + } |
| 53 | + |
| 54 | + /** |
| 55 | + * Issues the wikitext parse call |
| 56 | + * |
| 57 | + * @param {String} wikitext Wiki Text to be parsed by mediaWiki api call |
| 58 | + * @param {String} title Context title of the content to be parsed |
| 59 | + * @param {Function} callback Function called with api parser output |
| 60 | + */ |
| 61 | + mw.parseWikiText = function( wikitext, title, callback ) { |
| 62 | + mw.log("mw.parseWikiText text length: " + wikitext.length + ' title context: ' + title ); |
| 63 | + mw.load( 'JSON', function(){ |
| 64 | + $j.ajax({ |
| 65 | + type: 'POST', |
| 66 | + url: mw.getLocalApiUrl(), |
| 67 | + // Give the wiki 60 seconds to parse the wiki-text |
| 68 | + timeout : 60000, |
| 69 | + data: { |
| 70 | + 'action': 'parse', |
| 71 | + 'format': 'json', |
| 72 | + 'title' : title, |
| 73 | + 'text': wikitext |
| 74 | + }, |
| 75 | + dataType: 'text', |
| 76 | + success: function( data ) { |
| 77 | + var jsonData = JSON.parse( data ) ; |
| 78 | + // xxx should handle other failures |
| 79 | + callback( jsonData.parse.text['*'] ); |
| 80 | + }, |
| 81 | + error: function( XMLHttpRequest, textStatus, errorThrown ){ |
| 82 | + // xxx should better handle failures |
| 83 | + mw.log( "Error: mw.parseWikiText:" + textStatus ); |
| 84 | + callback( "Error: failed to parse wikitext " ); |
| 85 | + } |
| 86 | + }); |
| 87 | + }); |
| 88 | + } |
| 89 | + |
| 90 | + /** |
| 91 | + * mediaWiki JSON a wrapper for jQuery getJSON: |
| 92 | + * ( could also be named mw.apiRequest ) |
| 93 | + * |
| 94 | + * The mwEmbed version lets you skip the url part |
| 95 | + * mw.getJSON( [url], data, callback, [timeoutCallback] ); |
| 96 | + * |
| 97 | + * Lets you assume: |
| 98 | + * url is optional |
| 99 | + * ( If the first argument is not a string we assume a local mediaWiki api request ) |
| 100 | + * callback parameter is not needed for the request data |
| 101 | + * url param 'action'=>'query' is assumed ( if not set to something else in the "data" param |
| 102 | + * format is set to "json" automatically |
| 103 | + * automatically issues request over "POST" if the request api post type |
| 104 | + * automatically will setup apiProxy where request is cross domain |
| 105 | + * |
| 106 | + * @param {Mixed} url or data request |
| 107 | + * @param {Mixed} data or callback |
| 108 | + * @param {Function} callbcak function called on success |
| 109 | + * @param {Function} callbackTimeout - optional function called on timeout |
| 110 | + * Setting timeout callback also avoids default timed-out dialog for proxy requests |
| 111 | + */ |
| 112 | + mw.getJSON = function() { |
| 113 | + // Process the arguments: |
| 114 | + |
| 115 | + // Set up the url |
| 116 | + var url = false; |
| 117 | + url = ( typeof arguments[0] == 'string' ) ? arguments[0] : mw.getLocalApiUrl(); |
| 118 | + |
| 119 | + // Set up the data: |
| 120 | + var data = null; |
| 121 | + data = ( typeof arguments[0] == 'object' ) ? arguments[0] : null; |
| 122 | + if( !data && typeof arguments[1] == 'object' ) { |
| 123 | + data = arguments[1]; |
| 124 | + } |
| 125 | + |
| 126 | + // Setup the callback |
| 127 | + var callback = false; |
| 128 | + callback = ( typeof arguments[1] == 'function') ? arguments[1] : false; |
| 129 | + var cbinx = 1; |
| 130 | + if( ! callback && ( typeof arguments[2] == 'function') ) { |
| 131 | + callback = arguments[2]; |
| 132 | + cbinx = 2; |
| 133 | + } |
| 134 | + |
| 135 | + // Setup the timeoutCallback ( function after callback index ) |
| 136 | + var timeoutCallback = false; |
| 137 | + timeoutCallback = ( typeof arguments[ cbinx + 1 ] == 'function' ) ? arguments[ cbinx + 1 ] : false; |
| 138 | + |
| 139 | + // Make sure we got a url: |
| 140 | + if( !url ) { |
| 141 | + mw.log( 'Error: no api url for api request' ); |
| 142 | + return false; |
| 143 | + } |
| 144 | + |
| 145 | + // Add default action if unset: |
| 146 | + if( !data['action'] ) { |
| 147 | + data['action'] = 'query'; |
| 148 | + } |
| 149 | + |
| 150 | + // Add default format if not set: |
| 151 | + if( !data['format'] ) { |
| 152 | + data['format'] = 'json'; |
| 153 | + } |
| 154 | + |
| 155 | + // Setup callback wrapper for timeout |
| 156 | + var requestTimeOutFlag = false; |
| 157 | + var ranCallback = false; |
| 158 | + |
| 159 | + /** |
| 160 | + * local callback function to control timeout |
| 161 | + * @param {Object} data Result data |
| 162 | + */ |
| 163 | + var myCallback = function( data ){ |
| 164 | + if( ! requestTimeOutFlag ){ |
| 165 | + ranCallback = true; |
| 166 | + callback( data ); |
| 167 | + } |
| 168 | + } |
| 169 | + // Set the local timeout call based on defaultRequestTimeout |
| 170 | + setTimeout( function( ) { |
| 171 | + if( ! ranCallback ) { |
| 172 | + requestTimeOutFlag = true; |
| 173 | + mw.log( "Error:: request timed out: " + url ); |
| 174 | + if( timeoutCallback ){ |
| 175 | + timeoutCallback(); |
| 176 | + } |
| 177 | + } |
| 178 | + }, mw.getConfig( 'defaultRequestTimeout' ) * 1000 ); |
| 179 | + |
| 180 | + mw.log("run getJSON: " + mw.replaceUrlParams( url, data ) ); |
| 181 | + |
| 182 | + // Check if the request requires a "post" |
| 183 | + if( mw.checkRequestPost( data ) ) { |
| 184 | + |
| 185 | + // Check if we need to setup a proxy |
| 186 | + if( ! mw.isLocalDomain( url ) ) { |
| 187 | + |
| 188 | + //Set local scope ranCallback to true |
| 189 | + // ( ApiProxy handles timeouts internally ) |
| 190 | + ranCallback = true; |
| 191 | + |
| 192 | + // Load the proxy and issue the request |
| 193 | + mw.load( 'ApiProxy', function( ) { |
| 194 | + mw.ApiProxy.doRequest( url, data, callback, timeoutCallback); |
| 195 | + } ); |
| 196 | + |
| 197 | + } else { |
| 198 | + |
| 199 | + // Do the request an ajax post |
| 200 | + $j.post( url, data, myCallback, 'json'); |
| 201 | + } |
| 202 | + return ; |
| 203 | + } |
| 204 | + |
| 205 | + // If cross domain setup a callback: |
| 206 | + if( ! mw.isLocalDomain( url ) ) { |
| 207 | + if( url.indexOf( 'callback=' ) == -1 || data[ 'callback' ] == -1 ) { |
| 208 | + // jQuery specific jsonp format: ( second ? is replaced with the callback ) |
| 209 | + url += ( url.indexOf('?') == -1 ) ? '?callback=?' : '&callback=?'; |
| 210 | + } |
| 211 | + } |
| 212 | + // Pass off the jQuery getJSON request: |
| 213 | + $j.getJSON( url, data, myCallback ); |
| 214 | + } |
| 215 | + |
| 216 | + /** |
| 217 | + * Checks if a mw request data requires a post request or not |
| 218 | + * @param {Object} |
| 219 | + * @return {Boolean} |
| 220 | + * true if the request requires a post request |
| 221 | + * false if the request does not |
| 222 | + */ |
| 223 | + mw.checkRequestPost = function ( data ) { |
| 224 | + if( $j.inArray( data['action'], mw.getConfig( 'apiPostActions' ) ) != -1 ) { |
| 225 | + return true; |
| 226 | + } |
| 227 | + if( data['prop'] == 'info' && data['intoken'] ) { |
| 228 | + return true; |
| 229 | + } |
| 230 | + if( data['meta'] == 'userinfo' ) { |
| 231 | + return true; |
| 232 | + } |
| 233 | + return false; |
| 234 | + } |
| 235 | + |
| 236 | + /** |
| 237 | + * Check if the url is a request for the local domain |
| 238 | + * relative paths are "local" domain |
| 239 | + * @param {String} url Url for local domain |
| 240 | + * @return {Boolean} |
| 241 | + * true if url domain is local or relative |
| 242 | + * false if the domain is |
| 243 | + */ |
| 244 | + mw.isLocalDomain = function( url ) { |
| 245 | + if( mw.parseUri( document.URL ).host == mw.parseUri( url ).host |
| 246 | + || url.indexOf( '://' ) == -1 ) |
| 247 | + { |
| 248 | + return true; |
| 249 | + } |
| 250 | + return false; |
| 251 | + } |
| 252 | + |
| 253 | + /** |
| 254 | + * Api helper to grab an edit token |
| 255 | + * |
| 256 | + * @param {String} [apiUrl] Optional target API URL (uses default local api if unset) |
| 257 | + * @param {String} title The wiki page title you want to edit |
| 258 | + * @param {callback} callback Function to pass the token to. |
| 259 | + * issues callback with "false" if token not retrieved |
| 260 | + */ |
| 261 | + mw.getToken = function( apiUrl, title, callback ) { |
| 262 | + // Make the apiUrl be optional: |
| 263 | + if( typeof title == 'function' ) { |
| 264 | + callback = title; |
| 265 | + title = apiUrl; |
| 266 | + apiUrl = mw.getLocalApiUrl(); |
| 267 | + } |
| 268 | + |
| 269 | + mw.log( 'mw:getToken' ); |
| 270 | + |
| 271 | + var request = { |
| 272 | + 'prop': 'info', |
| 273 | + 'intoken': 'edit', |
| 274 | + 'titles': title |
| 275 | + }; |
| 276 | + mw.getJSON( apiUrl, request, function( data ) { |
| 277 | + for ( var i in data.query.pages ) { |
| 278 | + if ( data.query.pages[i]['edittoken'] ) { |
| 279 | + callback ( data.query.pages[i]['edittoken'] ); |
| 280 | + return ; |
| 281 | + } |
| 282 | + } |
| 283 | + // No token found: |
| 284 | + callback ( false ); |
| 285 | + } ); |
| 286 | + } |
| 287 | + |
| 288 | + /** |
| 289 | + * Api helper to grab the username |
| 290 | + * @param {String} [apiUrl] Optional target API url (uses default local api if unset) |
| 291 | + * @param {Function} callback Function to callback with username or false if not found |
| 292 | + * @param {Boolean} fresh A fresh check is issued. |
| 293 | + */ |
| 294 | + // Stub feature apiUserNameCache to avoid multiple calls |
| 295 | + // ( a more general api framework should be developed ) |
| 296 | + var apiUserNameCache = {}; |
| 297 | + mw.getUserName = function( apiUrl, callback, fresh ){ |
| 298 | + if( typeof apiUrl == 'function' ){ |
| 299 | + var callback = apiUrl; |
| 300 | + var apiUrl = mw.getLocalApiUrl(); |
| 301 | + } |
| 302 | + |
| 303 | + // If apiUrl is local check wgUserName global |
| 304 | + // before issuing the api request. |
| 305 | + if( mw.isLocalDomain( apiUrl ) ){ |
| 306 | + if( typeof wgUserName != 'undefined' && wgUserName !== null ) { |
| 307 | + callback( wgUserName ) |
| 308 | + // In case someone called this function without a callback |
| 309 | + return wgUserName; |
| 310 | + } |
| 311 | + } |
| 312 | + if( ! fresh && apiUserNameCache[ apiUrl ] ) { |
| 313 | + callback( apiUserNameCache[ apiUrl ] ); |
| 314 | + return ; |
| 315 | + } |
| 316 | + |
| 317 | + // Setup the api request |
| 318 | + var request = { |
| 319 | + 'action':'query', |
| 320 | + 'meta':'userinfo' |
| 321 | + } |
| 322 | + |
| 323 | + // Do request |
| 324 | + mw.getJSON( apiUrl, request, function( data ) { |
| 325 | + if( !data || !data.query || !data.query.userinfo || !data.query.userinfo.name ){ |
| 326 | + // Could not get user name user is not-logged in |
| 327 | + mw.log( " No userName in response " ); |
| 328 | + callback( false ); |
| 329 | + return ; |
| 330 | + } |
| 331 | + // Check for "not logged in" id == 0 |
| 332 | + if( data.query.userinfo.id == 0 ){ |
| 333 | + callback( false ); |
| 334 | + return ; |
| 335 | + } |
| 336 | + apiUserNameCache[ apiUrl ] = data.query.userinfo.name; |
| 337 | + // Else return the username: |
| 338 | + callback( data.query.userinfo.name ); |
| 339 | + }, function(){ |
| 340 | + // Timeout also results in callback( false ) ( no user found) |
| 341 | + callback( false ); |
| 342 | + } ); |
| 343 | + } |
| 344 | + |
| 345 | + /** |
| 346 | + * Get the api url for a given content provider key |
| 347 | + * @return {Mixed} |
| 348 | + * url for the provider |
| 349 | + * local wiki api if no apiProvider is set |
| 350 | + */ |
| 351 | + mw.getApiProviderURL = function( providerId ) { |
| 352 | + if( mw.getConfig( providerId + '_apiurl') ) { |
| 353 | + return mw.getConfig( providerId + '_apiurl'); |
| 354 | + } |
| 355 | + return mw.getLocalApiUrl(); |
| 356 | + }; |
| 357 | + |
| 358 | + /** |
| 359 | + * Get Api URL from mediaWiki page defined variables |
| 360 | + * @return {Mixed} |
| 361 | + * api url |
| 362 | + * false |
| 363 | + */ |
| 364 | + mw.getLocalApiUrl = function() { |
| 365 | + if ( typeof wgServer != 'undefined' && typeof wgScriptPath != 'undefined' ) { |
| 366 | + return wgServer + wgScriptPath + '/api.php'; |
| 367 | + } |
| 368 | + return false; |
| 369 | + }; |
| 370 | + |
| 371 | +}) ( window.mw ); |
\ No newline at end of file |
Property changes on: trunk/extensions/MwEmbed/MwEmbed/modules/ApiEmbed/mw.Api.js |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 372 | + text/plain |
Added: svn:executable |
2 | 373 | + * |
Index: trunk/extensions/MwEmbed/MwEmbed/modules/README |
— | — | @@ -0,0 +1,2 @@ |
| 2 | +If an mwEmbed module is used by Two or more sub components the module could be moved into this mwEmbed support extension |
| 3 | + |
Index: trunk/extensions/MwEmbed/MwEmbed/mwEmbed.old.js |
— | — | @@ -0,0 +1,2653 @@ |
| 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 |
| 8 | + * mwEmbed |
| 9 | + * Dual licensed under the MIT or GPL Version 2 licenses. |
| 10 | + * |
| 11 | + * @copyright (C) 2010 Kaltura |
| 12 | + * @author Michael Dale ( michael.dale at kaltura.com ) |
| 13 | + * |
| 14 | + * @url http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library |
| 15 | + * |
| 16 | + * Libraries used include code license in headers |
| 17 | + */ |
| 18 | + |
| 19 | +/** |
| 20 | + * Setup the "mw" global: |
| 21 | + */ |
| 22 | +if ( typeof window.mw == 'undefined' ) { |
| 23 | + window.mw = { }; |
| 24 | +} |
| 25 | + |
| 26 | +/** |
| 27 | + * Set the mwEmbedVersion |
| 28 | + */ |
| 29 | +var MW_EMBED_VERSION = '1.1h'; |
| 30 | + |
| 31 | +// Globals to pre-set ready functions in dynamic loading of mwEmbed |
| 32 | +if( typeof preMwEmbedReady == 'undefined'){ |
| 33 | + var preMwEmbedReady = []; |
| 34 | +} |
| 35 | +// Globals to pre-set config values in dynamic loading of mwEmbed |
| 36 | +if( typeof preMwEmbedConfig == 'undefined') { |
| 37 | + var preMwEmbedConfig = []; |
| 38 | +} |
| 39 | + |
| 40 | +/** |
| 41 | + * The global mw object: |
| 42 | + */ |
| 43 | +( function( mw ) { |
| 44 | + // The version of mwEmbed |
| 45 | + mw.version = MW_EMBED_VERSION; |
| 46 | + |
| 47 | + // List valid skins here: |
| 48 | + mw.validSkins = [ 'mvpcf', 'kskin' ]; |
| 49 | + |
| 50 | + // Storage variable for loaded style sheet keys |
| 51 | + if( ! mw.style ){ |
| 52 | + mw.style = { }; |
| 53 | + } |
| 54 | + |
| 55 | + /** |
| 56 | + * Configuration System: |
| 57 | + */ |
| 58 | + |
| 59 | + // Local scope configuration var: |
| 60 | + if( !mwConfig ){ |
| 61 | + var mwConfig = { }; |
| 62 | + } |
| 63 | + |
| 64 | + // mw scope mwUserConfig var. Stores user configuration |
| 65 | + var mwUserConfig = { }; |
| 66 | + |
| 67 | + /** |
| 68 | + * Setter for configuration values |
| 69 | + * |
| 70 | + * @param [Mixed] |
| 71 | + * name Name of configuration value {Object} Will iderate through |
| 72 | + * each key and call setConfig {String} Will set configuration by |
| 73 | + * string name to value |
| 74 | + * @param {String} |
| 75 | + * value Value of configuration name {Object} value Set of values |
| 76 | + * to be merged |
| 77 | + */ |
| 78 | + mw.setConfig = function ( name, value ) { |
| 79 | + if( typeof name == 'object' ) { |
| 80 | + for( var i in name ) { |
| 81 | + mw.setConfig( i, name[ i ] ); |
| 82 | + } |
| 83 | + return ; |
| 84 | + } |
| 85 | + // Check if we should "merge" the config |
| 86 | + if( typeof value == 'object' && typeof mwConfig[ name ] == 'object' ) { |
| 87 | + if ( value.constructor.toString().indexOf("Array") == -1 ){ |
| 88 | + for( var i in value ){ |
| 89 | + mwConfig[ name ][ i ] = value[ i ]; |
| 90 | + } |
| 91 | + } else { |
| 92 | + // merge in the array |
| 93 | + mwConfig[ name ] = mwConfig[ name ].concat( value ); |
| 94 | + } |
| 95 | + } else { |
| 96 | + mwConfig[ name ] = value; |
| 97 | + } |
| 98 | + }; |
| 99 | + |
| 100 | + /** |
| 101 | + * Set a default config value Will only update configuration if no value is |
| 102 | + * present |
| 103 | + * |
| 104 | + * @param [Mixed] |
| 105 | + * value Set configuration name to value {Object} Will iderate |
| 106 | + * through each key and call setDefaultConfig {String} Will set |
| 107 | + * configuration by string name to value |
| 108 | + */ |
| 109 | + mw.setDefaultConfig = function( name, value ) { |
| 110 | + if( typeof name == 'object' ) { |
| 111 | + for( var i in name ) { |
| 112 | + mw.setDefaultConfig( i, name[ i ] ); |
| 113 | + } |
| 114 | + return ; |
| 115 | + } |
| 116 | + // Only update the controls if undefined |
| 117 | + |
| 118 | + if( typeof mwConfig[ name ] == 'undefined' ) { |
| 119 | + mwConfig[ name ] = value; |
| 120 | + return ; |
| 121 | + } |
| 122 | + // Check if we should "merge" the config |
| 123 | + if( typeof value == 'object' && typeof mwConfig[ name ] == 'object' ) { |
| 124 | + if ( value.constructor.toString().indexOf("Array") == -1 ){ |
| 125 | + for( var i in value ){ |
| 126 | + if( typeof mwConfig[ name ][ i ] == 'undefined' ){ |
| 127 | + mwConfig[ name ][ i ] = value[ i ]; |
| 128 | + } |
| 129 | + } |
| 130 | + } else { |
| 131 | + // merge in the array |
| 132 | + mwConfig[ name ] = mwConfig[ name ].concat( value); |
| 133 | + } |
| 134 | + } |
| 135 | + }; |
| 136 | + |
| 137 | + /** |
| 138 | + * Getter for configuration values |
| 139 | + * |
| 140 | + * @param {String} |
| 141 | + * name of configuration value to get |
| 142 | + * @return {Mixed} value of configuration key returns "false" if key not |
| 143 | + * found |
| 144 | + */ |
| 145 | + mw.getConfig = function ( name ) { |
| 146 | + if( mwConfig[ name ] ) |
| 147 | + return mwConfig[ name ]; |
| 148 | + return false; |
| 149 | + }; |
| 150 | + |
| 151 | + /** |
| 152 | + * Loads the mwUserConfig from a cookie. |
| 153 | + * |
| 154 | + * Modules that want to use "User Config" should call this setup function in |
| 155 | + * their moduleLoader code. |
| 156 | + * |
| 157 | + * For performance interfaces using "user config" should load '$j.cookie' & |
| 158 | + * 'JSON' in their module loader |
| 159 | + * |
| 160 | + * By abstracting user preference we could eventually integrate a persistent |
| 161 | + * per-account preference system on the server. |
| 162 | + * |
| 163 | + * @parma {Function} callback Function to be called once userPrefrences are |
| 164 | + * loaded |
| 165 | + */ |
| 166 | + var setupUserConfigFlag = false; |
| 167 | + mw.setupUserConfig = function( callback ) { |
| 168 | + if( setupUserConfigFlag ) { |
| 169 | + if( callback ) { |
| 170 | + callback(); |
| 171 | + } |
| 172 | + return ; |
| 173 | + } |
| 174 | + // Do Setup user config: |
| 175 | + mw.load( [ '$j.cookie', 'JSON' ], function() { |
| 176 | + if( $j.cookie( 'mwUserConfig' ) ) { |
| 177 | + mwUserConfig = JSON.parse( $j.cookie( 'mwUserConfig' ) ); |
| 178 | + } |
| 179 | + setupUserConfigFlag = true; |
| 180 | + if( callback ) { |
| 181 | + callback(); |
| 182 | + } |
| 183 | + }); |
| 184 | + }; |
| 185 | + |
| 186 | + /** |
| 187 | + * Save a user configuration var to a cookie & local global variable Loads |
| 188 | + * the cookie plugin if not already loaded |
| 189 | + * |
| 190 | + * @param {String} |
| 191 | + * name Name of user configuration value |
| 192 | + * @param {String} |
| 193 | + * value Value of configuration name |
| 194 | + */ |
| 195 | + mw.setUserConfig = function ( name, value, cookieOptions ) { |
| 196 | + if( ! setupUserConfigFlag ) { |
| 197 | + mw.log( "Error: userConfig not setup" ); |
| 198 | + return false; |
| 199 | + } |
| 200 | + // Update local value |
| 201 | + mwUserConfig[ name ] = value; |
| 202 | + |
| 203 | + // Update the cookie ( '$j.cookie' & 'JSON' should already be loaded ) |
| 204 | + $j.cookie( 'mwUserConfig', JSON.stringify( mwUserConfig ) ); |
| 205 | + }; |
| 206 | + |
| 207 | + /** |
| 208 | + * Save a user configuration var to a cookie & local global variable |
| 209 | + * |
| 210 | + * @param {String} |
| 211 | + * name Name of user configuration value |
| 212 | + * @return value of the configuration name false if the configuration name |
| 213 | + * could not be found |
| 214 | + */ |
| 215 | + mw.getUserConfig = function ( name ) { |
| 216 | + if( mwUserConfig[ name ] ) |
| 217 | + return mwUserConfig[ name ]; |
| 218 | + return false; |
| 219 | + }; |
| 220 | + |
| 221 | + /** |
| 222 | + * Add a hook system for a target object / interface |
| 223 | + * |
| 224 | + * depricated you should instead use jQuery's bind and trigger |
| 225 | + * |
| 226 | + * @param {Object} |
| 227 | + * targetObj Interface Object to add hook system to. |
| 228 | + */ |
| 229 | + mw.addHookSystem = function( targetObj ) { |
| 230 | + |
| 231 | + // Setup the target object hook holder: |
| 232 | + targetObj[ 'hooks' ] = { }; |
| 233 | + |
| 234 | + /** |
| 235 | + * Adds a hook to the target object |
| 236 | + * |
| 237 | + * Should be called by clients to setup named hooks |
| 238 | + * |
| 239 | + * @param {String} |
| 240 | + * hookName Name of hook to be added |
| 241 | + * @param {Function} |
| 242 | + * hookFunction Function to be called at hook time |
| 243 | + */ |
| 244 | + targetObj.addHook = function( hookName, hookFunction ) { |
| 245 | + if( ! this.hooks[ hookName ] ) { |
| 246 | + this.hooks[ hookName ] = [ ]; |
| 247 | + } |
| 248 | + this.hooks[ hookName ].push( hookFunction ); |
| 249 | + }; |
| 250 | + |
| 251 | + /** |
| 252 | + * Runs all the hooks by a given name with reference to the host object |
| 253 | + * |
| 254 | + * Should be called by the host object at named execution points |
| 255 | + * |
| 256 | + * @param {String} |
| 257 | + * hookName Name of hook to be called |
| 258 | + * @return Value of hook result true interface should continue function |
| 259 | + * execution false interface should stop or return from method |
| 260 | + */ |
| 261 | + targetObj.runHook = function( hookName, options ) { |
| 262 | + if( this.hooks[ hookName ] ) { |
| 263 | + for( var i =0; i < this.hooks[ hookName ].length; i ++ ) { |
| 264 | + if( typeof( this.hooks[ hookName ][ i ] ) == 'function' ) { |
| 265 | + this.hooks[ hookName ][ i ]( options ); |
| 266 | + } |
| 267 | + } |
| 268 | + } |
| 269 | + }; |
| 270 | + }; |
| 271 | + |
| 272 | + // Add hooks system to the core "mw" object |
| 273 | + mw.addHookSystem( mw ); |
| 274 | + |
| 275 | + // Stores callbacks for resource loader loading |
| 276 | + var mwLoadDoneCB = { }; |
| 277 | + |
| 278 | + |
| 279 | + /** |
| 280 | + * Top level loader prototype: |
| 281 | + */ |
| 282 | + mw.loader = { |
| 283 | + /** |
| 284 | + * Javascript Module Loader functions |
| 285 | + * |
| 286 | + * @key Name of Module |
| 287 | + * @value function code to load module |
| 288 | + */ |
| 289 | + moduleLoaders : [], |
| 290 | + |
| 291 | + /** |
| 292 | + * Module resource list queue. |
| 293 | + * |
| 294 | + * @key Name of Module |
| 295 | + * @value .resourceList list of resources to be loaded .functionQueue |
| 296 | + * list of functions to be run once module is ready |
| 297 | + */ |
| 298 | + moduleLoadQueue: { }, |
| 299 | + |
| 300 | + /** |
| 301 | + * Javascript Class Paths |
| 302 | + * |
| 303 | + * @key Name of resource |
| 304 | + * @value Class file path |
| 305 | + */ |
| 306 | + resourcePaths : { }, |
| 307 | + |
| 308 | + /** |
| 309 | + * Stores resources that have been requested ( to avoid re-requesting the same resources ) |
| 310 | + * in concurrent requests ) |
| 311 | + */ |
| 312 | + requestedResourceQueue: { }, |
| 313 | + |
| 314 | + /** |
| 315 | + * javascript Resource Paths |
| 316 | + * |
| 317 | + * @key Name of resource |
| 318 | + * @value Name of depenent style sheet |
| 319 | + */ |
| 320 | + resourceStyleDependency: { }, |
| 321 | + |
| 322 | + /** |
| 323 | + * Core load function: |
| 324 | + * |
| 325 | + * @param {Mixed} |
| 326 | + * loadRequest: |
| 327 | + * |
| 328 | + * {String} Name of a module to be loaded Modules are added via |
| 329 | + * addModuleLoader and can define custom code needed to check config and |
| 330 | + * return a list of resources to be loaded |
| 331 | + * |
| 332 | + * {String} Name of a resource to loaded. Resources are added via |
| 333 | + * addResourcePaths function Using defined resource names avoids loading |
| 334 | + * the same resource twice by first checking if the named resource is |
| 335 | + * defined in the global javascript scope variable |
| 336 | + * |
| 337 | + * {String} Absolute or relative to url path The same file won't be |
| 338 | + * loaded twice |
| 339 | + * |
| 340 | + * {Array} can be an array of any combination of the above strings. Will |
| 341 | + * be loaded in-order or in a single resource loader request if |
| 342 | + * scriptLoader is available. |
| 343 | + * |
| 344 | + * {Array} {Array} Can be a set of Arrays for loading. Some browsers |
| 345 | + * execute included scripts out of order. This lets you chain sets of |
| 346 | + * request for those browsers. If using the server side resource loader |
| 347 | + * order is preserved in output and a single request will be used. |
| 348 | + * |
| 349 | + * @param {Function} |
| 350 | + * callback Function called once loading is complete |
| 351 | + * |
| 352 | + */ |
| 353 | + load: function( loadRequest, instanceCallback ) { |
| 354 | + // mw.log("mw.load:: " + loadRequest ); |
| 355 | + var _this = this; |
| 356 | + |
| 357 | + // Throw out any loadRequests that are not strings |
| 358 | + loadRequest = this.cleanLoadRequest( loadRequest ); |
| 359 | + |
| 360 | + // Ensure the callback is only called once per load instance |
| 361 | + var callback = function(){ |
| 362 | + // mw.log( 'instanceCallback::running callback: ' + |
| 363 | + // instanceCallback ); |
| 364 | + if( instanceCallback ){ |
| 365 | + // We pass the loadRequest back to the callback for easy |
| 366 | + // debugging of concurrency issues. |
| 367 | + // ( normally its not used ) |
| 368 | + instanceCallback( loadRequest ); |
| 369 | + instanceCallback = null; |
| 370 | + } |
| 371 | + }; |
| 372 | + |
| 373 | + // Check for empty loadRequest ( directly return the callback ) |
| 374 | + if( mw.isEmpty( loadRequest ) ) { |
| 375 | + mw.log( 'Empty load request: ( ' + loadRequest + ' ) ' ); |
| 376 | + callback( loadRequest ); |
| 377 | + return ; |
| 378 | + } |
| 379 | + |
| 380 | + |
| 381 | + // Check if its a multi-part request: |
| 382 | + if( typeof loadRequest == 'object' ) { |
| 383 | + if( loadRequest.length > 1 ) { |
| 384 | + this.loadMany ( loadRequest, callback ); |
| 385 | + return ; |
| 386 | + }else{ |
| 387 | + // If an array of length 1 set as first element |
| 388 | + loadRequest = loadRequest[0]; |
| 389 | + } |
| 390 | + } |
| 391 | + |
| 392 | + // Check for the module name loader function |
| 393 | + if( this.moduleLoaders[ loadRequest ] ) { |
| 394 | + var resourceSet = this.getModuleResourceSet( loadRequest ); |
| 395 | + if( !resourceSet ){ |
| 396 | + mw.log( "mw.load:: Error with module loader: " + loadRequest + ' ( no resource set defined )' ); |
| 397 | + return ; |
| 398 | + } |
| 399 | + |
| 400 | + // xxx should use refactor "ready" stuff into a "domReady" class |
| 401 | + // So we would not have local scope globals like this: |
| 402 | + if ( mwReadyFlag ) { |
| 403 | + // Load the module directly if load request is after |
| 404 | + // mw.ready has run |
| 405 | + this.load( resourceSet, callback ); |
| 406 | + } else { |
| 407 | + this.addToModuleLoaderQueue( |
| 408 | + loadRequest, |
| 409 | + resourceSet, |
| 410 | + callback |
| 411 | + ); |
| 412 | + } |
| 413 | + return ; |
| 414 | + } |
| 415 | + |
| 416 | + // Check for javascript resource |
| 417 | + if( this.getResourcePath( loadRequest ) ) { |
| 418 | + this.loadResource( loadRequest, callback ); |
| 419 | + return ; |
| 420 | + } |
| 421 | + |
| 422 | + // Try loading as a "file" or via ScriptLoader |
| 423 | + if( loadRequest ) { |
| 424 | + // Check if this resource was already requested |
| 425 | + if( typeof this.requestedResourceQueue[ loadRequest ] == 'object' ){ |
| 426 | + this.requestedResourceQueue[ loadRequest ].push( callback ); |
| 427 | + return ; |
| 428 | + } else { |
| 429 | + this.requestedResourceQueue[ loadRequest ] = []; |
| 430 | + } |
| 431 | + |
| 432 | + if( loadRequest.indexOf( '.js' ) == -1 && !mw.getResourceLoaderPath() ) { |
| 433 | + mw.log( 'Error: are you sure ' + loadRequest + ' is a file ( is it missing a resource path? ) ' ); |
| 434 | + } |
| 435 | + mw.getScript( loadRequest, function(){ |
| 436 | + // Check if we have requestedResources queue items: |
| 437 | + while( _this.requestedResourceQueue[ loadRequest ].length ){ |
| 438 | + _this.requestedResourceQueue[ loadRequest ].shift()( loadRequest ); |
| 439 | + } |
| 440 | + callback( loadRequest ); |
| 441 | + // empty the load request queue: |
| 442 | + _this.requestedResourceQueue[ loadRequest ] = []; |
| 443 | + }); |
| 444 | + return ; |
| 445 | + } |
| 446 | + |
| 447 | + // Possible error? |
| 448 | + mw.log( "Error could not handle load request: " + loadRequest ); |
| 449 | + }, |
| 450 | + |
| 451 | + getModuleResourceSet: function( moduleName ){ |
| 452 | + // Check if the module loader is a function ~run that function~ |
| 453 | + if( typeof ( this.moduleLoaders[ moduleName ] ) == 'function' ) { |
| 454 | + // Add the result of the module loader function |
| 455 | + return this.moduleLoaders[ moduleName ](); |
| 456 | + } else if( typeof ( this.moduleLoaders[ moduleName ] ) == 'object' ){ |
| 457 | + // set resourceSet directly |
| 458 | + return this.moduleLoaders[ moduleName ]; |
| 459 | + } |
| 460 | + return false; |
| 461 | + }, |
| 462 | + |
| 463 | + /** |
| 464 | + * Clean the loadRequest ( throw out any non-string items ) |
| 465 | + */ |
| 466 | + cleanLoadRequest: function( loadRequest ){ |
| 467 | + var cleanRequest = []; |
| 468 | + if( typeof loadRequest == 'string' ) |
| 469 | + return loadRequest; |
| 470 | + for( var i =0;i < loadRequest.length; i++ ){ |
| 471 | + if( typeof loadRequest[i] == 'object' ) { |
| 472 | + cleanRequest[i] = this.cleanLoadRequest( loadRequest[i] ); |
| 473 | + } else if( typeof loadRequest[i] == 'string' ){ |
| 474 | + cleanRequest[i] = $j.trim( loadRequest[i] ); |
| 475 | + } else{ |
| 476 | + // bad request type skip |
| 477 | + } |
| 478 | + } |
| 479 | + return cleanRequest; |
| 480 | + }, |
| 481 | + /** |
| 482 | + * Load a set of scripts. Will issue many load requests or package the |
| 483 | + * request for the resource loader |
| 484 | + * |
| 485 | + * @param {Object} |
| 486 | + * loadSet Set of scripts to be loaded |
| 487 | + * @param {Function} |
| 488 | + * callback Function to call once all scripts are loaded. |
| 489 | + */ |
| 490 | + loadMany: function( loadSet, callback ) { |
| 491 | + var _this = this; |
| 492 | + // Setup up the local "loadStates" |
| 493 | + var loadStates = { }; |
| 494 | + |
| 495 | + // Check if we can load via the "resource loader" ( mwEmbed was |
| 496 | + // included via scriptLoader ) |
| 497 | + if( mw.getResourceLoaderPath() ) { |
| 498 | + // Get the grouped loadStates variable |
| 499 | + loadStates = this.getGroupLoadState( loadSet ); |
| 500 | + if( mw.isEmpty( loadStates ) ) { |
| 501 | + // mw.log( 'loadMany:all resources already loaded'); |
| 502 | + callback(); |
| 503 | + return ; |
| 504 | + } |
| 505 | + }else{ |
| 506 | + // Check if its a dependency set ( nested objects ) |
| 507 | + if( typeof loadSet [ 0 ] == 'object' ) { |
| 508 | + _this.dependencyChainCallFlag[ loadSet ] = false; |
| 509 | + // Load sets of resources ( to preserver order for some |
| 510 | + // browsers ) |
| 511 | + _this.loadDependencyChain( loadSet, callback ); |
| 512 | + return ; |
| 513 | + } |
| 514 | + |
| 515 | + // Set the initial load state for every item in the loadSet |
| 516 | + for( var i = 0; i < loadSet.length ; i++ ) { |
| 517 | + var loadName = loadSet[ i ]; |
| 518 | + loadStates[ loadName ] = 0; |
| 519 | + } |
| 520 | + } |
| 521 | + |
| 522 | + // We are infact loading many: |
| 523 | + //mw.log("mw.load: LoadMany:: " + loadSet ); |
| 524 | + |
| 525 | + // Issue the load request check check loadStates to see if we are |
| 526 | + // "done" |
| 527 | + for( var loadName in loadStates ) { |
| 528 | + //mw.log("loadMany: load: " + loadName ); |
| 529 | + this.load( loadName, function ( loadName ) { |
| 530 | + loadStates[ loadName ] = 1; |
| 531 | + |
| 532 | + /* |
| 533 | + * for( var i in loadStates ) { mw.log( loadName + ' |
| 534 | + * finished of: ' + i + ' : ' + loadStates[i] ); } |
| 535 | + */ |
| 536 | + |
| 537 | + // Check if all load request states are set 1 |
| 538 | + var loadDone = true; |
| 539 | + for( var j in loadStates ) { |
| 540 | + if( loadStates[ j ] === 0 ) |
| 541 | + loadDone = false; |
| 542 | + } |
| 543 | + // Run the parent scope callback for "loadMany" |
| 544 | + if( loadDone ) { |
| 545 | + callback( loadName ); |
| 546 | + } |
| 547 | + } ); |
| 548 | + } |
| 549 | + }, |
| 550 | + |
| 551 | + /** |
| 552 | + * Get grouped load state for script loader |
| 553 | + * |
| 554 | + * Groups the scriptRequest where possible: Modules include "loader |
| 555 | + * code" so they are separated into pre-condition code to be run for |
| 556 | + * subsequent requests |
| 557 | + * |
| 558 | + * @param {Object} |
| 559 | + * loadSet Loadset to return grouped |
| 560 | + * @return {Object} grouped loadSet |
| 561 | + */ |
| 562 | + getGroupLoadState: function( loadSet ) { |
| 563 | + var groupedLoadSet = []; |
| 564 | + var loadStates = { }; |
| 565 | + // Merge load set into new groupedLoadSet |
| 566 | + if( typeof loadSet[0] == 'object' ) { |
| 567 | + for( var i = 0; i < loadSet.length ; i++ ) { |
| 568 | + for( var j = 0; j < loadSet[i].length ; j++ ) { |
| 569 | + // Make sure we have not already included it: |
| 570 | + groupedLoadSet.push( loadSet[i][j] ); |
| 571 | + } |
| 572 | + } |
| 573 | + } else { |
| 574 | + // Use the loadSet directly: |
| 575 | + groupedLoadSet = loadSet; |
| 576 | + } |
| 577 | + |
| 578 | + // Setup grouped loadStates Set: |
| 579 | + var groupClassKey = ''; |
| 580 | + var coma = ''; |
| 581 | + var uniqueResourceName = {}; |
| 582 | + for( var i=0; i < groupedLoadSet.length; i++ ) { |
| 583 | + var loadName = groupedLoadSet[ i ]; |
| 584 | + if( this.getResourcePath( loadName ) ) { |
| 585 | + // Check if not already in request queue and not defined in global namespace |
| 586 | + if( !mw.isset( loadName ) && ! uniqueResourceName[ loadName] ){ |
| 587 | + groupClassKey += coma + loadName; |
| 588 | + coma = ','; |
| 589 | + |
| 590 | + // Check for style sheet dependencies |
| 591 | + if( this.resourceStyleDependency[ loadName ] ){ |
| 592 | + groupClassKey += coma + this.resourceStyleDependency[ loadName ]; |
| 593 | + } |
| 594 | + } |
| 595 | + } else if ( this.moduleLoaders[ loadName ] ) { |
| 596 | + |
| 597 | + // Module loaders break up grouped script requests ( add the |
| 598 | + // current groupClassKey ) |
| 599 | + if( groupClassKey != '' ) { |
| 600 | + loadStates[ groupClassKey ] = 0; |
| 601 | + groupClassKey = coma = ''; |
| 602 | + } |
| 603 | + if( ! uniqueResourceName[ loadName] ){ |
| 604 | + // Add the module to the loadSate |
| 605 | + loadStates[ loadName ] = 0; |
| 606 | + } |
| 607 | + } |
| 608 | + uniqueResourceName[ loadName] = true; |
| 609 | + } |
| 610 | + |
| 611 | + // Add groupClassKey if set: |
| 612 | + if( groupClassKey != '' ) { |
| 613 | + loadStates [ groupClassKey ] = 0; |
| 614 | + } |
| 615 | + |
| 616 | + return loadStates; |
| 617 | + }, |
| 618 | + |
| 619 | + // Array to register that a callback has been called |
| 620 | + dependencyChainCallFlag: { }, |
| 621 | + |
| 622 | + /** |
| 623 | + * Load a sets of scripts satisfy dependency order for browsers that |
| 624 | + * execute dynamically included scripts out of order |
| 625 | + * |
| 626 | + * @param {Object} |
| 627 | + * loadChain A set of javascript arrays to be loaded. Sets |
| 628 | + * are requested in array order. |
| 629 | + */ |
| 630 | + loadDependencyChain: function( loadChain, callback ) { |
| 631 | + var _this = this; |
| 632 | + // Load with dependency checks |
| 633 | + var callSet = loadChain.shift(); |
| 634 | + this.load( callSet, function( cbname ) { |
| 635 | + if ( loadChain.length != 0 ) { |
| 636 | + _this.loadDependencyChain( loadChain, callback ); |
| 637 | + } else { |
| 638 | + // NOTE: IE gets called twice so we have check the |
| 639 | + // dependencyChainCallFlag before calling the callback |
| 640 | + if( _this.dependencyChainCallFlag[ callSet ] == callback ) { |
| 641 | + mw.log("... already called this callback for " + callSet ); |
| 642 | + return ; |
| 643 | + } |
| 644 | + _this.dependencyChainCallFlag[ callSet ] = callback; |
| 645 | + callback( ); |
| 646 | + } |
| 647 | + } ); |
| 648 | + }, |
| 649 | + |
| 650 | + /** |
| 651 | + * Add to the module loader queue |
| 652 | + */ |
| 653 | + addToModuleLoaderQueue: function( moduleName, resourceSet, callback ) { |
| 654 | + mw.log(" addToModuleLoaderQueue:: " + moduleName + ' resourceSet: ' + resourceSet ); |
| 655 | + if( this.moduleLoadQueue[ moduleName ] ){ |
| 656 | + // If the module is already in the queue just add its callback: |
| 657 | + this.moduleLoadQueue[ moduleName ].functionQueue.push( callback ); |
| 658 | + } else { |
| 659 | + // create the moduleLoadQueue item |
| 660 | + this.moduleLoadQueue[ moduleName ] = { |
| 661 | + 'resourceSet' : resourceSet, |
| 662 | + 'functionQueue' : [ callback ], |
| 663 | + 'loaded' : false |
| 664 | + }; |
| 665 | + } |
| 666 | + }, |
| 667 | + |
| 668 | + /** |
| 669 | + * Loops over all modules in queue, builds request sets based on config |
| 670 | + * request type |
| 671 | + */ |
| 672 | + runModuleLoadQueue: function(){ |
| 673 | + var _this = this; |
| 674 | + mw.log( "mw.runModuleLoadQueue:: " ); |
| 675 | + var runModuleFunctionQueue = function(){ |
| 676 | + // Run all the callbacks |
| 677 | + for( var moduleName in _this.moduleLoadQueue ){ |
| 678 | + while( _this.moduleLoadQueue[moduleName].functionQueue.length ) { |
| 679 | + _this.moduleLoadQueue[moduleName].functionQueue.shift()(); |
| 680 | + } |
| 681 | + } |
| 682 | + }; |
| 683 | + |
| 684 | + // Check for single request or javascript debug based loading: |
| 685 | + if( !mw.getResourceLoaderPath() || mw.getConfig( 'loader.groupStrategy' ) == 'single' ){ |
| 686 | + // if not using the resource load just do a normal array merge |
| 687 | + // ( for browsers like IE that don't follow first append first |
| 688 | + // execute rule ) |
| 689 | + var fullResourceList = []; |
| 690 | + for( var moduleName in this.moduleLoadQueue ) { |
| 691 | + var resourceSet = this.moduleLoadQueue[ moduleName ].resourceSet; |
| 692 | + // Lets try a global merge |
| 693 | + fullResourceList = $j.merge( fullResourceList, resourceSet ); |
| 694 | + } |
| 695 | + mw.load( fullResourceList, function(){ |
| 696 | + runModuleFunctionQueue(); |
| 697 | + }); |
| 698 | + return ; |
| 699 | + } |
| 700 | + |
| 701 | + // Else do per module group loading |
| 702 | + if( mw.getConfig( 'loader.groupStrategy' ) == 'module' ) { |
| 703 | + var fullResourceList = []; |
| 704 | + var sharedResourceList = []; |
| 705 | + |
| 706 | + for( var moduleName in this.moduleLoadQueue ) { |
| 707 | + // Build a shared dependencies list and load that separately |
| 708 | + // "first" |
| 709 | + // ( in IE we have to wait until its "ready" since it does |
| 710 | + // not follow dom order ) |
| 711 | + var moduleResourceList = this.getFlatModuleResourceList( moduleName ); |
| 712 | + // Build the sharedResourceList |
| 713 | + for( var i=0; i < moduleResourceList.length; i++ ){ |
| 714 | + var moduleResource = moduleResourceList[i]; |
| 715 | + // Check if already in the full resource list if so add |
| 716 | + // to shared. |
| 717 | + if( fullResourceList[ moduleResource ] ){ |
| 718 | + if( $j.inArray( moduleResource, sharedResourceList ) == -1 ){ |
| 719 | + sharedResourceList.push( moduleResource ); |
| 720 | + } |
| 721 | + } |
| 722 | + // Add to the fullResourceList |
| 723 | + fullResourceList[ moduleResource ] = true; |
| 724 | + } |
| 725 | + } |
| 726 | + |
| 727 | + // Local module request set ( stores the actual request we will |
| 728 | + // make after grouping shared resources |
| 729 | + var moduleRequestSet = {}; |
| 730 | + |
| 731 | + // Only add non-shared to respective modules load requests |
| 732 | + for( var moduleName in this.moduleLoadQueue ) { |
| 733 | + moduleRequestSet[ moduleName ] = []; |
| 734 | + var moduleResourceList = this.getFlatModuleResourceList( moduleName ); |
| 735 | + for( var i =0; i < moduleResourceList.length; i++ ){ |
| 736 | + var moduleResource = moduleResourceList[i]; |
| 737 | + if( $j.inArray( moduleResource, sharedResourceList ) == -1 ){ |
| 738 | + moduleRequestSet[ moduleName ].push( moduleResource ); |
| 739 | + } |
| 740 | + } |
| 741 | + } |
| 742 | + var sharedResourceLoadDone = false; |
| 743 | + // Check if modules are done |
| 744 | + var checkModulesDone = function(){ |
| 745 | + if( !sharedResourceLoadDone ){ |
| 746 | + return false; |
| 747 | + } |
| 748 | + for( var moduleName in _this.moduleLoadQueue ) { |
| 749 | + if( ! _this.moduleLoadQueue[ moduleName ].loaded ){ |
| 750 | + return false; |
| 751 | + } |
| 752 | + } |
| 753 | + runModuleFunctionQueue(); |
| 754 | + }; |
| 755 | + // Local instance of load requests to retain resourceSet |
| 756 | + // context: |
| 757 | + var localLoadCallInstance = function( moduleName, resourceSet ){ |
| 758 | + mw.load( resourceSet, function(){ |
| 759 | + _this.moduleLoadQueue[ moduleName ].loaded = true; |
| 760 | + checkModulesDone(); |
| 761 | + }); |
| 762 | + }; |
| 763 | + |
| 764 | + // Load the shared resources |
| 765 | + mw.load( sharedResourceList, function(){ |
| 766 | + // mw.log("Shared Resources loaded"); |
| 767 | + // xxx check if we are in "IE" and dependencies need to be |
| 768 | + // loaded "first" |
| 769 | + sharedResourceLoadDone = true; |
| 770 | + checkModulesDone(); |
| 771 | + }); |
| 772 | + // Load all module Request Set |
| 773 | + for( var moduleName in moduleRequestSet ){ |
| 774 | + localLoadCallInstance( moduleName, moduleRequestSet[ moduleName ] ); |
| 775 | + } |
| 776 | + } |
| 777 | + // xxx Here we could also do some "intelligent" grouping |
| 778 | + }, |
| 779 | + |
| 780 | + getFlatModuleResourceList: function( moduleName ){ |
| 781 | + var moduleList = []; |
| 782 | + for( var j in this.moduleLoadQueue[moduleName].resourceSet ){ |
| 783 | + // Check if we have a multi-set array: |
| 784 | + if( typeof this.moduleLoadQueue[moduleName].resourceSet[j] == 'object' ){ |
| 785 | + moduleList = $j.merge( moduleList, this.moduleLoadQueue[moduleName].resourceSet[j] ); |
| 786 | + } else { |
| 787 | + moduleList = $j.merge( moduleList, [ this.moduleLoadQueue[moduleName].resourceSet[j] ] ); |
| 788 | + } |
| 789 | + } |
| 790 | + return moduleList; |
| 791 | + }, |
| 792 | + /** |
| 793 | + * Loads javascript or css associated with a resourceName |
| 794 | + * |
| 795 | + * @param {String} |
| 796 | + * resourceName Name of resource to load |
| 797 | + * @param {Function} |
| 798 | + * callback Function to run once resource is loaded |
| 799 | + */ |
| 800 | + loadResource: function( resourceName , callback) { |
| 801 | + // mw.log("LoadResource:" + resourceName ); |
| 802 | + var _this = this; |
| 803 | + |
| 804 | + // Check for css dependency on resource name |
| 805 | + if( this.resourceStyleDependency[ resourceName ] ) { |
| 806 | + if( ! mw.isset( this.resourceStyleDependency[ resourceName ] )){ |
| 807 | + mw.log("loadResource:: dependent css resource: " + this.resourceStyleDependency[ resourceName ] ); |
| 808 | + _this.loadResource( this.resourceStyleDependency[ resourceName ] , function() { |
| 809 | + // Continue the original loadResource request. |
| 810 | + _this.loadResource( resourceName, callback ); |
| 811 | + }); |
| 812 | + return ; |
| 813 | + } |
| 814 | + } |
| 815 | + |
| 816 | + // Make sure the resource is not already defined: |
| 817 | + if ( mw.isset( resourceName ) ) { |
| 818 | + // mw.log( 'Class ( ' + resourceName + ' ) already defined ' ); |
| 819 | + callback( resourceName ); |
| 820 | + return ; |
| 821 | + } |
| 822 | + |
| 823 | + // Setup the Script Request var: |
| 824 | + var scriptRequest = null; |
| 825 | + |
| 826 | + |
| 827 | + // If the scriptloader is enabled use the resourceName as the |
| 828 | + // scriptRequest: |
| 829 | + if( mw.getResourceLoaderPath() ) { |
| 830 | + scriptRequest = resourceName; |
| 831 | + }else{ |
| 832 | + // Get the resource url: |
| 833 | + var baseClassPath = this.getResourcePath( resourceName ); |
| 834 | + // Add the mwEmbed path if not a root path or a full url |
| 835 | + if( baseClassPath.indexOf( '/' ) !== 0 && |
| 836 | + baseClassPath.indexOf( '://' ) === -1 ) { |
| 837 | + scriptRequest = mw.getMwEmbedPath() + baseClassPath; |
| 838 | + }else{ |
| 839 | + scriptRequest = baseClassPath; |
| 840 | + } |
| 841 | + if( ! scriptRequest ) { |
| 842 | + mw.log( "Error Could not get url for resource " + resourceName ); |
| 843 | + return false; |
| 844 | + } |
| 845 | + } |
| 846 | + // Include resource defined check for older browsers |
| 847 | + var resourceDone = false; |
| 848 | + |
| 849 | + // Set the loadDone callback per the provided resourceName |
| 850 | + mw.setLoadDoneCB( resourceName, callback ); |
| 851 | + // Issue the request to load the resource (include resource name in |
| 852 | + // result callback: |
| 853 | + mw.getScript( scriptRequest, function( scriptRequest ) { |
| 854 | + // If its a "style sheet" manually set its resource to true |
| 855 | + var ext = scriptRequest.substr( scriptRequest.split('?')[0].lastIndexOf( '.' ), 4 ).toLowerCase(); |
| 856 | + if( ext == '.css' && resourceName.substr(0,8) == 'mw.style' ){ |
| 857 | + mw.style[ resourceName.substr( 9 ) ] = true; |
| 858 | + } |
| 859 | + |
| 860 | + // Send warning if resourceName is not defined |
| 861 | + if(! mw.isset( resourceName ) |
| 862 | + && mwLoadDoneCB[ resourceName ] != 'done' ) { |
| 863 | + mw.log( 'Possible Error: ' + resourceName +' not set in time, or not defined in:' + "\n" |
| 864 | + + _this.getResourcePath( resourceName ) ); |
| 865 | + } |
| 866 | + |
| 867 | + // If ( debug mode ) and the script include is missing resource |
| 868 | + // messages |
| 869 | + // do a separate request to retrieve the msgs |
| 870 | + if( mw.currentClassMissingMessages ) { |
| 871 | + mw.log( " resourceName " + resourceName + " is missing messages" ); |
| 872 | + // Reset the currentClassMissingMessages flag |
| 873 | + mw.currentClassMissingMessages = false; |
| 874 | + |
| 875 | + // Load msgs for this resource: |
| 876 | + mw.loadResourceMessages( resourceName, function() { |
| 877 | + // Run the onDone callback |
| 878 | + mw.loadDone( resourceName ); |
| 879 | + } ); |
| 880 | + } else { |
| 881 | + // If not using the resource loader make sure the |
| 882 | + // resourceName is available before firing the loadDone |
| 883 | + if( !mw.getResourceLoaderPath() ) { |
| 884 | + mw.waitForObject( resourceName, function( resourceName ) { |
| 885 | + // Once object is ready run loadDone |
| 886 | + mw.loadDone( resourceName ); |
| 887 | + } ); |
| 888 | + } else { |
| 889 | + // loadDone should be appended to the bottom of the |
| 890 | + // resource loader response |
| 891 | + // mw.loadDone( resourceName ); |
| 892 | + } |
| 893 | + } |
| 894 | + } ); |
| 895 | + }, |
| 896 | + |
| 897 | + /** |
| 898 | + * Adds a module to the mwLoader object |
| 899 | + * |
| 900 | + * @param {String} |
| 901 | + * name Name of module |
| 902 | + * @param {Function} |
| 903 | + * moduleLoader Function that loads dependencies for a module |
| 904 | + */ |
| 905 | + addModuleLoader: function( name, moduleLoader ) { |
| 906 | + this.moduleLoaders [ name ] = moduleLoader; |
| 907 | + }, |
| 908 | + |
| 909 | + /** |
| 910 | + * Adds resource file path key value pairs |
| 911 | + * |
| 912 | + * @param {Object} |
| 913 | + * resourceSet JSON formated list of resource name file path |
| 914 | + * pairs. |
| 915 | + * |
| 916 | + * resourceSet must be strict JSON to allow the php scriptLoader to |
| 917 | + * parse the file paths. |
| 918 | + */ |
| 919 | + addResourcePaths: function( resourceSet ) { |
| 920 | + var prefix = ( mw.getConfig( 'loaderContext' ) )? |
| 921 | + mw.getConfig( 'loaderContext' ): ''; |
| 922 | + |
| 923 | + for( var i in resourceSet ) { |
| 924 | + this.resourcePaths[ i ] = prefix + resourceSet[ i ]; |
| 925 | + } |
| 926 | + }, |
| 927 | + |
| 928 | + /* |
| 929 | + * Adds a named style sheet dependency to a named resource |
| 930 | + * |
| 931 | + * @parma {Object} resourceSet JSON formated list of resource names and |
| 932 | + * associated style sheet names |
| 933 | + */ |
| 934 | + addStyleResourceDependency: function( resourceSet ){ |
| 935 | + for( var i in resourceSet ){ |
| 936 | + this.resourceStyleDependency[ i ] = resourceSet[i]; |
| 937 | + } |
| 938 | + }, |
| 939 | + |
| 940 | + /** |
| 941 | + * Get a resource path from a resourceName if no resource found return |
| 942 | + * false |
| 943 | + */ |
| 944 | + getResourcePath: function( resourceName ) { |
| 945 | + if( this.resourcePaths[ resourceName ] ) |
| 946 | + return this.resourcePaths[ resourceName ]; |
| 947 | + return false; |
| 948 | + } |
| 949 | + }; |
| 950 | + |
| 951 | + /** |
| 952 | + * Load done callback for script loader |
| 953 | + * |
| 954 | + * @param {String} |
| 955 | + * requestName Name of the load request |
| 956 | + */ |
| 957 | + mw.loadDone = function( requestName ) { |
| 958 | + if( !mwLoadDoneCB[ requestName ] ) { |
| 959 | + return true; |
| 960 | + } |
| 961 | + while( mwLoadDoneCB[ requestName ].length ) { |
| 962 | + // check if mwLoadDoneCB is already "done" |
| 963 | + // the function list is not an object |
| 964 | + if( typeof mwLoadDoneCB[ requestName ] != 'object' ) |
| 965 | + { |
| 966 | + break; |
| 967 | + } |
| 968 | + var func = mwLoadDoneCB[ requestName ].pop(); |
| 969 | + if( typeof func == 'function' ) { |
| 970 | + // mw.log( "LoadDone: " + requestName + ' run callback::' + |
| 971 | + // func); |
| 972 | + func( requestName ); |
| 973 | + }else{ |
| 974 | + mw.log('mwLoadDoneCB: Error non callback function on stack'); |
| 975 | + } |
| 976 | + } |
| 977 | + // Set the load request name to done |
| 978 | + mwLoadDoneCB[ requestName ] = 'done'; |
| 979 | + }; |
| 980 | + |
| 981 | + /** |
| 982 | + * Set a load done callback |
| 983 | + * |
| 984 | + * @param {String} |
| 985 | + * requestName Name of resource or request set |
| 986 | + * @param {Function} |
| 987 | + * callback Function called once requestName is ready |
| 988 | + */ |
| 989 | + mw.setLoadDoneCB = function( requestName, callback ) { |
| 990 | + // If the requestName is already done loading just callback |
| 991 | + if( mwLoadDoneCB[ requestName ] == 'done' ) { |
| 992 | + callback( requestName ); |
| 993 | + } |
| 994 | + // Setup the function queue if unset |
| 995 | + if( typeof mwLoadDoneCB[ requestName ] != 'object' ) { |
| 996 | + mwLoadDoneCB[ requestName ] = []; |
| 997 | + } |
| 998 | + mwLoadDoneCB[ requestName ].push( callback ); |
| 999 | + }; |
| 1000 | + |
| 1001 | + /** |
| 1002 | + * Shortcut entry points / convenience functions: Lets you write mw.load() |
| 1003 | + * instead of mw.loader.load() only these entry points should be used. |
| 1004 | + * |
| 1005 | + * future closure optimizations could minify internal function names |
| 1006 | + */ |
| 1007 | + |
| 1008 | + /** |
| 1009 | + * Load Object entry point: Loads a requested set of javascript |
| 1010 | + */ |
| 1011 | + mw.load = function( loadRequest, callback ) { |
| 1012 | + return mw.loader.load( loadRequest, callback ); |
| 1013 | + }; |
| 1014 | + |
| 1015 | + /** |
| 1016 | + * Add module entry point: Adds a module to the mwLoader object |
| 1017 | + */ |
| 1018 | + mw.addModuleLoader = function ( name, loaderFunction ) { |
| 1019 | + return mw.loader.addModuleLoader( name, loaderFunction ); |
| 1020 | + }; |
| 1021 | + |
| 1022 | + /** |
| 1023 | + * Add Class File Paths entry point: |
| 1024 | + */ |
| 1025 | + mw.addResourcePaths = function ( resourceSet ) { |
| 1026 | + return mw.loader.addResourcePaths( resourceSet ); |
| 1027 | + }; |
| 1028 | + |
| 1029 | + mw.addStyleResourceDependency = function ( resourceSet ) { |
| 1030 | + return mw.loader.addStyleResourceDependency( resourceSet ); |
| 1031 | + }; |
| 1032 | + |
| 1033 | + /** |
| 1034 | + * Get Class File Path entry point: |
| 1035 | + */ |
| 1036 | + mw.getResourcePath = function( resourceName ) { |
| 1037 | + return mw.loader.getResourcePath( resourceName ); |
| 1038 | + }; |
| 1039 | + |
| 1040 | + |
| 1041 | + /** |
| 1042 | + * Utility Functions |
| 1043 | + */ |
| 1044 | + |
| 1045 | + /** |
| 1046 | + * addLoaderDialog small helper for displaying a loading dialog |
| 1047 | + * |
| 1048 | + * @param {String} |
| 1049 | + * dialogHtml text Html of the loader msg |
| 1050 | + */ |
| 1051 | + mw.addLoaderDialog = function( dialogHtml ) { |
| 1052 | + if( typeof dialogHtml == 'undefined'){ |
| 1053 | + dialogHtml =''; |
| 1054 | + } |
| 1055 | + var $dialog = mw.addDialog( { |
| 1056 | + 'title' : dialogHtml, |
| 1057 | + 'content' : dialogHtml + '<br>' + |
| 1058 | + $j('<div />') |
| 1059 | + .loadingSpinner() |
| 1060 | + .html() |
| 1061 | + }); |
| 1062 | + return $dialog; |
| 1063 | + }; |
| 1064 | + |
| 1065 | + /** |
| 1066 | + * Close the loader dialog created with addLoaderDialog |
| 1067 | + */ |
| 1068 | + mw.closeLoaderDialog = function() { |
| 1069 | + // Make sure the dialog resource is present |
| 1070 | + if( !mw.isset( '$j.ui.dialog' ) ) { |
| 1071 | + return false; |
| 1072 | + } |
| 1073 | + // Close with timeout since jquery ui binds with timeout: |
| 1074 | + // ui dialog line 530 |
| 1075 | + setTimeout( function(){ |
| 1076 | + $j( '#mwTempLoaderDialog' ) |
| 1077 | + .dialog( 'destroy' ); |
| 1078 | + } , 10); |
| 1079 | + }; |
| 1080 | + |
| 1081 | + /** |
| 1082 | + * Add a (temporary) dialog window: |
| 1083 | + * |
| 1084 | + * @param {Object} with following keys: |
| 1085 | + * title: {String} Title string for the dialog |
| 1086 | + * content: {String} to be inserted in msg box |
| 1087 | + * buttons: {Object} A button object for the dialog Can be a string |
| 1088 | + * for the close button |
| 1089 | + * any jquery.ui.dialog option |
| 1090 | + */ |
| 1091 | + mw.addDialog = function ( options ) { |
| 1092 | + // Remove any other dialog |
| 1093 | + $j( '#mwTempLoaderDialog' ).remove(); |
| 1094 | + |
| 1095 | + if( !options){ |
| 1096 | + options = {}; |
| 1097 | + } |
| 1098 | + |
| 1099 | + // Extend the default options with provided options |
| 1100 | + var options = $j.extend({ |
| 1101 | + 'bgiframe': true, |
| 1102 | + 'draggable': true, |
| 1103 | + 'resizable': false, |
| 1104 | + 'modal': true, |
| 1105 | + 'position' : ['center', 'center'] |
| 1106 | + }, options ); |
| 1107 | + |
| 1108 | + if( ! options.title || ! options.content ){ |
| 1109 | + mw.log("Error: mwEmbed addDialog missing required options ( title, content ) "); |
| 1110 | + return ; |
| 1111 | + } |
| 1112 | + |
| 1113 | + // Append the dialog div on top: |
| 1114 | + $j( 'body' ).append( |
| 1115 | + $j('<div />') |
| 1116 | + .attr( { |
| 1117 | + 'id' : "mwTempLoaderDialog", |
| 1118 | + 'title' : options.title |
| 1119 | + }) |
| 1120 | + .hide() |
| 1121 | + .append( options.content ) |
| 1122 | + ); |
| 1123 | + |
| 1124 | + // Build the uiRequest |
| 1125 | + var uiRequest = [ '$j.ui.dialog' ]; |
| 1126 | + if( options.draggable ){ |
| 1127 | + uiRequest.push( '$j.ui.mouse' ); |
| 1128 | + uiRequest.push( '$j.ui.draggable' ); |
| 1129 | + } |
| 1130 | + if( options.resizable ){ |
| 1131 | + uiRequest.push( '$j.ui.resizable' ); |
| 1132 | + } |
| 1133 | + |
| 1134 | + // Special button string |
| 1135 | + if ( typeof options.buttons == 'string' ) { |
| 1136 | + var buttonMsg = options.buttons; |
| 1137 | + buttons = { }; |
| 1138 | + options.buttons[ buttonMsg ] = function() { |
| 1139 | + $j( this ).dialog( 'close' ); |
| 1140 | + }; |
| 1141 | + } |
| 1142 | + |
| 1143 | + // Load the dialog resources |
| 1144 | + mw.load([ |
| 1145 | + [ |
| 1146 | + '$j.ui', |
| 1147 | + '$j.widget', |
| 1148 | + '$j.ui.mouse', |
| 1149 | + '$j.ui.position' |
| 1150 | + ], |
| 1151 | + uiRequest |
| 1152 | + ], function() { |
| 1153 | + var $dialog = $j( '#mwTempLoaderDialog' ).show().dialog( options ); |
| 1154 | + // center the dialog |
| 1155 | + // xxx figure out why jquery ui is messing up here |
| 1156 | + /*$j( '#mwTempLoaderDialog' ).parent('.ui-dialog').css({ |
| 1157 | + 'position' : 'absolute', |
| 1158 | + 'left' : '50%', |
| 1159 | + 'margin-left': -1 * $dialog.width()/2, |
| 1160 | + 'top' : '50%', |
| 1161 | + 'margin-top': -1 * $dialog.height()/2 |
| 1162 | + }); */ |
| 1163 | + } ); |
| 1164 | + return $j( '#mwTempLoaderDialog' ); |
| 1165 | + }; |
| 1166 | + |
| 1167 | + /** |
| 1168 | + * Mobile HTML5 has special properties for html5 video:: |
| 1169 | + * |
| 1170 | + * NOTE: should be phased out in favor of browser feature detection where possible |
| 1171 | + */ |
| 1172 | + mw.isMobileHTML5 = function() { |
| 1173 | + // check mobile safari foce ( for debug ) |
| 1174 | + if( mw.getConfig( 'forceMobileHTML5' ) || document.URL.indexOf('forceMobileHTML5') != -1 ){ |
| 1175 | + return true; |
| 1176 | + } |
| 1177 | + if (( navigator.userAgent.indexOf('iPhone') != -1) || |
| 1178 | + ( navigator.userAgent.indexOf('iPod') != -1) || |
| 1179 | + ( navigator.userAgent.indexOf('iPad') != -1) || |
| 1180 | + ( mw.isAndroid2() ) |
| 1181 | + ) { |
| 1182 | + return true; |
| 1183 | + } |
| 1184 | + return false; |
| 1185 | + }; |
| 1186 | + // Android 2 has some restrictions vs other mobile platforms |
| 1187 | + mw.isAndroid2 = function(){ |
| 1188 | + if ( navigator.userAgent.indexOf('Android 2.') != -1) { |
| 1189 | + return true; |
| 1190 | + } |
| 1191 | + return false; |
| 1192 | + }; |
| 1193 | + |
| 1194 | + /** |
| 1195 | + * Similar to php isset function checks if the variable exists. Does a safe |
| 1196 | + * check of a descendant method or variable |
| 1197 | + * |
| 1198 | + * @param {String} |
| 1199 | + * objectPath |
| 1200 | + * @return {Boolean} true if objectPath exists false if objectPath is |
| 1201 | + * undefined |
| 1202 | + */ |
| 1203 | + mw.isset = function( objectPath ) { |
| 1204 | + if ( !objectPath || typeof objectPath != 'string') { |
| 1205 | + return false; |
| 1206 | + } |
| 1207 | + var pathSet = objectPath.split( '.' ); |
| 1208 | + var cur_path = ''; |
| 1209 | + |
| 1210 | + for ( var p = 0; p < pathSet.length; p++ ) { |
| 1211 | + cur_path = ( cur_path == '' ) ? cur_path + pathSet[p] : cur_path + '.' + pathSet[p]; |
| 1212 | + eval( 'var ptest = typeof ( ' + cur_path + ' ); ' ); |
| 1213 | + if ( ptest == 'undefined' ) { |
| 1214 | + return false; |
| 1215 | + } |
| 1216 | + } |
| 1217 | + return true; |
| 1218 | + }; |
| 1219 | + |
| 1220 | + /** |
| 1221 | + * Wait for a object to be defined and the call the callback |
| 1222 | + * |
| 1223 | + * @param {Object} |
| 1224 | + * objectName Name of object to be defined |
| 1225 | + * @param {Function} |
| 1226 | + * callback Function to call once object is defined |
| 1227 | + * @param {Null} |
| 1228 | + * callNumber Used internally to keep track of number of times |
| 1229 | + * waitForObject has been called |
| 1230 | + */ |
| 1231 | + var waitTime = 1200; // About 30 seconds |
| 1232 | + mw.waitForObject = function( objectName, callback, _callNumber) { |
| 1233 | + // mw.log( 'waitForObject: ' + objectName + ' cn: ' + _callNumber); |
| 1234 | + |
| 1235 | + // Increment callNumber: |
| 1236 | + if( !_callNumber ) { |
| 1237 | + _callNumber = 1; |
| 1238 | + } else { |
| 1239 | + _callNumber++; |
| 1240 | + } |
| 1241 | + |
| 1242 | + if( _callNumber > waitTime ) { |
| 1243 | + mw.log( "Error: waiting for object: " + objectName + ' timeout ' ); |
| 1244 | + callback( false ); |
| 1245 | + return ; |
| 1246 | + } |
| 1247 | + |
| 1248 | + // If the object is defined ( or we are done loading from a callback ) |
| 1249 | + if ( mw.isset( objectName ) || mwLoadDoneCB[ objectName ] == 'done' ) { |
| 1250 | + callback( objectName ); |
| 1251 | + }else{ |
| 1252 | + setTimeout( function( ) { |
| 1253 | + mw.waitForObject( objectName, callback, _callNumber); |
| 1254 | + }, 25); |
| 1255 | + } |
| 1256 | + }; |
| 1257 | + |
| 1258 | + /** |
| 1259 | + * Check if an object is empty or if its an empty string. |
| 1260 | + * |
| 1261 | + * @param {Object} |
| 1262 | + * object Object to be checked |
| 1263 | + */ |
| 1264 | + mw.isEmpty = function( object ) { |
| 1265 | + if( typeof object == 'string' ) { |
| 1266 | + if( object == '' ) return true; |
| 1267 | + // Non empty string: |
| 1268 | + return false; |
| 1269 | + } |
| 1270 | + |
| 1271 | + // If an array check length: |
| 1272 | + if( Object.prototype.toString.call( object ) === "[object Array]" |
| 1273 | + && object.length == 0 ) { |
| 1274 | + return true; |
| 1275 | + } |
| 1276 | + |
| 1277 | + // Else check as an object: |
| 1278 | + for( var i in object ) { return false; } |
| 1279 | + |
| 1280 | + // Else object is empty: |
| 1281 | + return true; |
| 1282 | + }; |
| 1283 | + |
| 1284 | + /** |
| 1285 | + * Log a string msg to the console |
| 1286 | + * |
| 1287 | + * all mw.log statements will be removed on minification so lots of mw.log |
| 1288 | + * calls will not impact performance in non debug mode |
| 1289 | + * |
| 1290 | + * @param {String} |
| 1291 | + * string String to output to console |
| 1292 | + */ |
| 1293 | + mw.log = function( string ) { |
| 1294 | + // Add any prepend debug strings if necessary |
| 1295 | + if ( mw.getConfig( 'Mw.LogPrepend' ) ){ |
| 1296 | + string = mw.getConfig( 'Mw.LogPrepend' ) + string; |
| 1297 | + } |
| 1298 | + |
| 1299 | + if ( window.console ) { |
| 1300 | + window.console.log( string ); |
| 1301 | + } else { |
| 1302 | + /** |
| 1303 | + * Old IE and non-Firebug debug: ( commented out for now ) |
| 1304 | + */ |
| 1305 | + |
| 1306 | + /*var log_elm = document.getElementById('mv_js_log'); |
| 1307 | + if(!log_elm) { |
| 1308 | + document.getElementsByTagName("body")[0].innerHTML += '<div ' + |
| 1309 | + 'style="position:absolute;z-index:500;bottom:0px;left:0px;right:0px;height:200px;">' + |
| 1310 | + '<textarea id="mv_js_log" cols="120" rows="12"></textarea>' + |
| 1311 | + '</div>'; |
| 1312 | + } |
| 1313 | + var log_elm = document.getElementById('mv_js_log'); |
| 1314 | + if(log_elm) { |
| 1315 | + log_elm.value+=string+"\n"; |
| 1316 | + // scroll to bottom: |
| 1317 | + log_elm.scrollTop = log_elm.scrollHeight; |
| 1318 | + }*/ |
| 1319 | + } |
| 1320 | + }; |
| 1321 | + |
| 1322 | + // Setup the local mwOnLoadFunctions array: |
| 1323 | + var mwOnLoadFunctions = []; |
| 1324 | + |
| 1325 | + // mw Ready flag ( set once mwEmbed is ready ) |
| 1326 | + var mwReadyFlag = false; |
| 1327 | + |
| 1328 | + /** |
| 1329 | + * Enables load hooks to run once mwEmbeed is "ready" Will ensure jQuery is |
| 1330 | + * available, is in the $j namespace and mw interfaces and configuration has |
| 1331 | + * been loaded and applied |
| 1332 | + * |
| 1333 | + * This is different from jQuery(document).ready() ( jQuery ready is not |
| 1334 | + * friendly with dynamic includes and not friendly with core interface |
| 1335 | + * asynchronous build out. ) |
| 1336 | + * |
| 1337 | + * @param {Function} |
| 1338 | + * callback Function to run once DOM and jQuery are ready |
| 1339 | + */ |
| 1340 | + mw.ready = function( callback ) { |
| 1341 | + if( mwReadyFlag === false ) { |
| 1342 | + // Add the callbcak to the onLoad function stack |
| 1343 | + mwOnLoadFunctions.push ( callback ); |
| 1344 | + } else { |
| 1345 | + // If mwReadyFlag is already "true" issue the callback directly: |
| 1346 | + callback(); |
| 1347 | + } |
| 1348 | + }; |
| 1349 | + |
| 1350 | + /** |
| 1351 | + * Runs all the queued functions called by mwEmbedSetup |
| 1352 | + */ |
| 1353 | + mw.runReadyFunctions = function ( ) { |
| 1354 | + mw.log('mw.runReadyFunctions: ' + mwOnLoadFunctions.length ); |
| 1355 | + // Run any pre-setup ready functions |
| 1356 | + while( preMwEmbedReady.length ){ |
| 1357 | + preMwEmbedReady.shift()(); |
| 1358 | + } |
| 1359 | + // Run all the queued functions: |
| 1360 | + while( mwOnLoadFunctions.length ) { |
| 1361 | + mwOnLoadFunctions.shift()(); |
| 1362 | + } |
| 1363 | + |
| 1364 | + // Sets mwReadyFlag to true so that future mw.ready run the |
| 1365 | + // callback directly |
| 1366 | + mwReadyFlag = true; |
| 1367 | + |
| 1368 | + // Once we have run all the queued functions |
| 1369 | + mw.loader.runModuleLoadQueue(); |
| 1370 | + |
| 1371 | + }; |
| 1372 | + |
| 1373 | + |
| 1374 | + /** |
| 1375 | + * Wrapper for jQuery getScript, Uses the scriptLoader if enabled |
| 1376 | + * |
| 1377 | + * |
| 1378 | + * @param {String} |
| 1379 | + * scriptRequest The requested path or resourceNames for the |
| 1380 | + * scriptLoader |
| 1381 | + * @param {Function} |
| 1382 | + * callback Function to call once script is loaded |
| 1383 | + */ |
| 1384 | + mw.getScript = function( scriptRequest, callback ) { |
| 1385 | + // mw.log( "mw.getScript::" + scriptRequest ); |
| 1386 | + // Setup the local scope callback instace |
| 1387 | + var myCallback = function(){ |
| 1388 | + if( callback ) { |
| 1389 | + callback( scriptRequest ); |
| 1390 | + } |
| 1391 | + }; |
| 1392 | + // Set the base url based scriptLoader availability & type of |
| 1393 | + // scriptRequest |
| 1394 | + // ( presently script loader only handles "classes" not relative urls: |
| 1395 | + var scriptLoaderPath = mw.getResourceLoaderPath(); |
| 1396 | + |
| 1397 | + // Check if its a resource name, ( ie does not start with "/" and does |
| 1398 | + // not include :// |
| 1399 | + var isResourceName = ( scriptRequest.indexOf('://') == -1 && scriptRequest.indexOf('/') !== 0 )? true : false; |
| 1400 | + |
| 1401 | + var ext = scriptRequest.substr( scriptRequest.lastIndexOf( '.' ), 4 ).toLowerCase(); |
| 1402 | + var isCssFile = ( ext == '.css') ? true : false ; |
| 1403 | + |
| 1404 | + if( scriptLoaderPath && isResourceName ) { |
| 1405 | + url = scriptLoaderPath + '?class=' + scriptRequest ; |
| 1406 | + } else { |
| 1407 | + // Add the mwEmbed path if a relative path request |
| 1408 | + url = ( isResourceName ) ? mw.getMwEmbedPath() : ''; |
| 1409 | + url+= scriptRequest; |
| 1410 | + } |
| 1411 | + |
| 1412 | + // Add on the request parameters to the url: |
| 1413 | + url += ( url.indexOf( '?' ) == -1 )? '?' : '&'; |
| 1414 | + url += mw.getUrlParam(); |
| 1415 | + |
| 1416 | + // Only log sciprts ( Css is logged via "add css" ) |
| 1417 | + if( !isCssFile ){ |
| 1418 | + mw.log( 'mw.getScript: ' + url ); |
| 1419 | + } |
| 1420 | + |
| 1421 | + // If jQuery is available and debug is off load the script via jQuery |
| 1422 | + // ( will use XHR if on same domain ) |
| 1423 | + if( mw.isset( 'window.jQuery' ) |
| 1424 | + && mw.getConfig( 'debug' ) === false |
| 1425 | + && typeof $j != 'undefined' |
| 1426 | + && mw.parseUri( url ).protocal != 'file' |
| 1427 | + && !isCssFile ) |
| 1428 | + { |
| 1429 | + $j.getScript( url, myCallback); |
| 1430 | + return ; |
| 1431 | + } |
| 1432 | + |
| 1433 | + /** |
| 1434 | + * No jQuery OR In debug mode OR Is css file |
| 1435 | + * :: inject the script instead of doing an XHR eval |
| 1436 | + */ |
| 1437 | + |
| 1438 | + // load style sheet directly if requested loading css |
| 1439 | + if( isCssFile ){ |
| 1440 | + mw.getStyleSheet( url, myCallback); |
| 1441 | + return ; |
| 1442 | + } |
| 1443 | + |
| 1444 | + // Load and bind manually: ( copied from jQuery ajax function ) |
| 1445 | + var head = document.getElementsByTagName("head")[ 0 ]; |
| 1446 | + var script = document.createElement("script"); |
| 1447 | + script.setAttribute( 'src', url ); |
| 1448 | + |
| 1449 | + // Attach handlers ( if using script loader it issues onDone callback as |
| 1450 | + // well ) |
| 1451 | + script.onload = script.onreadystatechange = function() { |
| 1452 | + if (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") { |
| 1453 | + myCallback(); |
| 1454 | + } |
| 1455 | + }; |
| 1456 | + // mw.log(" append script: " + script.src ); |
| 1457 | + // Append the script to the DOM: |
| 1458 | + head.appendChild( script ); |
| 1459 | + }; |
| 1460 | + |
| 1461 | + /** |
| 1462 | + * Add a style sheet string to the document head |
| 1463 | + * |
| 1464 | + * @param {String} |
| 1465 | + * cssResourceName Name of style sheet that has been defined |
| 1466 | + * @param {String} |
| 1467 | + * cssString Css Payload to be added to head of document |
| 1468 | + */ |
| 1469 | + mw.addStyleString = function( cssResourceName, cssString ) { |
| 1470 | + if( mw.style[ cssResourceName ] ) { |
| 1471 | + mw.log(" Style: ( " + cssResourceName + ' ) already set' ); |
| 1472 | + return true; |
| 1473 | + } |
| 1474 | + // Set the style to true ( to not request it again ) |
| 1475 | + mw.style[ cssResourceName ] = true; |
| 1476 | + // Add the spinner directly ( without jQuery in case we have to |
| 1477 | + // dynamically load jQuery ) |
| 1478 | + mw.log( 'Adding style:' + cssResourceName + " to dom " ); |
| 1479 | + var styleNode = document.createElement('style'); |
| 1480 | + styleNode.type = "text/css"; |
| 1481 | + // Use cssText or createTextNode depending on browser: |
| 1482 | + if( ( window.attachEvent && !window.opera ) ) { |
| 1483 | + styleNode.styleSheet.cssText = cssString; |
| 1484 | + } else { |
| 1485 | + var styleText = document.createTextNode( cssString ); |
| 1486 | + styleNode.appendChild( styleText ); |
| 1487 | + } |
| 1488 | + var head = document.getElementsByTagName("head")[0]; |
| 1489 | + head.appendChild( styleNode ); |
| 1490 | + }; |
| 1491 | + |
| 1492 | + /** |
| 1493 | + * Get a style sheet and append the style sheet to the DOM |
| 1494 | + * |
| 1495 | + * @param {Mixed} |
| 1496 | + * {String} url Url of the style sheet to be loaded {Function} |
| 1497 | + * callback Function called once sheet is ready |
| 1498 | + */ |
| 1499 | + mw.getStyleSheet = function( url , callback) { |
| 1500 | + // Add URL params ( if not already included ) |
| 1501 | + if ( url.indexOf( '?' ) == -1 ) { |
| 1502 | + url += '?' + mw.getUrlParam(); |
| 1503 | + } |
| 1504 | + |
| 1505 | + // Check if style sheet is already included: |
| 1506 | + var foundSheet = false; |
| 1507 | + $j( 'link' ).each( function() { |
| 1508 | + var currentSheet = $j( this) .attr( 'href' ); |
| 1509 | + var sheetParts = currentSheet.split('?'); |
| 1510 | + var urlParts = url.split('?'); |
| 1511 | + // if the base url's match check the parameters: |
| 1512 | + if( sheetParts[0] == urlParts[0] && sheetParts[1]) { |
| 1513 | + // Check if url params match ( sort to do string compare ) |
| 1514 | + if( sheetParts[1].split( '&' ).sort().join('') == |
| 1515 | + urlParts[1].split('&').sort().join('') ) { |
| 1516 | + foundSheet = true; |
| 1517 | + } |
| 1518 | + } |
| 1519 | + } ); |
| 1520 | + if( foundSheet ) { |
| 1521 | + mw.log( 'skiped sheet: ' + url); |
| 1522 | + if( callback) { |
| 1523 | + callback(); |
| 1524 | + } |
| 1525 | + return ; |
| 1526 | + } |
| 1527 | + |
| 1528 | + mw.log( ' add css: ' + url ); |
| 1529 | + $j( 'head' ).append( |
| 1530 | + $j('<link />').attr( { |
| 1531 | + 'rel' : 'stylesheet', |
| 1532 | + 'type' : 'text/css', |
| 1533 | + 'href' : url |
| 1534 | + } ) |
| 1535 | + ); |
| 1536 | + // No easy way to check css "onLoad" attribute |
| 1537 | + // In production sheets are loaded via resource loader and fire the |
| 1538 | + // onDone function call. |
| 1539 | + if( callback ) { |
| 1540 | + callback(); |
| 1541 | + } |
| 1542 | + }; |
| 1543 | + |
| 1544 | + mw.getRelativeMwEmbedPath = function(){ |
| 1545 | + return mw.getMwEmbedPath(true); |
| 1546 | + }; |
| 1547 | + /** |
| 1548 | + * Get the path to the mwEmbed folder |
| 1549 | + */ |
| 1550 | + mw.getMwEmbedPath = function( relativePath ) { |
| 1551 | + // Get mwEmbed src: |
| 1552 | + var src = mw.getMwEmbedSrc(); |
| 1553 | + var mwpath = null; |
| 1554 | + |
| 1555 | + // Check for direct include of the mwEmbed.js |
| 1556 | + if ( src.indexOf( 'mwEmbed.js' ) !== -1 ) { |
| 1557 | + mwpath = src.substr( 0, src.indexOf( 'mwEmbed.js' ) ); |
| 1558 | + } |
| 1559 | + |
| 1560 | + // Check for scriptLoader include of mwEmbed: |
| 1561 | + if ( src.indexOf( 'mwResourceLoader.php' ) !== -1 ) { |
| 1562 | + // Script loader is in the root of MediaWiki, Include the default |
| 1563 | + // mwEmbed extension path: |
| 1564 | + mwpath = src.substr( 0, src.indexOf( 'mwResourceLoader.php' ) ) + mw.getConfig( 'mediaWikiEmbedPath' ); |
| 1565 | + } |
| 1566 | + |
| 1567 | + // resource loader has ResourceLoader name when local: |
| 1568 | + if( src.indexOf( 'ResourceLoader.php' ) !== -1 ) { |
| 1569 | + mwpath = src.substr( 0, src.indexOf( 'ResourceLoader.php' ) ); |
| 1570 | + } |
| 1571 | + |
| 1572 | + // For static packages mwEmbed packages start with: "mwEmbed-" |
| 1573 | + if( src.indexOf( 'mwEmbed-' ) !== -1 && src.indexOf( '-static' ) !== -1 ) { |
| 1574 | + mwpath = src.substr( 0, src.indexOf( 'mwEmbed-' ) ); |
| 1575 | + } |
| 1576 | + |
| 1577 | + // Error out if we could not get the path: |
| 1578 | + if( mwpath === null ) { |
| 1579 | + mw.log( "Error could not get mwEmbed path " ); |
| 1580 | + return ; |
| 1581 | + } |
| 1582 | + |
| 1583 | + // Update the cached var with the absolute path: |
| 1584 | + if( !relativePath ){ |
| 1585 | + mwpath = mw.absoluteUrl( mwpath ) ; |
| 1586 | + } |
| 1587 | + return mwpath; |
| 1588 | + }; |
| 1589 | + |
| 1590 | + /** |
| 1591 | + * Get Script loader path |
| 1592 | + * |
| 1593 | + * @returns {String}|{Boolean} Url of the scriptLodaer false if the |
| 1594 | + * scriptLoader is not used |
| 1595 | + */ |
| 1596 | + mw.getResourceLoaderPath = function( ) { |
| 1597 | + var src = mw.getMwEmbedSrc(); |
| 1598 | + if ( src.indexOf( 'mwResourceLoader.php' ) !== -1 || |
| 1599 | + src.indexOf( 'ResourceLoader.php' ) !== -1 ) |
| 1600 | + { |
| 1601 | + // Return just the script part of the url |
| 1602 | + return src.split('?')[0]; |
| 1603 | + } |
| 1604 | + return false; |
| 1605 | + }; |
| 1606 | + |
| 1607 | + /** |
| 1608 | + * Given a float number of seconds, returns npt format response. ( ignore |
| 1609 | + * days for now ) |
| 1610 | + * |
| 1611 | + * @param {Float} |
| 1612 | + * sec Seconds |
| 1613 | + * @param {Boolean} |
| 1614 | + * verbose If hours and milliseconds should padded be displayed. |
| 1615 | + * @return {Float} String npt format |
| 1616 | + */ |
| 1617 | + mw.seconds2npt = function( sec, verbose ) { |
| 1618 | + if ( isNaN( sec ) ) { |
| 1619 | + mw.log("Warning: trying to get npt time on NaN:" + sec); |
| 1620 | + return '0:00:00'; |
| 1621 | + } |
| 1622 | + |
| 1623 | + var tm = mw.seconds2Measurements( sec ); |
| 1624 | + |
| 1625 | + // Round the number of seconds to the required number of significant |
| 1626 | + // digits |
| 1627 | + if ( verbose ) { |
| 1628 | + tm.seconds = Math.round( tm.seconds * 1000 ) / 1000; |
| 1629 | + } else { |
| 1630 | + tm.seconds = Math.round( tm.seconds ); |
| 1631 | + } |
| 1632 | + if ( tm.seconds < 10 ){ |
| 1633 | + tm.seconds = '0' + tm.seconds; |
| 1634 | + } |
| 1635 | + if( tm.hours == 0 && !verbose ){ |
| 1636 | + hoursStr = ''; |
| 1637 | + } else { |
| 1638 | + if ( tm.minutes < 10 && verbose) { |
| 1639 | + tm.minutes = '0' + tm.minutes; |
| 1640 | + } |
| 1641 | + |
| 1642 | + if( tm.hours < 10 && verbose){ |
| 1643 | + tm.hours = '0' + tm.hours; |
| 1644 | + } |
| 1645 | + |
| 1646 | + hoursStr = tm.hours + ':'; |
| 1647 | + } |
| 1648 | + return hoursStr + tm.minutes + ":" + tm.seconds; |
| 1649 | + }; |
| 1650 | + |
| 1651 | + /** |
| 1652 | + * Given seconds return array with 'days', 'hours', 'min', 'seconds' |
| 1653 | + * |
| 1654 | + * @param {float} |
| 1655 | + * sec Seconds to be converted into time measurements |
| 1656 | + */ |
| 1657 | + mw.seconds2Measurements = function ( sec ){ |
| 1658 | + var tm = {}; |
| 1659 | + tm.days = Math.floor( sec / ( 3600 * 24 ) ); |
| 1660 | + tm.hours = Math.floor( sec / 3600 ); |
| 1661 | + tm.minutes = Math.floor( ( sec / 60 ) % 60 ); |
| 1662 | + tm.seconds = sec % 60; |
| 1663 | + return tm; |
| 1664 | + }; |
| 1665 | + |
| 1666 | + /** |
| 1667 | + * Take hh:mm:ss,ms or hh:mm:ss.ms input, return the number of seconds |
| 1668 | + * |
| 1669 | + * @param {String} |
| 1670 | + * npt_str NPT time string |
| 1671 | + * @return {Float} Number of seconds |
| 1672 | + */ |
| 1673 | + mw.npt2seconds = function ( npt_str ) { |
| 1674 | + if ( !npt_str ) { |
| 1675 | + // mw.log('npt2seconds:not valid ntp:'+ntp); |
| 1676 | + return false; |
| 1677 | + } |
| 1678 | + // Strip {npt:}01:02:20 or 32{s} from time if present |
| 1679 | + npt_str = npt_str.replace( /npt:|s/g, '' ); |
| 1680 | + |
| 1681 | + var hour = 0; |
| 1682 | + var min = 0; |
| 1683 | + var sec = 0; |
| 1684 | + |
| 1685 | + times = npt_str.split( ':' ); |
| 1686 | + if ( times.length == 3 ) { |
| 1687 | + sec = times[2]; |
| 1688 | + min = times[1]; |
| 1689 | + hour = times[0]; |
| 1690 | + } else if ( times.length == 2 ) { |
| 1691 | + sec = times[1]; |
| 1692 | + min = times[0]; |
| 1693 | + } else { |
| 1694 | + sec = times[0]; |
| 1695 | + } |
| 1696 | + // Sometimes a comma is used instead of period for ms |
| 1697 | + sec = sec.replace( /,\s?/, '.' ); |
| 1698 | + // Return seconds float |
| 1699 | + return parseInt( hour * 3600 ) + parseInt( min * 60 ) + parseFloat( sec ); |
| 1700 | + }; |
| 1701 | + |
| 1702 | + // Local mwEmbedSrc variable ( for cache of mw.getMwEmbedSrc ) |
| 1703 | + var mwEmbedSrc = null; |
| 1704 | + |
| 1705 | + /** |
| 1706 | + * Gets the mwEmbed script src attribute |
| 1707 | + */ |
| 1708 | + mw.getMwEmbedSrc = function() { |
| 1709 | + if ( mwEmbedSrc ) { |
| 1710 | + return mwEmbedSrc; |
| 1711 | + } |
| 1712 | + |
| 1713 | + // Get all the javascript includes: |
| 1714 | + var js_elements = document.getElementsByTagName( "script" ); |
| 1715 | + for ( var i = 0; i < js_elements.length; i++ ) { |
| 1716 | + // Check for mwEmbed.js and/or script loader |
| 1717 | + var src = js_elements[i].getAttribute( "src" ); |
| 1718 | + if ( src ) { |
| 1719 | + if ( // Check for mwEmbed.js ( debug mode ) |
| 1720 | + ( src.indexOf( 'mwEmbed.js' ) !== -1 && src.indexOf( 'MediaWiki:Gadget') == -1 ) |
| 1721 | + || // Check for resource loader |
| 1722 | + ( |
| 1723 | + ( src.indexOf( 'mwResourceLoader.php' ) !== -1 || src.indexOf( 'ResourceLoader.php' ) !== -1 ) |
| 1724 | + && |
| 1725 | + src.indexOf( 'mwEmbed' ) !== -1 |
| 1726 | + ) |
| 1727 | + || // Check for static mwEmbed package |
| 1728 | + ( src.indexOf( 'mwEmbed' ) !== -1 && src.indexOf( 'static' ) !== -1 ) |
| 1729 | + ) { |
| 1730 | + mwEmbedSrc = src; |
| 1731 | + return mwEmbedSrc; |
| 1732 | + } |
| 1733 | + } |
| 1734 | + } |
| 1735 | + mw.log( 'Error: getMwEmbedSrc failed to get script path' ); |
| 1736 | + return false; |
| 1737 | + }; |
| 1738 | + |
| 1739 | + // Local mwUrlParam variable ( for cache of mw.getUrlParam ) |
| 1740 | + var mwUrlParam = null; |
| 1741 | + |
| 1742 | + /** |
| 1743 | + * Get URL Parameters per parameters in the host script include |
| 1744 | + */ |
| 1745 | + mw.getUrlParam = function() { |
| 1746 | + if ( mwUrlParam ) { |
| 1747 | + return mwUrlParam; |
| 1748 | + } |
| 1749 | + |
| 1750 | + var mwEmbedSrc = mw.getMwEmbedSrc(); |
| 1751 | + var req_param = ''; |
| 1752 | + |
| 1753 | + // If we already have a URI, add it to the param request: |
| 1754 | + var urid = mw.parseUri( mwEmbedSrc ).queryKey['urid']; |
| 1755 | + |
| 1756 | + // If we're in debug mode, get a fresh unique request key and pass on |
| 1757 | + // "debug" param |
| 1758 | + if ( mw.parseUri( mwEmbedSrc ).queryKey['debug'] == 'true' ) { |
| 1759 | + mw.setConfig( 'debug', true ); |
| 1760 | + var d = new Date(); |
| 1761 | + req_param += 'urid=' + d.getTime() + '&debug=true'; |
| 1762 | + |
| 1763 | + } else if ( urid ) { |
| 1764 | + // Just pass on the existing urid: |
| 1765 | + req_param += 'urid=' + urid; |
| 1766 | + } else { |
| 1767 | + // Otherwise, Use the mwEmbed version |
| 1768 | + req_param += 'urid=' + mw.version; |
| 1769 | + } |
| 1770 | + |
| 1771 | + // Add the language param if present: |
| 1772 | + var langKey = mw.parseUri( mwEmbedSrc ).queryKey['uselang']; |
| 1773 | + if ( langKey ) |
| 1774 | + req_param += '&uselang=' + langKey; |
| 1775 | + |
| 1776 | + // Update the local cache and return the value |
| 1777 | + mwUrlParam = req_param; |
| 1778 | + return mwUrlParam; |
| 1779 | + }; |
| 1780 | + |
| 1781 | + /** |
| 1782 | + * Replace url parameters via newParams key value pairs |
| 1783 | + * |
| 1784 | + * @param {String} |
| 1785 | + * url Source url to be updated |
| 1786 | + * @param {Object} |
| 1787 | + * newParams key, value paris to swap in |
| 1788 | + * @return {String} the updated url |
| 1789 | + */ |
| 1790 | + mw.replaceUrlParams = function( url, newParams ) { |
| 1791 | + var parsedUrl = mw.parseUri( url ); |
| 1792 | + |
| 1793 | + if ( parsedUrl.protocol != '' ) { |
| 1794 | + var new_url = parsedUrl.protocol + '://' + parsedUrl.authority + parsedUrl.path + '?'; |
| 1795 | + } else { |
| 1796 | + var new_url = parsedUrl.path + '?'; |
| 1797 | + } |
| 1798 | + |
| 1799 | + // Merge new params: |
| 1800 | + for( var key in newParams ) { |
| 1801 | + parsedUrl.queryKey[ key ] = newParams[ key ]; |
| 1802 | + } |
| 1803 | + |
| 1804 | + // Output to new_url |
| 1805 | + var amp = ''; |
| 1806 | + for ( var key in parsedUrl.queryKey ) { |
| 1807 | + var val = parsedUrl.queryKey[ key ]; |
| 1808 | + new_url += amp + key + '=' + val; |
| 1809 | + amp = '&'; |
| 1810 | + } |
| 1811 | + return new_url; |
| 1812 | + }; |
| 1813 | + |
| 1814 | + /** |
| 1815 | + * parseUri 1.2.2 (c) Steven Levithan <stevenlevithan.com> MIT License |
| 1816 | + */ |
| 1817 | + mw.parseUri = function (str) { |
| 1818 | + var o = mw.parseUri.options, |
| 1819 | + m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), |
| 1820 | + uri = {}, |
| 1821 | + i = 14; |
| 1822 | + |
| 1823 | + while (i--) uri[o.key[i]] = m[i] || ""; |
| 1824 | + |
| 1825 | + uri[o.q.name] = {}; |
| 1826 | + uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { |
| 1827 | + if ($1) uri[o.q.name][$1] = $2; |
| 1828 | + }); |
| 1829 | + |
| 1830 | + return uri; |
| 1831 | + }; |
| 1832 | + |
| 1833 | + /** |
| 1834 | + * Parse URI function |
| 1835 | + * |
| 1836 | + * For documentation on its usage see: |
| 1837 | + * http://stevenlevithan.com/demo/parseuri/js/ |
| 1838 | + */ |
| 1839 | + mw.parseUri.options = { |
| 1840 | + strictMode: false, |
| 1841 | + key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", |
| 1842 | + "port", "relative", "path", "directory", "file", "query", "anchor"], |
| 1843 | + q: { |
| 1844 | + name: "queryKey", |
| 1845 | + parser: /(?:^|&)([^&=]*)=?([^&]*)/g |
| 1846 | + }, |
| 1847 | + parser: { |
| 1848 | + strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, |
| 1849 | + loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ |
| 1850 | + } |
| 1851 | + }; |
| 1852 | + |
| 1853 | + /** |
| 1854 | + * getAbsoluteUrl takes a src and returns the absolute location given the |
| 1855 | + * document.URL or a contextUrl param |
| 1856 | + * |
| 1857 | + * @param {String} src path or url |
| 1858 | + * @param {String} contextUrl The domain / context for creating an absolute url |
| 1859 | + * from a relative path |
| 1860 | + * @return {String} absolute url |
| 1861 | + */ |
| 1862 | +mw.absoluteUrl = function( src, contextUrl ) { |
| 1863 | + |
| 1864 | + var parsedSrc = mw.parseUri( src ); |
| 1865 | + |
| 1866 | + // Source is already absolute return: |
| 1867 | + if( parsedSrc.protocol != '') { |
| 1868 | + return src; |
| 1869 | + } |
| 1870 | + |
| 1871 | + // Get parent Url location the context URL |
| 1872 | + if( !contextUrl ) { |
| 1873 | + contextUrl = document.URL; |
| 1874 | + } |
| 1875 | + var parsedUrl = mw.parseUri( contextUrl ); |
| 1876 | + |
| 1877 | + // Check for IE local file that does not flip the slashes |
| 1878 | + if( parsedUrl.directory == '' && parsedUrl.protocol == 'file' ){ |
| 1879 | + // pop off the file |
| 1880 | + var fileUrl = contextUrl.split( '\\'); |
| 1881 | + fileUrl.pop(); |
| 1882 | + return fileUrl.join('\\') + '\\' + src; |
| 1883 | + } |
| 1884 | + |
| 1885 | + // Check for leading slash: |
| 1886 | + if( src.indexOf( '/' ) === 0 ) { |
| 1887 | + return parsedUrl.protocol + '://' + parsedUrl.authority + src; |
| 1888 | + }else{ |
| 1889 | + return parsedUrl.protocol + '://' + parsedUrl.authority + parsedUrl.directory + src; |
| 1890 | + } |
| 1891 | + }; |
| 1892 | + /** |
| 1893 | + * Check if a given source string is likely a url |
| 1894 | + * |
| 1895 | + * @return {boolean} |
| 1896 | + * true if a url |
| 1897 | + * false if a string |
| 1898 | + */ |
| 1899 | + mw.isUrl = function( src ){ |
| 1900 | + var parsedSrc = mw.parseUri( src ); |
| 1901 | + // if the url is just a string source and host will match |
| 1902 | + return ( parsedSrc.host != parsedSrc.source ); |
| 1903 | + }; |
| 1904 | + |
| 1905 | + /** |
| 1906 | + * Escape quotes in a text string |
| 1907 | + * |
| 1908 | + * @param {String} |
| 1909 | + * text String to be escaped |
| 1910 | + * @return {string} escaped text string |
| 1911 | + */ |
| 1912 | + mw.escapeQuotes = function( text ) { |
| 1913 | + var re = new RegExp("'","g"); |
| 1914 | + text = text.replace(re,"\\'"); |
| 1915 | + re = new RegExp("\\n","g"); |
| 1916 | + text = text.replace(re,"\\n"); |
| 1917 | + return mw.escapeQuotesHTML(text); |
| 1918 | + }; |
| 1919 | + |
| 1920 | + /** |
| 1921 | + * Escape an HTML text string |
| 1922 | + * |
| 1923 | + * @param {String} |
| 1924 | + * text String to be escaped |
| 1925 | + * @return {string} escaped text html string |
| 1926 | + */ |
| 1927 | + mw.escapeQuotesHTML = function( text ) { |
| 1928 | + var replaceMap = { |
| 1929 | + "&" : "&", |
| 1930 | + '"' : """, |
| 1931 | + '<' : "<", |
| 1932 | + '>' : ">" |
| 1933 | + }; |
| 1934 | + for( var i in replaceMap ){ |
| 1935 | + text = text.split(i).join( replaceMap[i]); |
| 1936 | + } |
| 1937 | + return text; |
| 1938 | + }; |
| 1939 | + |
| 1940 | + |
| 1941 | + // Array of setup functions |
| 1942 | + var mwSetupFunctions = []; |
| 1943 | + |
| 1944 | + /** |
| 1945 | + * Add a function to be run during setup ( prior to mw.ready) this is useful |
| 1946 | + * for building out interfaces that should be ready before mw.ready is |
| 1947 | + * called. |
| 1948 | + * |
| 1949 | + * @param {callback} |
| 1950 | + * Function Callback function must accept a ready function |
| 1951 | + * callback to be called once setup is done |
| 1952 | + */ |
| 1953 | + mw.addSetupHook = function( callback ) { |
| 1954 | + mwSetupFunctions.push ( callback ) ; |
| 1955 | + }; |
| 1956 | + |
| 1957 | + /** |
| 1958 | + * One time "setup" for mwEmbed run onDomReady ( so calls to setConfg apply |
| 1959 | + * to setup ) |
| 1960 | + */ |
| 1961 | + // Flag to ensure setup is only run once: |
| 1962 | + var mwSetupFlag = false; |
| 1963 | + mw.setupMwEmbed = function ( ) { |
| 1964 | + // Only run the setup once: |
| 1965 | + if( mwSetupFlag ) { |
| 1966 | + return ; |
| 1967 | + } |
| 1968 | + mwSetupFlag = true; |
| 1969 | + |
| 1970 | + // Apply any pre-setup config: |
| 1971 | + mw.setConfig( preMwEmbedConfig ); |
| 1972 | + |
| 1973 | + |
| 1974 | + mw.log( 'mw:setupMwEmbed SRC:: ' + mw.getMwEmbedSrc() ); |
| 1975 | + |
| 1976 | + // Check core mwEmbed loader.js file ( to get configuration and paths ) |
| 1977 | + mw.checkCoreLoaderFile( function(){ |
| 1978 | + // Make sure we have jQuery |
| 1979 | + mw.load( 'window.jQuery', function() { |
| 1980 | + |
| 1981 | + // Add jQuery to $j var. |
| 1982 | + if ( ! window[ '$j' ] ) { |
| 1983 | + window[ '$j' ] = jQuery.noConflict(); |
| 1984 | + } |
| 1985 | + // Setup user config: |
| 1986 | + mw.setupUserConfig( function(){ |
| 1987 | + // Get module loader.js, and language files |
| 1988 | + // ( will hit callback directly if set via resource loader ) |
| 1989 | + mw.checkModuleLoaderFiles( function() { |
| 1990 | + |
| 1991 | + // Set the User language |
| 1992 | + if( typeof wgUserLanguage != 'undefined' && mw.isValidLang( wgUserLanguage) ) { |
| 1993 | + mw.setConfig( 'userLanguage', wgUserLanguage ); |
| 1994 | + }else{ |
| 1995 | + // Grab it from the included url |
| 1996 | + var langKey = mw.parseUri( mw.getMwEmbedSrc() ).queryKey['uselang']; |
| 1997 | + if ( langKey && mw.isValidLang( langKey ) ) { |
| 1998 | + mw.setConfig( 'userLanguage', langKey); |
| 1999 | + } |
| 2000 | + } |
| 2001 | + |
| 2002 | + // Update the image path |
| 2003 | + mw.setConfig( 'imagesPath', mw.getMwEmbedPath() + 'skins/common/images/' ); |
| 2004 | + |
| 2005 | + // Set up AJAX to not send dynamic URLs for loading scripts |
| 2006 | + $j.ajaxSetup( { |
| 2007 | + cache: true |
| 2008 | + } ); |
| 2009 | + |
| 2010 | + // Update the magic keywords |
| 2011 | + mw.Language.magicSetup(); |
| 2012 | + |
| 2013 | + // Set up mvEmbed utility jQuery bindings |
| 2014 | + mw.dojQueryBindings(); |
| 2015 | + |
| 2016 | + |
| 2017 | + // Special Hack for conditional jquery ui inclusion ( once |
| 2018 | + // Usability extension |
| 2019 | + // registers the jquery.ui skin in mw.style |
| 2020 | + if( mw.hasJQueryUiCss() ){ |
| 2021 | + mw.style[ 'ui_' + mw.getConfig( 'jQueryUISkin' ) ] = true; |
| 2022 | + } |
| 2023 | + |
| 2024 | + |
| 2025 | + // Make sure style sheets are loaded: |
| 2026 | + mw.load( ['mw.style.mwCommon'] , function(){ |
| 2027 | + // Run all the setup function hooks |
| 2028 | + // NOTE: setup functions are added via addSetupHook |
| 2029 | + // calls |
| 2030 | + // and must include a callback. |
| 2031 | + // |
| 2032 | + // Once complete we can run .ready() queued functions |
| 2033 | + function runSetupFunctions() { |
| 2034 | + if( mwSetupFunctions.length ) { |
| 2035 | + mwSetupFunctions.shift()( function() { |
| 2036 | + runSetupFunctions(); |
| 2037 | + } ); |
| 2038 | + }else{ |
| 2039 | + mw.runReadyFunctions(); |
| 2040 | + } |
| 2041 | + } |
| 2042 | + runSetupFunctions(); |
| 2043 | + } ); |
| 2044 | + |
| 2045 | + } ); |
| 2046 | + }); |
| 2047 | + }); |
| 2048 | + }); |
| 2049 | + }; |
| 2050 | + |
| 2051 | + /** |
| 2052 | + * Checks for jquery ui css by name jquery-ui-1.7.2.css NOTE: this is a hack |
| 2053 | + * for usability jquery-ui in the future usability should register a |
| 2054 | + * resource in mw.skin |
| 2055 | + * |
| 2056 | + * @return true if found, return false if not found |
| 2057 | + */ |
| 2058 | + mw.hasJQueryUiCss = function(){ |
| 2059 | + var hasUiCss = false; |
| 2060 | + var cssStyleSheetNames = ['jquery-ui-1.7.2.css', 'jquery-ui.css']; |
| 2061 | + // Load the jQuery ui skin if usability skin not set |
| 2062 | + $j( 'link' ).each( function( na, linkNode ){ |
| 2063 | + $j.each( cssStyleSheetNames, function(inx, sheetName ){ |
| 2064 | + if( $j( linkNode ).attr( 'href' ).indexOf( sheetName ) != -1 ){ |
| 2065 | + hasUiCss = true; |
| 2066 | + return true; |
| 2067 | + } |
| 2068 | + }); |
| 2069 | + } ); |
| 2070 | + // Check all the "style" nodes for @import for sheet name |
| 2071 | + // xxx Note: we could do this a bit cleaner with regEx |
| 2072 | + $j( 'style' ).each( function( na, styleNode ){ |
| 2073 | + $j.each( cssStyleSheetNames, function(inx, sheetName ){ |
| 2074 | + if( $j( styleNode ).text().indexOf( '@import' ) != -1 |
| 2075 | + && |
| 2076 | + $j( styleNode ).text().indexOf( sheetName ) != -1 ) |
| 2077 | + { |
| 2078 | + hasUiCss=true; |
| 2079 | + return true; |
| 2080 | + } |
| 2081 | + }); |
| 2082 | + }); |
| 2083 | + return hasUiCss; |
| 2084 | + }; |
| 2085 | + |
| 2086 | + /** |
| 2087 | + * Loads the core mwEmbed "loader.js" file config |
| 2088 | + * |
| 2089 | + * NOTE: if using the ScriptLoader all the loaders and localization |
| 2090 | + * converters are included automatically |
| 2091 | + * |
| 2092 | + * @param {Function} |
| 2093 | + * callback Function called once core loader file is loaded |
| 2094 | + */ |
| 2095 | + mw.checkCoreLoaderFile = function( callback ) { |
| 2096 | + // Check if we are using scriptloader ( handles loader include |
| 2097 | + // automatically ) |
| 2098 | + if( mw.getResourceLoaderPath() ) { |
| 2099 | + callback(); |
| 2100 | + return ; |
| 2101 | + } |
| 2102 | + |
| 2103 | + // Check if we are using a static package ( mwEmbed path includes |
| 2104 | + // -static ) |
| 2105 | + if( mw.isStaticPackge() ){ |
| 2106 | + callback(); |
| 2107 | + return ; |
| 2108 | + } |
| 2109 | + |
| 2110 | + // Add the Core loader to the request |
| 2111 | + // The follow code is ONLY RUN in debug / raw file mode |
| 2112 | + mw.load( 'loader.js', callback ); |
| 2113 | + }; |
| 2114 | + |
| 2115 | + /** |
| 2116 | + * Checks if the javascript is a static package ( not using resource loader ) |
| 2117 | + * |
| 2118 | + * @return {boolean} true the included script is static false the included |
| 2119 | + * script |
| 2120 | + */ |
| 2121 | + mw.isStaticPackge = function(){ |
| 2122 | + var src = mw.getMwEmbedSrc(); |
| 2123 | + if( src.indexOf('-static') !== -1 ){ |
| 2124 | + return true; |
| 2125 | + } |
| 2126 | + return false; |
| 2127 | + }; |
| 2128 | + |
| 2129 | + /** |
| 2130 | + * Check for resource loader module loaders, and localization files |
| 2131 | + * |
| 2132 | + * NOTE: if using the ScriptLoader all the loaders and localization |
| 2133 | + * converters are included automatically. |
| 2134 | + */ |
| 2135 | + mw.checkModuleLoaderFiles = function( callback ) { |
| 2136 | + mw.log( 'doLoaderCheck::' ); |
| 2137 | + |
| 2138 | + // Check if we are using scriptloader ( handles loader include |
| 2139 | + // automatically ) |
| 2140 | + // Or if mwEmbed is a static package ( all resources are already loaded |
| 2141 | + // ) |
| 2142 | + if( mw.getResourceLoaderPath() || mw.isStaticPackge() ) { |
| 2143 | + callback(); |
| 2144 | + return ; |
| 2145 | + } |
| 2146 | + |
| 2147 | + // Load the configured modules / components |
| 2148 | + // The follow code is ONLY RUN in debug / raw file mode |
| 2149 | + var loaderRequest = []; |
| 2150 | + |
| 2151 | + // Load enabled components |
| 2152 | + var enabledComponents = mw.getConfig( 'coreComponents' ); |
| 2153 | + function loadEnabledComponents( enabledComponents ){ |
| 2154 | + if( ! enabledComponents.length ){ |
| 2155 | + // If no more components load modules:: |
| 2156 | + |
| 2157 | + // Add the enabledModules loaders: |
| 2158 | + var enabledModules = mw.getConfig( 'enabledModules' ); |
| 2159 | + loadEnabledModules( enabledModules ); |
| 2160 | + return ; |
| 2161 | + } |
| 2162 | + var componentName = enabledComponents.shift(); |
| 2163 | + mw.load( componentName, function(){ |
| 2164 | + loadEnabledComponents( enabledComponents ); |
| 2165 | + } ); |
| 2166 | + } |
| 2167 | + loadEnabledComponents( enabledComponents ); |
| 2168 | + |
| 2169 | + |
| 2170 | + // Set the loader context and get each loader individually |
| 2171 | + function loadEnabledModules( enabledModules ){ |
| 2172 | + if( ! enabledModules.length ){ |
| 2173 | + // If no more modules left load the LanguageFile |
| 2174 | + addLanguageFile(); |
| 2175 | + return ; |
| 2176 | + } |
| 2177 | + var moduleName = enabledModules.shift(); |
| 2178 | + mw.setConfig( 'loaderContext', 'modules/' + moduleName + '/' ); |
| 2179 | + mw.load( 'modules/' + moduleName + '/loader.js', function(){ |
| 2180 | + loadEnabledModules( enabledModules ); |
| 2181 | + } ); |
| 2182 | + } |
| 2183 | + |
| 2184 | + function addLanguageFile(){ |
| 2185 | + // Add the language file |
| 2186 | + var langLoaderRequest = []; |
| 2187 | + |
| 2188 | + if( mw.getConfig( 'userLanguage' ) ) { |
| 2189 | + var langCode = mw.getConfig( 'userLanguage' ); |
| 2190 | + |
| 2191 | + // Load the language resource if not default 'en' |
| 2192 | + var transformKey = mw.getLangTransformKey( langCode ); |
| 2193 | + if( transformKey != 'en' ){ |
| 2194 | + // Upper case the first letter: |
| 2195 | + langCode = langCode.substr(0,1).toUpperCase() + langCode.substr( 1, langCode.length ); |
| 2196 | + langLoaderRequest.push( 'languages/classes/Language' + |
| 2197 | + langCode + '.js' ); |
| 2198 | + } |
| 2199 | + |
| 2200 | + } |
| 2201 | + if ( ! langLoaderRequest.length ) { |
| 2202 | + addLocalSettings(); |
| 2203 | + return ; |
| 2204 | + } |
| 2205 | + |
| 2206 | + // Load the language if set |
| 2207 | + mw.load( langLoaderRequest, function(){ |
| 2208 | + mw.log( 'Done moduleLoaderCheck request' ); |
| 2209 | + addLocalSettings(); |
| 2210 | + } ); |
| 2211 | + } |
| 2212 | + function addLocalSettings(){ |
| 2213 | + var continueCallback = function(){ |
| 2214 | + // Set the mwModuleLoaderCheckFlag flag to true |
| 2215 | + mwModuleLoaderCheckFlag = true; |
| 2216 | + callback(); |
| 2217 | + }; |
| 2218 | + if( mw.getConfig( 'LoadLocalSettings') != true ){ |
| 2219 | + continueCallback(); |
| 2220 | + return; |
| 2221 | + } |
| 2222 | + mw.log("Load loacal settings"); |
| 2223 | + mw.load( 'localSettings.js', function(){ |
| 2224 | + continueCallback(); |
| 2225 | + }); |
| 2226 | + } |
| 2227 | + |
| 2228 | + }; |
| 2229 | + |
| 2230 | + /** |
| 2231 | + * Checks if a css style rule exists |
| 2232 | + * |
| 2233 | + * On a page with lots of rules it can take some time so avoid calling this |
| 2234 | + * function where possible and cache its result |
| 2235 | + * |
| 2236 | + * NOTE: this only works for style sheets on the same domain :( |
| 2237 | + * |
| 2238 | + * @param {String} |
| 2239 | + * styleRule Style rule name to check |
| 2240 | + * @return {Boolean} true if the rule exists false if the rule does not |
| 2241 | + * exist |
| 2242 | + */ |
| 2243 | + mw.styleRuleExists = function ( styleRule ) { |
| 2244 | + // Set up the skin paths configuration |
| 2245 | + for( var i=0 ; i < document.styleSheets.length ; i++ ) { |
| 2246 | + var rules = null; |
| 2247 | + try{ |
| 2248 | + if ( document.styleSheets[i].cssRules ) |
| 2249 | + rules = document.styleSheets[i].cssRules; |
| 2250 | + else if (document.styleSheets[0].rules) |
| 2251 | + rules = document.styleSheets[i].rules; |
| 2252 | + for(var j=0 ; j < rules.length ; j++ ) { |
| 2253 | + var rule = rules[j].selectorText; |
| 2254 | + if( rule && rule.indexOf( styleRule ) != -1 ) { |
| 2255 | + return true; |
| 2256 | + } |
| 2257 | + } |
| 2258 | + }catch ( e ) { |
| 2259 | + mw.log( 'Error: cant check rule on cross domain style sheet:' + document.styleSheets[i].href ); |
| 2260 | + } |
| 2261 | + } |
| 2262 | + return false; |
| 2263 | + }; |
| 2264 | + |
| 2265 | + // Flag to register the domReady has been called |
| 2266 | + var mwDomReadyFlag = false; |
| 2267 | + |
| 2268 | + // Flag to register if the domreadyHooks have been called |
| 2269 | + var mwModuleLoaderCheckFlag = false; |
| 2270 | + |
| 2271 | + /** |
| 2272 | + * This will get called when the DOM is ready Will check configuration and |
| 2273 | + * issue a mw.setupMwEmbed call if needed |
| 2274 | + */ |
| 2275 | + mw.domReady = function ( ) { |
| 2276 | + if( mwDomReadyFlag ) { |
| 2277 | + return ; |
| 2278 | + } |
| 2279 | + mw.log( 'run:domReady:: ' + document.getElementsByTagName('video').length ); |
| 2280 | + // Set the onDomReady Flag |
| 2281 | + mwDomReadyFlag = true; |
| 2282 | + |
| 2283 | + // Give us a chance to get to the bottom of the script. |
| 2284 | + // When loading mwEmbed asynchronously the dom ready gets called |
| 2285 | + // directly and in some browsers beets the $j = jQuery.noConflict(); |
| 2286 | + // call |
| 2287 | + // and causes symbol undefined errors. |
| 2288 | + setTimeout(function(){ |
| 2289 | + mw.setupMwEmbed(); |
| 2290 | + },1); |
| 2291 | + }; |
| 2292 | + |
| 2293 | + /** |
| 2294 | + * A version comparison utility function Handles version of types |
| 2295 | + * {Major}.{MinorN}.{Patch} |
| 2296 | + * |
| 2297 | + * Note this just handles version numbers not patch letters. |
| 2298 | + * |
| 2299 | + * @param {String} |
| 2300 | + * minVersion Minnium version needed |
| 2301 | + * @param {String} |
| 2302 | + * clientVersion Client version to be checked |
| 2303 | + * |
| 2304 | + * @return true if the version is at least of minVersion false if the |
| 2305 | + * version is less than minVersion |
| 2306 | + */ |
| 2307 | + mw.versionIsAtLeast = function( minVersion, clientVersion ) { |
| 2308 | + var minVersionParts = minVersion.split('.'); |
| 2309 | + var clientVersionParts = clientVersion.split('.'); |
| 2310 | + for( var i =0; i < minVersionParts.length; i++ ) { |
| 2311 | + if( parseInt( clientVersionParts[i] ) > parseInt( minVersionParts[i] ) ) { |
| 2312 | + return true; |
| 2313 | + } |
| 2314 | + if( parseInt( clientVersionParts[i] ) < parseInt( minVersionParts[i] ) ) { |
| 2315 | + return false; |
| 2316 | + } |
| 2317 | + } |
| 2318 | + // Same version: |
| 2319 | + return true; |
| 2320 | + }; |
| 2321 | + |
| 2322 | + /** |
| 2323 | + * Runs all the triggers on a given object with a single "callback" |
| 2324 | + * |
| 2325 | + * Normal tirgger calls will run the callback directly multiple times for |
| 2326 | + * every binded function. |
| 2327 | + * |
| 2328 | + * With runTriggersCallback() callback is not called until all the binded |
| 2329 | + * events have been run. |
| 2330 | + * |
| 2331 | + * @param {object} |
| 2332 | + * targetObject Target object to run triggers on |
| 2333 | + * @param {string} |
| 2334 | + * triggerName Name of trigger to be run |
| 2335 | + * @param {function} |
| 2336 | + * callback Function called once all triggers have been run |
| 2337 | + * |
| 2338 | + */ |
| 2339 | + mw.runTriggersCallback = function( targetObject, triggerName, callback ){ |
| 2340 | + mw.log( 'mw.runTriggersCallback:: ' + triggerName ); |
| 2341 | + // If events are not present directly run callback |
| 2342 | + if( ! $j( targetObject ).data( 'events' ) || |
| 2343 | + ! $j( targetObject ).data( 'events' )[ triggerName ] ) { |
| 2344 | + mw.log( ' trigger name not found: ' + triggerName ); |
| 2345 | + callback(); |
| 2346 | + return ; |
| 2347 | + } |
| 2348 | + var callbackSet = $j( targetObject ).data( 'events' )[ triggerName ]; |
| 2349 | + if( !callbackSet || callbackSet.length === 0 ){ |
| 2350 | + mw.log( ' No events run the callback directly: ' + triggerName ); |
| 2351 | + // No events run the callback directly |
| 2352 | + callback(); |
| 2353 | + return ; |
| 2354 | + } |
| 2355 | + // Set the callbackCount |
| 2356 | + var callbackCount = ( callbackSet.length )? callbackSet.length : 1; |
| 2357 | + |
| 2358 | + mw.log(" runTriggersCallback:: " + callbackCount ); |
| 2359 | + var callInx = 0; |
| 2360 | + $j( targetObject ).trigger( triggerName, function() { |
| 2361 | + callInx++; |
| 2362 | + if( callInx == callbackCount ){ |
| 2363 | + //mw.log(" callbackCountReached run:: " + callback); |
| 2364 | + // Run callback |
| 2365 | + callback(); |
| 2366 | + } |
| 2367 | + } ); |
| 2368 | + }; |
| 2369 | + /** |
| 2370 | + * Utility jQuery bindings Setup after jQuery is available ). |
| 2371 | + */ |
| 2372 | + mw.dojQueryBindings = function() { |
| 2373 | + mw.log( 'mw.dojQueryBindings' ); |
| 2374 | + ( function( $ ) { |
| 2375 | + |
| 2376 | + /** |
| 2377 | + * Set a given selector html to the loading spinner: |
| 2378 | + */ |
| 2379 | + $.fn.loadingSpinner = function( ) { |
| 2380 | + if ( this ) { |
| 2381 | + $j( this ).html( |
| 2382 | + $j( '<div />' ) |
| 2383 | + .addClass( "loadingSpinner" ) |
| 2384 | + ); |
| 2385 | + } |
| 2386 | + return this; |
| 2387 | + }; |
| 2388 | + /** |
| 2389 | + * Add an absolute overlay spinner useful for cases where the |
| 2390 | + * element does not display child elements, ( images, video ) |
| 2391 | + */ |
| 2392 | + $.fn.getAbsoluteOverlaySpinner = function(){ |
| 2393 | + var pos = $j( this ).offset(); |
| 2394 | + var posLeft = ( $j( this ).width() ) ? |
| 2395 | + parseInt( pos.left + ( .5 * $j( this ).width() ) -16 ) : |
| 2396 | + pos.left + 30; |
| 2397 | + |
| 2398 | + var posTop = ( $j( this ).height() ) ? |
| 2399 | + parseInt( pos.top + ( .5 * $j( this ).height() ) -16 ) : |
| 2400 | + pos.top + 30; |
| 2401 | + |
| 2402 | + var $spinner = $j('<div />') |
| 2403 | + .loadingSpinner() |
| 2404 | + .css({ |
| 2405 | + 'width' : 32, |
| 2406 | + 'height' : 32, |
| 2407 | + 'position': 'absolute', |
| 2408 | + 'top' : posTop + 'px', |
| 2409 | + 'left' : posLeft + 'px' |
| 2410 | + }); |
| 2411 | + $j('body').append( $spinner ); |
| 2412 | + return $spinner; |
| 2413 | + }; |
| 2414 | + |
| 2415 | + /** |
| 2416 | + * dragDrop file loader |
| 2417 | + */ |
| 2418 | + $.fn.dragFileUpload = function ( conf ) { |
| 2419 | + if ( this.selector ) { |
| 2420 | + var _this = this; |
| 2421 | + // load the dragger and "setup" |
| 2422 | + mw.load( ['$j.fn.dragDropFile'], function() { |
| 2423 | + $j( _this.selector ).dragDropFile(); |
| 2424 | + } ); |
| 2425 | + } |
| 2426 | + }; |
| 2427 | + |
| 2428 | + /** |
| 2429 | + * Shortcut to a themed button Should be depreciated for $.button |
| 2430 | + * bellow |
| 2431 | + */ |
| 2432 | + $.btnHtml = function( msg, styleClass, iconId, opt ) { |
| 2433 | + if ( !opt ) |
| 2434 | + opt = { }; |
| 2435 | + var href = ( opt.href ) ? opt.href : '#'; |
| 2436 | + var target_attr = ( opt.target ) ? ' target="' + opt.target + '" ' : ''; |
| 2437 | + var style_attr = ( opt.style ) ? ' style="' + opt.style + '" ' : ''; |
| 2438 | + return '<a href="' + href + '" ' + target_attr + style_attr + |
| 2439 | + ' class="ui-state-default ui-corner-all ui-icon_link ' + |
| 2440 | + styleClass + '"><span class="ui-icon ui-icon-' + iconId + '" ></span>' + |
| 2441 | + '<span class="btnText">' + msg + '</span></a>'; |
| 2442 | + }; |
| 2443 | + |
| 2444 | + // Shortcut to jQuery button ( should replace all btnHtml with |
| 2445 | + // button ) |
| 2446 | + var mw_default_button_options = { |
| 2447 | + // The class name for the button link |
| 2448 | + 'class' : '', |
| 2449 | + |
| 2450 | + // The style properties for the button link |
| 2451 | + 'style' : { }, |
| 2452 | + |
| 2453 | + // The text of the button link |
| 2454 | + 'text' : '', |
| 2455 | + |
| 2456 | + // The icon id that precedes the button link: |
| 2457 | + 'icon' : 'carat-1-n' |
| 2458 | + }; |
| 2459 | + |
| 2460 | + $.button = function( options ) { |
| 2461 | + var options = $j.extend( {}, mw_default_button_options, options); |
| 2462 | + |
| 2463 | + // Button: |
| 2464 | + var $button = $j('<a />') |
| 2465 | + .attr('href', '#') |
| 2466 | + .addClass( 'ui-state-default ui-corner-all ui-icon_link' ); |
| 2467 | + // Add css if set: |
| 2468 | + if( options.css ) { |
| 2469 | + $button.css( options.css ); |
| 2470 | + } |
| 2471 | + |
| 2472 | + if( options['class'] ) { |
| 2473 | + $button.addClass( options['class'] ); |
| 2474 | + } |
| 2475 | + |
| 2476 | + |
| 2477 | + // return the button: |
| 2478 | + $button.append( |
| 2479 | + $j('<span />').addClass( 'ui-icon ui-icon-' + options.icon ), |
| 2480 | + $j('<span />').addClass( 'btnText' ) |
| 2481 | + .text( options.text ) |
| 2482 | + ) |
| 2483 | + .buttonHover(); // add buttonHover binding; |
| 2484 | + if( !options.text ){ |
| 2485 | + $button.css('padding', '1em'); |
| 2486 | + } |
| 2487 | + return $button; |
| 2488 | + }; |
| 2489 | + |
| 2490 | + // Shortcut to bind hover state |
| 2491 | + $.fn.buttonHover = function() { |
| 2492 | + $j( this ).hover( |
| 2493 | + function() { |
| 2494 | + $j( this ).addClass( 'ui-state-hover' ); |
| 2495 | + }, |
| 2496 | + function() { |
| 2497 | + $j( this ).removeClass( 'ui-state-hover' ); |
| 2498 | + } |
| 2499 | + ); |
| 2500 | + return this; |
| 2501 | + }; |
| 2502 | + |
| 2503 | + /** |
| 2504 | + * Resize a dialog to fit the window |
| 2505 | + * |
| 2506 | + * @param {Object} |
| 2507 | + * options horizontal and vertical space ( default 50 ) |
| 2508 | + */ |
| 2509 | + $.fn.dialogFitWindow = function( options ) { |
| 2510 | + var opt_default = { 'hspace':50, 'vspace':50 }; |
| 2511 | + if ( !options ) |
| 2512 | + var options = { }; |
| 2513 | + options = $j.extend( opt_default, options ); |
| 2514 | + $j( this.selector ).dialog( 'option', 'width', $j( window ).width() - options.hspace ); |
| 2515 | + $j( this.selector ).dialog( 'option', 'height', $j( window ).height() - options.vspace ); |
| 2516 | + $j( this.selector ).dialog( 'option', 'position', 'center' ); |
| 2517 | + // update the child position: (some of this should be pushed |
| 2518 | + // up-stream via dialog config options |
| 2519 | + $j( this.selector + '~ .ui-dialog-buttonpane' ).css( { |
| 2520 | + 'position':'absolute', |
| 2521 | + 'left':'0px', |
| 2522 | + 'right':'0px', |
| 2523 | + 'bottom':'0px' |
| 2524 | + } ); |
| 2525 | + }; |
| 2526 | + |
| 2527 | + } )( $j ); |
| 2528 | + }; |
| 2529 | + |
| 2530 | +} )( window.mw ); |
| 2531 | + |
| 2532 | + |
| 2533 | +/** |
| 2534 | + * Set DOM-ready call We copy jQuery( document ).ready here since sometimes |
| 2535 | + * mwEmbed.js is included without jQuery and we need our own "ready" system so |
| 2536 | + * that mwEmbed interfaces can support async built out and the include of |
| 2537 | + * jQuery. |
| 2538 | + */ |
| 2539 | +var mwDomIsReady = false; |
| 2540 | +function runMwDomReady(){ |
| 2541 | + mwDomIsReady = true; |
| 2542 | + if( mw.domReady ){ |
| 2543 | + mw.domReady(); |
| 2544 | + } |
| 2545 | +} |
| 2546 | +// Check if already ready: |
| 2547 | +if ( document.readyState === "complete" ) { |
| 2548 | + runMwDomReady(); |
| 2549 | +} |
| 2550 | + |
| 2551 | +// Cleanup functions for the document ready method |
| 2552 | +if ( document.addEventListener ) { |
| 2553 | + DOMContentLoaded = function() { |
| 2554 | + document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); |
| 2555 | + runMwDomReady(); |
| 2556 | + }; |
| 2557 | + |
| 2558 | +} else if ( document.attachEvent ) { |
| 2559 | + DOMContentLoaded = function() { |
| 2560 | + // Make sure body exists, at least, in case IE gets a little overzealous |
| 2561 | + // (ticket #5443). |
| 2562 | + if ( document.readyState === "complete" ) { |
| 2563 | + document.detachEvent( "onreadystatechange", DOMContentLoaded ); |
| 2564 | + runMwDomReady(); |
| 2565 | + } |
| 2566 | + }; |
| 2567 | +} |
| 2568 | +// Mozilla, Opera and webkit nightlies currently support this event |
| 2569 | +if ( document.addEventListener ) { |
| 2570 | + // Use the handy event callback |
| 2571 | + document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); |
| 2572 | + |
| 2573 | + // A fallback to window.onload, that will always work |
| 2574 | + window.addEventListener( "load", mw.domReady, false ); |
| 2575 | + |
| 2576 | +// If IE event model is used |
| 2577 | +} else if ( document.attachEvent ) { |
| 2578 | + // ensure firing before onload, |
| 2579 | + // maybe late but safe also for iframes |
| 2580 | + document.attachEvent("onreadystatechange", DOMContentLoaded); |
| 2581 | + |
| 2582 | + // A fallback to window.onload, that will always work |
| 2583 | + window.attachEvent( "onload", runMwDomReady ); |
| 2584 | + |
| 2585 | + // If IE and not a frame |
| 2586 | + // continually check to see if the document is ready |
| 2587 | + var toplevel = false; |
| 2588 | + |
| 2589 | + try { |
| 2590 | + toplevel = window.frameElement == null; |
| 2591 | + } catch(e) {} |
| 2592 | + |
| 2593 | + if ( document.documentElement.doScroll && toplevel ) { |
| 2594 | + doScrollCheck(); |
| 2595 | + } |
| 2596 | +} |
| 2597 | +// The DOM ready check for Internet Explorer |
| 2598 | +function doScrollCheck() { |
| 2599 | + if ( mwDomIsReady ) { |
| 2600 | + return; |
| 2601 | + } |
| 2602 | + |
| 2603 | + try { |
| 2604 | + // If IE is used, use the trick by Diego Perini |
| 2605 | + // http://javascript.nwbox.com/IEContentLoaded/ |
| 2606 | + document.documentElement.doScroll("left"); |
| 2607 | + } catch( error ) { |
| 2608 | + setTimeout( doScrollCheck, 1 ); |
| 2609 | + return; |
| 2610 | + } |
| 2611 | + |
| 2612 | + // and execute any waiting functions |
| 2613 | + runMwDomReady(); |
| 2614 | +} |
| 2615 | + |
| 2616 | + |
| 2617 | +// If using the resource loader and jQuery has not been set give a warning to |
| 2618 | +// the user: |
| 2619 | +// (this is needed because packaged loader.js files could refrence jQuery ) |
| 2620 | +if( mw.getResourceLoaderPath() && !window.jQuery ) { |
| 2621 | + mw.log( 'Error: jQuery is required for mwEmbed, please update your resource loader request' ); |
| 2622 | +} |
| 2623 | + |
| 2624 | +if( mw.isStaticPackge() && !window.jQuery ){ |
| 2625 | + alert( 'Error: jQuery is required for mwEmbed '); |
| 2626 | +} |
| 2627 | + |
| 2628 | +/** |
| 2629 | + * Hack to keep jQuery in $ when its already there, but also use noConflict to |
| 2630 | + * get $j = jQuery |
| 2631 | + * |
| 2632 | + * This way sites that use $ for jQuery continue to work after including mwEmbed |
| 2633 | + * javascript. |
| 2634 | + * |
| 2635 | + * Also if jQuery is included prior to mwEmbed we ensure $j is set |
| 2636 | + */ |
| 2637 | + |
| 2638 | +if( window.jQuery ){ |
| 2639 | + if( ! mw.versionIsAtLeast( '1.4.0', jQuery.fn.jquery ) ){ |
| 2640 | + if( window.console && window.console.log ) { |
| 2641 | + console.log( 'Error mwEmbed requires jQuery 1.4 or above' ); |
| 2642 | + } |
| 2643 | + } |
| 2644 | + var dollarFlag = false; |
| 2645 | + if( $ && $.fn && $.fn.jquery ) { |
| 2646 | + // NOTE we could check the version of |
| 2647 | + // jQuery and do a removal call if too old |
| 2648 | + dollarFlag = true; |
| 2649 | + } |
| 2650 | + window[ '$j' ] = jQuery.noConflict(); |
| 2651 | + if( dollarFlag ) { |
| 2652 | + window[ '$' ] = jQuery.noConflict(); |
| 2653 | + } |
| 2654 | +} |
Property changes on: trunk/extensions/MwEmbed/MwEmbed/mwEmbed.old.js |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 2655 | + native |
Index: trunk/extensions/MwEmbed/MwEmbed/mwEmbed.js |
— | — | @@ -1,2535 +1,9 @@ |
2 | | -// Add support for html5 / mwEmbed elements to IE ( comment must come before js code ) |
3 | | -// For discussion and comments, see: http://remysharp.com/2009/01/07/html5-enabling-script/ |
4 | | -/*@cc_on@if(@_jscript_version<9){'video audio source track'.replace(/\w+/g,function(n){document.createElement(n)})}@end@*/ |
5 | | - |
6 | 2 | /** |
7 | | - * @license |
8 | | - * mwEmbed |
9 | | - * Dual licensed under the MIT or GPL Version 2 licenses. |
10 | | - * |
11 | | - * @copyright (C) 2010 Kaltura |
12 | | - * @author Michael Dale ( michael.dale at kaltura.com ) |
13 | | - * |
14 | | - * @url http://www.kaltura.org/project/HTML5_Video_Media_JavaScript_Library |
15 | | - * |
16 | | - * Libraries used include code license in headers |
17 | | - */ |
18 | | - |
19 | | -/** |
20 | | - * Setup the "mw" global: |
21 | | - */ |
22 | | -if ( typeof window.mw == 'undefined' ) { |
23 | | - window.mw = { }; |
24 | | -} |
25 | | - |
26 | | -/** |
27 | | - * Set the mwEmbedVersion |
28 | | - */ |
29 | | -var MW_EMBED_VERSION = '1.1g'; |
30 | | - |
31 | | -// Globals to pre-set ready functions in dynamic loading of mwEmbed |
32 | | -if( typeof preMwEmbedReady == 'undefined'){ |
33 | | - var preMwEmbedReady = []; |
34 | | -} |
35 | | -// Globals to pre-set config values in dynamic loading of mwEmbed |
36 | | -if( typeof preMwEmbedConfig == 'undefined') { |
37 | | - var preMwEmbedConfig = []; |
38 | | -} |
39 | | - |
40 | | -/** |
41 | | - * The global mw object: |
42 | | - */ |
43 | | -( function( mw ) { |
44 | | - // The version of mwEmbed |
45 | | - mw.version = MW_EMBED_VERSION |
46 | | - |
47 | | - // List valid skins here: |
48 | | - mw.validSkins = [ 'mvpcf', 'kskin' ]; |
49 | | - |
50 | | - // Storage variable for loaded style sheet keys |
51 | | - mw.style = { }; |
52 | | - |
53 | | - /** |
54 | | - * Configuration System: |
55 | | - */ |
56 | | - |
57 | | - // Local scope configuration var: |
58 | | - if( !mwConfig ){ |
59 | | - var mwConfig = { }; |
60 | | - } |
61 | | - |
62 | | - // Local scope mwUserConfig var. Stores user configuration |
63 | | - var mwUserConfig = { }; |
64 | | - |
65 | | - /** |
66 | | - * Setter for configuration values |
67 | | - * |
68 | | - * @param [Mixed] |
69 | | - * name Name of configuration value {Object} Will iderate through |
70 | | - * each key and call setConfig {String} Will set configuration by |
71 | | - * string name to value |
72 | | - * @param {String} |
73 | | - * value Value of configuration name {Object} value Set of values |
74 | | - * to be merged |
75 | | - */ |
76 | | - mw.setConfig = function ( name, value ) { |
77 | | - if( typeof name == 'object' ) { |
78 | | - for( var i in name ) { |
79 | | - mw.setConfig( i, name[ i ] ); |
80 | | - } |
81 | | - return ; |
82 | | - } |
83 | | - // Check if we should "merge" the config |
84 | | - if( typeof value == 'object' && typeof mwConfig[ name ] == 'object' ) { |
85 | | - for( var i in value ){ |
86 | | - mwConfig[ name ][ i ] = value[ i ]; |
87 | | - } |
88 | | - } else { |
89 | | - mwConfig[ name ] = value; |
90 | | - } |
91 | | - } |
92 | | - |
93 | | - /** |
94 | | - * Set a default config value Will only update configuration if no value is |
95 | | - * present |
96 | | - * |
97 | | - * @param [Mixed] |
98 | | - * value Set configuration name to value {Object} Will iderate |
99 | | - * through each key and call setDefaultConfig {String} Will set |
100 | | - * configuration by string name to value |
101 | | - */ |
102 | | - mw.setDefaultConfig = function( name, value ) { |
103 | | - if( typeof name == 'object' ) { |
104 | | - for( var i in name ) { |
105 | | - mw.setDefaultConfig( i, name[ i ] ); |
106 | | - } |
107 | | - return ; |
108 | | - } |
109 | | - // Only update the controls if undefined ( ie don't override false |
110 | | - // properties ) |
111 | | - if( typeof mwConfig[ name ] == 'undefined') { |
112 | | - mwConfig[ name ] = value; |
113 | | - } |
114 | | - } |
115 | | - |
116 | | - /** |
117 | | - * Getter for configuration values |
118 | | - * |
119 | | - * @param {String} |
120 | | - * name of configuration value to get |
121 | | - * @return {Mixed} value of configuration key returns "false" if key not |
122 | | - * found |
123 | | - */ |
124 | | - mw.getConfig = function ( name ) { |
125 | | - if( mwConfig[ name ] ) |
126 | | - return mwConfig[ name ]; |
127 | | - return false; |
128 | | - } |
129 | | - |
130 | | - /** |
131 | | - * Loads the mwUserConfig from a cookie. |
132 | | - * |
133 | | - * Modules that want to use "User Config" should call this setup function in |
134 | | - * their moduleLoader code. |
135 | | - * |
136 | | - * For performance interfaces using "user config" should load '$j.cookie' & |
137 | | - * 'JSON' in their module loader |
138 | | - * |
139 | | - * By abstracting user preference we could eventually integrate a persistent |
140 | | - * per-account preference system on the server. |
141 | | - * |
142 | | - * @parma {Function} callback Function to be called once userPrefrences are |
143 | | - * loaded |
144 | | - */ |
145 | | - var setupUserConfigFlag = false; |
146 | | - mw.setupUserConfig = function( callback ) { |
147 | | - if( setupUserConfigFlag ) { |
148 | | - if( callback ) { |
149 | | - callback(); |
150 | | - } |
151 | | - return ; |
152 | | - } |
153 | | - // Do Setup user config: |
154 | | - mw.load( [ '$j.cookie', 'JSON' ], function() { |
155 | | - if( $j.cookie( 'mwUserConfig' ) ) { |
156 | | - mwUserConfig = JSON.parse( $j.cookie( 'mwUserConfig' ) ); |
157 | | - } |
158 | | - setupUserConfigFlag = true; |
159 | | - if( callback ) { |
160 | | - callback(); |
161 | | - } |
162 | | - }); |
163 | | - } |
164 | | - |
165 | | - /** |
166 | | - * Save a user configuration var to a cookie & local global variable Loads |
167 | | - * the cookie plugin if not already loaded |
168 | | - * |
169 | | - * @param {String} |
170 | | - * name Name of user configuration value |
171 | | - * @param {String} |
172 | | - * value Value of configuration name |
173 | | - */ |
174 | | - mw.setUserConfig = function ( name, value, cookieOptions ) { |
175 | | - if( ! setupUserConfigFlag ) { |
176 | | - mw.log( "Error: userConfig not setup" ); |
177 | | - return false; |
178 | | - } |
179 | | - // Update local value |
180 | | - mwUserConfig[ name ] = value; |
181 | | - |
182 | | - // Update the cookie ( '$j.cookie' & 'JSON' should already be loaded ) |
183 | | - $j.cookie( 'mwUserConfig', JSON.stringify( mwUserConfig ) ); |
184 | | - } |
185 | | - |
186 | | - /** |
187 | | - * Save a user configuration var to a cookie & local global variable |
188 | | - * |
189 | | - * @param {String} |
190 | | - * name Name of user configuration value |
191 | | - * @return value of the configuration name false if the configuration name |
192 | | - * could not be found |
193 | | - */ |
194 | | - mw.getUserConfig = function ( name ) { |
195 | | - if( mwUserConfig[ name ] ) |
196 | | - return mwUserConfig[ name ]; |
197 | | - return false; |
198 | | - } |
199 | | - |
200 | | - /** |
201 | | - * Add a hook system for a target object / interface |
202 | | - * |
203 | | - * depricated you should instead use jQuery's bind and trigger |
204 | | - * |
205 | | - * @param {Object} |
206 | | - * targetObj Interface Object to add hook system to. |
207 | | - */ |
208 | | - mw.addHookSystem = function( targetObj ) { |
209 | | - |
210 | | - // Setup the target object hook holder: |
211 | | - targetObj[ 'hooks' ] = { }; |
212 | | - |
213 | | - /** |
214 | | - * Adds a hook to the target object |
215 | | - * |
216 | | - * Should be called by clients to setup named hooks |
217 | | - * |
218 | | - * @param {String} |
219 | | - * hookName Name of hook to be added |
220 | | - * @param {Function} |
221 | | - * hookFunction Function to be called at hook time |
222 | | - */ |
223 | | - targetObj.addHook = function( hookName, hookFunction ) { |
224 | | - if( ! this.hooks[ hookName ] ) { |
225 | | - this.hooks[ hookName ] = [ ]; |
226 | | - } |
227 | | - this.hooks[ hookName ].push( hookFunction ) |
228 | | - } |
229 | | - |
230 | | - /** |
231 | | - * Runs all the hooks by a given name with reference to the host object |
232 | | - * |
233 | | - * Should be called by the host object at named execution points |
234 | | - * |
235 | | - * @param {String} |
236 | | - * hookName Name of hook to be called |
237 | | - * @return Value of hook result true interface should continue function |
238 | | - * execution false interface should stop or return from method |
239 | | - */ |
240 | | - targetObj.runHook = function( hookName, options ) { |
241 | | - if( this.hooks[ hookName ] ) { |
242 | | - for( var i =0; i < this.hooks[ hookName ].length; i ++ ) { |
243 | | - if( typeof( this.hooks[ hookName ][ i ] ) == 'function' ) { |
244 | | - this.hooks[ hookName ][ i ]( options ); |
245 | | - } |
246 | | - } |
247 | | - } |
248 | | - } |
249 | | - } |
250 | | - |
251 | | - // Add hooks system to the core "mw" object |
252 | | - mw.addHookSystem( mw ); |
253 | | - |
254 | | - // Stores callbacks for resource loader loading |
255 | | - var mwLoadDoneCB = { }; |
256 | | - |
257 | | - |
258 | | - /** |
259 | | - * Top level loader prototype: |
260 | | - */ |
261 | | - mw.loader = { |
262 | | - /** |
263 | | - * Javascript Module Loader functions |
264 | | - * |
265 | | - * @key Name of Module |
266 | | - * @value function code to load module |
267 | | - */ |
268 | | - moduleLoaders : [], |
269 | | - |
270 | | - /** |
271 | | - * Module resource list queue. |
272 | | - * |
273 | | - * @key Name of Module |
274 | | - * @value .resourceList list of resources to be loaded .functionQueue |
275 | | - * list of functions to be run once module is ready |
276 | | - */ |
277 | | - moduleLoadQueue: { }, |
278 | | - |
279 | | - /** |
280 | | - * Javascript Class Paths |
281 | | - * |
282 | | - * @key Name of resource |
283 | | - * @value Class file path |
284 | | - */ |
285 | | - resourcePaths : { }, |
286 | | - |
287 | | - /** |
288 | | - * javascript Resource Paths |
289 | | - * |
290 | | - * @key Name of resource |
291 | | - * @value Name of depenent style sheet |
292 | | - */ |
293 | | - resourceStyleDependency: { }, |
294 | | - |
295 | | - /** |
296 | | - * Core load function: |
297 | | - * |
298 | | - * @param {Mixed} |
299 | | - * loadRequest: |
300 | | - * |
301 | | - * {String} Name of a module to be loaded Modules are added via |
302 | | - * addModuleLoader and can define custom code needed to check config and |
303 | | - * return a list of resources to be loaded |
304 | | - * |
305 | | - * {String} Name of a resource to loaded. Resources are added via |
306 | | - * addResourcePaths function Using defined resource names avoids loading |
307 | | - * the same resource twice by first checking if the named resource is |
308 | | - * defined in the global javascript scope variable |
309 | | - * |
310 | | - * {String} Absolute or relative to url path The same file won't be |
311 | | - * loaded twice |
312 | | - * |
313 | | - * {Array} can be an array of any combination of the above strings. Will |
314 | | - * be loaded in-order or in a single resource loader request if |
315 | | - * scriptLoader is available. |
316 | | - * |
317 | | - * {Array} {Array} Can be a set of Arrays for loading. Some browsers |
318 | | - * execute included scripts out of order. This lets you chain sets of |
319 | | - * request for those browsers. If using the server side resource loader |
320 | | - * order is preserved in output and a single request will be used. |
321 | | - * |
322 | | - * @param {Function} |
323 | | - * callback Function called once loading is complete |
324 | | - * |
325 | | - */ |
326 | | - load: function( loadRequest, instanceCallback ) { |
327 | | - // mw.log("mw.load:: " + loadRequest ); |
328 | | - |
329 | | - // Throw out any loadRequests that are not strings |
330 | | - loadRequest = this.cleanLoadRequest( loadRequest ); |
331 | | - |
332 | | - // Ensure the callback is only called once per load instance |
333 | | - var callback = function(){ |
334 | | - // mw.log( 'instanceCallback::running callback: ' + |
335 | | - // instanceCallback ); |
336 | | - if( instanceCallback ){ |
337 | | - // We pass the loadRequest back to the callback for easy |
338 | | - // debugging of concurrency issues. |
339 | | - // ( normally its not used ) |
340 | | - instanceCallback( loadRequest ); |
341 | | - instanceCallback = null; |
342 | | - } |
343 | | - } |
344 | | - |
345 | | - // Check for empty loadRequest ( directly return the callback ) |
346 | | - if( mw.isEmpty( loadRequest ) ) { |
347 | | - mw.log( 'Empty load request: ( ' + loadRequest + ' ) ' ); |
348 | | - callback( loadRequest ); |
349 | | - return ; |
350 | | - } |
351 | | - |
352 | | - |
353 | | - // Check if its a multi-part request: |
354 | | - if( typeof loadRequest == 'object' ) { |
355 | | - if( loadRequest.length > 1 ) { |
356 | | - this.loadMany ( loadRequest, callback ); |
357 | | - return ; |
358 | | - }else{ |
359 | | - // If an array of length 1 set as first element |
360 | | - loadRequest = loadRequest[0]; |
361 | | - } |
362 | | - } |
363 | | - |
364 | | - // Check for the module name loader function |
365 | | - if( this.moduleLoaders[ loadRequest ] ) { |
366 | | - var resourceSet = this.getModuleResourceSet( loadRequest ); |
367 | | - if( !resourceSet ){ |
368 | | - mw.log( "mw.load:: Error with module loader: " + loadRequest + ' ( no resource set defined )' ); |
369 | | - return ; |
370 | | - } |
371 | | - |
372 | | - // xxx should use refactor "ready" stuff into a "domReady" class |
373 | | - // So we would not have local scope globals like this: |
374 | | - if ( mwReadyFlag ) { |
375 | | - // Load the module directly if load request is after |
376 | | - // mw.ready has run |
377 | | - this.load( resourceSet, callback ); |
378 | | - } else { |
379 | | - this.addToModuleLoaderQueue( |
380 | | - loadRequest, |
381 | | - resourceSet, |
382 | | - callback |
383 | | - ); |
384 | | - } |
385 | | - return ; |
386 | | - } |
387 | | - |
388 | | - // Check for javascript resource |
389 | | - if( this.getResourcePath( loadRequest ) ) { |
390 | | - this.loadResource( loadRequest, callback ); |
391 | | - return ; |
392 | | - } |
393 | | - |
394 | | - // Try loading as a "file" or via ScriptLoader |
395 | | - if( loadRequest ) { |
396 | | - if( loadRequest.indexOf( '.js' ) == -1 && !mw.getResourceLoaderPath() ) { |
397 | | - mw.log( 'Error: are you sure ' + loadRequest + ' is a file ( is it missing a resource path? ) ' ); |
398 | | - } |
399 | | - mw.getScript( loadRequest, callback ); |
400 | | - return ; |
401 | | - } |
402 | | - |
403 | | - // Possible error? |
404 | | - mw.log( "Error could not handle load request: " + loadRequest ); |
405 | | - }, |
406 | | - |
407 | | - getModuleResourceSet: function( moduleName ){ |
408 | | - // Check if the module loader is a function ~run that function~ |
409 | | - if( typeof ( this.moduleLoaders[ moduleName ] ) == 'function' ) { |
410 | | - // Add the result of the module loader function |
411 | | - return this.moduleLoaders[ moduleName ](); |
412 | | - } else if( typeof ( this.moduleLoaders[ moduleName ] ) == 'object' ){ |
413 | | - // set resourceSet directly |
414 | | - return this.moduleLoaders[ moduleName ]; |
415 | | - } |
416 | | - return false; |
417 | | - }, |
418 | | - |
419 | | - /** |
420 | | - * Clean the loadRequest ( throw out any non-string items ) |
421 | | - */ |
422 | | - cleanLoadRequest: function( loadRequest ){ |
423 | | - var cleanRequest = []; |
424 | | - if( typeof loadRequest == 'string' ) |
425 | | - return loadRequest; |
426 | | - for( var i =0;i < loadRequest.length; i++ ){ |
427 | | - if( typeof loadRequest[i] == 'object' ) { |
428 | | - cleanRequest[i] = this.cleanLoadRequest( loadRequest[i] ); |
429 | | - } else if( typeof loadRequest[i] == 'string' ){ |
430 | | - cleanRequest[i] = $j.trim( loadRequest[i] ); |
431 | | - } else{ |
432 | | - // bad request type skip |
433 | | - } |
434 | | - } |
435 | | - return cleanRequest; |
436 | | - }, |
437 | | - /** |
438 | | - * Load a set of scripts. Will issue many load requests or package the |
439 | | - * request for the resource loader |
440 | | - * |
441 | | - * @param {Object} |
442 | | - * loadSet Set of scripts to be loaded |
443 | | - * @param {Function} |
444 | | - * callback Function to call once all scripts are loaded. |
445 | | - */ |
446 | | - loadMany: function( loadSet, callback ) { |
447 | | - var _this = this; |
448 | | - // Setup up the local "loadStates" |
449 | | - var loadStates = { }; |
450 | | - |
451 | | - // Check if we can load via the "resource loader" ( mwEmbed was |
452 | | - // included via scriptLoader ) |
453 | | - if( mw.getResourceLoaderPath() ) { |
454 | | - // Get the grouped loadStates variable |
455 | | - loadStates = this.getGroupLoadState( loadSet ); |
456 | | - if( mw.isEmpty( loadStates ) ) { |
457 | | - // mw.log( 'loadMany:all resources already loaded'); |
458 | | - callback(); |
459 | | - return ; |
460 | | - } |
461 | | - }else{ |
462 | | - // Check if its a dependency set ( nested objects ) |
463 | | - if( typeof loadSet [ 0 ] == 'object' ) { |
464 | | - _this.dependencyChainCallFlag[ loadSet ] = false; |
465 | | - // Load sets of resources ( to preserver order for some |
466 | | - // browsers ) |
467 | | - _this.loadDependencyChain( loadSet, callback ); |
468 | | - return ; |
469 | | - } |
470 | | - |
471 | | - // Set the initial load state for every item in the loadSet |
472 | | - for( var i = 0; i < loadSet.length ; i++ ) { |
473 | | - var loadName = loadSet[ i ]; |
474 | | - loadStates[ loadName ] = 0; |
475 | | - } |
476 | | - } |
477 | | - |
478 | | - // We are infact loading many: |
479 | | - mw.log("mw.load: LoadMany:: " + loadSet ); |
480 | | - |
481 | | - // Issue the load request check check loadStates to see if we are |
482 | | - // "done" |
483 | | - for( var loadName in loadStates ) { |
484 | | - // mw.log("loadMany: load: " + loadName ); |
485 | | - this.load( loadName, function ( loadName ) { |
486 | | - loadStates[ loadName ] = 1; |
487 | | - |
488 | | - /* |
489 | | - * for( var i in loadStates ) { mw.log( loadName + ' |
490 | | - * finished of: ' + i + ' : ' + loadStates[i] ); } |
491 | | - */ |
492 | | - |
493 | | - // Check if all load request states are set 1 |
494 | | - var loadDone = true; |
495 | | - for( var j in loadStates ) { |
496 | | - if( loadStates[ j ] === 0 ) |
497 | | - loadDone = false; |
498 | | - } |
499 | | - // Run the parent scope callback for "loadMany" |
500 | | - if( loadDone ) { |
501 | | - callback( loadName ); |
502 | | - } |
503 | | - } ); |
504 | | - } |
505 | | - }, |
506 | | - |
507 | | - /** |
508 | | - * Get grouped load state for script loader |
509 | | - * |
510 | | - * Groups the scriptRequest where possible: Modules include "loader |
511 | | - * code" so they are separated into pre-condition code to be run for |
512 | | - * subsequent requests |
513 | | - * |
514 | | - * @param {Object} |
515 | | - * loadSet Loadset to return grouped |
516 | | - * @return {Object} grouped loadSet |
517 | | - */ |
518 | | - getGroupLoadState: function( loadSet ) { |
519 | | - var groupedLoadSet = []; |
520 | | - var loadStates = { }; |
521 | | - // Merge load set into new groupedLoadSet |
522 | | - if( typeof loadSet[0] == 'object' ) { |
523 | | - for( var i = 0; i < loadSet.length ; i++ ) { |
524 | | - for( var j = 0; j < loadSet[i].length ; j++ ) { |
525 | | - // Make sure we have not already included it: |
526 | | - groupedLoadSet.push( loadSet[i][j] ); |
527 | | - } |
528 | | - } |
529 | | - } else { |
530 | | - // Use the loadSet directly: |
531 | | - groupedLoadSet = loadSet; |
532 | | - } |
533 | | - |
534 | | - // Setup grouped loadStates Set: |
535 | | - var groupClassKey = ''; |
536 | | - var coma = ''; |
537 | | - for( var i=0; i < groupedLoadSet.length; i++ ) { |
538 | | - var loadName = groupedLoadSet[ i ]; |
539 | | - |
540 | | - |
541 | | - if( this.getResourcePath( loadName ) ) { |
542 | | - // Only add to group request if not already set: |
543 | | - if ( !mw.isset( loadName ) ) { |
544 | | - groupClassKey += coma + loadName |
545 | | - coma = ','; |
546 | | - |
547 | | - // Check for style sheet dependencies |
548 | | - if( this.resourceStyleDependency[ loadName ] ){ |
549 | | - groupClassKey += coma + this.resourceStyleDependency[ loadName ]; |
550 | | - } |
551 | | - } |
552 | | - } else if ( this.moduleLoaders[ loadName ] ) { |
553 | | - |
554 | | - // Module loaders break up grouped script requests ( add the |
555 | | - // current groupClassKey ) |
556 | | - if( groupClassKey != '' ) { |
557 | | - loadStates[ groupClassKey ] = 0; |
558 | | - groupClassKey = coma = ''; |
559 | | - } |
560 | | - // Add the module to the loadSate |
561 | | - loadStates[ loadName ] = 0; |
562 | | - } |
563 | | - } |
564 | | - |
565 | | - // Add groupClassKey if set: |
566 | | - if( groupClassKey != '' ) { |
567 | | - loadStates [ groupClassKey ] = 0; |
568 | | - } |
569 | | - |
570 | | - return loadStates; |
571 | | - }, |
572 | | - |
573 | | - // Array to register that a callback has been called |
574 | | - dependencyChainCallFlag: { }, |
575 | | - |
576 | | - /** |
577 | | - * Load a sets of scripts satisfy dependency order for browsers that |
578 | | - * execute dynamically included scripts out of order |
579 | | - * |
580 | | - * @param {Object} |
581 | | - * loadChain A set of javascript arrays to be loaded. Sets |
582 | | - * are requested in array order. |
583 | | - */ |
584 | | - loadDependencyChain: function( loadChain, callback ) { |
585 | | - var _this = this; |
586 | | - // Load with dependency checks |
587 | | - var callSet = loadChain.shift(); |
588 | | - this.load( callSet, function( cbname ) { |
589 | | - if ( loadChain.length != 0 ) { |
590 | | - _this.loadDependencyChain( loadChain, callback ); |
591 | | - } else { |
592 | | - // NOTE: IE gets called twice so we have check the |
593 | | - // dependencyChainCallFlag before calling the callback |
594 | | - if( _this.dependencyChainCallFlag[ callSet ] == callback ) { |
595 | | - mw.log("... already called this callback for " + callSet ); |
596 | | - return ; |
597 | | - } |
598 | | - _this.dependencyChainCallFlag[ callSet ] = callback; |
599 | | - callback( ); |
600 | | - } |
601 | | - } ); |
602 | | - }, |
603 | | - |
604 | | - /** |
605 | | - * Add to the module loader queue |
606 | | - */ |
607 | | - addToModuleLoaderQueue: function( moduleName, resourceSet, callback ) { |
608 | | - mw.log(" addToModuleLoaderQueue:: " + moduleName + ' resourceSet: ' + resourceSet ); |
609 | | - if( this.moduleLoadQueue[ moduleName ] ){ |
610 | | - // If the module is already in the queue just add its callback: |
611 | | - this.moduleLoadQueue[ moduleName ].functionQueue.push( callback ); |
612 | | - } else { |
613 | | - // create the moduleLoadQueue item |
614 | | - this.moduleLoadQueue[ moduleName ] = { |
615 | | - 'resourceSet' : resourceSet, |
616 | | - 'functionQueue' : [ callback ], |
617 | | - 'loaded' : false |
618 | | - }; |
619 | | - } |
620 | | - }, |
621 | | - |
622 | | - /** |
623 | | - * Loops over all modules in queue, builds request sets based on config |
624 | | - * request type |
625 | | - */ |
626 | | - runModuleLoadQueue: function(){ |
627 | | - var _this = this; |
628 | | - mw.log( "mw.runModuleLoadQueue:: " ); |
629 | | - var runModuleFunctionQueue = function(){ |
630 | | - // Run all the callbacks |
631 | | - for( var moduleName in _this.moduleLoadQueue ){ |
632 | | - while( _this.moduleLoadQueue[moduleName].functionQueue.length ) { |
633 | | - _this.moduleLoadQueue[moduleName].functionQueue.shift()(); |
634 | | - } |
635 | | - } |
636 | | - } |
637 | | - |
638 | | - // Check for single request or javascript debug based loading: |
639 | | - if( !mw.getResourceLoaderPath() || mw.getConfig( 'loader.groupStrategy' ) == 'single' ){ |
640 | | - // if not using the resource load just do a normal array merge |
641 | | - // ( for browsers like IE that don't follow first append first |
642 | | - // execute rule ) |
643 | | - var fullResourceList = []; |
644 | | - for( var moduleName in this.moduleLoadQueue ) { |
645 | | - var resourceSet = this.moduleLoadQueue[ moduleName ].resourceSet; |
646 | | - // Lets try a global merge |
647 | | - fullResourceList = $j.merge( fullResourceList, resourceSet ); |
648 | | - } |
649 | | - mw.load( fullResourceList, function(){ |
650 | | - runModuleFunctionQueue(); |
651 | | - }); |
652 | | - return ; |
653 | | - } |
654 | | - |
655 | | - // Else do per module group loading |
656 | | - if( mw.getConfig( 'loader.groupStrategy' ) == 'module' ) { |
657 | | - var fullResourceList = []; |
658 | | - var sharedResourceList = []; |
659 | | - |
660 | | - for( var moduleName in this.moduleLoadQueue ) { |
661 | | - // Build a shared dependencies list and load that separately |
662 | | - // "first" |
663 | | - // ( in IE we have to wait until its "ready" since it does |
664 | | - // not follow dom order ) |
665 | | - var moduleResourceList = this.getFlatModuleResourceList( moduleName ); |
666 | | - // Build the sharedResourceList |
667 | | - for( var i=0; i < moduleResourceList.length; i++ ){ |
668 | | - var moduleResource = moduleResourceList[i]; |
669 | | - // Check if already in the full resource list if so add |
670 | | - // to shared. |
671 | | - if( fullResourceList[ moduleResource ] ){ |
672 | | - if( $j.inArray( moduleResource, sharedResourceList ) == -1 ){ |
673 | | - sharedResourceList.push( moduleResource ); |
674 | | - } |
675 | | - } |
676 | | - // Add to the fullResourceList |
677 | | - fullResourceList[ moduleResource ] = true; |
678 | | - } |
679 | | - } |
680 | | - |
681 | | - // Local module request set ( stores the actual request we will |
682 | | - // make after grouping shared resources |
683 | | - var moduleRequestSet = {}; |
684 | | - |
685 | | - // Only add non-shared to respective modules load requests |
686 | | - for( var moduleName in this.moduleLoadQueue ) { |
687 | | - moduleRequestSet[ moduleName ] = []; |
688 | | - var moduleResourceList = this.getFlatModuleResourceList( moduleName ); |
689 | | - for( var i =0; i < moduleResourceList.length; i++ ){ |
690 | | - var moduleResource = moduleResourceList[i]; |
691 | | - if( $j.inArray( moduleResource, sharedResourceList ) == -1 ){ |
692 | | - moduleRequestSet[ moduleName ].push( moduleResource ); |
693 | | - } |
694 | | - } |
695 | | - } |
696 | | - var sharedResourceLoadDone = false; |
697 | | - // Check if modules are done |
698 | | - var checkModulesDone = function(){ |
699 | | - if( !sharedResourceLoadDone ){ |
700 | | - return false; |
701 | | - } |
702 | | - for( var moduleName in _this.moduleLoadQueue ) { |
703 | | - if( ! _this.moduleLoadQueue[ moduleName ].loaded ){ |
704 | | - return false; |
705 | | - } |
706 | | - } |
707 | | - runModuleFunctionQueue(); |
708 | | - } |
709 | | - // Local instance of load requests to retain resourceSet |
710 | | - // context: |
711 | | - var localLoadCallInstance = function( moduleName, resourceSet ){ |
712 | | - mw.load( resourceSet, function(){ |
713 | | - _this.moduleLoadQueue[ moduleName ].loaded = true; |
714 | | - checkModulesDone(); |
715 | | - }); |
716 | | - } |
717 | | - |
718 | | - // Load the shared resources |
719 | | - mw.load( sharedResourceList, function(){ |
720 | | - // mw.log("Shared Resources loaded"); |
721 | | - // xxx check if we are in "IE" and dependencies need to be |
722 | | - // loaded "first" |
723 | | - sharedResourceLoadDone = true; |
724 | | - checkModulesDone(); |
725 | | - }); |
726 | | - // Load all module Request Set |
727 | | - for( var moduleName in moduleRequestSet ){ |
728 | | - localLoadCallInstance( moduleName, moduleRequestSet[ moduleName ] ); |
729 | | - } |
730 | | - } |
731 | | - // xxx Here we could also do some "intelligent" grouping |
732 | | - }, |
733 | | - |
734 | | - getFlatModuleResourceList: function( moduleName ){ |
735 | | - var moduleList = []; |
736 | | - for( var j in this.moduleLoadQueue[moduleName].resourceSet ){ |
737 | | - // Check if we have a multi-set array: |
738 | | - if( typeof this.moduleLoadQueue[moduleName].resourceSet[j] == 'object' ){ |
739 | | - moduleList = $j.merge( moduleList, this.moduleLoadQueue[moduleName].resourceSet[j] ); |
740 | | - } else { |
741 | | - moduleList = $j.merge( moduleList, [ this.moduleLoadQueue[moduleName].resourceSet[j] ] ); |
742 | | - } |
743 | | - } |
744 | | - return moduleList; |
745 | | - }, |
746 | | - /** |
747 | | - * Loads javascript or css associated with a resourceName |
748 | | - * |
749 | | - * @param {String} |
750 | | - * resourceName Name of resource to load |
751 | | - * @param {Function} |
752 | | - * callback Function to run once resource is loaded |
753 | | - */ |
754 | | - loadResource: function( resourceName , callback) { |
755 | | - // mw.log("LoadResource:" + resourceName ); |
756 | | - var _this = this; |
757 | | - |
758 | | - // Check for css dependency on resource name |
759 | | - if( this.resourceStyleDependency[ resourceName ] ) { |
760 | | - if( ! mw.isset( this.resourceStyleDependency[ resourceName ] )){ |
761 | | - mw.log("loadResource:: dependent css resource: " + this.resourceStyleDependency[ resourceName ] ); |
762 | | - _this.loadResource( this.resourceStyleDependency[ resourceName ] , function() { |
763 | | - // Continue the original loadResource request. |
764 | | - _this.loadResource( resourceName, callback ); |
765 | | - }); |
766 | | - return ; |
767 | | - } |
768 | | - } |
769 | | - |
770 | | - // Make sure the resource is not already defined: |
771 | | - if ( mw.isset( resourceName ) ) { |
772 | | - // mw.log( 'Class ( ' + resourceName + ' ) already defined ' ); |
773 | | - callback( resourceName ); |
774 | | - return ; |
775 | | - } |
776 | | - |
777 | | - // Setup the Script Request var: |
778 | | - var scriptRequest = null; |
779 | | - |
780 | | - |
781 | | - // If the scriptloader is enabled use the resourceName as the |
782 | | - // scriptRequest: |
783 | | - if( mw.getResourceLoaderPath() ) { |
784 | | - scriptRequest = resourceName; |
785 | | - }else{ |
786 | | - // Get the resource url: |
787 | | - var baseClassPath = this.getResourcePath( resourceName ); |
788 | | - // Add the mwEmbed path if not a root path or a full url |
789 | | - if( baseClassPath.indexOf( '/' ) !== 0 && |
790 | | - baseClassPath.indexOf( '://' ) === -1 ) { |
791 | | - scriptRequest = mw.getMwEmbedPath() + baseClassPath; |
792 | | - }else{ |
793 | | - scriptRequest = baseClassPath; |
794 | | - } |
795 | | - if( ! scriptRequest ) { |
796 | | - mw.log( "Error Could not get url for resource " + resourceName ); |
797 | | - return false; |
798 | | - } |
799 | | - } |
800 | | - // Include resource defined check for older browsers |
801 | | - var resourceDone = false; |
802 | | - |
803 | | - // Set the loadDone callback per the provided resourceName |
804 | | - mw.setLoadDoneCB( resourceName, callback ); |
805 | | - // Issue the request to load the resource (include resource name in |
806 | | - // result callback: |
807 | | - mw.getScript( scriptRequest, function( scriptRequest ) { |
808 | | - // If its a "style sheet" manually set its resource to true |
809 | | - var ext = scriptRequest.substr( scriptRequest.split('?')[0].lastIndexOf( '.' ), 4 ).toLowerCase(); |
810 | | - if( ext == '.css' && resourceName.substr(0,8) == 'mw.style' ){ |
811 | | - mw.style[ resourceName.substr( 9 ) ] = true; |
812 | | - } |
813 | | - |
814 | | - // Send warning if resourceName is not defined |
815 | | - if(! mw.isset( resourceName ) |
816 | | - && mwLoadDoneCB[ resourceName ] != 'done' ) { |
817 | | - mw.log( 'Possible Error: ' + resourceName +' not set in time, or not defined in:' + "\n" |
818 | | - + _this.getResourcePath( resourceName ) ); |
819 | | - } |
820 | | - |
821 | | - // If ( debug mode ) and the script include is missing resource |
822 | | - // messages |
823 | | - // do a separate request to retrieve the msgs |
824 | | - if( mw.currentClassMissingMessages ) { |
825 | | - mw.log( " resourceName " + resourceName + " is missing messages" ); |
826 | | - // Reset the currentClassMissingMessages flag |
827 | | - mw.currentClassMissingMessages = false; |
828 | | - |
829 | | - // Load msgs for this resource: |
830 | | - mw.loadResourceMessages( resourceName, function() { |
831 | | - // Run the onDone callback |
832 | | - mw.loadDone( resourceName ); |
833 | | - } ); |
834 | | - } else { |
835 | | - // If not using the resource loader make sure the |
836 | | - // resourceName is available before firing the loadDone |
837 | | - if( !mw.getResourceLoaderPath() ) { |
838 | | - mw.waitForObject( resourceName, function( resourceName ) { |
839 | | - // Once object is ready run loadDone |
840 | | - mw.loadDone( resourceName ); |
841 | | - } ); |
842 | | - } else { |
843 | | - // loadDone should be appended to the bottom of the |
844 | | - // resource loader response |
845 | | - // mw.loadDone( resourceName ); |
846 | | - } |
847 | | - } |
848 | | - } ); |
849 | | - }, |
850 | | - |
851 | | - /** |
852 | | - * Adds a module to the mwLoader object |
853 | | - * |
854 | | - * @param {String} |
855 | | - * name Name of module |
856 | | - * @param {Function} |
857 | | - * moduleLoader Function that loads dependencies for a module |
858 | | - */ |
859 | | - addModuleLoader: function( name, moduleLoader ) { |
860 | | - this.moduleLoaders [ name ] = moduleLoader; |
861 | | - }, |
862 | | - |
863 | | - /** |
864 | | - * Adds resource file path key value pairs |
865 | | - * |
866 | | - * @param {Object} |
867 | | - * resourceSet JSON formated list of resource name file path |
868 | | - * pairs. |
869 | | - * |
870 | | - * resourceSet must be strict JSON to allow the php scriptLoader to |
871 | | - * parse the file paths. |
872 | | - */ |
873 | | - addResourcePaths: function( resourceSet ) { |
874 | | - var prefix = ( mw.getConfig( 'loaderContext' ) )? |
875 | | - mw.getConfig( 'loaderContext' ): ''; |
876 | | - |
877 | | - for( var i in resourceSet ) { |
878 | | - this.resourcePaths[ i ] = prefix + resourceSet[ i ]; |
879 | | - } |
880 | | - }, |
881 | | - |
882 | | - /* |
883 | | - * Adds a named style sheet dependency to a named resource |
884 | | - * |
885 | | - * @parma {Object} resourceSet JSON formated list of resource names and |
886 | | - * associated style sheet names |
887 | | - */ |
888 | | - addStyleResourceDependency: function( resourceSet ){ |
889 | | - for( var i in resourceSet ){ |
890 | | - this.resourceStyleDependency[ i ] = resourceSet[i]; |
891 | | - } |
892 | | - }, |
893 | | - |
894 | | - /** |
895 | | - * Get a resource path from a resourceName if no resource found return |
896 | | - * false |
897 | | - */ |
898 | | - getResourcePath: function( resourceName ) { |
899 | | - if( this.resourcePaths[ resourceName ] ) |
900 | | - return this.resourcePaths[ resourceName ] |
901 | | - return false; |
902 | | - } |
903 | | - } |
904 | | - |
905 | | - /** |
906 | | - * Load done callback for script loader |
907 | | - * |
908 | | - * @param {String} |
909 | | - * requestName Name of the load request |
910 | | - */ |
911 | | - mw.loadDone = function( requestName ) { |
912 | | - if( !mwLoadDoneCB[ requestName ] ) { |
913 | | - return true; |
914 | | - } |
915 | | - while( mwLoadDoneCB[ requestName ].length ) { |
916 | | - // check if mwLoadDoneCB is already "done" |
917 | | - // the function list is not an object |
918 | | - if( typeof mwLoadDoneCB[ requestName ] != 'object' ) |
919 | | - { |
920 | | - break; |
921 | | - } |
922 | | - var func = mwLoadDoneCB[ requestName ].pop(); |
923 | | - if( typeof func == 'function' ) { |
924 | | - // mw.log( "LoadDone: " + requestName + ' run callback::' + |
925 | | - // func); |
926 | | - func( requestName ); |
927 | | - }else{ |
928 | | - mw.log('mwLoadDoneCB: Error non callback function on stack'); |
929 | | - } |
930 | | - } |
931 | | - // Set the load request name to done |
932 | | - mwLoadDoneCB[ requestName ] = 'done'; |
933 | | - }; |
934 | | - |
935 | | - /** |
936 | | - * Set a load done callback |
937 | | - * |
938 | | - * @param {String} |
939 | | - * requestName Name of resource or request set |
940 | | - * @param {Function} |
941 | | - * callback Function called once requestName is ready |
942 | | - */ |
943 | | - mw.setLoadDoneCB = function( requestName, callback ) { |
944 | | - // If the requestName is already done loading just callback |
945 | | - if( mwLoadDoneCB[ requestName ] == 'done' ) { |
946 | | - callback( requestName ) |
947 | | - } |
948 | | - // Setup the function queue if unset |
949 | | - if( typeof mwLoadDoneCB[ requestName ] != 'object' ) { |
950 | | - mwLoadDoneCB[ requestName ] = []; |
951 | | - } |
952 | | - mwLoadDoneCB[ requestName ].push( callback ); |
953 | | - }; |
954 | | - |
955 | | - /** |
956 | | - * Shortcut entry points / convenience functions: Lets you write mw.load() |
957 | | - * instead of mw.loader.load() only these entry points should be used. |
958 | | - * |
959 | | - * future closure optimizations could minify internal function names |
960 | | - */ |
961 | | - |
962 | | - /** |
963 | | - * Load Object entry point: Loads a requested set of javascript |
964 | | - */ |
965 | | - mw.load = function( loadRequest, callback ) { |
966 | | - return mw.loader.load( loadRequest, callback ); |
967 | | - } |
968 | | - |
969 | | - /** |
970 | | - * Add module entry point: Adds a module to the mwLoader object |
971 | | - */ |
972 | | - mw.addModuleLoader = function ( name, loaderFunction ) { |
973 | | - return mw.loader.addModuleLoader( name, loaderFunction ); |
974 | | - } |
975 | | - |
976 | | - /** |
977 | | - * Add Class File Paths entry point: |
978 | | - */ |
979 | | - mw.addResourcePaths = function ( resourceSet ) { |
980 | | - return mw.loader.addResourcePaths( resourceSet ); |
981 | | - } |
982 | | - |
983 | | - mw.addStyleResourceDependency = function ( resourceSet ) { |
984 | | - return mw.loader.addStyleResourceDependency( resourceSet ); |
985 | | - } |
986 | | - |
987 | | - /** |
988 | | - * Get Class File Path entry point: |
989 | | - */ |
990 | | - mw.getResourcePath = function( resourceName ) { |
991 | | - return mw.loader.getResourcePath( resourceName ); |
992 | | - } |
993 | | - |
994 | | - |
995 | | - /** |
996 | | - * Utility Functions |
997 | | - */ |
998 | | - |
999 | | - /** |
1000 | | - * addLoaderDialog small helper for displaying a loading dialog |
1001 | | - * |
1002 | | - * @param {String} |
1003 | | - * dialogHtml text Html of the loader msg |
1004 | | - */ |
1005 | | - mw.addLoaderDialog = function( dialogHtml ) { |
1006 | | - $dialog = mw.addDialog( { |
1007 | | - 'title' : dialogHtml, |
1008 | | - 'content' : dialogHtml + '<br>' + |
1009 | | - $j('<div />') |
1010 | | - .loadingSpinner() |
1011 | | - .html() |
1012 | | - }); |
1013 | | - return $dialog; |
1014 | | - } |
1015 | | - |
1016 | | - /** |
1017 | | - * Mobile Safari has special properties for html5 video:: |
1018 | | - * |
1019 | | - * NOTE: should be moved to browser detection script |
1020 | | - */ |
1021 | | - mw.isMobileSafari = function() { |
1022 | | - // check mobile safari foce ( for debug ) |
1023 | | - if( mw.getConfig( 'forceMobileSafari' ) ){ |
1024 | | - return true; |
1025 | | - } |
1026 | | - if ((navigator.userAgent.indexOf('iPhone') != -1) || |
1027 | | - (navigator.userAgent.indexOf('iPod') != -1) || |
1028 | | - (navigator.userAgent.indexOf('iPad') != -1)) { |
1029 | | - return true; |
1030 | | - } |
1031 | | - return false; |
1032 | | - } |
1033 | | - |
1034 | | - /** |
1035 | | - * Add a (temporary) dialog window: |
1036 | | - * |
1037 | | - * @param {Object} with following keys: |
1038 | | - * title: {String} Title string for the dialog |
1039 | | - * content: {String} to be inserted in msg box |
1040 | | - * buttons: {Object} A button object for the dialog Can be a string |
1041 | | - * for the close button |
1042 | | - * any jquery.ui.dialog option |
1043 | | - */ |
1044 | | - mw.addDialog = function ( options ) { |
1045 | | - // Remove any other dialog |
1046 | | - $j( '#mwTempLoaderDialog' ).remove(); |
1047 | | - |
1048 | | - if( !options){ |
1049 | | - options = {}; |
1050 | | - } |
1051 | | - |
1052 | | - // Extend the default options with provided options |
1053 | | - var options = $j.extend({ |
1054 | | - 'bgiframe': true, |
1055 | | - 'draggable': true, |
1056 | | - 'resizable': false, |
1057 | | - 'modal': true |
1058 | | - }, options ); |
1059 | | - |
1060 | | - if( ! options.title || ! options.content ){ |
1061 | | - mw.log("Error: mwEmbed addDialog missing required options ( title, content ) ") |
1062 | | - return ; |
1063 | | - } |
1064 | | - |
1065 | | - // Append the dialog div on top: |
1066 | | - $j( 'body' ).append( |
1067 | | - $j('<div />') |
1068 | | - .attr( { |
1069 | | - 'id' : "mwTempLoaderDialog", |
1070 | | - 'title' : options.title |
1071 | | - }) |
1072 | | - .css({ |
1073 | | - 'display': 'none' |
1074 | | - }) |
1075 | | - .append( options.content ) |
1076 | | - ); |
1077 | | - |
1078 | | - // Build the uiRequest |
1079 | | - var uiRequest = [ '$j.ui.dialog' ]; |
1080 | | - if( options.draggable ){ |
1081 | | - uiRequest.push( '$j.ui.draggable' ) |
1082 | | - } |
1083 | | - if( options.resizable ){ |
1084 | | - uiRequest.push( '$j.ui.resizable' ); |
1085 | | - } |
1086 | | - |
1087 | | - // Special button string |
1088 | | - if ( typeof options.buttons == 'string' ) { |
1089 | | - var buttonMsg = options.buttons; |
1090 | | - buttons = { }; |
1091 | | - options.buttons[ buttonMsg ] = function() { |
1092 | | - $j( this ).dialog( 'close' ); |
1093 | | - } |
1094 | | - } |
1095 | | - |
1096 | | - // Load the dialog resources |
1097 | | - mw.load([ |
1098 | | - [ |
1099 | | - '$j.ui' |
1100 | | - ], |
1101 | | - uiRequest |
1102 | | - ], function() { |
1103 | | - $j( '#mwTempLoaderDialog' ).dialog( options ); |
1104 | | - } ); |
1105 | | - return $j( '#mwTempLoaderDialog' ); |
1106 | | - } |
1107 | | - |
1108 | | - /** |
1109 | | - * Close the loader dialog created with addLoaderDialog |
1110 | | - */ |
1111 | | - mw.closeLoaderDialog = function() { |
1112 | | - // Make sure the dialog resource is present |
1113 | | - if( !mw.isset( '$j.ui.dialog' ) ) { |
1114 | | - return false; |
1115 | | - } |
1116 | | - $j( '#mwTempLoaderDialog' ).dialog( 'destroy' ).remove(); |
1117 | | - } |
1118 | | - |
1119 | | - |
1120 | | - /** |
1121 | | - * Similar to php isset function checks if the variable exists. Does a safe |
1122 | | - * check of a descendant method or variable |
1123 | | - * |
1124 | | - * @param {String} |
1125 | | - * objectPath |
1126 | | - * @return {Boolean} true if objectPath exists false if objectPath is |
1127 | | - * undefined |
1128 | | - */ |
1129 | | - mw.isset = function( objectPath ) { |
1130 | | - if ( !objectPath ) { |
1131 | | - return false; |
1132 | | - } |
1133 | | - var pathSet = objectPath.split( '.' ); |
1134 | | - var cur_path = ''; |
1135 | | - |
1136 | | - for ( var p = 0; p < pathSet.length; p++ ) { |
1137 | | - cur_path = ( cur_path == '' ) ? cur_path + pathSet[p] : cur_path + '.' + pathSet[p]; |
1138 | | - eval( 'var ptest = typeof ( ' + cur_path + ' ); ' ); |
1139 | | - if ( ptest == 'undefined' ) { |
1140 | | - return false; |
1141 | | - } |
1142 | | - } |
1143 | | - return true; |
1144 | | - } |
1145 | | - |
1146 | | - /** |
1147 | | - * Wait for a object to be defined and the call the callback |
1148 | | - * |
1149 | | - * @param {Object} |
1150 | | - * objectName Name of object to be defined |
1151 | | - * @param {Function} |
1152 | | - * callback Function to call once object is defined |
1153 | | - * @param {Null} |
1154 | | - * callNumber Used internally to keep track of number of times |
1155 | | - * waitForObject has been called |
1156 | | - */ |
1157 | | - var waitTime = 1200; // About 30 seconds |
1158 | | - mw.waitForObject = function( objectName, callback, _callNumber) { |
1159 | | - // mw.log( 'waitForObject: ' + objectName + ' cn: ' + _callNumber); |
1160 | | - |
1161 | | - // Increment callNumber: |
1162 | | - if( !_callNumber ) { |
1163 | | - _callNumber = 1; |
1164 | | - } else { |
1165 | | - _callNumber++; |
1166 | | - } |
1167 | | - |
1168 | | - if( _callNumber > waitTime ) { |
1169 | | - mw.log( "Error: waiting for object: " + objectName + ' timeout ' ); |
1170 | | - callback( false ); |
1171 | | - return ; |
1172 | | - } |
1173 | | - |
1174 | | - // If the object is defined ( or we are done loading from a callback ) |
1175 | | - if ( mw.isset( objectName ) || mwLoadDoneCB[ objectName ] == 'done' ) { |
1176 | | - callback( objectName ) |
1177 | | - }else{ |
1178 | | - setTimeout( function( ) { |
1179 | | - mw.waitForObject( objectName, callback, _callNumber); |
1180 | | - }, 25); |
1181 | | - } |
1182 | | - } |
1183 | | - |
1184 | | - /** |
1185 | | - * Check if an object is empty or if its an empty string. |
1186 | | - * |
1187 | | - * @param {Object} |
1188 | | - * object Object to be checked |
1189 | | - */ |
1190 | | - mw.isEmpty = function( object ) { |
1191 | | - if( typeof object == 'string' ) { |
1192 | | - if( object == '' ) return true; |
1193 | | - // Non empty string: |
1194 | | - return false; |
1195 | | - } |
1196 | | - |
1197 | | - // If an array check length: |
1198 | | - if( Object.prototype.toString.call( object ) === "[object Array]" |
1199 | | - && object.length == 0 ) { |
1200 | | - return true; |
1201 | | - } |
1202 | | - |
1203 | | - // Else check as an object: |
1204 | | - for( var i in object ) { return false; } |
1205 | | - |
1206 | | - // Else object is empty: |
1207 | | - return true; |
1208 | | - } |
1209 | | - |
1210 | | - /** |
1211 | | - * Log a string msg to the console |
1212 | | - * |
1213 | | - * all mw.log statements will be removed on minification so lots of mw.log |
1214 | | - * calls will not impact performance in non debug mode |
1215 | | - * |
1216 | | - * @param {String} |
1217 | | - * string String to output to console |
1218 | | - */ |
1219 | | - mw.log = function( string ) { |
1220 | | - // Add any prepend debug strings if necessary |
1221 | | - if ( mw.getConfig( 'pre-append-log' ) ){ |
1222 | | - string = mw.getConfig( 'pre-append-log' ) + string; |
1223 | | - } |
1224 | | - |
1225 | | - if ( window.console ) { |
1226 | | - window.console.log( string ); |
1227 | | - } else { |
1228 | | - /** |
1229 | | - * Old IE and non-Firebug debug: ( commented out for now ) |
1230 | | - */ |
1231 | | - /*var log_elm = document.getElementById('mv_js_log'); |
1232 | | - if(!log_elm) { |
1233 | | - document.getElementsByTagName("body")[0].innerHTML += '<div ' + |
1234 | | - 'style="position:absolute;z-index:500;bottom:0px;left:0px;right:0px;height:200px;">' + |
1235 | | - '<textarea id="mv_js_log" cols="120" rows="12"></textarea>' + |
1236 | | - '</div>'; |
1237 | | - } |
1238 | | - var log_elm = document.getElementById('mv_js_log'); |
1239 | | - if(log_elm) { |
1240 | | - log_elm.value+=string+"\n"; |
1241 | | - }*/ |
1242 | | - } |
1243 | | - } |
1244 | | - |
1245 | | - // Setup the local mwOnLoadFunctions array: |
1246 | | - var mwOnLoadFunctions = []; |
1247 | | - |
1248 | | - // mw Ready flag ( set once mwEmbed is ready ) |
1249 | | - var mwReadyFlag = false; |
1250 | | - |
1251 | | - /** |
1252 | | - * Enables load hooks to run once mwEmbeed is "ready" Will ensure jQuery is |
1253 | | - * available, is in the $j namespace and mw interfaces and configuration has |
1254 | | - * been loaded and applied |
1255 | | - * |
1256 | | - * This is different from jQuery(document).ready() ( jQuery ready is not |
1257 | | - * friendly with dynamic includes and not friendly with core interface |
1258 | | - * asynchronous build out. ) |
1259 | | - * |
1260 | | - * @param {Function} |
1261 | | - * callback Function to run once DOM and jQuery are ready |
1262 | | - */ |
1263 | | - mw.ready = function( callback ) { |
1264 | | - if( mwReadyFlag === false ) { |
1265 | | - // Add the callbcak to the onLoad function stack |
1266 | | - mwOnLoadFunctions.push ( callback ); |
1267 | | - } else { |
1268 | | - // If mwReadyFlag is already "true" issue the callback directly: |
1269 | | - callback(); |
1270 | | - } |
1271 | | - } |
1272 | | - |
1273 | | - /** |
1274 | | - * Runs all the queued functions called by mwEmbedSetup |
1275 | | - */ |
1276 | | - mw.runReadyFunctions = function ( ) { |
1277 | | - mw.log('mw.runReadyFunctions: ' + mwOnLoadFunctions.length ); |
1278 | | - // Run any pre-setup ready functions |
1279 | | - while( preMwEmbedReady.length ){ |
1280 | | - preMwEmbedReady.shift()(); |
1281 | | - } |
1282 | | - // Run all the queued functions: |
1283 | | - while( mwOnLoadFunctions.length ) { |
1284 | | - mwOnLoadFunctions.shift()(); |
1285 | | - } |
1286 | | - |
1287 | | - // Sets mwReadyFlag to true so that future mw.ready run the |
1288 | | - // callback directly |
1289 | | - mwReadyFlag = true; |
1290 | | - |
1291 | | - // Once we have run all the queued functions |
1292 | | - mw.loader.runModuleLoadQueue(); |
1293 | | - |
1294 | | - } |
1295 | | - |
1296 | | - |
1297 | | - /** |
1298 | | - * Wrapper for jQuery getScript, Uses the scriptLoader if enabled |
1299 | | - * |
1300 | | - * |
1301 | | - * @param {String} |
1302 | | - * scriptRequest The requested path or resourceNames for the |
1303 | | - * scriptLoader |
1304 | | - * @param {Function} |
1305 | | - * callback Function to call once script is loaded |
1306 | | - */ |
1307 | | - mw.getScript = function( scriptRequest, callback ) { |
1308 | | - // mw.log( "mw.getScript::" + scriptRequest ); |
1309 | | - // Setup the local scope callback instace |
1310 | | - var myCallback = function(){ |
1311 | | - if( callback ) { |
1312 | | - callback( scriptRequest ); |
1313 | | - } |
1314 | | - } |
1315 | | - // Set the base url based scriptLoader availability & type of |
1316 | | - // scriptRequest |
1317 | | - // ( presently script loader only handles "classes" not relative urls: |
1318 | | - var scriptLoaderPath = mw.getResourceLoaderPath(); |
1319 | | - |
1320 | | - // Check if its a resource name, ( ie does not start with "/" and does |
1321 | | - // not include :// |
1322 | | - var isResourceName = ( scriptRequest.indexOf('://') == -1 && scriptRequest.indexOf('/') !== 0 )? true : false; |
1323 | | - |
1324 | | - var ext = scriptRequest.substr( scriptRequest.lastIndexOf( '.' ), 4 ).toLowerCase(); |
1325 | | - var isCssFile = ( ext == '.css') ? true : false ; |
1326 | | - |
1327 | | - if( scriptLoaderPath && isResourceName ) { |
1328 | | - url = scriptLoaderPath + '?class=' + scriptRequest; |
1329 | | - } else { |
1330 | | - // Add the mwEmbed path if a relative path request |
1331 | | - url = ( isResourceName ) ? mw.getMwEmbedPath() : ''; |
1332 | | - url+= scriptRequest; |
1333 | | - } |
1334 | | - |
1335 | | - // Add on the request parameters to the url: |
1336 | | - url += ( url.indexOf( '?' ) == -1 )? '?' : '&'; |
1337 | | - url += mw.getUrlParam(); |
1338 | | - |
1339 | | - // Only log sciprts ( Css is logged via "add css" ) |
1340 | | - if( !isCssFile ){ |
1341 | | - mw.log( 'mw.getScript: ' + url ); |
1342 | | - } |
1343 | | - |
1344 | | - // If jQuery is available and debug is off load the scirpt via jQuery |
1345 | | - // ( will use XHR if on same domain ) |
1346 | | - if( mw.isset( 'window.jQuery' ) |
1347 | | - && mw.getConfig( 'debug' ) === false |
1348 | | - && typeof $j != 'undefined' |
1349 | | - && !isCssFile ) |
1350 | | - { |
1351 | | - $j.getScript( url, myCallback); |
1352 | | - return ; |
1353 | | - } |
1354 | | - |
1355 | | - /** |
1356 | | - * No jQuery OR In debug mode OR Is css file |
1357 | | - * :: inject the script instead of doing an XHR eval |
1358 | | - */ |
1359 | | - |
1360 | | - // load style sheet directly if requested loading css |
1361 | | - if( isCssFile ){ |
1362 | | - mw.getStyleSheet( url, myCallback); |
1363 | | - return ; |
1364 | | - } |
1365 | | - |
1366 | | - // Load and bind manually: ( copied from jQuery ajax function ) |
1367 | | - var head = document.getElementsByTagName("head")[ 0 ]; |
1368 | | - var script = document.createElement("script"); |
1369 | | - script.setAttribute( 'src', url ); |
1370 | | - |
1371 | | - // Attach handlers ( if using script loader it issues onDone callback as |
1372 | | - // well ) |
1373 | | - script.onload = script.onreadystatechange = function() { |
1374 | | - if (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") { |
1375 | | - myCallback(); |
1376 | | - } |
1377 | | - }; |
1378 | | - // mw.log(" append script: " + script.src ); |
1379 | | - // Append the script to the DOM: |
1380 | | - head.appendChild( script ); |
1381 | | - }; |
1382 | | - |
1383 | | - /** |
1384 | | - * Add a style sheet string to the document head |
1385 | | - * |
1386 | | - * @param {String} |
1387 | | - * cssResourceName Name of style sheet that has been defined |
1388 | | - * @param {String} |
1389 | | - * cssString Css Payload to be added to head of document |
1390 | | - */ |
1391 | | - mw.addStyleString = function( cssResourceName, cssString ) { |
1392 | | - if( mw.style[ cssResourceName ] ) { |
1393 | | - mw.log(" Style: ( " + cssResourceName + ' ) already set' ); |
1394 | | - return true; |
1395 | | - } |
1396 | | - // Set the style to true ( to not request it again ) |
1397 | | - mw.style[ cssResourceName ] = true; |
1398 | | - // Add the spinner directly ( without jQuery in case we have to |
1399 | | - // dynamically load jQuery ) |
1400 | | - mw.log( 'Adding style:' + cssResourceName + " to dom " ); |
1401 | | - var styleNode = document.createElement('style'); |
1402 | | - styleNode.type = "text/css"; |
1403 | | - // Use cssText or createTextNode depending on browser: |
1404 | | - if( ( window.attachEvent && !window.opera ) ) { |
1405 | | - styleNode.styleSheet.cssText = cssString; |
1406 | | - } else { |
1407 | | - var styleText = document.createTextNode( cssString ); |
1408 | | - styleNode.appendChild( styleText ); |
1409 | | - } |
1410 | | - var head = document.getElementsByTagName("head")[0]; |
1411 | | - head.appendChild( styleNode ); |
1412 | | - }; |
1413 | | - |
1414 | | - /** |
1415 | | - * Get a style sheet and append the style sheet to the DOM |
1416 | | - * |
1417 | | - * @param {Mixed} |
1418 | | - * {String} url Url of the style sheet to be loaded {Function} |
1419 | | - * callback Function called once sheet is ready |
1420 | | - */ |
1421 | | - mw.getStyleSheet = function( url , callback) { |
1422 | | - // Add URL params ( if not already included ) |
1423 | | - if ( url.indexOf( '?' ) == -1 ) { |
1424 | | - url += '?' + mw.getUrlParam(); |
1425 | | - } |
1426 | | - |
1427 | | - // Check if style sheet is already included: |
1428 | | - var foundSheet = false; |
1429 | | - $j( 'link' ).each( function() { |
1430 | | - var currentSheet = $j( this) .attr( 'href' ); |
1431 | | - var sheetParts = currentSheet.split('?'); |
1432 | | - var urlParts = url.split('?'); |
1433 | | - // if the base url's match check the parameters: |
1434 | | - if( sheetParts[0] == urlParts[0] && sheetParts[1]) { |
1435 | | - // Check if url params match ( sort to do string compare ) |
1436 | | - if( sheetParts[1].split( '&' ).sort().join('') == |
1437 | | - urlParts[1].split('&').sort().join('') ) { |
1438 | | - foundSheet = true; |
1439 | | - } |
1440 | | - } |
1441 | | - } ); |
1442 | | - if( foundSheet ) { |
1443 | | - mw.log( 'skiped sheet: ' + url); |
1444 | | - if( callback) { |
1445 | | - callback(); |
1446 | | - } |
1447 | | - return ; |
1448 | | - } |
1449 | | - |
1450 | | - mw.log( ' add css: ' + url ); |
1451 | | - $j( 'head' ).append( |
1452 | | - $j('<link />').attr( { |
1453 | | - 'rel' : 'stylesheet', |
1454 | | - 'type' : 'text/css', |
1455 | | - 'href' : url |
1456 | | - } ) |
1457 | | - ); |
1458 | | - // No easy way to check css "onLoad" attribute |
1459 | | - // In production sheets are loaded via resource loader and fire the |
1460 | | - // onDone function call. |
1461 | | - if( callback ) { |
1462 | | - callback(); |
1463 | | - } |
1464 | | - }; |
1465 | | - |
1466 | | - |
1467 | | - // Local mwEmbedPath variable ( for cache of mw.getMwEmbedPath ) |
1468 | | - var mwEmbedPath = null; |
1469 | | - |
1470 | | - /** |
1471 | | - * Get the path to the mwEmbed folder |
1472 | | - */ |
1473 | | - mw.getMwEmbedPath = function() { |
1474 | | - if ( mwEmbedPath ) { |
1475 | | - return mwEmbedPath; |
1476 | | - } |
1477 | | - |
1478 | | - // Get mwEmbed src: |
1479 | | - var src = mw.getMwEmbedSrc(); |
1480 | | - var mwpath = null; |
1481 | | - |
1482 | | - // Check for direct include of the mwEmbed.js |
1483 | | - if ( src.indexOf( 'mwEmbed.js' ) !== -1 ) { |
1484 | | - mwpath = src.substr( 0, src.indexOf( 'mwEmbed.js' ) ); |
1485 | | - } |
1486 | | - |
1487 | | - // Check for scriptLoader include of mwEmbed: |
1488 | | - if ( src.indexOf( 'mwResourceLoader.php' ) !== -1 ) { |
1489 | | - // Script loader is in the root of MediaWiki, Include the default |
1490 | | - // mwEmbed extension path: |
1491 | | - mwpath = src.substr( 0, src.indexOf( 'mwResourceLoader.php' ) ) + mw.getConfig( 'mediaWikiEmbedPath' ); |
1492 | | - } |
1493 | | - |
1494 | | - // resource loader has ResourceLoader name when local: |
1495 | | - if( src.indexOf( 'ResourceLoader.php' ) !== -1 ) { |
1496 | | - mwpath = src.substr( 0, src.indexOf( 'ResourceLoader.php' ) ); |
1497 | | - } |
1498 | | - |
1499 | | - // For static packages mwEmbed packages start with: "mwEmbed-" |
1500 | | - if( src.indexOf( 'mwEmbed-' ) !== -1 && src.indexOf( '-static' ) !== -1 ) { |
1501 | | - mwpath = src.substr( 0, src.indexOf( 'mwEmbed-' ) ); |
1502 | | - } |
1503 | | - |
1504 | | - // Error out if we could not get the path: |
1505 | | - if( mwpath === null ) { |
1506 | | - mw.log( "Error could not get mwEmbed path " ); |
1507 | | - return ; |
1508 | | - } |
1509 | | - |
1510 | | - // Update the cached var with the absolute path: |
1511 | | - mwEmbedPath = mw.absoluteUrl( mwpath ) ; |
1512 | | - return mwEmbedPath; |
1513 | | - } |
1514 | | - |
1515 | | - /** |
1516 | | - * Get Script loader path |
1517 | | - * |
1518 | | - * @returns {String}|{Boolean} Url of the scriptLodaer false if the |
1519 | | - * scriptLoader is not used |
1520 | | - */ |
1521 | | - mw.getResourceLoaderPath = function( ) { |
1522 | | - var src = mw.getMwEmbedSrc(); |
1523 | | - if ( src.indexOf( 'mwResourceLoader.php' ) !== -1 || |
1524 | | - src.indexOf( 'ResourceLoader.php' ) !== -1 ) |
1525 | | - { |
1526 | | - // Return just the script part of the url |
1527 | | - return src.split('?')[0]; |
1528 | | - } |
1529 | | - return false; |
1530 | | - } |
1531 | | - |
1532 | | - /** |
1533 | | - * Given a float number of seconds, returns npt format response. ( ignore |
1534 | | - * days for now ) |
1535 | | - * |
1536 | | - * @param {Float} |
1537 | | - * sec Seconds |
1538 | | - * @param {Boolean} |
1539 | | - * show_ms If milliseconds should be displayed. |
1540 | | - * @return {Float} String npt format |
1541 | | - */ |
1542 | | - mw.seconds2npt = function( sec, show_ms ) { |
1543 | | - if ( isNaN( sec ) ) { |
1544 | | - mw.log("Warning: trying to get npt time on NaN:" + sec); |
1545 | | - return '0:00:00'; |
1546 | | - } |
1547 | | - |
1548 | | - var tm = mw.seconds2Measurements( sec ) |
1549 | | - |
1550 | | - // Round the number of seconds to the required number of significant |
1551 | | - // digits |
1552 | | - if ( show_ms ) { |
1553 | | - tm.seconds = Math.round( tm.seconds * 1000 ) / 1000; |
1554 | | - } else { |
1555 | | - tm.seconds = Math.round( tm.seconds ); |
1556 | | - } |
1557 | | - if ( tm.seconds < 10 ){ |
1558 | | - tm.seconds = '0' + tm.seconds; |
1559 | | - } |
1560 | | - if( tm.hours == 0 ){ |
1561 | | - hoursStr = '' |
1562 | | - } else { |
1563 | | - if ( tm.minutes < 10 ) |
1564 | | - tm.minutes = '0' + tm.minutes; |
1565 | | - |
1566 | | - hoursStr = tm.hours + ":"; |
1567 | | - } |
1568 | | - return hoursStr + tm.minutes + ":" + tm.seconds; |
1569 | | - } |
1570 | | - |
1571 | | - /** |
1572 | | - * Given seconds return array with 'days', 'hours', 'min', 'seconds' |
1573 | | - * |
1574 | | - * @param {float} |
1575 | | - * sec Seconds to be converted into time measurements |
1576 | | - */ |
1577 | | - mw.seconds2Measurements = function ( sec ){ |
1578 | | - var tm = {}; |
1579 | | - tm.days = Math.floor( sec / ( 3600 * 24 ) ) |
1580 | | - tm.hours = Math.floor( sec / 3600 ); |
1581 | | - tm.minutes = Math.floor( ( sec / 60 ) % 60 ); |
1582 | | - tm.seconds = sec % 60; |
1583 | | - return tm; |
1584 | | - } |
1585 | | - |
1586 | | - /** |
1587 | | - * Take hh:mm:ss,ms or hh:mm:ss.ms input, return the number of seconds |
1588 | | - * |
1589 | | - * @param {String} |
1590 | | - * npt_str NPT time string |
1591 | | - * @return {Float} Number of seconds |
1592 | | - */ |
1593 | | - mw.npt2seconds = function ( npt_str ) { |
1594 | | - if ( !npt_str ) { |
1595 | | - // mw.log('npt2seconds:not valid ntp:'+ntp); |
1596 | | - return false; |
1597 | | - } |
1598 | | - // Strip {npt:}01:02:20 or 32{s} from time if present |
1599 | | - npt_str = npt_str.replace( /npt:|s/g, '' ); |
1600 | | - |
1601 | | - var hour = 0; |
1602 | | - var min = 0; |
1603 | | - var sec = 0; |
1604 | | - |
1605 | | - times = npt_str.split( ':' ); |
1606 | | - if ( times.length == 3 ) { |
1607 | | - sec = times[2]; |
1608 | | - min = times[1]; |
1609 | | - hour = times[0]; |
1610 | | - } else if ( times.length == 2 ) { |
1611 | | - sec = times[1]; |
1612 | | - min = times[0]; |
1613 | | - } else { |
1614 | | - sec = times[0]; |
1615 | | - } |
1616 | | - // Sometimes a comma is used instead of period for ms |
1617 | | - sec = sec.replace( /,\s?/, '.' ); |
1618 | | - // Return seconds float |
1619 | | - return parseInt( hour * 3600 ) + parseInt( min * 60 ) + parseFloat( sec ); |
1620 | | - } |
1621 | | - |
1622 | | - // Local mwEmbedSrc variable ( for cache of mw.getMwEmbedSrc ) |
1623 | | - var mwEmbedSrc = null; |
1624 | | - |
1625 | | - /** |
1626 | | - * Gets the mwEmbed script src attribute |
1627 | | - */ |
1628 | | - mw.getMwEmbedSrc = function() { |
1629 | | - if ( mwEmbedSrc ) { |
1630 | | - return mwEmbedSrc; |
1631 | | - } |
1632 | | - |
1633 | | - // Get all the javascript includes: |
1634 | | - var js_elements = document.getElementsByTagName( "script" ); |
1635 | | - for ( var i = 0; i < js_elements.length; i++ ) { |
1636 | | - // Check for mwEmbed.js and/or script loader |
1637 | | - var src = js_elements[i].getAttribute( "src" ); |
1638 | | - if ( src ) { |
1639 | | - if ( // Check for mwEmbed.js ( debug mode ) |
1640 | | - ( src.indexOf( 'mwEmbed.js' ) !== -1 && src.indexOf( 'MediaWiki:Gadget') == -1 ) |
1641 | | - || // Check for resource loader |
1642 | | - ( |
1643 | | - ( src.indexOf( 'mwResourceLoader.php' ) !== -1 || src.indexOf( 'ResourceLoader.php' ) !== -1 ) |
1644 | | - && |
1645 | | - src.indexOf( 'mwEmbed' ) !== -1 |
1646 | | - ) |
1647 | | - || // Check for static mwEmbed package |
1648 | | - ( src.indexOf( 'mwEmbed' ) !== -1 && src.indexOf( 'static' ) !== -1 ) |
1649 | | - ) { |
1650 | | - mwEmbedSrc = src; |
1651 | | - return mwEmbedSrc; |
1652 | | - } |
1653 | | - } |
1654 | | - } |
1655 | | - mw.log( 'Error: getMwEmbedSrc failed to get script path' ); |
1656 | | - return false; |
1657 | | - } |
1658 | | - |
1659 | | - // Local mwUrlParam variable ( for cache of mw.getUrlParam ) |
1660 | | - var mwUrlParam = null; |
1661 | | - |
1662 | | - /** |
1663 | | - * Get URL Parameters per parameters in the host script include |
1664 | | - */ |
1665 | | - mw.getUrlParam = function() { |
1666 | | - if ( mwUrlParam ) { |
1667 | | - return mwUrlParam; |
1668 | | - } |
1669 | | - |
1670 | | - var mwEmbedSrc = mw.getMwEmbedSrc(); |
1671 | | - var req_param = ''; |
1672 | | - |
1673 | | - // If we already have a URI, add it to the param request: |
1674 | | - var urid = mw.parseUri( mwEmbedSrc ).queryKey['urid'] |
1675 | | - |
1676 | | - // If we're in debug mode, get a fresh unique request key and pass on |
1677 | | - // "debug" param |
1678 | | - if ( mw.parseUri( mwEmbedSrc ).queryKey['debug'] == 'true' ) { |
1679 | | - mw.setConfig( 'debug', true ); |
1680 | | - var d = new Date(); |
1681 | | - req_param += 'urid=' + d.getTime() + '&debug=true'; |
1682 | | - |
1683 | | - } else if ( urid ) { |
1684 | | - // Just pass on the existing urid: |
1685 | | - req_param += 'urid=' + urid; |
1686 | | - } else { |
1687 | | - // Otherwise, Use the mwEmbed version |
1688 | | - req_param += 'urid=' + mw.version; |
1689 | | - } |
1690 | | - |
1691 | | - // Add the language param if present: |
1692 | | - var langKey = mw.parseUri( mwEmbedSrc ).queryKey['uselang']; |
1693 | | - if ( langKey ) |
1694 | | - req_param += '&uselang=' + langKey; |
1695 | | - |
1696 | | - // Update the local cache and return the value |
1697 | | - mwUrlParam = req_param; |
1698 | | - return mwUrlParam; |
1699 | | - } |
1700 | | - |
1701 | | - /** |
1702 | | - * Replace url parameters via newParams key value pairs |
1703 | | - * |
1704 | | - * @param {String} |
1705 | | - * url Source url to be updated |
1706 | | - * @param {Object} |
1707 | | - * newParams key, value paris to swap in |
1708 | | - * @return {String} the updated url |
1709 | | - */ |
1710 | | - mw.replaceUrlParams = function( url, newParams ) { |
1711 | | - var parsedUrl = mw.parseUri( url ); |
1712 | | - |
1713 | | - if ( parsedUrl.protocol != '' ) { |
1714 | | - var new_url = parsedUrl.protocol + '://' + parsedUrl.authority + parsedUrl.path + '?'; |
1715 | | - } else { |
1716 | | - var new_url = parsedUrl.path + '?'; |
1717 | | - } |
1718 | | - |
1719 | | - // Merge new params: |
1720 | | - for( var key in newParams ) { |
1721 | | - parsedUrl.queryKey[ key ] = newParams[ key ]; |
1722 | | - } |
1723 | | - |
1724 | | - // Output to new_url |
1725 | | - var amp = ''; |
1726 | | - for ( var key in parsedUrl.queryKey ) { |
1727 | | - var val = parsedUrl.queryKey[ key ]; |
1728 | | - new_url += amp + key + '=' + val; |
1729 | | - amp = '&'; |
1730 | | - } |
1731 | | - return new_url; |
1732 | | - } |
1733 | | - |
1734 | | - /** |
1735 | | - * parseUri 1.2.2 (c) Steven Levithan <stevenlevithan.com> MIT License |
1736 | | - */ |
1737 | | - mw.parseUri = function (str) { |
1738 | | - var o = mw.parseUri.options, |
1739 | | - m = o.parser[o.strictMode ? "strict" : "loose"].exec(str), |
1740 | | - uri = {}, |
1741 | | - i = 14; |
1742 | | - |
1743 | | - while (i--) uri[o.key[i]] = m[i] || ""; |
1744 | | - |
1745 | | - uri[o.q.name] = {}; |
1746 | | - uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) { |
1747 | | - if ($1) uri[o.q.name][$1] = $2; |
1748 | | - }); |
1749 | | - |
1750 | | - return uri; |
1751 | | - }; |
1752 | | - |
1753 | | - /** |
1754 | | - * Parse URI function |
1755 | | - * |
1756 | | - * For documentation on its usage see: |
1757 | | - * http://stevenlevithan.com/demo/parseuri/js/ |
1758 | | - */ |
1759 | | - mw.parseUri.options = { |
1760 | | - strictMode: false, |
1761 | | - key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", |
1762 | | - "port", "relative", "path", "directory", "file", "query", "anchor"], |
1763 | | - q: { |
1764 | | - name: "queryKey", |
1765 | | - parser: /(?:^|&)([^&=]*)=?([^&]*)/g |
1766 | | - }, |
1767 | | - parser: { |
1768 | | - strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/, |
1769 | | - loose: /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/ |
1770 | | - } |
1771 | | - }; |
1772 | | - |
1773 | | - /** |
1774 | | - * getAbsoluteUrl takes a src and returns the absolute location given the |
1775 | | - * document.URL |
1776 | | - * |
1777 | | - * @param {String} |
1778 | | - * src path or url |
1779 | | - * @return {String} absolute url |
1780 | | - */ |
1781 | | - mw.absoluteUrl = function( src, contextUrl ) { |
1782 | | - var parsedSrc = mw.parseUri( src ); |
1783 | | - // Source is already absolute return: |
1784 | | - if( parsedSrc.protocol != '') { |
1785 | | - return src; |
1786 | | - } |
1787 | | - |
1788 | | - // Get parent Url location the context URL |
1789 | | - if( contextUrl) { |
1790 | | - var parsedUrl = mw.parseUri( contextUrl ); |
1791 | | - } else { |
1792 | | - var parsedUrl = mw.parseUri( document.URL ); |
1793 | | - } |
1794 | | - |
1795 | | - // Check for leading slash: |
1796 | | - if( src.indexOf( '/' ) === 0 ) { |
1797 | | - return parsedUrl.protocol + '://' + parsedUrl.authority + src; |
1798 | | - }else{ |
1799 | | - return parsedUrl.protocol + '://' + parsedUrl.authority + parsedUrl.directory + src; |
1800 | | - } |
1801 | | - }; |
1802 | | - |
1803 | | - /** |
1804 | | - * Escape quotes in a text string |
1805 | | - * |
1806 | | - * @param {String} |
1807 | | - * text String to be escaped |
1808 | | - * @return {string} escaped text string |
1809 | | - */ |
1810 | | - mw.escapeQuotes = function( text ) { |
1811 | | - var re = new RegExp("'","g"); |
1812 | | - text = text.replace(re,"\\'"); |
1813 | | - re = new RegExp("\\n","g"); |
1814 | | - text = text.replace(re,"\\n"); |
1815 | | - return mw.escapeQuotesHTML(text); |
1816 | | - }; |
1817 | | - |
1818 | | - /** |
1819 | | - * Escape an HTML text string |
1820 | | - * |
1821 | | - * @param {String} |
1822 | | - * text String to be escaped |
1823 | | - * @return {string} escaped text html string |
1824 | | - */ |
1825 | | - mw.escapeQuotesHTML = function( text ) { |
1826 | | - var replaceMap = { |
1827 | | - "&" : "&", |
1828 | | - '"' : """, |
1829 | | - '<' : "<", |
1830 | | - '>' : ">" |
1831 | | - } |
1832 | | - for( var i in replaceMap ){ |
1833 | | - text = text.split(i).join( replaceMap[i]); |
1834 | | - } |
1835 | | - return text; |
1836 | | - }; |
1837 | | - |
1838 | | - // Array of setup functions |
1839 | | - var mwSetupFunctions = []; |
1840 | | - |
1841 | | - /** |
1842 | | - * Add a function to be run during setup ( prior to mw.ready) this is useful |
1843 | | - * for building out interfaces that should be ready before mw.ready is |
1844 | | - * called. |
1845 | | - * |
1846 | | - * @param {callback} |
1847 | | - * Function Callback function must accept a ready function |
1848 | | - * callback to be called once setup is done |
1849 | | - */ |
1850 | | - mw.addSetupHook = function( callback ) { |
1851 | | - mwSetupFunctions.push ( callback ) ; |
1852 | | - }; |
1853 | | - |
1854 | | - /** |
1855 | | - * One time "setup" for mwEmbed run onDomReady ( so calls to setConfg apply |
1856 | | - * to setup ) |
1857 | | - */ |
1858 | | - // Flag to ensure setup is only run once: |
1859 | | - var mwSetupFlag = false; |
1860 | | - mw.setupMwEmbed = function ( ) { |
1861 | | - // Only run the setup once: |
1862 | | - if( mwSetupFlag ) { |
1863 | | - return ; |
1864 | | - } |
1865 | | - mwSetupFlag = true; |
1866 | | - |
1867 | | - // Apply any pre-setup config: |
1868 | | - mw.setConfig( preMwEmbedConfig ); |
1869 | | - |
1870 | | - |
1871 | | - mw.log( 'mw:setupMwEmbed SRC:: ' + mw.getMwEmbedSrc() ); |
1872 | | - |
1873 | | - // Check core mwEmbed loader.js file ( to get configuration and paths ) |
1874 | | - mw.checkCoreLoaderFile( function(){ |
1875 | | - // Make sure we have jQuery |
1876 | | - mw.load( 'window.jQuery', function() { |
1877 | | - |
1878 | | - // Add jQuery to $j var. |
1879 | | - if ( ! window[ '$j' ] ) { |
1880 | | - window[ '$j' ] = jQuery.noConflict(); |
1881 | | - } |
1882 | | - |
1883 | | - // Get module loader.js, and language files |
1884 | | - // ( will hit callback directly if set via resource loader ) |
1885 | | - mw.checkModuleLoaderFiles( function() { |
1886 | | - |
1887 | | - // Set the User language |
1888 | | - if( typeof wgUserLanguage != 'undefined' && mw.isValidLang( wgUserLanguage) ) { |
1889 | | - mw.setConfig( 'userLanguage', wgUserLanguage ) |
1890 | | - }else{ |
1891 | | - // Grab it from the included url |
1892 | | - var langKey = mw.parseUri( mw.getMwEmbedSrc() ).queryKey['uselang']; |
1893 | | - if ( langKey && mw.isValidLang( langKey ) ) { |
1894 | | - mw.setConfig( 'userLanguage', langKey); |
1895 | | - } |
1896 | | - } |
1897 | | - |
1898 | | - // Update the image path |
1899 | | - mw.setConfig( 'imagesPath', mw.getMwEmbedPath() + 'skins/common/images/' ); |
1900 | | - |
1901 | | - // Set up AJAX to not send dynamic URLs for loading scripts |
1902 | | - $j.ajaxSetup( { |
1903 | | - cache: true |
1904 | | - } ); |
1905 | | - |
1906 | | - // Update the magic keywords |
1907 | | - mw.Language.magicSetup(); |
1908 | | - |
1909 | | - // Set up mvEmbed utility jQuery bindings |
1910 | | - mw.dojQueryBindings(); |
1911 | | - |
1912 | | - |
1913 | | - // Special Hack for conditional jquery ui inclusion ( once |
1914 | | - // Usability extension |
1915 | | - // registers the jquery.ui skin in mw.style |
1916 | | - if( mw.hasJQueryUiCss() ){ |
1917 | | - mw.style[ 'ui_' + mw.getConfig( 'jQueryUISkin' ) ] = true; |
1918 | | - } |
1919 | | - |
1920 | | - |
1921 | | - // Make sure style sheets are loaded: |
1922 | | - mw.load( ['mw.style.mwCommon'] , function(){ |
1923 | | - // Run all the setup function hooks |
1924 | | - // NOTE: setup functions are added via addSetupHook |
1925 | | - // calls |
1926 | | - // and must include a callback. |
1927 | | - // |
1928 | | - // Once complete we can run .ready() queued functions |
1929 | | - function runSetupFunctions() { |
1930 | | - if( mwSetupFunctions.length ) { |
1931 | | - mwSetupFunctions.shift()( function() { |
1932 | | - runSetupFunctions(); |
1933 | | - } ); |
1934 | | - }else{ |
1935 | | - mw.runReadyFunctions(); |
1936 | | - } |
1937 | | - } |
1938 | | - runSetupFunctions(); |
1939 | | - } ); |
1940 | | - |
1941 | | - } ); |
1942 | | - }); |
1943 | | - }); |
1944 | | - }; |
1945 | | - |
1946 | | - /** |
1947 | | - * Checks for jquery ui css by name jquery-ui-1.7.2.css NOTE: this is a hack |
1948 | | - * for usability jquery-ui in the future usability should register a |
1949 | | - * resource in mw.skin |
1950 | | - * |
1951 | | - * @return true if found, return false if not found |
1952 | | - */ |
1953 | | - mw.hasJQueryUiCss = function(){ |
1954 | | - var hasUiCss = false; |
1955 | | - // Load the jQuery ui skin if usability skin not set |
1956 | | - $j( 'link' ).each( function( na, linkNode ){ |
1957 | | - if( $j( linkNode ).attr( 'href' ).indexOf( 'jquery-ui-1.7.2.css' ) != -1 ) { |
1958 | | - hasUiCss = true; |
1959 | | - return true; |
1960 | | - } |
1961 | | - } ); |
1962 | | - // Check all the "style" nodes for @import of jquery-ui-1.7.2.css |
1963 | | - // xxx Note: we could do this a bit cleaner with regEx |
1964 | | - $j( 'style' ).each( function( na, styleNode ){ |
1965 | | - if( $j( styleNode ).text().indexOf( '@import' ) != -1 |
1966 | | - && $j( styleNode ).text().indexOf( 'jquery-ui-1.7.2.css' ) != -1 ){ |
1967 | | - hasUiCss=true; |
1968 | | - } |
1969 | | - }); |
1970 | | - |
1971 | | - return hasUiCss; |
1972 | | - } |
1973 | | - |
1974 | | - /** |
1975 | | - * Loads the core mwEmbed "loader.js" file config |
1976 | | - * |
1977 | | - * NOTE: if using the ScriptLoader all the loaders and localization |
1978 | | - * converters are included automatically |
1979 | | - * |
1980 | | - * @param {Function} |
1981 | | - * callback Function called once core loader file is loaded |
1982 | | - */ |
1983 | | - mw.checkCoreLoaderFile = function( callback ) { |
1984 | | - // Check if we are using scriptloader ( handles loader include |
1985 | | - // automatically ) |
1986 | | - if( mw.getResourceLoaderPath() ) { |
1987 | | - callback(); |
1988 | | - return ; |
1989 | | - } |
1990 | | - |
1991 | | - // Check if we are using a static package ( mwEmbed path includes |
1992 | | - // -static ) |
1993 | | - if( mw.isStaticPackge() ){ |
1994 | | - callback(); |
1995 | | - return ; |
1996 | | - } |
1997 | | - |
1998 | | - // Add the Core loader to the request |
1999 | | - // The follow code is ONLY RUN in debug / raw file mode |
2000 | | - mw.load( 'loader.js', callback ); |
2001 | | - } |
2002 | | - |
2003 | | - /** |
2004 | | - * Checks if the javascript is a static package ( not using resource loader ) |
2005 | | - * |
2006 | | - * @return {boolean} true the included script is static false the included |
2007 | | - * script |
2008 | | - */ |
2009 | | - mw.isStaticPackge = function(){ |
2010 | | - var src = mw.getMwEmbedSrc(); |
2011 | | - if( src.indexOf('-static') !== -1 ){ |
2012 | | - return true; |
2013 | | - } |
2014 | | - return false; |
2015 | | - } |
2016 | | - |
2017 | | - /** |
2018 | | - * Check for resource loader module loaders, and localization files |
2019 | | - * |
2020 | | - * NOTE: if using the ScriptLoader all the loaders and localization |
2021 | | - * converters are included automatically. |
2022 | | - */ |
2023 | | - mw.checkModuleLoaderFiles = function( callback ) { |
2024 | | - mw.log( 'doLoaderCheck::' ); |
2025 | | - |
2026 | | - // Check if we are using scriptloader ( handles loader include |
2027 | | - // automatically ) |
2028 | | - // Or if mwEmbed is a static package ( all resources are already loaded |
2029 | | - // ) |
2030 | | - if( mw.getResourceLoaderPath() || mw.isStaticPackge() ) { |
2031 | | - callback(); |
2032 | | - return ; |
2033 | | - } |
2034 | | - |
2035 | | - // Load the configured modules / components |
2036 | | - // The follow code is ONLY RUN in debug / raw file mode |
2037 | | - var loaderRequest = []; |
2038 | | - |
2039 | | - // Load enabled components |
2040 | | - var enabledComponents = mw.getConfig( 'coreComponents' ); |
2041 | | - function loadEnabledComponents( enabledComponents ){ |
2042 | | - if( ! enabledComponents.length ){ |
2043 | | - // If no more components load modules:: |
2044 | | - |
2045 | | - // Add the enabledModules loaders: |
2046 | | - var enabledModules = mw.getConfig( 'enabledModules' ); |
2047 | | - loadEnabledModules( enabledModules ); |
2048 | | - return ; |
2049 | | - } |
2050 | | - var componentName = enabledComponents.shift(); |
2051 | | - mw.load( componentName, function(){ |
2052 | | - loadEnabledComponents( enabledComponents ); |
2053 | | - } ); |
2054 | | - } |
2055 | | - loadEnabledComponents( enabledComponents ); |
2056 | | - |
2057 | | - |
2058 | | - // Set the loader context and get each loader individually |
2059 | | - function loadEnabledModules( enabledModules ){ |
2060 | | - if( ! enabledModules.length ){ |
2061 | | - // If no more modules left load the LanguageFile |
2062 | | - addLanguageFile(); |
2063 | | - return ; |
2064 | | - } |
2065 | | - var moduleName = enabledModules.shift(); |
2066 | | - mw.setConfig( 'loaderContext', 'modules/' + moduleName + '/' ); |
2067 | | - mw.load( 'modules/' + moduleName + '/loader.js', function(){ |
2068 | | - loadEnabledModules( enabledModules ); |
2069 | | - } ); |
2070 | | - } |
2071 | | - |
2072 | | - function addLanguageFile(){ |
2073 | | - // Add the language file |
2074 | | - var langLoaderRequest = []; |
2075 | | - |
2076 | | - if( mw.getConfig( 'userLanguage' ) ) { |
2077 | | - var langCode = mw.getConfig( 'userLanguage' ); |
2078 | | - |
2079 | | - // Load the language resource if not default 'en' |
2080 | | - var transformKey = mw.getLangTransformKey( langCode ); |
2081 | | - if( transformKey != 'en' ){ |
2082 | | - // Upper case the first letter: |
2083 | | - langCode = langCode.substr(0,1).toUpperCase() + langCode.substr( 1, langCode.length ); |
2084 | | - langLoaderRequest.push( 'languages/classes/Language' + |
2085 | | - langCode + '.js' ); |
2086 | | - } |
2087 | | - |
2088 | | - } |
2089 | | - if ( ! langLoaderRequest.length ) { |
2090 | | - callback(); |
2091 | | - return ; |
2092 | | - } |
2093 | | - |
2094 | | - // Load the launage if set |
2095 | | - mw.load( langLoaderRequest, function(){ |
2096 | | - mw.log( 'Done moduleLoaderCheck request' ); |
2097 | | - // Set the mwModuleLoaderCheckFlag flag to true |
2098 | | - mwModuleLoaderCheckFlag = true; |
2099 | | - callback(); |
2100 | | - } ); |
2101 | | - } |
2102 | | - |
2103 | | - } |
2104 | | - |
2105 | | - /** |
2106 | | - * Checks if a css style rule exists |
2107 | | - * |
2108 | | - * On a page with lots of rules it can take some time so avoid calling this |
2109 | | - * function where possible and cache its result |
2110 | | - * |
2111 | | - * NOTE: this only works for style sheets on the same domain :( |
2112 | | - * |
2113 | | - * @param {String} |
2114 | | - * styleRule Style rule name to check |
2115 | | - * @return {Boolean} true if the rule exists false if the rule does not |
2116 | | - * exist |
2117 | | - */ |
2118 | | - mw.styleRuleExists = function ( styleRule ) { |
2119 | | - // Set up the skin paths configuration |
2120 | | - for( var i=0 ; i < document.styleSheets.length ; i++ ) { |
2121 | | - var rules = null; |
2122 | | - try{ |
2123 | | - if ( document.styleSheets[i].cssRules ) |
2124 | | - rules = document.styleSheets[i].cssRules |
2125 | | - else if (document.styleSheets[0].rules) |
2126 | | - rules = document.styleSheets[i].rules |
2127 | | - for(var j=0 ; j < rules.length ; j++ ) { |
2128 | | - var rule = rules[j].selectorText; |
2129 | | - if( rule && rule.indexOf( styleRule ) != -1 ) { |
2130 | | - return true; |
2131 | | - } |
2132 | | - } |
2133 | | - }catch ( e ) { |
2134 | | - mw.log( 'Error: cant check rule on cross domain style sheet:' + document.styleSheets[i].href ); |
2135 | | - } |
2136 | | - } |
2137 | | - return false; |
2138 | | - } |
2139 | | - |
2140 | | - // Flag to register the domReady has been called |
2141 | | - var mwDomReadyFlag = false; |
2142 | | - |
2143 | | - // Flag to register if the domreadyHooks have been called |
2144 | | - var mwModuleLoaderCheckFlag = false; |
2145 | | - |
2146 | | - /** |
2147 | | - * This will get called when the DOM is ready Will check configuration and |
2148 | | - * issue a mw.setupMwEmbed call if needed |
2149 | | - */ |
2150 | | - mw.domReady = function ( ) { |
2151 | | - if( mwDomReadyFlag ) { |
2152 | | - return ; |
2153 | | - } |
2154 | | - mw.log( 'run:domReady:: ' + document.getElementsByTagName('video').length ); |
2155 | | - // Set the onDomReady Flag |
2156 | | - mwDomReadyFlag = true; |
2157 | | - |
2158 | | - // Give us a chance to get to the bottom of the script. |
2159 | | - // When loading mwEmbed asynchronously the dom ready gets called |
2160 | | - // directly and in some browsers beets the $j = jQuery.noConflict(); |
2161 | | - // call |
2162 | | - // and causes symbol undefined errors. |
2163 | | - setTimeout(function(){ |
2164 | | - mw.setupMwEmbed(); |
2165 | | - },1); |
2166 | | - } |
2167 | | - |
2168 | | - /** |
2169 | | - * A version comparison utility function Handles version of types |
2170 | | - * {Major}.{MinorN}.{Patch} |
2171 | | - * |
2172 | | - * Note this just handles version numbers not patch letters. |
2173 | | - * |
2174 | | - * @param {String} |
2175 | | - * minVersion Minnium version needed |
2176 | | - * @param {String} |
2177 | | - * clientVersion Client version to be checked |
2178 | | - * |
2179 | | - * @return true if the version is at least of minVersion false if the |
2180 | | - * version is less than minVersion |
2181 | | - */ |
2182 | | - mw.versionIsAtLeast = function( minVersion, clientVersion ) { |
2183 | | - var minVersionParts = minVersion.split('.') |
2184 | | - var clientVersionParts = clientVersion.split('.'); |
2185 | | - for( var i =0; i < minVersionParts.length; i++ ) { |
2186 | | - if( parseInt( clientVersionParts[i] ) > parseInt( minVersionParts[i] ) ) { |
2187 | | - return true; |
2188 | | - } |
2189 | | - if( parseInt( clientVersionParts[i] ) < parseInt( minVersionParts[i] ) ) { |
2190 | | - return false; |
2191 | | - } |
2192 | | - } |
2193 | | - // Same version: |
2194 | | - return true; |
2195 | | - } |
2196 | | - |
2197 | | - /** |
2198 | | - * Runs all the triggers on a given object with a single "callback" |
2199 | | - * |
2200 | | - * Normal tirgger calls will run the callback directly multiple times for |
2201 | | - * every binded function. |
2202 | | - * |
2203 | | - * With runTriggersCallback() callback is not called until all the binded |
2204 | | - * events have been run. |
2205 | | - * |
2206 | | - * @param {object} |
2207 | | - * targetObject Target object to run triggers on |
2208 | | - * @param {string} |
2209 | | - * triggerName Name of trigger to be run |
2210 | | - * @param {function} |
2211 | | - * callback Function called once all triggers have been run |
2212 | | - * |
2213 | | - */ |
2214 | | - mw.runTriggersCallback = function( targetObject, triggerName, callback ){ |
2215 | | - mw.log( ' runTriggersCallback:: ' + triggerName ); |
2216 | | - // If events are not present directly run callback |
2217 | | - if( ! $j( targetObject ).data( 'events' ) || |
2218 | | - ! $j( targetObject ).data( 'events' )[ triggerName ] ) { |
2219 | | - mw.log( ' trigger name not found: ' + triggerName ); |
2220 | | - callback(); |
2221 | | - return ; |
2222 | | - } |
2223 | | - var callbackSet = $j( targetObject ).data( 'events' )[ triggerName ]; |
2224 | | - if( !callbackSet || callbackSet.length === 0 ){ |
2225 | | - mw.log( ' No events run the callback directly: ' + triggerName ); |
2226 | | - // No events run the callback directly |
2227 | | - callback(); |
2228 | | - return ; |
2229 | | - } |
2230 | | - // Set the callbackCount |
2231 | | - var callbackCount = ( callbackSet.length )? callbackSet.length : 1; |
2232 | | - |
2233 | | - mw.log(" runTriggersCallback:: " + callbackCount ); |
2234 | | - var callInx = 0; |
2235 | | - $j( targetObject ).trigger( triggerName, function() { |
2236 | | - callInx++; |
2237 | | - if( callInx == callbackCount ){ |
2238 | | - // Run callback |
2239 | | - callback(); |
2240 | | - } |
2241 | | - } ); |
2242 | | - } |
2243 | | - /** |
2244 | | - * Utility jQuery bindings Setup after jQuery is available ). |
2245 | | - */ |
2246 | | - mw.dojQueryBindings = function() { |
2247 | | - mw.log( 'mw.dojQueryBindings' ); |
2248 | | - ( function( $ ) { |
2249 | | - |
2250 | | - /** |
2251 | | - * Set a given selector html to the loading spinner: |
2252 | | - */ |
2253 | | - $.fn.loadingSpinner = function( ) { |
2254 | | - if ( this ) { |
2255 | | - $j( this ).html( |
2256 | | - $j( '<div />' ) |
2257 | | - .addClass( "loadingSpinner" ) |
2258 | | - ); |
2259 | | - } |
2260 | | - /* |
2261 | | - * //var csstransforms = false; if ( Modernizr.csstransforms ) { |
2262 | | - * var barNumber = 7; var barContent = ''; var barSpacingDegrees = |
2263 | | - * 360 / barNumber; var barOpacityDelta = 1 / (barNumber); for |
2264 | | - * (i = 1; i < barNumber+1; i++) { barContent += '<div |
2265 | | - * class="bar' + i + '" style="-moz-transform:rotate(' + (i-1) * |
2266 | | - * barSpacingDegrees + 'deg) translate(0, |
2267 | | - * -40px);-webkit-transform:rotate(' + (i-1) * barSpacingDegrees + |
2268 | | - * 'deg) translate(0, -40px);opacity:' + (i) * barOpacityDelta + '; |
2269 | | - * background:#000"/>'; } $j( this ).html( $j( '<div />' ) |
2270 | | - * .addClass( "cssLoadingSpinner" ) .html( barContent ) ); var |
2271 | | - * rotations = 0; setInterval( function ( ) { |
2272 | | - * $j('.cssLoadingSpinner') |
2273 | | - * .css('-moz-transform','rotate('+rotations+'deg)') |
2274 | | - * .css('-webkit-transform','rotate('+rotations+'deg)'); if( |
2275 | | - * rotations == 360 ) { rotations = 0; } rotations += 5; }, 25); } |
2276 | | - */ |
2277 | | - return this; |
2278 | | - } |
2279 | | - /** |
2280 | | - * Add an absolute overlay spinner useful for cases where the |
2281 | | - * element does not display child elements, ( images, video ) |
2282 | | - */ |
2283 | | - $.fn.getAbsoluteOverlaySpinner = function(){ |
2284 | | - var pos = $j( this ).offset(); |
2285 | | - var posLeft = ( $j( this ).width() ) ? |
2286 | | - parseInt( pos.left + ( .4 * $j( this ).width() ) ) : |
2287 | | - pos.left + 30; |
2288 | | - |
2289 | | - var posTop = ( $j( this ).height() ) ? |
2290 | | - parseInt( pos.top + ( .4 * $j( this ).height() ) ) : |
2291 | | - pos.top + 30; |
2292 | | - |
2293 | | - var $spinner = $j('<div />') |
2294 | | - .loadingSpinner() |
2295 | | - .css({ |
2296 | | - 'width' : 32, |
2297 | | - 'height' : 32, |
2298 | | - 'position': 'absolute', |
2299 | | - 'top' : posTop + 'px', |
2300 | | - 'left' : posLeft + 'px' |
2301 | | - }); |
2302 | | - $j('body').append( $spinner ); |
2303 | | - return $spinner; |
2304 | | - } |
2305 | | - |
2306 | | - /** |
2307 | | - * dragDrop file loader |
2308 | | - */ |
2309 | | - $.fn.dragFileUpload = function ( conf ) { |
2310 | | - if ( this.selector ) { |
2311 | | - var _this = this; |
2312 | | - // load the dragger and "setup" |
2313 | | - mw.load( ['$j.fn.dragDropFile'], function() { |
2314 | | - $j( _this.selector ).dragDropFile(); |
2315 | | - } ); |
2316 | | - } |
2317 | | - } |
2318 | | - |
2319 | | - /** |
2320 | | - * Shortcut to a themed button Should be depreciated for $.button |
2321 | | - * bellow |
2322 | | - */ |
2323 | | - $.btnHtml = function( msg, styleClass, iconId, opt ) { |
2324 | | - if ( !opt ) |
2325 | | - opt = { }; |
2326 | | - var href = ( opt.href ) ? opt.href : '#'; |
2327 | | - var target_attr = ( opt.target ) ? ' target="' + opt.target + '" ' : ''; |
2328 | | - var style_attr = ( opt.style ) ? ' style="' + opt.style + '" ' : ''; |
2329 | | - return '<a href="' + href + '" ' + target_attr + style_attr + |
2330 | | - ' class="ui-state-default ui-corner-all ui-icon_link ' + |
2331 | | - styleClass + '"><span class="ui-icon ui-icon-' + iconId + '" ></span>' + |
2332 | | - '<span class="btnText">' + msg + '</span></a>'; |
2333 | | - }; |
2334 | | - |
2335 | | - // Shortcut to jQuery button ( should replace all btnHtml with |
2336 | | - // button ) |
2337 | | - var mw_default_button_options = { |
2338 | | - // The class name for the button link |
2339 | | - 'class' : '', |
2340 | | - |
2341 | | - // The style properties for the button link |
2342 | | - 'style' : { }, |
2343 | | - |
2344 | | - // The text of the button link |
2345 | | - 'text' : '', |
2346 | | - |
2347 | | - // The icon id that precedes the button link: |
2348 | | - 'icon_id' : 'carat-1-n' |
2349 | | - }; |
2350 | | - |
2351 | | - $.button = function( options ) { |
2352 | | - var options = $j.extend( mw_default_button_options, options); |
2353 | | - |
2354 | | - // Button: |
2355 | | - var $btn = $j('<a />') |
2356 | | - .attr('href', '#') |
2357 | | - .addClass( 'ui-state-default ui-corner-all ui-icon_link' ); |
2358 | | - // Add css if set: |
2359 | | - if( options.css ) { |
2360 | | - $btn.css( options.css ) |
2361 | | - } |
2362 | | - |
2363 | | - if( options['class'] ) { |
2364 | | - $btn.addClass( options['class'] ) |
2365 | | - } |
2366 | | - |
2367 | | - |
2368 | | - // return the button: |
2369 | | - return $btn.append( |
2370 | | - $j('<span />').addClass( 'ui-icon ui-icon-' + options.icon_id ), |
2371 | | - $j('<span />').addClass( 'btnText' ) |
2372 | | - .text( options.text ) |
2373 | | - ) |
2374 | | - .buttonHover(); // add buttonHover binding; |
2375 | | - }; |
2376 | | - |
2377 | | - // Shortcut to bind hover state |
2378 | | - $.fn.buttonHover = function() { |
2379 | | - $j( this ).hover( |
2380 | | - function() { |
2381 | | - $j( this ).addClass( 'ui-state-hover' ); |
2382 | | - }, |
2383 | | - function() { |
2384 | | - $j( this ).removeClass( 'ui-state-hover' ); |
2385 | | - } |
2386 | | - ) |
2387 | | - return this; |
2388 | | - }; |
2389 | | - |
2390 | | - /** |
2391 | | - * Resize a dialog to fit the window |
2392 | | - * |
2393 | | - * @param {Object} |
2394 | | - * options horizontal and vertical space ( default 50 ) |
2395 | | - */ |
2396 | | - $.fn.dialogFitWindow = function( options ) { |
2397 | | - var opt_default = { 'hspace':50, 'vspace':50 }; |
2398 | | - if ( !options ) |
2399 | | - var options = { }; |
2400 | | - options = $j.extend( opt_default, options ); |
2401 | | - $j( this.selector ).dialog( 'option', 'width', $j( window ).width() - options.hspace ); |
2402 | | - $j( this.selector ).dialog( 'option', 'height', $j( window ).height() - options.vspace ); |
2403 | | - $j( this.selector ).dialog( 'option', 'position', 'center' ); |
2404 | | - // update the child position: (some of this should be pushed |
2405 | | - // up-stream via dialog config options |
2406 | | - $j( this.selector + '~ .ui-dialog-buttonpane' ).css( { |
2407 | | - 'position':'absolute', |
2408 | | - 'left':'0px', |
2409 | | - 'right':'0px', |
2410 | | - 'bottom':'0px' |
2411 | | - } ); |
2412 | | - }; |
2413 | | - |
2414 | | - } )( $j ); |
2415 | | - } |
2416 | | - |
2417 | | -} )( window.mw ); |
2418 | | - |
2419 | | - |
2420 | | -/** |
2421 | | - * Set DOM-ready call We copy jQuery( document ).ready here since sometimes |
2422 | | - * mwEmbed.js is included without jQuery and we need our own "ready" system so |
2423 | | - * that mwEmbed interfaces can support async built out and the include of |
2424 | | - * jQuery. |
2425 | | - */ |
2426 | | -var mwDomIsReady = false; |
2427 | | -function runMwDomReady(){ |
2428 | | - mwDomIsReady = true; |
2429 | | - if( mw.domReady ){ |
2430 | | - mw.domReady() |
2431 | | - } |
2432 | | -} |
2433 | | -// Check if already ready: |
2434 | | -if ( document.readyState === "complete" ) { |
2435 | | - runMwDomReady(); |
2436 | | -} |
2437 | | - |
2438 | | -// Cleanup functions for the document ready method |
2439 | | -if ( document.addEventListener ) { |
2440 | | - DOMContentLoaded = function() { |
2441 | | - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); |
2442 | | - runMwDomReady(); |
2443 | | - }; |
2444 | | - |
2445 | | -} else if ( document.attachEvent ) { |
2446 | | - DOMContentLoaded = function() { |
2447 | | - // Make sure body exists, at least, in case IE gets a little overzealous |
2448 | | - // (ticket #5443). |
2449 | | - if ( document.readyState === "complete" ) { |
2450 | | - document.detachEvent( "onreadystatechange", DOMContentLoaded ); |
2451 | | - runMwDomReady(); |
2452 | | - } |
2453 | | - }; |
2454 | | -} |
2455 | | -// Mozilla, Opera and webkit nightlies currently support this event |
2456 | | -if ( document.addEventListener ) { |
2457 | | - // Use the handy event callback |
2458 | | - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); |
2459 | | - |
2460 | | - // A fallback to window.onload, that will always work |
2461 | | - window.addEventListener( "load", mw.domReady, false ); |
2462 | | - |
2463 | | -// If IE event model is used |
2464 | | -} else if ( document.attachEvent ) { |
2465 | | - // ensure firing before onload, |
2466 | | - // maybe late but safe also for iframes |
2467 | | - document.attachEvent("onreadystatechange", DOMContentLoaded); |
2468 | | - |
2469 | | - // A fallback to window.onload, that will always work |
2470 | | - window.attachEvent( "onload", runMwDomReady ); |
2471 | | - |
2472 | | - // If IE and not a frame |
2473 | | - // continually check to see if the document is ready |
2474 | | - var toplevel = false; |
2475 | | - |
2476 | | - try { |
2477 | | - toplevel = window.frameElement == null; |
2478 | | - } catch(e) {} |
2479 | | - |
2480 | | - if ( document.documentElement.doScroll && toplevel ) { |
2481 | | - doScrollCheck(); |
2482 | | - } |
2483 | | -} |
2484 | | -// The DOM ready check for Internet Explorer |
2485 | | -function doScrollCheck() { |
2486 | | - if ( mwDomIsReady ) { |
2487 | | - return; |
2488 | | - } |
2489 | | - |
2490 | | - try { |
2491 | | - // If IE is used, use the trick by Diego Perini |
2492 | | - // http://javascript.nwbox.com/IEContentLoaded/ |
2493 | | - document.documentElement.doScroll("left"); |
2494 | | - } catch( error ) { |
2495 | | - setTimeout( doScrollCheck, 1 ); |
2496 | | - return; |
2497 | | - } |
2498 | | - |
2499 | | - // and execute any waiting functions |
2500 | | - runMwDomReady(); |
2501 | | -} |
2502 | | - |
2503 | | - |
2504 | | -// If using the resource loader and jQuery has not been set give a warning to |
2505 | | -// the user: |
2506 | | -// (this is needed because packaged loader.js files could refrence jQuery ) |
2507 | | -if( mw.getResourceLoaderPath() && !window.jQuery ) { |
2508 | | - mw.log( 'Error: jQuery is required for mwEmbed, please update your resource loader request' ); |
2509 | | -} |
2510 | | - |
2511 | | -if( mw.isStaticPackge() && !window.jQuery ){ |
2512 | | - alert( 'Error: jQuery is required for mwEmbed '); |
2513 | | -} |
2514 | | - |
2515 | | -/** |
2516 | | - * Hack to keep jQuery in $ when its already there, but also use noConflict to |
2517 | | - * get $j = jQuery |
2518 | | - * |
2519 | | - * This way sites that use $ for jQuery continue to work after including mwEmbed |
2520 | | - * javascript. |
2521 | | - * |
2522 | | - * Also if jQuery is included prior to mwEmbed we ensure $j is set |
2523 | | - */ |
2524 | | - |
2525 | | -if( window.jQuery ){ |
2526 | | - var dollarFlag = false; |
2527 | | - if( $ && $.fn && $.fn.jquery ) { |
2528 | | - // NOTE we could check the version of |
2529 | | - // jQuery and do a removal call if too old |
2530 | | - dollarFlag = true; |
2531 | | - } |
2532 | | - window[ '$j' ] = jQuery.noConflict(); |
2533 | | - if( dollarFlag ) { |
2534 | | - window[ '$' ] = jQuery.noConflict(); |
2535 | | - } |
2536 | | -} |
| 3 | +* MwEmbed.js is a meta package for the mwEmbed platform. |
| 4 | +* |
| 5 | +* For legacy support, this file invokes the mwEmbed platform with debug mode enabled. |
| 6 | +* |
| 7 | +* This mode has been deprecated, you should instead directly request the debug package |
| 8 | +* |
| 9 | +* When using mwEmbed in mediaWiki, this file will never be accessed. |
| 10 | +*/ |
Index: trunk/extensions/TimedMediaHandler/TimedText/TimedText.resourceList.php |
— | — | @@ -1,16 +0,0 @@ |
2 | | -<?php |
3 | | - |
4 | | -/** |
5 | | - * EmbedPlayer module resource list array |
6 | | - */ |
7 | | - |
8 | | -return array( |
9 | | - // Top level TimedText name: |
10 | | - "mw.TimedText" => array( "scripts" => "mw.TimedText.js" ), |
11 | | - "mw.style.TimedText" => array( "scripts" => "css/mw.style.TimedText.css"), |
12 | | - |
13 | | - "mw.TimedTextEdit" => array( "scripts" => "mw.TimedTextEdit.js"), |
14 | | - "mw.style.TimedTextEdit" => array( "scripts" => "css/mw.style.TimedTextEdit.css"), |
15 | | - |
16 | | - "RemoteMwTimedText" => array( "scripts" => "remotes/RemoteMwTimedText.js") |
17 | | -); |
\ No newline at end of file |
Index: trunk/extensions/TimedMediaHandler/TimedText/remotes/RemoteMwTimedText.js |
— | — | @@ -0,0 +1,188 @@ |
| 2 | +/** |
| 3 | +* Stop-gap for mediaWiki php based timed text support |
| 4 | +* |
| 5 | +* Does some transformations to normal wiki timed Text pages to make them look |
| 6 | +* like the php output that we will eventually want to have |
| 7 | +*/ |
| 8 | + |
| 9 | +mw.addMessageKeys( [ |
| 10 | + "mwe-timedtext-language-subtitles-for-clip", |
| 11 | + "mwe-timedtext-language-no-subtitles-for-clip" |
| 12 | +]); |
| 13 | + |
| 14 | +RemoteMwTimedText = function( options ) { |
| 15 | + return this.init( options ); |
| 16 | +} |
| 17 | +mw_default_remote_text_options = [ |
| 18 | + 'action', |
| 19 | + 'title', |
| 20 | + 'target', |
| 21 | + 'orgBody' |
| 22 | +]; |
| 23 | +RemoteMwTimedText.prototype = { |
| 24 | + |
| 25 | + init: function( options ) { |
| 26 | + for(var i in mw_default_remote_text_options) { |
| 27 | + var opt = mw_default_remote_text_options[i] |
| 28 | + if( options[ opt ] ) { |
| 29 | + this[ opt ] = options[ opt ]; |
| 30 | + } |
| 31 | + } |
| 32 | + }, |
| 33 | + updateUI: function() { |
| 34 | + // Check page type |
| 35 | + if( this.action == 'view' ) { |
| 36 | + this.showViewUI(); |
| 37 | + }else{ |
| 38 | + //restore |
| 39 | + } |
| 40 | + }, |
| 41 | + showViewUI: function() { |
| 42 | + var _this = this; |
| 43 | + var fileTitleKey = this.title.split('.'); |
| 44 | + this.extension = fileTitleKey.pop(); |
| 45 | + this.langKey = fileTitleKey.pop(); |
| 46 | + this.fileTitleKey = fileTitleKey.join('.'); |
| 47 | + |
| 48 | + this.getTitleResource( this.fileTitleKey, function( resource ) { |
| 49 | + _this.embedViewUI( resource ); |
| 50 | + }); |
| 51 | + }, |
| 52 | + embedViewUI: function( resource ) { |
| 53 | + var _this = this; |
| 54 | + // Load the player module: |
| 55 | + mw.load( 'EmbedPlayer', function() { |
| 56 | + // Add the embed code: ( jquery wrapping of "video" fails ) |
| 57 | + $j( _this.target ).append( |
| 58 | + $j( '<div class="videoLoading">').html( |
| 59 | + '<video id="timed-text-player-embed" '+ |
| 60 | + 'style="width:' + resource.width + 'px;height:' + resource.height + 'px;" '+ |
| 61 | + 'class="kskin" ' + //We need to centrally store this config somewhere |
| 62 | + 'poster="' + resource.poster + '" ' + |
| 63 | + 'src="' + resource.src + '" ' + |
| 64 | + 'apiTitleKey="' + resource.apiTitleKey + '" >' + |
| 65 | + '</video><br><br><br><br>' |
| 66 | + ) |
| 67 | + ); |
| 68 | + $j('.videoLoading').hide(); |
| 69 | + // embed the player with the pre-selected langauge: |
| 70 | + _this.embedPlayerLang(); |
| 71 | + }); |
| 72 | + }, |
| 73 | + /* |
| 74 | + * embeds a player with the current language key pre selected |
| 75 | + */ |
| 76 | + embedPlayerLang: function() { |
| 77 | + var _this = this; |
| 78 | + if( wgArticlePath ) { |
| 79 | + var $fileLink = $j('<div>').append( |
| 80 | + $j('<a>').attr({ |
| 81 | + 'href' : wgArticlePath.replace( '$1', 'File:' + _this.fileTitleKey) |
| 82 | + }) |
| 83 | + .text( _this.fileTitleKey.replace('_', ' ') ) |
| 84 | + ) |
| 85 | + } |
| 86 | + |
| 87 | + // Rewrite the player (any video tags on the page) |
| 88 | + $j('#timed-text-player-embed').embedPlayer( function() { |
| 89 | + //Select the timed text for the page: |
| 90 | + |
| 91 | + //remove the loader |
| 92 | + $j('.loadingSpinner').remove(); |
| 93 | + |
| 94 | + var player = $j('#timed-text-player-embed').get(0); |
| 95 | + |
| 96 | + |
| 97 | + if( !player.timedText ) { |
| 98 | + mw.log("Error: no timedText method on embedPlayer" ); |
| 99 | + return ; |
| 100 | + } |
| 101 | + // Set the userLanguage: |
| 102 | + player.timedText.config.userLanugage = this.langKey; |
| 103 | + |
| 104 | + // Make sure the timed text sources are loaded: |
| 105 | + player.timedText.setupTextSources( function() { |
| 106 | + |
| 107 | + var source = player.timedText.getSourceByLanguage( _this.langKey ); |
| 108 | + var pageMsgKey = 'mwe-timedtext-language-subtitles-for-clip'; |
| 109 | + if( ! source ) { |
| 110 | + pageMsgKey = "mwe-timedtext-language-no-subtitles-for-clip" |
| 111 | + } |
| 112 | + // Add the page msg to the top |
| 113 | + $j( _this.target ).prepend( |
| 114 | + $j('<h3>') |
| 115 | + .html( |
| 116 | + gM(pageMsgKey, [ unescape( mw.Language.names[ _this.langKey ] ), $fileLink.html() ] ) |
| 117 | + ) |
| 118 | + ); |
| 119 | + // Select the language if possible: |
| 120 | + if( source ) { |
| 121 | + player.timedText.selectTextSource( source ); |
| 122 | + } |
| 123 | + // Un-hide the player |
| 124 | + $j('.videoLoading').show(); |
| 125 | + } ); |
| 126 | + } ); |
| 127 | + }, |
| 128 | + |
| 129 | + /** |
| 130 | + * Gets the properties of a given title as a resource |
| 131 | + * @param {String} fileTitle Title of media asset to embed |
| 132 | + * @param {Function} callback [Optional] Function to call once asset is embedded |
| 133 | + */ |
| 134 | + getTitleResource: function( fileTitle, callback ) { |
| 135 | + var _this = this; |
| 136 | + // Get all the embed details: |
| 137 | + var request = { |
| 138 | + 'titles' : 'File:' + fileTitle, |
| 139 | + 'prop' : 'imageinfo|revisions', |
| 140 | + 'iiprop' : 'url|mime|size', |
| 141 | + 'iiurlwidth' : mw.getConfig( 'EmbedPlayer.DefaultSize').split('x').pop(), |
| 142 | + 'rvprop' : 'content' |
| 143 | + } |
| 144 | + // (only works for commons right now) |
| 145 | + mw.getJSON( request, function( data ) { |
| 146 | + // Check for "page not found" |
| 147 | + if( data.query.pages['-1'] ) { |
| 148 | + //restore content: |
| 149 | + $j(_this.target).html( _this.orgBody ); |
| 150 | + return ; |
| 151 | + } |
| 152 | + // Check for redirect |
| 153 | + for ( var i in data.query.pages ) { |
| 154 | + var page = data.query.pages[i]; |
| 155 | + if ( page.revisions[0]['*'] && page.revisions[0]['*'].indexOf( '#REDIRECT' ) === 0 ) { |
| 156 | + var re = new RegExp( /[^\[]*\[\[([^\]]*)/ ); |
| 157 | + var pt = page.revisions[0]['*'].match( re ); |
| 158 | + if ( pt[1] ) { |
| 159 | + mw.log( 'found redirect tyring: ' + pt[1] ) |
| 160 | + _this.embedByTitle( pt[1], callback); |
| 161 | + return ; |
| 162 | + } else { |
| 163 | + mw.log( 'Error: getTitleResource could not process redirect' ); |
| 164 | + callback( false ); |
| 165 | + return false; |
| 166 | + } |
| 167 | + } |
| 168 | + mw.log( "should process data result" ); |
| 169 | + // Else process the result |
| 170 | + var resource = _this.getResource( page ); |
| 171 | + callback( resource ); |
| 172 | + } |
| 173 | + } ); |
| 174 | + }, |
| 175 | + |
| 176 | + /** |
| 177 | + * Get the embed code from response resource and sends it a callback |
| 178 | + */ |
| 179 | + getResource: function( page ) { |
| 180 | + return { |
| 181 | + 'apiTitleKey' : page.title.replace(/File:/ig, '' ), |
| 182 | + 'link' : page.imageinfo[0].descriptionurl, |
| 183 | + 'poster' : page.imageinfo[0].thumburl, |
| 184 | + 'src' : page.imageinfo[0].url, |
| 185 | + 'width' : page.imageinfo[0].width, |
| 186 | + 'height': page.imageinfo[0].height |
| 187 | + }; |
| 188 | + } |
| 189 | +}; |
Property changes on: trunk/extensions/TimedMediaHandler/TimedText/remotes/RemoteMwTimedText.js |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 190 | + text/plain |
Added: svn:executable |
2 | 191 | + * |
Index: trunk/extensions/TimedMediaHandler/TimedText/tests/Player_Timed_Text.html |
— | — | @@ -0,0 +1,182 @@ |
| 2 | +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
| 3 | +"http://www.w3.org/TR/html4/loose.dtd"> |
| 4 | +<html> |
| 5 | +<head> |
| 6 | + <title>sample mv embed</title> |
| 7 | + <!-- <script type="text/javascript" src="../../../mwEmbed.js?debug=true"></script> --> |
| 8 | + <script type="text/javascript" src="../../../ResourceLoader.php?class=window.jQuery,mwEmbed&debug=true"></script> |
| 9 | + <script type="text/javascript"> |
| 10 | + $j( document ).ready(function(){ |
| 11 | + $j('#inlineTracksTextArea').text( |
| 12 | + $j.trim( $j('#inlineTracks').html() ) |
| 13 | + ); |
| 14 | + $j('#apiExampleTextArea').text( |
| 15 | + $j.trim( $j('#apiExample').html() ) |
| 16 | + ) |
| 17 | + }); |
| 18 | + |
| 19 | + </script> |
| 20 | +</head> |
| 21 | +<body> |
| 22 | +<h3> mwEmbed Timed Text Examples:</h3> |
| 23 | +Click on the little lower right "CC" icon to expose the timed text |
| 24 | + <table border="1" cellpadding="6" width="950"> |
| 25 | + |
| 26 | + <tr> |
| 27 | + <td id="apiExample" valign="top" width="410"> |
| 28 | + <video |
| 29 | + style="width:512px;height:288px" |
| 30 | + durationHint="7:52" |
| 31 | + apiTitleKey="Yochai_Benkler_-_On_Autonomy,_Control_and_Cultural_Experience.ogg" |
| 32 | + apiProvider="commons" |
| 33 | + class="kskin"></video> |
| 34 | + <td valign="top"> |
| 35 | + Commons Video API based timedText discovery<br> |
| 36 | + |
| 37 | + <textarea id="apiExampleTextArea" style="width:600px;height:180px"></textarea> |
| 38 | + </td> |
| 39 | + </tr> |
| 40 | + |
| 41 | + |
| 42 | + <tr> |
| 43 | + <td id="inlineTracks" valign="top" width="410"> |
| 44 | + |
| 45 | + <video style="width:544px;height:304px;" |
| 46 | + poster="http://upload.wikimedia.org/wikipedia/commons/thumb/b/bd/Elephants_Dream.ogg/seek%3D13-Elephants_Dream.ogg.jpg" |
| 47 | + duration="10:53" |
| 48 | + linkback="http://www.elephantsdream.org/" > |
| 49 | + <source type="video/ogg" src="http://upload.wikimedia.org/wikipedia/commons/b/bd/Elephants_Dream.ogg" ></source> |
| 50 | + <source type="video/h264" src="http://www.archive.org/download/ElephantsDream/ed_1024_512kb.mp4"></source> |
| 51 | + |
| 52 | + |
| 53 | + <!-- Subtitles --> |
| 54 | + |
| 55 | + <track kind="subtitles" id="video_af" srclang="af" |
| 56 | + src="media/elephants_dream/elephant.afrikaans.srt"></track> |
| 57 | + |
| 58 | + <track kind="subtitles" id="video_ar" srclang="ar" |
| 59 | + src="media/elephants_dream/elephant.arabic.srt"></track> |
| 60 | + |
| 61 | + <track kind="subtitles" id="video_bn" srclang="bn" |
| 62 | + src="media/elephants_dream/elephant.bangla.srt"></track> |
| 63 | + |
| 64 | + <track kind="subtitles" id="video_br" srclang="br" |
| 65 | + src="media/elephants_dream/elephant.breton.srt"></track> |
| 66 | + |
| 67 | + <track kind="subtitles" id="video_bg" srclang="bg" |
| 68 | + src="media/elephants_dream/elephant.bulgarian.srt"></track> |
| 69 | + |
| 70 | + <track kind="subtitles" id="video_ca" srclang="ca" |
| 71 | + src="media/elephants_dream/elephant.catalan-utf8.srt"></track> |
| 72 | + |
| 73 | + <track kind="subtitles" id="video_zh" srclang="zh" |
| 74 | + src="media/elephants_dream/elephant.chinese.srt"></track> |
| 75 | + |
| 76 | + <track kind="subtitles" id="video_cz" srclang="cs" |
| 77 | + src="media/elephants_dream/elephant.czech.srt"></track> |
| 78 | + |
| 79 | + <track kind="subtitles" id="video_da" srclang="da" |
| 80 | + src="media/elephants_dream/elephant.danish.srt"></track> |
| 81 | + |
| 82 | + <track kind="subtitles" id="video_nl" srclang="nl" |
| 83 | + src="media/elephants_dream/elephant.dutch.srt"></track> |
| 84 | + |
| 85 | + <track kind="subtitles" id="video_en" srclang="en" |
| 86 | + src="media/elephants_dream/elephant.english.srt"></track> |
| 87 | + |
| 88 | + <track kind="subtitles" id="video_et" srclang="et" |
| 89 | + src="media/elephants_dream/elephant.estonian.srt"></track> |
| 90 | + |
| 91 | + <track kind="subtitles" id="video_fi" srclang="fi" |
| 92 | + src="media/elephants_dream/elephant.finnish.srt"></track> |
| 93 | + |
| 94 | + <track kind="subtitles" id="video_fr" srclang="fr" |
| 95 | + src="media/elephants_dream/elephant.french.srt"></track> |
| 96 | + |
| 97 | + <track kind="subtitles" id="video_de" srclang="de" |
| 98 | + src="media/elephants_dream/elephant.german.srt"></track> |
| 99 | + |
| 100 | + <track kind="subtitles" id="video_el" srclang="el" |
| 101 | + src="media/elephants_dream/elephant.greek.srt"></track> |
| 102 | + |
| 103 | + <track kind="subtitles" id="video_he" srclang="he" |
| 104 | + src="media/elephants_dream/elephant.hebrew.srt"></track> |
| 105 | + |
| 106 | + <track kind="subtitles" id="video_hu" srclang="hu" |
| 107 | + src="media/elephants_dream/elephant.hungarian-utf8.srt"></track> |
| 108 | + |
| 109 | + <track kind="subtitles" id="video_it" srclang="it" |
| 110 | + src="media/elephants_dream/elephant.italian.srt"></track> |
| 111 | + |
| 112 | + <track kind="subtitles" id="video_ja" srclang="ja" |
| 113 | + src="media/elephants_dream/elephant.japanese.srt"></track> |
| 114 | + |
| 115 | + <track kind="subtitles" id="video_ja" srclang="ja" |
| 116 | + src="media/elephants_dream/elephant.japanese-euc.srt"></track> |
| 117 | + |
| 118 | + <track kind="subtitles" id="video_mt" srclang="mt" |
| 119 | + src="media/elephants_dream/elephant.maltese_utf8.srt"></track> |
| 120 | + |
| 121 | + <track kind="subtitles" id="video_nn" srclang="nn" |
| 122 | + src="media/elephants_dream/elephant.norwegian.srt"></track> |
| 123 | + |
| 124 | + <track kind="subtitles" id="video_pl" srclang="pl" |
| 125 | + src="media/elephants_dream/elephant.polish.srt"></track> |
| 126 | + |
| 127 | + <track kind="subtitles" id="video_pt" srclang="pt" |
| 128 | + src="media/elephants_dream/elephant.portuguese.srt"></track> |
| 129 | + |
| 130 | + <track kind="subtitles" id="video_pt_br" srclang="pt-br" |
| 131 | + src="media/elephants_dream/elephant.brazilian.srt"></track> |
| 132 | + |
| 133 | + <track kind="subtitles" id="video_ro" srclang="ro" |
| 134 | + src="media/elephants_dream/elephant.romanian.srt"></track> |
| 135 | + |
| 136 | + <track kind="subtitles" id="video_ru" srclang="ru" |
| 137 | + src="media/elephants_dream/elephant.russian.srt"></track> |
| 138 | + |
| 139 | + |
| 140 | + <!-- Captions --> |
| 141 | + <track kind="captions" id="video_sl" srclang="sl" |
| 142 | + src="media/elephants_dream/elephant.slovenian.srt"></track> |
| 143 | + |
| 144 | + <track kind="captions" id="video_es" srclang="es" |
| 145 | + src="media/elephants_dream/elephant.spanish.srt"></track> |
| 146 | + |
| 147 | + <track kind="captions" id="video_es_mx" srclang="es-mx" |
| 148 | + src="media/elephants_dream/elephant.spanish-us.srt"></track> |
| 149 | + |
| 150 | + <track kind="captions" id="video_sk" srclang="sk" |
| 151 | + src="media/elephants_dream/elephant.slovak.srt"></track> |
| 152 | + |
| 153 | + <track kind="captions" id="video_sv" srclang="sv" |
| 154 | + src="media/elephants_dream/elephant.swedish.srt"></track> |
| 155 | + |
| 156 | + |
| 157 | + <!-- Audio Description --> |
| 158 | + <track kind="descriptions" id="audiodesc" srclang="en" |
| 159 | + src="media/elephants_dream/audiodescription.srt"></track> |
| 160 | + |
| 161 | + <!-- Chapters --> |
| 162 | + <track kind="chapters" id="chapters" srclang="en" label="Chapters" |
| 163 | + src="media/elephants_dream/chapters.srt"></track> |
| 164 | + |
| 165 | + </video> |
| 166 | + |
| 167 | + </td> |
| 168 | + |
| 169 | + <td valign="top"> |
| 170 | + <h4>Text track inline embed example</h4> |
| 171 | + see: <a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/video.html#the-track-element">HTML5 timed text spec</a> |
| 172 | + <br><textarea id="inlineTracksTextArea" style="width:600px;height:180px"> |
| 173 | + |
| 174 | + </textarea> |
| 175 | + </td> |
| 176 | + </tr> |
| 177 | + |
| 178 | + |
| 179 | + </table> |
| 180 | + |
| 181 | +</body> |
| 182 | +</html> |
| 183 | + |
Property changes on: trunk/extensions/TimedMediaHandler/TimedText/tests/Player_Timed_Text.html |
___________________________________________________________________ |
Added: svn:mime-type |
1 | 184 | + text/plain |
Index: trunk/extensions/TimedMediaHandler/TimedText/TimedText.resources.php |
— | — | @@ -0,0 +1,16 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * EmbedPlayer module resource list array |
| 6 | + */ |
| 7 | + |
| 8 | +return array( |
| 9 | + // Top level TimedText name: |
| 10 | + "mw.TimedText" => array( "scripts" => "mw.TimedText.js" ), |
| 11 | + "mw.style.TimedText" => array( "scripts" => "css/mw.style.TimedText.css"), |
| 12 | + |
| 13 | + "mw.TimedTextEdit" => array( "scripts" => "mw.TimedTextEdit.js"), |
| 14 | + "mw.style.TimedTextEdit" => array( "scripts" => "css/mw.style.TimedTextEdit.css"), |
| 15 | + |
| 16 | + "RemoteMwTimedText" => array( "scripts" => "remotes/RemoteMwTimedText.js") |
| 17 | +); |
\ No newline at end of file |
Index: trunk/extensions/TimedMediaHandler/EmbedPlayer/EmbedPlayer.resourceList.php |
— | — | @@ -1,28 +0,0 @@ |
2 | | -<?php |
3 | | - |
4 | | -/** |
5 | | - * EmbedPlayer module resource list array |
6 | | - */ |
7 | | - |
8 | | -return array( |
9 | | - "mw.EmbedPlayer" => array( 'scripts'=> "mw.EmbedPlayer.js" ), |
10 | | - |
11 | | - "mw.EmbedPlayerKplayer" => array( 'scripts'=> "mw.EmbedPlayerKplayer.js" ), |
12 | | - "mw.EmbedPlayerGeneric" => array( 'scripts'=> "mw.EmbedPlayerGeneric.js" ), |
13 | | - "mw.EmbedPlayerHtml" => array( 'scripts'=> "mw.EmbedPlayerHtml.js" ), |
14 | | - "mw.EmbedPlayerJava" => array( 'scripts'=> "mw.EmbedPlayerJava.js"), |
15 | | - "mw.EmbedPlayerNative" => array( 'scripts'=> "mw.EmbedPlayerNative.js" ), |
16 | | - |
17 | | - "mw.EmbedPlayerVlc" => array( 'scripts'=> "mw.EmbedPlayerVlc.js" ), |
18 | | - |
19 | | - "mw.PlayerControlBuilder" => array( 'scripts' => "skins/mw.PlayerControlBuilder.js" ), |
20 | | - |
21 | | - "mw.style.EmbedPlayer" => array( 'scripts'=> "skins/mw.style.EmbedPlayer.css" ), |
22 | | - |
23 | | - "mw.style.PlayerSkinKskin" => array( 'scripts' => "skins/kskin/mw.style.PlayerSkinKskin.css" ), |
24 | | - |
25 | | - "mw.PlayerSkinKskin" => array( 'scripts' => "skins/kskin/mw.PlayerSkinKskin.js"), |
26 | | - |
27 | | - "mw.PlayerSkinMvpcf" => array( 'scripts'=> "skins/mvpcf/mw.PlayerSkinMvpcf.js"), |
28 | | - "mw.style.PlayerSkinMvpcf" => array( 'scripts'=> "skins/mvpcf/mw.style.PlayerSkinMvpcf.css"), |
29 | | -); |
\ No newline at end of file |
Index: trunk/extensions/TimedMediaHandler/EmbedPlayer/mw.EmbedPlayer.js |
— | — | @@ -194,7 +194,8 @@ |
195 | 195 | |
196 | 196 | // Number of milliseconds between interface updates |
197 | 197 | 'EmbedPlayer.MonitorRate' : 250 |
198 | | -} |
| 198 | +}); |
| 199 | + |
199 | 200 | /** |
200 | 201 | * The base source attribute checks |
201 | 202 | * also see: http://dev.w3.org/html5/spec/Overview.html#the-source-element |
— | — | @@ -2390,7 +2391,7 @@ |
2391 | 2392 | mw.getConfig( 'imagesPath' ) + 'vid_default_thumb.jpg'; |
2392 | 2393 | |
2393 | 2394 | // Poster support is not very consistent in browsers |
2394 | | - // use a jpg poster image: |
| 2395 | + // use a jpeg poster image: |
2395 | 2396 | $j( this ).html( |
2396 | 2397 | $j( '<img />' ) |
2397 | 2398 | .css({ |
Index: trunk/extensions/TimedMediaHandler/EmbedPlayer/skins/mw.PlayerControlBuilder.js |
— | — | @@ -1757,7 +1757,7 @@ |
1758 | 1758 | } ); |
1759 | 1759 | |
1760 | 1760 | // Up the z-index of the default status indicator: |
1761 | | - $playHead.find( 'ui-slider-handle' ).css( 'z-index', 4 ); |
| 1761 | + $playHead.find( '.ui-slider-handle' ).css( 'z-index', 4 ); |
1762 | 1762 | $playHead.find( '.ui-slider-range' ).addClass( 'ui-corner-all' ).css( 'z-index', 2 ); |
1763 | 1763 | |
1764 | 1764 | // Add buffer html: |
Index: trunk/extensions/TimedMediaHandler/EmbedPlayer/EmbedPlayer.resources.php |
— | — | @@ -0,0 +1,28 @@ |
| 2 | +<?php |
| 3 | + |
| 4 | +/** |
| 5 | + * EmbedPlayer module resource list array |
| 6 | + */ |
| 7 | + |
| 8 | +return array( |
| 9 | + "mw.EmbedPlayer" => array( 'scripts'=> "mw.EmbedPlayer.js" ), |
| 10 | + |
| 11 | + "mw.EmbedPlayerKplayer" => array( 'scripts'=> "mw.EmbedPlayerKplayer.js" ), |
| 12 | + "mw.EmbedPlayerGeneric" => array( 'scripts'=> "mw.EmbedPlayerGeneric.js" ), |
| 13 | + "mw.EmbedPlayerHtml" => array( 'scripts'=> "mw.EmbedPlayerHtml.js" ), |
| 14 | + "mw.EmbedPlayerJava" => array( 'scripts'=> "mw.EmbedPlayerJava.js"), |
| 15 | + "mw.EmbedPlayerNative" => array( 'scripts'=> "mw.EmbedPlayerNative.js" ), |
| 16 | + |
| 17 | + "mw.EmbedPlayerVlc" => array( 'scripts'=> "mw.EmbedPlayerVlc.js" ), |
| 18 | + |
| 19 | + "mw.PlayerControlBuilder" => array( 'scripts' => "skins/mw.PlayerControlBuilder.js" ), |
| 20 | + |
| 21 | + "mw.style.EmbedPlayer" => array( 'scripts'=> "skins/mw.style.EmbedPlayer.css" ), |
| 22 | + |
| 23 | + "mw.style.PlayerSkinKskin" => array( 'scripts' => "skins/kskin/mw.style.PlayerSkinKskin.css" ), |
| 24 | + |
| 25 | + "mw.PlayerSkinKskin" => array( 'scripts' => "skins/kskin/mw.PlayerSkinKskin.js"), |
| 26 | + |
| 27 | + "mw.PlayerSkinMvpcf" => array( 'scripts'=> "skins/mvpcf/mw.PlayerSkinMvpcf.js"), |
| 28 | + "mw.style.PlayerSkinMvpcf" => array( 'scripts'=> "skins/mvpcf/mw.style.PlayerSkinMvpcf.css"), |
| 29 | +); |
\ No newline at end of file |
Index: trunk/extensions/TimedMediaHandler/EmbedPlayer/EmbedPlayer.loader.js |
— | — | @@ -10,7 +10,7 @@ |
11 | 11 | mw.setDefaultConfig( { |
12 | 12 | // What tags will be re-written to video player by default |
13 | 13 | // Set to empty string or null to avoid automatic video tag rewrites to embedPlayer |
14 | | - "EmbedPlayer.RewriteTags" : "video,audio,playlist" |
| 14 | + "EmbedPlayer.RewriteTags" : "video,audio" |
15 | 15 | } ); |
16 | 16 | |
17 | 17 | /** |
— | — | @@ -44,7 +44,7 @@ |
45 | 45 | mw.rewritePagePlayerTags = function() { |
46 | 46 | mw.log( 'EmbedPlayer:: Document::' + mw.documentHasPlayerTags() ); |
47 | 47 | if( mw.documentHasPlayerTags() ) { |
48 | | - var rewriteElementCount = 0; |
| 48 | + var rewriteElementCount = 0; |
49 | 49 | |
50 | 50 | // Set each player to loading ( as early on as possible ) |
51 | 51 | $j( mw.getConfig( 'EmbedPlayer.RewriteTags' ) ).each( function( index, element ){ |
Index: trunk/extensions/AddMediaWizard/AddMedia/mw.UploadHandler.js |
— | — | @@ -82,7 +82,7 @@ |
83 | 83 | myUpload.setupForm( ); |
84 | 84 | } |
85 | 85 | |
86 | | - // Update the selecto to include pointer to upload handler |
| 86 | + // Update the selector to include pointer to upload handler |
87 | 87 | var selectorElement = $j( this.selector ).get( 0 ); |
88 | 88 | selectorElement[ 'uploadHandler' ] = myUpload; |
89 | 89 | }; |
— | — | @@ -140,8 +140,13 @@ |
141 | 141 | } else { |
142 | 142 | // Setup the default DialogInterface UI |
143 | 143 | this.ui = new mw.UploadDialogInterface(); |
144 | | - } |
145 | | - |
| 144 | + } |
| 145 | + |
| 146 | + // Don't rewrite on reuploads |
| 147 | + if( $j("[name='wpForReUpload']").val() ) { |
| 148 | + this.rewriteDescriptionText = false; |
| 149 | + } |
| 150 | + |
146 | 151 | // Setup ui uploadHandler pointer |
147 | 152 | this.ui.uploadHandler = this; |
148 | 153 | |
— | — | @@ -552,7 +557,7 @@ |
553 | 558 | * @param {String} source The source filed |
554 | 559 | */ |
555 | 560 | getCommentText: function( comment, license, copyStatus, source ) { |
556 | | - var pageText = '== ' + gM( 'mwe-filedesc' ) + " ==\n" + comment + "\n"; |
| 561 | + var pageText = '== ' + mw.Language.msgNoTrans( 'mwe-filedesc' ) + " ==\n" + comment + "\n"; |
557 | 562 | if( copyStatus ){ |
558 | 563 | pageText += '== ' + gM( 'mwe-filestatus' ) + " ==\n" + copyStatus + "\n"; |
559 | 564 | } |
— | — | @@ -560,8 +565,8 @@ |
561 | 566 | pageText += '== ' + gM( 'mwe-filesource' ) + " ==\n" + source + "\n"; |
562 | 567 | } |
563 | 568 | if ( license ) { |
564 | | - pageText += '== ' + gM( 'mwe-license-header' ) + " ==\n" + '{{' + license + '}}' + "\n"; |
565 | | - } |
| 569 | + pageText += '== ' + mw.Language.msgNoTrans( 'mwe-license-header' ) + " ==\n" + '{{' + license + '}}' + "\n"; |
| 570 | + } |
566 | 571 | return pageText; |
567 | 572 | }, |
568 | 573 | |
Index: trunk/extensions/AddMediaWizard/AddMedia/searchLibs/mediaWikiSearch.js |
— | — | @@ -25,7 +25,7 @@ |
26 | 26 | /** |
27 | 27 | * Adds a resource by its Title |
28 | 28 | * |
29 | | - * @param {String} title Title of the resource to be added |
| 29 | + * @param {String} title Title of the resource to be added (in the form of a wgPageName) |
30 | 30 | * @param {Function} callback Function called once title resource acquired |
31 | 31 | */ |
32 | 32 | getByTitle:function( title , callback ) { |
— | — | @@ -47,7 +47,13 @@ |
48 | 48 | callback( _this.addSingleResult( data ) ); |
49 | 49 | }); |
50 | 50 | }, |
51 | | - |
| 51 | + |
| 52 | + /** |
| 53 | + * Add a resource by its Url |
| 54 | + * |
| 55 | + * @param {String} url The url of the resource to be added |
| 56 | + * @param {Function} callback Function called once the resource is acquired |
| 57 | + */ |
52 | 58 | getResourceFromUrl: function( url, callback ){ |
53 | 59 | var title = this.getTitleKeyFromMwUrl( url ); |
54 | 60 | if( !title) { |
— | — | @@ -56,21 +62,25 @@ |
57 | 63 | } |
58 | 64 | this.getByTitle(title , callback ); |
59 | 65 | }, |
| 66 | + |
60 | 67 | /** |
61 | | - * Does best effort to get the title key from a mediawiki url |
| 68 | + * Does best effort to get the title key from a mediawiki url |
| 69 | + * |
| 70 | + * @param {String} url The url for which we want to find the title |
| 71 | + * @return {String} The title in a form that should mirror wgPageName |
62 | 72 | */ |
63 | 73 | getTitleKeyFromMwUrl: function( url ){ |
64 | 74 | // try for title key param |
65 | 75 | var titleKey = mw.parseUri( url ).queryKey['title']; |
66 | 76 | if( titleKey ){ |
67 | | - return titleKey; |
| 77 | + return decodeURIComponent( titleKey ).replace( / /g, "_"); |
68 | 78 | } |
69 | 79 | // else try for title url map |
70 | 80 | titleKey = url.replace( this.provider.detailsUrl.replace( '$1', ''), '' ); |
71 | 81 | if( titleKey != url ){ |
72 | | - return titleKey; |
| 82 | + return decodeURI(titleKey).replace( / /g, "_" );; |
73 | 83 | } |
74 | | - mw.log("Error: mediaWikiSearch:: getResourceFromUrl could not get title form url: " + url ); |
| 84 | + mw.log("Error: mediaWikiSearch:: getResourceFromUrl could not get title from url: " + url ); |
75 | 85 | return false; |
76 | 86 | }, |
77 | 87 | |
— | — | @@ -94,7 +104,7 @@ |
95 | 105 | var pound = ''; |
96 | 106 | // loop over the data and group by title |
97 | 107 | if ( data.query && data.query.recentchanges ) { |
98 | | - for ( var i in data.query.recentchanges ) { |
| 108 | + for ( var i=0; i < data.query.recentchanges.length; i++ ) { |
99 | 109 | var rc = data.query.recentchanges[i]; |
100 | 110 | if ( !titleSet[ rc.title ] ) { |
101 | 111 | titleSet[ rc.title ] = true; |
— | — | @@ -135,16 +145,17 @@ |
136 | 146 | // Build the image request |
137 | 147 | var request = { |
138 | 148 | 'action':'query', |
139 | | - 'generator':'search', |
140 | | - 'gsrsearch': search_query , |
141 | | - 'gsrnamespace':6, // (only search the "file" namespace (audio, video, images) |
142 | | - 'gsrwhat': 'text', |
143 | | - 'gsrlimit': this.provider.limit, |
144 | | - 'gsroffset': this.provider.offset, |
145 | | - 'prop':'imageinfo|revisions|categories', |
146 | | - 'iiprop':'url|mime|size|metadata', |
147 | | - 'iiurlwidth': parseInt( this.rsd.thumb_width ), |
148 | | - 'rvprop':'content' |
| 149 | + 'generator': 'search', |
| 150 | + 'gsrsearch': search_query , |
| 151 | + 'gsrnamespace': 6, // (only search the "file" namespace (audio, video, images) |
| 152 | + 'gsrwhat': 'text', |
| 153 | + 'gsrlimit': this.provider.limit, |
| 154 | + 'gsroffset': this.provider.offset, |
| 155 | + 'prop': 'imageinfo|revisions|categories', |
| 156 | + 'iiprop': 'url|mime|size|metadata', |
| 157 | + 'iiurlwidth': parseInt( this.rsd.thumb_width ), |
| 158 | + 'rvprop': 'content', |
| 159 | + 'redirects': true |
149 | 160 | }; |
150 | 161 | |
151 | 162 | // Do the api request: |
— | — | @@ -183,42 +194,39 @@ |
184 | 195 | if ( data.query && data.query.pages ) { |
185 | 196 | for ( var page_id in data.query.pages ) { |
186 | 197 | var page = data.query.pages[ page_id ]; |
187 | | - |
188 | | - // Make sure the reop is shared (don't show for now it confusing things) |
| 198 | + |
| 199 | + // Make sure the repo is shared (don't show for now it confusing things) |
189 | 200 | // @@todo support remote repository better |
190 | 201 | if ( page.imagerepository == 'shared' ) { |
191 | 202 | continue; |
192 | 203 | } |
193 | | - |
194 | | - // Make sure the page is not a redirect |
195 | | - if ( page.revisions && page.revisions[0] && |
196 | | - page.revisions[0]['*'] && page.revisions[0]['*'].indexOf( '#REDIRECT' ) === 0 ) { |
197 | | - // skip page is redirect |
198 | | - continue; |
199 | | - } |
200 | | - |
| 204 | + |
201 | 205 | // Skip if its an empty or missing imageinfo: |
202 | 206 | if ( !page.imageinfo ){ |
203 | 207 | continue; |
204 | 208 | } |
205 | | - |
| 209 | + |
206 | 210 | // Get the url safe titleKey from the descriptionurl |
207 | | - var titleKey = page.imageinfo[0].descriptionurl.split( '/' ) |
208 | | - ; |
| 211 | +<<<<<<< .mine |
| 212 | + var titleKey = page.imageinfo[0].descriptionurl.split( '/' ); |
209 | 213 | titleKey = unescape( |
210 | 214 | titleKey[ titleKey.length - 1 ] |
211 | 215 | .replace( 'index.php?title=', '') |
212 | 216 | ); |
213 | 217 | |
| 218 | +======= |
| 219 | + var titleKey = page.title.replace( / /g, "_" ); |
| 220 | + |
| 221 | +>>>>>>> .r75107 |
214 | 222 | var resource = { |
215 | 223 | 'id' : page_id, |
216 | 224 | 'titleKey' : titleKey, |
217 | 225 | 'link' : page.imageinfo[0].descriptionurl, |
218 | 226 | 'title' : page.title.replace(/Image:|File:|.jpg|.png|.svg|.ogg|.ogv|.oga/ig, ''), |
219 | 227 | 'poster' : page.imageinfo[0].thumburl, |
220 | | - 'thumbwidth' : page.imageinfo[0].thumbwidth, |
221 | | - 'thumbheight': page.imageinfo[0].thumbheight, |
222 | | - 'width' : page.imageinfo[0].width, |
| 228 | + 'thumbwidth' : page.imageinfo[0].thumbwidth, |
| 229 | + 'thumbheight' : page.imageinfo[0].thumbheight, |
| 230 | + 'width' : page.imageinfo[0].width, |
223 | 231 | 'height' : page.imageinfo[0].height, |
224 | 232 | 'mime' : page.imageinfo[0].mime, |
225 | 233 | 'src' : page.imageinfo[0].url, |
— | — | @@ -231,7 +239,7 @@ |
232 | 240 | } |
233 | 241 | }; |
234 | 242 | |
235 | | - for( var i in page.imageinfo[0].metadata ){ |
| 243 | + for( var i=0; page.imageinfo[0].metadata && i < page.imageinfo[0].metadata.length; i++ ){ |
236 | 244 | if( page.imageinfo[0].metadata[i].name == 'length' ){ |
237 | 245 | resource.duration = page.imageinfo[0].metadata[i].value; |
238 | 246 | } |
— | — | @@ -421,4 +429,4 @@ |
422 | 430 | '|Description =' + resource.inlineDesc + "\n" + |
423 | 431 | '}}'; |
424 | 432 | } |
425 | | -} |
\ No newline at end of file |
| 433 | +} |
Index: trunk/extensions/AddMediaWizard/AddMedia/loader.js |
— | — | @@ -78,8 +78,8 @@ |
79 | 79 | '$j.ui' |
80 | 80 | ], |
81 | 81 | [ |
| 82 | + '$j.widget', |
82 | 83 | '$j.ui.mouse', |
83 | | - '$j.widget', |
84 | 84 | '$j.ui.progressbar', |
85 | 85 | '$j.ui.position', |
86 | 86 | '$j.ui.dialog', |
Index: trunk/extensions/AddMediaWizard/AddMedia/mw.RemoteSearchDriver.js |
— | — | @@ -1439,7 +1439,7 @@ |
1440 | 1440 | checkCopyURLApiResult: function( data, callback ) { |
1441 | 1441 | var _this = this; |
1442 | 1442 | // Api checks: |
1443 | | - for ( var i in data.paraminfo.modules[0].parameters ) { |
| 1443 | + for ( var i=0; i < data.paraminfo.modules[0].parameters.length; i++ ) { |
1444 | 1444 | var pname = data.paraminfo.modules[0].parameters[i].name; |
1445 | 1445 | if ( pname == 'url' ) { |
1446 | 1446 | mw.log( 'Autodetect Upload Mode: api: copy by url:: ' ); |
— | — | @@ -1479,7 +1479,7 @@ |
1480 | 1480 | 'uiprop' : 'rights' |
1481 | 1481 | }; |
1482 | 1482 | mw.getJSON( _this.upload_api_target, request, function( data ) { |
1483 | | - for ( var i in data.query.userinfo.rights ) { |
| 1483 | + for ( var i=0; i < data.query.userinfo.rights.length; i++ ) { |
1484 | 1484 | var right = data.query.userinfo.rights[i]; |
1485 | 1485 | // mw.log('checking: ' + right ) ; |
1486 | 1486 | if ( right == 'upload_by_url' ) { |
— | — | @@ -2342,8 +2342,8 @@ |
2343 | 2343 | |
2344 | 2344 | // Add libraries resizable and hoverIntent to support video edit tools |
2345 | 2345 | var librarySet = [ |
2346 | | - 'mw.ClipEdit', |
2347 | | - 'mw.style.ClipEdit', |
| 2346 | + 'mw.ClipEdit', |
| 2347 | + 'mw.style.ClipEdit', |
2348 | 2348 | '$j.ui.resizable' |
2349 | 2349 | ]; |
2350 | 2350 | mw.load( librarySet, function() { |
— | — | @@ -3287,4 +3287,4 @@ |
3288 | 3288 | // Run / update search display: |
3289 | 3289 | this.showResults( ); |
3290 | 3290 | } |
3291 | | -}; |
\ No newline at end of file |
| 3291 | +}; |
Index: trunk/extensions/AddMediaWizard/ClipEdit/mw.ClipEdit.js |
— | — | @@ -2,37 +2,8 @@ |
3 | 3 | * mw.ClipEdit handles the edit interfaces for images and video |
4 | 4 | */ |
5 | 5 | |
6 | | -// set gMsg object: |
7 | | -mw.addMessages( { |
8 | | - "mwe-clipedit-crop" : "Crop image", |
9 | | - "mwe-clipedit-apply_crop" : "Apply crop to image", |
10 | | - "mwe-clipedit-reset_crop" : "Reset crop", |
11 | | - "mwe-clipedit-insert_image_page" : "Insert into page", |
12 | | - "mwe-clipedit-insert_into_sequence" : "Insert into sequence", |
13 | | - "mwe-clipedit-preview_insert" : "Preview insert", |
14 | | - "mwe-clipedit-cancel_image_insert" : "Cancel insert", |
15 | | - "mwe-clipedit-sc_attributes" : "Clip detail edit", |
16 | | - "mwe-clipedit-sc_inoutpoints" : "Set in-out points", |
17 | | - "mwe-clipedit-sc_overlays" : "Overlays", |
18 | | - "mwe-clipedit-sc_audio" : "Audio control", |
19 | | - "mwe-clipedit-sc_duration" : "Duration", |
20 | | - "mwe-clipedit-template_properties" : "Template properties", |
21 | | - "mwe-clipedit-custom_title" : "Custom title", |
22 | | - "mwe-clipedit-edit_properties" : "Edit properties", |
23 | | - "mwe-clipedit-other_properties" : "Other properties", |
24 | | - "mwe-clipedit-resource_page" : "Resource page:", |
25 | | - "mwe-clipedit-set_in_out_points" : "Set in-out points", |
26 | | - "mwe-clipedit-start_time" : "Start time", |
27 | | - "mwe-clipedit-end_time" : "End time", |
28 | | - "mwe-clipedit-preview_inout" : "Preview in-out points", |
29 | | - "mwe-clipedit-edit-tools" : "Edit tools", |
30 | | - "mwe-clipedit-inline-description" : "Caption", |
31 | | - "mwe-clipedit-edit-video-tools" : "Edit video tools:", |
32 | | - "mwe-clipedit-duration" : "Duration:", |
33 | | - "mwe-clipedit-layout" : "Layout", |
34 | | - "mwe-clipedit-layout_right" : "Right side image layout", |
35 | | - "mwe-clipedit-layout_left" : "Left side image layout" |
36 | | -} ); |
| 6 | +// include all module messages |
| 7 | +mw.includeAllModuleMessages(); |
37 | 8 | |
38 | 9 | /** |
39 | 10 | * The default clipEdit values |