3fa47100905c32301d9cb244e7f9577885e5a294
[lhc/web/wiklou.git] / js2 / mwEmbed / mv_embed.js
1 /*
2 * ~mv_embed ~
3 * for details see: http://metavid.org/wiki/index.php/Mv_embed
4 *
5 * All Metavid Wiki code is Released under the GPL2
6 * for more info visit http://metavid.org/wiki/Code
7 *
8 * @url http://metavid.org
9 *
10 * parseUri:
11 * http://stevenlevithan.com/demo/parseuri/js/
12 *
13 * config values you can manually set the location of the mv_embed folder here
14 * (in cases where media will be hosted in a different place than the embedding page)
15 *
16 */
17 //fix multiple instances of mv_embed (ie include twice from two different servers)
18 var MV_DO_INIT=true;
19 if( MV_EMBED_VERSION ){
20 MV_DO_INIT=false;
21 }
22 //used to grab fresh copies of scripts. (should be changed on commit)
23 var MV_EMBED_VERSION = '1.0r19';
24
25 /*
26 * Configuration variables (can be set from some precceding script)
27 * set up mwConfig global overide any of the defaultMwConfig values:
28 * @@ more config valuse on the way ;)
29 */
30 var defaultMwConfig = {
31 'skin_name': 'mvpcf',
32 'video_size':'400x300'
33 }
34
35 if(!mwConfig)
36 var mwConfig = {};
37
38 //install the default config values for anything not set in mwConfig
39 checkDefaultMwConfig();
40
41 //whether or not to load java from an iframe.
42 //note: this is necessary for remote embedding because of java security model)
43 if(!mv_java_iframe)
44 var mv_java_iframe = true;
45
46 //for when useing mv_embed with script-loader in root mediawiki path
47 var mediaWiki_mvEmbed_path = 'js2/mwEmbed/';
48
49 var global_player_list = new Array(); //the global player list per page
50 var global_req_cb = new Array(); //the global request callback array
51 var _global = this; //global obj
52 var mv_init_done=false;
53 var global_cb_count =0;
54
55 /*parseUri class parses URIs:*/
56 var parseUri=function(d){var o=parseUri.options,value=o.parser[o.strictMode?"strict":"loose"].exec(d);for(var i=0,uri={};i<14;i++){uri[o.key[i]]=value[i]||""}uri[o.q.name]={};uri[o.key[12]].replace(o.q.parser,function(a,b,c){if(b)uri[o.q.name][b]=c});return uri};parseUri.options={strictMode:false,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*):?([^:@]*))?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}};
57
58
59 //get mv_embed location if it has not been set
60 if( !mv_embed_path ){
61 var mv_embed_path = getMvEmbedPath();
62 }
63
64 //setup the skin path:
65 var mv_jquery_skin_path = mv_embed_path + 'jquery/jquery.ui/themes/redmond/';
66 var mv_skin_img_path = mv_embed_path + 'skins/' + mwConfig['skin_name'] + '/images/';
67 var mv_default_thumb_url = mv_skin_img_path + 'vid_default_thumb.jpg';
68
69
70 //init the global Msg if not already
71 if(!gMsg){var gMsg={};}
72
73 //laguage msg loader:
74 function loadGM( msgSet ){
75 for(var i in msgSet){
76 gMsg[ i ] = msgSet[i];
77 }
78 }
79
80 //all default msg in [English] should be overwritten by the CMS language msg system.
81 loadGM({
82 "mwe-loading_txt" : "loading <blink>...<\/blink>",
83 "mwe-loading_title" : "Loading...",
84 "mwe-size-gigabytes" : "$1 GB",
85 "mwe-size-megabytes" : "$1 MB",
86 "mwe-size-kilobytes" : "$1 K",
87 "mwe-size-bytes" : "$1 B"
88 });
89
90 /**
91 * AutoLoader paths (this should mirror the file: jsAutoloadLocalClasses.php )
92 * any file _not_ listed here won't be auto-loadable
93 * @path the path to the file (or set of files) with ending slash
94 * @gClasses the set of classes
95 * if an array $j.className become jquery.className.js
96 * if an asssociative object then key => value paris are used
97 */
98 if(typeof mvAutoLoadClasses == 'undefined')
99 mvAutoLoadClasses = {};
100
101 //the script that loads the classet
102 function lcPaths( classSet){
103 for(var i in classSet){
104 mvAutoLoadClasses[i] = classSet[i];
105 }
106 }
107
108 function mvGetClassPath(k){
109 if( mvAutoLoadClasses[k] ){
110 //js_log('got classpath:' + k + ' : '+ mvClassPaths[k]);
111 return mvAutoLoadClasses[k];
112 }else{
113 return js_error('could not find path for requested class ' + k );
114 }
115 }
116 if(typeof mvCssPaths == 'undefined')
117 mvCssPaths = {};
118
119 function lcCssPath(cssSet){
120 for(var i in cssSet){
121 mvCssPaths[i]= mv_embed_path + cssSet[i];
122 }
123 }
124
125 /*
126 * -- Load Class Paths --
127 *
128 * MUST BE VALID JSON (NOT JS)
129 * is used by the scriptloader to autoLoad classes (so we only define this once for php & javascript)
130 *
131 * this is more verbose than earlier version that compressed paths
132 * but its all good gziping help compress repetative path strings
133 * grouped by
134 *
135 * right now php AutoLoader only reads this mv_embed.js file
136 * in the future we could have multiple lcPath calls that php reads
137 * (if our autoloading class list becomes too long) just have to add thouse
138 * files to the jsAutoLoader file list.
139 */
140 lcPaths({
141 "mv_embed" : "mv_embed.js",
142 "window.jQuery" : "jquery/jquery-1.3.2.js",
143 "$j.fn.pngFix" : "jquery/plugins/jquery.pngFix.js",
144 "$j.fn.autocomplete": "jquery/plugins/jquery.autocomplete.js",
145 "$j.fn.hoverIntent" : "jquery/plugins/jquery.hoverIntent.js",
146 "$j.fn.datePicker" : "jquery/plugins/jquery.datePicker.js",
147 "$j.ui" : "jquery/jquery.ui/ui/ui.core.js",
148 "$j.fn.ColorPicker" : "libClipEdit/colorpicker/js/colorpicker.js",
149 "$j.Jcrop" : "libClipEdit/Jcrop/js/jquery.Jcrop.js",
150 "$j.fn.simpleUploadForm": "libAddMedia/simpleUploadForm.js",
151
152 "ctrlBuilder" : "skins/ctrlBuilder.js",
153 "kskin" : "skins/kskin/kskin.js",
154 "mvpcf" : "skins/mvpcf/mvpcf.js",
155
156 "$j.secureEvalJSON" : "jquery/plugins/jquery.secureEvalJSON.js",
157 "$j.cookie" : "jquery/plugins/jquery.cookie.js",
158 "$j.contextMenu" : "jquery/plugins/jquery.contextMenu.js",
159
160 "$j.effects.blind" : "jquery/jquery.ui/ui/effects.blind.js",
161 "$j.effects.drop" : "jquery/jquery.ui/ui/effects.drop.js",
162 "$j.effects.pulsate" : "jquery/jquery.ui/ui/effects.pulsate.js",
163 "$j.effects.transfer" : "jquery/jquery.ui/ui/effects.transfer.js",
164 "$j.ui.droppable" : "jquery/jquery.ui/ui/ui.droppable.js",
165 "$j.ui.slider" : "jquery/jquery.ui/ui/ui.slider.js",
166 "$j.effects.bounce" : "jquery/jquery.ui/ui/effects.bounce.js",
167 "$j.effects.explode" : "jquery/jquery.ui/ui/effects.explode.js",
168 "$j.effects.scale" : "jquery/jquery.ui/ui/effects.scale.js",
169 "$j.ui.datepicker" : "jquery/jquery.ui/ui/ui.datepicker.js",
170 "$j.ui.progressbar" : "jquery/jquery.ui/ui/ui.progressbar.js",
171 "$j.ui.sortable" : "jquery/jquery.ui/ui/ui.sortable.js",
172 "$j.effects.clip" : "jquery/jquery.ui/ui/effects.clip.js",
173 "$j.effects.fold" : "jquery/jquery.ui/ui/effects.fold.js",
174 "$j.effects.shake" : "jquery/jquery.ui/ui/effects.shake.js",
175 "$j.ui.dialog" : "jquery/jquery.ui/ui/ui.dialog.js",
176 "$j.ui.resizable" : "jquery/jquery.ui/ui/ui.resizable.js",
177 "$j.ui.tabs" : "jquery/jquery.ui/ui/ui.tabs.js",
178 "$j.effects.core" : "jquery/jquery.ui/ui/effects.core.js",
179 "$j.effects.highlight" : "jquery/jquery.ui/ui/effects.highlight.js",
180 "$j.effects.slide" : "jquery/jquery.ui/ui/effects.slide.js",
181 "$j.ui.accordion" : "jquery/jquery.ui/ui/ui.accordion.js",
182 "$j.ui.draggable" : "jquery/jquery.ui/ui/ui.draggable.js",
183 "$j.ui.selectable" : "jquery/jquery.ui/ui/ui.selectable.js",
184
185 "mvFirefogg" : "libAddMedia/mvFirefogg.js",
186 "mvAdvFirefogg" : "libAddMedia/mvAdvFirefogg.js",
187 "mvBaseUploadInterface" : "libAddMedia/mvBaseUploadInterface.js",
188 "remoteSearchDriver" : "libAddMedia/remoteSearchDriver.js",
189 "seqRemoteSearchDriver" : "libAddMedia/seqRemoteSearchDriver.js",
190
191 "baseRemoteSearch" : "libAddMedia/searchLibs/baseRemoteSearch.js",
192 "mediaWikiSearch" : "libAddMedia/searchLibs/mediaWikiSearch.js",
193 "metavidSearch" : "libAddMedia/searchLibs/metavidSearch.js",
194 "archiveOrgSearch" : "libAddMedia/searchLibs/archiveOrgSearch.js",
195 "baseRemoteSearch" : "libAddMedia/searchLibs/baseRemoteSearch.js",
196
197 "mvClipEdit" : "libClipEdit/mvClipEdit.js",
198
199 "embedVideo" : "libEmbedVideo/embedVideo.js",
200 "flashEmbed" : "libEmbedVideo/flashEmbed.js",
201 "genericEmbed" : "libEmbedVideo/genericEmbed.js",
202 "htmlEmbed" : "libEmbedVideo/htmlEmbed.js",
203 "javaEmbed" : "libEmbedVideo/javaEmbed.js",
204 "nativeEmbed" : "libEmbedVideo/nativeEmbed.js",
205 "quicktimeEmbed" : "libEmbedVideo/quicktimeEmbed.js",
206 "vlcEmbed" : "libEmbedVideo/vlcEmbed.js",
207
208 "mvPlayList" : "libSequencer/mvPlayList.js",
209 "mvSequencer" : "libSequencer/mvSequencer.js",
210 "mvFirefoggRender" : "libSequencer/mvFirefoggRender.js",
211 "mvTimedEffectsEdit": "libSequencer/mvTimedEffectsEdit.js",
212
213 "libTimedText" : "libTimedText/mvTextInterface.js"
214
215 });
216
217 //depencency mapping for css files for self contained included plugins:
218 lcCssPath({
219 '$j.Jcrop' : 'libClipEdit/Jcrop/css/jquery.Jcrop.css',
220 '$j.fn.ColorPicker' : 'libClipEdit/colorpicker/css/colorpicker.css'
221 })
222
223 /**
224 * Language Functions:
225 *
226 * These functions try to losely mirro the functionality of Language.php in mediaWiki
227 */
228 function gM( key , args ) {
229 var ms ='';
230 if ( key in gMsg ) {
231 ms = gMsg[ key ];
232 if(typeof args == 'object' || typeof args == 'array'){
233 for(var v in args){
234 //msg test replace arguments start at 1 insted of zero:
235 var rep = '\$'+ ( parseInt(v) + 1 );
236 ms = ms.replace( rep, args[v]);
237 }
238 }else if(typeof args =='string' || typeof args =='number'){
239 ms = ms.replace(/\$1/, args);
240 }
241 return ms;
242 } else{
243 //key is missing return indication:
244 return '&lt;' + key + '&gt;';
245 }
246 }
247 /*
248 * msgSet is either a string corresponding to a single msg to load
249 * or msgSet is an array with set of msg to load
250 */
251 function gMsgLoadRemote(msgSet, callback){
252 var ammessages = '';
253 if(typeof msgSet == 'object' ){
254 for(var i in msgSet){
255 ammessages += msgSet[i] + '|';
256 }
257 }else if(typeof msgSet == 'string'){
258 ammessages += msgSet;
259 }
260 if(ammessages == ''){
261 js_log('gMsgLoadRemote::no msg set requested');
262 return false;
263 }
264 do_api_req({
265 'data':{
266 'meta':'allmessages',
267 'ammessages':ammessages
268 }
269 },function(data){
270 if(data.query.allmessages){
271 var msgs = data.query.allmessages;
272 for(var i in msgs){
273 var ld = {};
274 ld[ msgs[i]['name'] ] = msgs[i]['*'];
275 loadGM( ld );
276 }
277 }
278 //load the result into local msg var
279 callback();
280 });
281 }
282
283 /**
284 * Format a size in bytes for output, using an appropriate
285 * unit (B, KB, MB or GB) according to the magnitude in question
286 *
287 * @param size Size to format
288 * @return string Plain text (not HTML)
289 */
290 function formatSize( size ) {
291 // For small sizes no decimal places necessary
292 var round = 0;
293 var msg = '';
294 if( size > 1024 ) {
295 size = size / 1024;
296 if( size > 1024 ) {
297 size = size / 1024;
298 // For MB and bigger two decimal places are smarter
299 round = 2;
300 if( size > 1024 ) {
301 size = size / 1024;
302 msg = 'mwe-size-gigabytes';
303 } else {
304 msg = 'mwe-size-megabytes';
305 }
306 } else {
307 msg = 'mwe-size-kilobytes';
308 }
309 } else {
310 msg = 'mwe-size-bytes';
311 }
312 //javascript does not let you do precession points in rounding
313 var p = Math.pow(10,round);
314 var size = Math.round( size * p ) / p;
315 //@@todo we need a formatNum and we need to request some special packaged info to deal with that case.
316 return gM( msg , size );
317 }
318
319 //gets the loading image:
320 function mv_get_loading_img( style , class_attr ){
321 var style_txt = (style)?style:'';
322 var class_attr = (class_attr)?'class="'+class_attr+'"':'class="mv_loading_img"';
323 return '<div '+class_attr+' style="' + style +'"></div>';
324 }
325
326 function mv_set_loading(target, load_id){
327 var id_attr = ( load_id )?' id="' + load_id + '" ':'';
328 $j(target).append('<div '+id_attr+' style="position:absolute;top:0px;left:0px;height:100%;width:100%;'+
329 'background-color:#FFF;">' +
330 mv_get_loading_img('top:30px;left:30px') +
331 '</div>');
332 }
333
334 /**
335 * mvJsLoader class handles initialization and js file loads
336 */
337 var mvJsLoader = {
338 libreq : {},
339 libs : {},
340 //base lib flags:
341 onReadyEvents:new Array(),
342 doneReadyEvents:false,
343 jQueryCheckFlag:false,
344 //to keep consistency across threads:
345 ptime:0,
346 ctime:0,
347 load_error:false, //load error flag (false by default)
348 load_time:0,
349 callbacks:new Array(),
350 cur_path: null,
351 missing_path : null,
352 doLoad:function(loadLibs, callback){
353 this.ctime++;
354 if( loadLibs && loadLibs.length!=0 ){ //setup this.libs:
355
356 //first check if we already have this lib loaded
357 var all_libs_loaded=true;
358 for(var i=0; i< loadLibs.length; i++){
359 //check if the lib is already loaded:
360 if( ! this.checkObjPath( loadLibs[i] ) ){
361 all_libs_loaded=false;
362 }
363 }
364 if( all_libs_loaded ){
365 js_log('all libs already loaded skipping... load req');
366 callback();
367 return ;
368 }
369 //do a check for any css we may need and get it:
370 for(var i=0; i< loadLibs.length; i++){
371 if( typeof mvCssPaths[ loadLibs[i] ] != 'undefined' ){
372 loadExternalCss( mvCssPaths[ loadLibs[i] ]);
373 }
374 }
375
376 //check if we should use the script loader to combine all the requests into one:
377 if( typeof mwSlScript != 'undefined' ){
378 var class_set = '';
379 var last_class = '';
380 var coma = '';
381 for(var i=0; i< loadLibs.length; i++){
382 var curLib = loadLibs[i];
383 //only add if not included yet:
384 if( ! this.checkObjPath( curLib ) ){
385 class_set+=coma + curLib ;
386 last_class=curLib;
387 coma=',';
388 }
389 }
390 var puri = parseUri( getMvEmbedURL() );
391 if( (getMvEmbedURL().indexOf('://')!=-1) && puri.host != parseUri( document.URL).host){
392 mwSlScript = puri.protocol + '://' + puri.authority + mwSlScript;
393 }
394
395 var dbug_attr = (puri.queryKey['debug'])?'&debug=true':'';
396 this.libs[ last_class ] = mwSlScript + '?class=' + class_set +
397 '&urid=' + getMvUniqueReqId() + dbug_attr;
398
399 }else{
400 //do many requests:
401 for(var i=0; i< loadLibs.length; i++){
402 var curLib = loadLibs[i];
403 if(curLib){
404 var libLoc = mvGetClassPath(curLib);
405 // do a direct load of the file (pass along unique request id from request or mv_embed Version )
406 var qmark = (libLoc.indexOf('?')!==true)?'?':'&';
407 this.libs[curLib] = mv_embed_path + libLoc + qmark + 'urid='+ getMvUniqueReqId();
408 }
409 }
410 }
411 }
412 if( callback ){
413 this.callbacks.push(callback);
414 }
415 if( this.checkLoading() ){
416 if( this.load_time++ > 1000){ //time out after ~80seconds
417 js_error( gM('error_load_lib') + this.missing_path );
418 this.load_error=true;
419 }else{
420 setTimeout( 'mvJsLoader.doLoad()', 20 );
421 }
422 }else{
423 //js_log('checkLoading passed run callbacks');
424 //only do callback if we are in the same instance (weird concurency issue)
425 var cb_count=0;
426 for(var i=0; i < this.callbacks.length; i++)
427 cb_count++;
428 //js_log('REST LIBS: loading is: '+ loading + ' run callbacks: '+cb_count +' p:'+ this.ptime +' c:'+ this.ctime);
429 //reset the libs
430 this.libs={};
431 //js_log('done loading do call: ' + this.callbacks[0] );
432 while( this.callbacks.length !=0 ){
433 if( this.ptime== ( this.ctime-1) ){ //enforce thread consistency
434 this.callbacks.pop()();
435 //func = this.callbacks.pop();
436 //js_log(' run: '+this.ctime+ ' p: ' + this.ptime + ' ' +loading+ ' :'+ func);
437 //func();
438 }else{
439 //re-issue doLoad ( ptime will be set to ctime so we should catch up)
440 setTimeout( 'mvJsLoader.doLoad()', 25 );
441 break;
442 }
443 }
444 }
445 this.ptime=this.ctime;
446 },
447 doLoadFullPaths:function(loadObj, callback){
448
449 },
450 doLoadDepMode:function(loadChain, callback){
451 //firefox executes js ~in-order of it being included~ so just directly issue request:
452 if( $j.browser.firefox ){
453 var loadSet = [];
454 for(var i=0; i< loadChain.length;i++){
455 for(var j=0;j<loadChain[i].length;j++){
456 loadSet.push(loadChain[i][j]);
457 }
458 }
459 mvJsLoader.doLoad(loadSet, callback);
460 }else{
461 //safari and IE tend to execute out of order so load with dependenciy checks
462 mvJsLoader.doLoad(loadChain.shift(),function(){
463 if(loadChain.length!=0){
464 mvJsLoader.doLoadDepMode(loadChain, callback);
465 }else{
466 callback();
467 }
468 });
469 } },
470 checkLoading:function(){
471 var loading=0;
472 var i=null;
473 for(var i in this.libs){ //for in loop oky on object
474 if( !this.checkObjPath( i ) ){
475 if(!this.libreq[i]){
476 loadExternalJs( this.libs[i] );
477 }
478
479 this.libreq[i]=1;
480 //js_log("has not yet loaded: " + i);
481 loading=1;
482 }
483 }
484 return loading;
485 },
486 checkObjPath:function( libVar ){
487 if(!libVar)
488 return false;
489 var objPath = libVar.split('.')
490 var cur_path ='';
491 for(var p=0; p < objPath.length; p++){
492 cur_path = (cur_path=='')?cur_path+objPath[p]:cur_path+'.'+objPath[p];
493 eval( 'var ptest = typeof ( '+ cur_path + ' ); ');
494 if( ptest == 'undefined'){
495 this.missing_path = cur_path;
496 return false;
497 }
498 }
499 this.cur_path = cur_path;
500 return true;
501 },
502 /**
503 * checks for jQuery and adds the $j noConflict var
504 */
505 jQueryCheck:function(callback){
506 //skip stuff if $j is already loaded:
507 if(_global['$j'] && callback)
508 callback();
509 var _this = this;
510 //load jquery
511 _this.doLoad([
512 'window.jQuery'
513 ],function(){
514 _global['$j'] = jQuery.noConflict();
515 //set up ajax to not send dynamic urls for loading scripts (we control that with the scriptLoader)
516 $j.ajaxSetup({
517 cache: true
518 });
519 js_log('jquery loaded');
520 //setup mvEmbed jquery bindigns:
521 mv_jqueryBindings();
522 //run the callback
523 if(callback){
524 callback();
525 }
526 });
527 },
528 embedVideoCheck:function( callback ){
529 var _this = this;
530 js_log('embedVideoCheck:');
531 //set videonojs to loading
532 //issue a style sheet request get both mv_embed and jquery styles:
533 loadExternalCss( mv_jquery_skin_path + 'jquery-ui-1.7.1.custom.css' );
534 loadExternalCss( mv_embed_path + 'skins/'+mwConfig['skin_name']+'/styles.css');
535
536 //make sure we have jQuery
537 _this.jQueryCheck(function(){
538 $j('.videonojs').html( gM('mwe-loading_txt') );
539 var depReq = [
540 [
541 '$j.ui',
542 'embedVideo',
543 'ctrlBuilder',
544 '$j.cookie'
545 ],
546 [
547 '$j.ui.slider'
548 ]
549 ];
550 //add png fix if needed:
551 if($j.browser.msie || $j.browser.version < 7)
552 depReq[0].push( '$j.fn.pngFix' );
553
554 _this.doLoadDepMode(depReq,function(){
555 embedTypes.init();
556 callback();
557 $j('.videonojs').remove();
558 });
559 });
560 },
561 addLoadEvent:function(fn){
562 this.onReadyEvents.push(fn);
563 },
564 //checks the jQuery flag (this way when remote embeding we don't load jQuery
565 // unless js2AddOnloadHook was used or there is video on the page
566 runQuededFunctions:function(){
567 var _this = this;
568 this.doneReadyEvents=true;
569 if(this.jQueryCheckFlag){
570 this.jQueryCheck(function(){
571 _this.runReadyEvents();
572 });
573 }else{
574 this.runReadyEvents();
575 }
576 },
577 runReadyEvents:function(){
578 js_log("runReadyEvents");
579 while( this.onReadyEvents.length ){
580 this.onReadyEvents.shift()();
581 }
582 }
583
584 }
585 //load an external JS (similar to jquery .require plugin)
586 //but checks for object availability rather than load state
587
588 /*********** INITIALIZATION CODE *************
589 * this will get called when DOM is ready
590 *********************************************/
591 /* jQuery .ready does not work when jQuery is loaded dynamically
592 * for an example of the problem see:1.1.3 working:http://pastie.caboo.se/92588
593 * and >= 1.1.4 not working: http://pastie.caboo.se/92595
594 * $j(document).ready( function(){ */
595 function mwdomReady(force){
596 js_log('f:mwdomReady:');
597 if( !force && mv_init_done ){
598 js_log("mv_init_done already done do nothing...");
599 return false;
600 }
601 mv_init_done=true;
602 //handle the execution of Queded function with jQuery "ready"
603
604 //check if this page does have video or playlist
605 var e = [
606 document.getElementsByTagName("video"),
607 document.getElementsByTagName("audio"),
608 document.getElementsByTagName("playlist")
609 ];
610 if(e[0].length!=0 || e[1].length!=0 || e[2].length!=0){
611 js_log('we have items to rewrite');
612
613 //load libs and proccess:
614 mvJsLoader.embedVideoCheck(function(){
615 //run any queded global events:
616 mv_video_embed( function(){
617 mvJsLoader.runQuededFunctions();
618 });
619 });
620 }else{
621 //if we already have jQuery make sure its loaded into its proper context $j
622 //run any queded global events:
623 mvJsLoader.runQuededFunctions();
624 }
625 }
626 //js2AddOnloadHook: ensure jQuery and the DOM are ready:
627 function js2AddOnloadHook( func ) {
628 //make sure the skin/style sheets are avaliable always:
629 loadExternalCss( mv_jquery_skin_path + 'jquery-ui-1.7.1.custom.css' );
630 loadExternalCss( mv_embed_path + 'skins/'+mwConfig['skin_name']+'/styles.css');
631
632 //if we have already run the dom ready just run the function directly:
633 if( mvJsLoader.doneReadyEvents ){
634 //make sure jQuery is there:
635 mvJsLoader.jQueryCheck(function(){
636 func();
637 });
638 }else{
639 //if using js2AddOnloadHook we need to get jQuery into place (if its not already included)
640 mvJsLoader.jQueryCheckFlag = true;
641 mvJsLoader.addLoadEvent( func );
642 };
643 }
644 //depreciated mwAddOnloadHook in favor of js2 naming (for clear seperation of js2 code from old mw code
645 var mwAddOnloadHook = js2AddOnloadHook;
646 /*
647 * this function allows for targeted rewriting
648 */
649 function rewrite_by_id( vid_id, ready_callback ){
650 js_log('f:rewrite_by_id: ' + vid_id);
651 //force a recheck of the dom for playlist or video element:
652 mvJsLoader.embedVideoCheck(function(){
653 mv_video_embed(ready_callback, vid_id );
654 });
655 }
656 //depricated in favor of updates to oggHanlder
657 function rewrite_for_oggHanlder( vidIdList ){
658 for(var i = 0; i < vidIdList.length ; i++){
659 var vidId = vidIdList[i];
660 js_log('looking at vid: ' + i +' ' + vidId);
661 //grab the thumbnail and src video
662 var pimg = $j('#'+vidId + ' img');
663 var poster_attr = 'poster = "' + pimg.attr('src') + '" ';
664 var pwidth = pimg.attr('width');
665 var pheight = pimg.attr('height');
666
667 var type_attr = '';
668 //check for audio
669 if( pwidth=='22' && pheight=='22'){
670 pwidth='400';
671 pheight='300';
672 type_attr = 'type="audio/ogg"';
673 poster_attr = '';
674 }
675
676 //parsed values:
677 var src = '';
678 var duration = '';
679
680 var re = new RegExp( /videoUrl(&quot;:?\s*)*([^&]*)/ );
681 src = re.exec( $j('#'+vidId).html() )[2];
682
683 var re = new RegExp( /length(&quot;:?\s*)*([^&]*)/ );
684 duration = re.exec( $j('#'+vidId).html() )[2];
685
686 var re = new RegExp( /offset(&quot;:?\s*)*([^&]*)/ );
687 offset = re.exec( $j('#'+vidId).html() )[2];
688 var offset_attr = (offset)? 'startOffset="'+ offset + '"': '';
689
690 if( src ){
691 //replace the top div with mv_embed based player:
692 var vid_html = '<video id="vid_' + i +'" '+
693 'src="' + src + '" ' +
694 poster_attr + ' ' +
695 type_attr + ' ' +
696 offset_attr + ' ' +
697 'duration="' + duration + '" ' +
698 'style="width:' + pwidth + 'px;height:' +
699 pheight + 'px;"></video>';
700 //js_log("video html: " + vid_html);
701 $j('#'+vidId).html( vid_html );
702 }
703
704 //rewrite that video id:
705 rewrite_by_id('vid_' + i);
706 }
707 }
708
709
710 /*********** INITIALIZATION CODE *************
711 * set DOM ready callback to init_mv_embed
712 *********************************************/
713 // for Mozilla browsers
714 if (document.addEventListener ) {
715 document.addEventListener("DOMContentLoaded", function(){mwdomReady()}, false);
716 }else{
717 //backup "onload" method in case on DOMContentLoaded does not exist
718 window.onload = function(){ mwdomReady() };
719 }
720 /*
721 * should depreciate and use jquery.ui.dialog instead
722 */
723 function mv_write_modal(content, speed){
724 $j('#modalbox,#mv_overlay').remove();
725 $j('body').append('<div id="modalbox" style="background:#DDD;border:3px solid #666666;font-size:115%;'+
726 'top:30px;left:20px;right:20px;bottom:30px;position:fixed;z-index:100;">'+
727 content +
728 '</div>'+
729 '<div id="mv_overlay" style="background:#000;cursor:wait;height:100%;left:0;position:fixed;'+
730 'top:0;width:100%;z-index:5;filter:alpha(opacity=60);-moz-opacity: 0.6;'+
731 'opacity: 0.6;"/>');
732 $j('#modalbox,#mv_overlay').show( speed );
733 }
734 function mv_remove_modal(speed){
735 $j('#modalbox,#mv_overlay').remove( speed);
736 }
737
738 /*
739 * stores all the mwEmbed jQuery specific bindings
740 * (setup after jQuery is avaliable)
741 * lets you call rewrites in a jquery "way"
742 *
743 * @@ eventually we should refactor mwCode over to jQuery style plugins
744 * and mv_embed.js will just hanndle dependency mapping and loading.
745 *
746 */
747 function mv_jqueryBindings(){
748 js_log('mv_jqueryBindings');
749 (function($) {
750 $.fn.addMediaWiz = function( iObj, callback ){
751 //first set the cursor for the button to "loading"
752 $j(this.selector).css('cursor','wait').attr('title', gM('mwe-loading_title'));
753
754 iObj['target_invocation'] = this.selector;
755
756 //load the mv_embed_base skin:
757 loadExternalCss( mv_jquery_skin_path + 'jquery-ui-1.7.1.custom.css' );
758 loadExternalCss( mv_embed_path + 'skins/'+mwConfig['skin_name']+'/styles.css' );
759 //load all the req libs:
760 mvJsLoader.jQueryCheck(function(){
761 //load with staged dependeinces (for ie and safari that don't execute in order)
762 mvJsLoader.doLoadDepMode([
763 [ 'remoteSearchDriver',
764 '$j.cookie',
765 '$j.ui'
766 ],[
767 '$j.ui.resizable',
768 '$j.ui.draggable',
769 '$j.ui.dialog',
770 '$j.ui.tabs',
771 '$j.ui.sortable'
772 ]
773 ], function(){
774 iObj['instance_name']= 'rsdMVRS';
775 _global['rsdMVRS'] = new remoteSearchDriver( iObj );
776 if( callback ){
777 callback( _global['rsdMVRS'] );
778 }
779 });
780 });
781 }
782 $.fn.sequencer = function( iObj, callback){
783 //debugger;
784 iObj['target_sequence_container'] = this.selector;
785 //issue a request to get the css file (if not already included):
786 loadExternalCss( mv_jquery_skin_path + 'jquery-ui-1.7.1.custom.css');
787 loadExternalCss( mv_embed_path+'skins/'+mwConfig['skin_name']+'/mv_sequence.css');
788 //make sure we have the required mv_embed libs (they are not loaded when no video element is on the page)
789 mvJsLoader.embedVideoCheck(function(){
790 //load playlist object and then jquery ui stuff:
791 mvJsLoader.doLoadDepMode([
792 [
793 'mvPlayList',
794 '$j.ui',
795 '$j.contextMenu',
796 '$j.secureEvalJSON',
797 'mvSequencer'
798 ],
799 [
800 '$j.ui.accordion',
801 '$j.ui.dialog',
802 '$j.ui.droppable',
803 '$j.ui.draggable',
804 '$j.ui.progressbar',
805 '$j.ui.sortable',
806 '$j.ui.resizable',
807 '$j.ui.slider',
808 '$j.ui.tabs'
809 ]
810 ], function(){
811 js_log('calling new mvSequencer');
812 //init the sequence object (it will take over from there) no more than one mvSeq obj for now:
813 if(!_global['mvSeq']){
814 _global['mvSeq'] = new mvSequencer(iObj);
815 }else{
816 js_log('mvSeq already init');
817 }
818 });
819 });
820 }
821 /*
822 * the firefogg jquery function:
823 * @@note this firefogg envocation could be made to work more like real jquery plugins
824 */
825 $.fn.firefogg = function( iObj, callback ) {
826 if(!iObj)
827 iObj={};
828 //add base theme css:
829 loadExternalCss( mv_jquery_skin_path + 'jquery-ui-1.7.1.custom.css');
830 loadExternalCss( mv_embed_path + 'skins/'+mwConfig['skin_name']+'/styles.css' );
831
832 //check if we already have firefogg loaded (the call just updates properties for that element)
833 var sElm = $j(this.selector).get(0);
834 if(sElm['firefogg']){
835 if(sElm['firefogg']=='loading'){
836 js_log("Error: called firefogg operations on Firefogg selector that is not done loading");
837 return false;
838 }
839 //update properties:
840 for(var i in iObj){
841 js_log("firefogg::updated: "+ i + ' to '+ iObj[i]);
842 sElm['firefogg'][i] = iObj[i];
843 }
844 return sElm['firefogg'];
845 }else{
846 //avoid concurency
847 sElm['firefogg'] = 'loading';
848 }
849 //add the selector:
850 iObj['selector'] = this.selector;
851
852 var loadSet = [
853 [
854 'mvBaseUploadInterface',
855 'mvFirefogg',
856 '$j.ui'
857 ],
858 [
859 '$j.ui.progressbar',
860 '$j.ui.dialog'
861 ]
862 ];
863 if( iObj.encoder_interface ){
864 loadSet.push([
865 'mvAdvFirefogg',
866 '$j.cookie',
867 '$j.ui.accordion',
868 '$j.ui.slider',
869 '$j.ui.datepicker'
870 ]);
871 }
872 //make sure we have everything loaded that we need:
873 mvJsLoader.doLoadDepMode( loadSet, function(){
874 js_log('firefogg libs loaded. target select:' + iObj.selector);
875 //select interface provicer based on if we want to include the encoder interface or not:
876 if(iObj.encoder_interface){
877 var myFogg = new mvAdvFirefogg( iObj );
878 }else{
879 var myFogg = new mvFirefogg( iObj );
880 }
881 if(myFogg){
882 myFogg.doRewrite( callback );
883 var selectorElement = $j( iObj.selector ).get(0);
884 selectorElement['firefogg']=myFogg;
885 }
886 });
887 }
888 //takes a input player as the selector and exposes basic rendering controls
889 $.fn.firefoggRender = function( iObj, callback ){
890 //check if we already have render loaded then just pass on updates/actions
891 var sElm = $j(this.selector).get(0);
892 if(sElm['fogg_render']){
893 if(sElm['fogg_render']=='loading'){
894 js_log("Error: called firefoggRender while loading");
895 return false;
896 }
897 //call or update the property:
898 }
899 sElm['fogg_render']='loading';
900 //add the selector:
901 iObj['player_target'] = this.selector;
902 mvJsLoader.doLoad([
903 'mvFirefogg',
904 'mvFirefoggRender'
905 ],function(){
906 sElm['fogg_render']= new mvFirefoggRender( iObj );
907 if( callback && typeof callback == 'function' )
908 callback( sElm['fogg_render'] );
909 });
910 }
911
912 $.fn.baseUploadInterface = function(iObj){
913 mvJsLoader.doLoadDepMode([
914 [
915 'mvBaseUploadInterface',
916 '$j.ui',
917 ],
918 [
919 '$j.ui.progressbar',
920 '$j.ui.dialog'
921 ]
922 ],function(){
923 myUp = new mvBaseUploadInterface( iObj );
924 myUp.setupForm();
925 });
926 }
927
928 //shortcut to a themed button:
929 $.btnHtml = function(msg, className, iconId, opt){
930 if(!opt)
931 opt = {};
932 var href = (opt.href)?opt.href:'#';
933 var target_attr = (opt.target)?' target="' + opt.target + '" ':'';
934 var style_attr = (opt.style)?' style="'+opt.style +'" ':'';
935 return '<a href="' + href + '" ' + target_attr + style_attr +' class="ui-state-default ui-corner-all ui-icon_link ' +
936 className + '"><span class="ui-icon ui-icon-' + iconId + '" />' +
937 msg + '</a>';
938 }
939 //shortcut to bind hover state:
940 $.fn.btnBind = function(){
941 $j(this).hover(
942 function(){
943 $j(this).addClass('ui-state-hover');
944 },
945 function(){
946 $j(this).removeClass('ui-state-hover');
947 }
948 )
949 return this;
950 }
951
952 })(jQuery);
953 }
954 /*
955 * utility functions:
956 */
957 //simple url re-writer for rewriting urls (could probably be refactored into an inline regular expresion)
958 function getURLParamReplace( url, opt ){
959 var pSrc = parseUri( url );
960 if(pSrc.protocol != '' ){
961 var new_url = pSrc.protocol +'://'+ pSrc.authority + pSrc.path +'?';
962 }else{
963 var new_url = pSrc.path +'?';
964 }
965 var amp = '';
966 for(var key in pSrc.queryKey){
967 var val = pSrc.queryKey[ key ];
968 //do override if requested
969 if( opt[ key ] )
970 val = opt[ key ];
971 new_url+= amp + key + '=' + val;
972 amp = '&';
973 };
974 //add any vars that did were not originally there:
975 for(var i in opt){
976 if(!pSrc.queryKey[i]){
977 new_url+=amp + i + '=' + opt[i];
978 amp = '&';
979 }
980 }
981 return new_url;
982 }
983 /**
984 * seconds2npt given a float seconds returns npt format response:
985 * @param float seconds
986 * @param boolean if we should show ms or not.
987 */
988 function seconds2npt(sec, show_ms){
989 if( isNaN( sec ) ){
990 //js_log("warning: trying to get npt time on NaN:" + sec);
991 return '0:0:0';
992 }
993 var hours = Math.floor(sec/ 3600);
994 var minutes = Math.floor((sec/60) % 60);
995 var seconds = sec % 60;
996 //round the second amount requested significant digits
997 if(show_ms){
998 seconds = Math.round( seconds * 1000 ) / 1000;
999 }else{
1000 seconds = Math.round( seconds );
1001 }
1002 if(seconds <10 )
1003 seconds = '0'+ seconds;
1004 if(minutes < 10 )
1005 minutes = '0' + minutes;
1006
1007 return hours+":"+minutes+":"+seconds;
1008 }
1009 /*
1010 * takes hh:mm:ss,ms or hh:mm:ss.ms input returns number of seconds
1011 */
1012 function npt2seconds( npt_str ){
1013 if(!npt_str){
1014 //js_log('npt2seconds:not valid ntp:'+ntp);
1015 return false;
1016 }
1017 //strip npt: time definition if present
1018 npt_str = npt_str.replace('npt:', '');
1019
1020 times = npt_str.split(':');
1021 if(times.length!=3){
1022 js_log('error: npt2seconds on ' + npt_str);
1023 return false;
1024 }
1025 //sometimes the comma is used inplace of pereid for ms
1026 times[2] = times[2].replace(/,\s?/,'.');
1027 //return seconds float (ie take seconds float value if present):
1028 return parseInt(times[0]*3600)+parseInt(times[1]*60)+parseFloat(times[2]);
1029 }
1030 /*
1031 * simple helper to grab a edit token
1032 *
1033 * @param title the wiki page title you want to edit )
1034 * @param api_url 'optional' the target api url
1035 * @param callback the callback function to pass the token or "false" to
1036 */
1037 function get_mw_token( title, api_url, callback){
1038 js_log(':get_mw_token:');
1039 if(!title && wgUserName){
1040 title = 'User:' + wgUserName;
1041 }
1042 var reqObj = {
1043 'action':'query',
1044 'prop':'info',
1045 'intoken':'edit',
1046 'titles':title
1047 };
1048 do_api_req( {
1049 'data': reqObj,
1050 'url' : api_url
1051 },function(data){
1052 for(var i in data.query.pages){
1053 if(data.query.pages[i]['edittoken']){
1054 if(typeof callback == 'function')
1055 callback ( data.query.pages[i]['edittoken'] );
1056 }
1057 }
1058 //no token found:
1059 return false;
1060 }
1061 );
1062 }
1063 //does a remote or local api request based on request url
1064 //@param options: url, data, cbParam, callback
1065 function do_api_req( options, callback ){
1066 if(typeof options.data != 'object'){
1067 return js_error('Error: request paramaters must be an object');;
1068 }
1069 //gennerate the url if its missing:
1070 if( typeof options.url == 'undefined' || options.url === false){
1071 if(!wgServer || ! wgScriptPath){
1072 return js_error('Error: no api url for api request');;
1073 }
1074 //update to api.php (if index.php was in the wgScript path):
1075 options.url = mwGetLocalApiUrl();
1076 }
1077 if( typeof options.data == 'undefined' )
1078 options.data = {};
1079
1080 //force format to json (if not already set)
1081 options.data['format'] = 'json';
1082
1083 //if action not set assume query
1084 if(!options.data['action'])
1085 options.data['action']='query';
1086
1087 js_log('do api req: ' + options.url +'?' + jQuery.param(options.data) );
1088 //build request string:
1089 if( parseUri( document.URL ).host == parseUri( options.url ).host ){
1090 //local request do api request directly
1091 $j.ajax({
1092 type: "POST",
1093 url: options.url,
1094 data: options.data,
1095 dataType:'json', //api requests _should_ always return JSON data:
1096 async: false,
1097 success:function(data){
1098 callback( data );
1099 },
1100 error:function(e){
1101 js_error( ' error' + e +' in getting: ' + options.url);
1102 }
1103 });
1104 }else{
1105 //set the callback param if not already set:
1106 if( typeof options.jsonCB == 'undefined')
1107 options.jsonCB = 'callback';
1108
1109 var req_url = options.url;
1110 var paramAnd = (req_url.indexOf('?')==-1)?'?':'&';
1111 //put all the values into the GET req:
1112 for(var i in options.data){
1113 req_url += paramAnd + encodeURIComponent( i ) + '=' + encodeURIComponent( options.data[i] );
1114 paramAnd ='&';
1115 }
1116 var fname = 'mycpfn_' + ( global_cb_count++ );
1117 _global[ fname ] = callback;
1118 req_url += '&' + options.jsonCB + '=' + fname;
1119 loadExternalJs( req_url );
1120 }
1121 }
1122 function mwGetLocalApiUrl(url){
1123 if (wgServer && wgScriptPath){
1124 return wgServer + wgScriptPath + '/api.php';
1125 }
1126 return false;
1127 }
1128 //grab wiki form error for wiki html page proccessing (should be depricated)
1129 function grabWikiFormError ( result_page ){
1130 var res = {};
1131 sp = result_page.indexOf('<span class="error">');
1132 if(sp!=-1){
1133 se = result_page.indexOf('</span>', sp);
1134 res.error_txt = result_page.substr(sp, (sp-se)) + '</span>';
1135 }else{
1136 //look for warning:
1137 sp = result_page.indexOf('<ul class="warning">')
1138 if(sp != -1){
1139 se = result_page.indexOf('</ul>', sp);
1140 res.error_txt = result_page.substr(sp, (se-sp)) + '</ul>';
1141 //try and add the ignore form item:
1142 sfp = result_page.indexOf('<form method="post"');
1143 if(sfp!=-1){
1144 sfe = result_page.indexOf('</form>', sfp);
1145 res.form_txt = result_page.substr(sfp, ( sfe - sfp )) + '</form>';
1146 }
1147 }else{
1148 //one more error type check:
1149 sp = result_page.indexOf('class="mw-warning-with-logexcerpt">')
1150 if(sp!=-1){
1151 se = result_page.indexOf('</div>', sp);
1152 res.error_txt = result_page.substr(sp, ( se - sp )) + '</div>';
1153 }
1154 }
1155 }
1156 return res;
1157 }
1158 //do a "normal" request
1159 function do_request(req_url, callback){
1160 js_log('do_request::req_url:' + req_url + ' != ' + parseUri( req_url).host);
1161 //if we are doing a request to the same domain or relative link do a normal GET:
1162 if( parseUri(document.URL).host == parseUri(req_url).host ||
1163 req_url.indexOf('://') == -1 ){ //relative url
1164 //do a direct request:
1165 $j.ajax({
1166 type: "GET",
1167 url:req_url,
1168 async: false,
1169 success:function(data){
1170 callback( data );
1171 }
1172 });
1173 }else{
1174 //get data via DOM injection with callback
1175 global_req_cb.push(callback);
1176 //prepend json_ to feed_format if not already requesting json format
1177 if( req_url.indexOf("feed_format=")!=-1 && req_url.indexOf("feed_format=json")==-1)
1178 req_url = req_url.replace(/feed_format=/, 'feed_format=json_');
1179 loadExternalJs( req_url + '&cb=mv_jsdata_cb&cb_inx=' + (global_req_cb.length-1));
1180 }
1181 }
1182
1183 function mv_jsdata_cb(response){
1184 js_log('f:mv_jsdata_cb:'+ response['cb_inx']);
1185 //run the callback from the global req cb object:
1186 if( !global_req_cb[response['cb_inx']] ){
1187 js_log('missing req cb index');
1188 return false;
1189 }
1190 if( !response['pay_load'] ){
1191 js_log("missing pay load");
1192 return false;
1193 }
1194 //switch on content type:
1195 switch(response['content-type']){
1196 case 'text/plain':
1197 break;
1198 case 'text/xml':
1199 if(typeof response['pay_load'] == 'string'){
1200 //js_log('load string:'+"\n"+ response['pay_load']);
1201 //debugger;
1202 //attempt to parse as xml for IE
1203 if( $j.browser.msie ){
1204 var xmldata=new ActiveXObject("Microsoft.XMLDOM");
1205 xmldata.async="false";
1206 xmldata.loadXML(response['pay_load']);
1207 }else{ //for others (firefox, safari etc)
1208 try{
1209 var xmldata = (new DOMParser()).parseFromString(response['pay_load'], "text/xml");
1210 }catch(e) {
1211 js_log('XML parse ERROR: ' + e.message);
1212 }
1213 }
1214 //@@todo hanndle xml parser errors
1215 if(xmldata)response['pay_load']=xmldata;
1216 }
1217 break
1218 default:
1219 js_log('bad response type' + response['content-type']);
1220 return false;
1221 break;
1222 }
1223 global_req_cb[response['cb_inx']]( response['pay_load'] );
1224 }
1225 //load external js via dom injection
1226 function loadExternalJs( url, callback ){
1227 js_log('load js: '+ url);
1228 //if(window['$j']) //use jquery call:
1229 /*$j.ajax({
1230 type: "GET",
1231 url: url,
1232 dataType: 'script',
1233 cache: true
1234 });*/
1235 // else{
1236 var e = document.createElement("script");
1237 e.setAttribute('src', url);
1238 e.setAttribute('type', "text/javascript");
1239 /*if(callback)
1240 e.onload = callback;
1241 */
1242 //e.setAttribute('defer', true);
1243 document.getElementsByTagName("head")[0].appendChild(e);
1244 // }
1245 }
1246 function styleSheetPresent(url){
1247 style_elements = document.getElementsByTagName('link');
1248 if( style_elements.length > 0) {
1249 for(i = 0; i < style_elements.length; i++) {
1250 if(style_elements[i].href == url)
1251 return true;
1252 }
1253 }
1254 return false;
1255 }
1256 function loadExternalCss(url){
1257 //if could have script loader group thes css request
1258 //but debatable it may hurt more than it helps with caching and all
1259 if(typeof url =='object'){
1260 for(var i in url){
1261 loadExternalCss ( url[i] );
1262 }
1263 return ;
1264 }
1265
1266 if( url.indexOf('?') == -1 ){
1267 url+='?'+getMvUniqueReqId();
1268 }
1269 if(!styleSheetPresent(url) ){
1270 js_log('load css: ' + url);
1271 var e = document.createElement("link");
1272 e.href = url;
1273 e.type = "text/css";
1274 e.rel = 'stylesheet';
1275 document.getElementsByTagName("head")[0].appendChild(e);
1276 }
1277 }
1278 function getMvEmbedURL(){
1279 if( _global['mv_embed_url'] )
1280 return _global['mv_embed_url'];
1281 var js_elements = document.getElementsByTagName("script");
1282 for(var i=0; i < js_elements.length; i++){
1283 //check for normal mv_embed.js and or script loader
1284 var src = js_elements[i].getAttribute("src");
1285 if( src ){
1286 if( src.indexOf('mv_embed.js') !=-1 || (
1287 ( src.indexOf('mwScriptLoader.php') != -1 || src.indexOf('jsScriptLoader.php') != -1 )
1288 && src.indexOf('mv_embed') != -1) ){ //(check for class=mv_embed script_loader call)
1289 _global['mv_embed_url'] = src;
1290 return src;
1291 }
1292 }
1293 }
1294 js_error('Error: getMvEmbedURL failed to get Embed Path');
1295 return false;
1296 }
1297 //gets a unique request id to ensure fresh javascript
1298 function getMvUniqueReqId(){
1299 if( _global['urid'] )
1300 return _global['urid'];
1301 var mv_embed_url = getMvEmbedURL();
1302 //if we have a uri retun that:
1303 var urid = parseUri( mv_embed_url).queryKey['urid']
1304 if( urid ){
1305 _global['urid'] = urid;
1306 return urid;
1307 }
1308 //if in debug mode get a fresh unique request key:
1309 if( parseUri( mv_embed_url ).queryKey['debug'] == 'true'){
1310 var d = new Date();
1311 var urid = d.getTime();
1312 _global['urid'] = urid;
1313 return urid;
1314 }
1315 //else just return the mv_embed version;
1316 return MV_EMBED_VERSION;
1317 }
1318 /*
1319 * sets the global mv_embed path based on the scripts location
1320 */
1321 function getMvEmbedPath(){
1322 if( _global['mv_embed_path'])
1323 return _global['mv_embed_path'];
1324 var mv_embed_url = getMvEmbedURL();
1325 if( mv_embed_url.indexOf('mv_embed.js') !== -1 ){
1326 mv_embed_path = mv_embed_url.substr(0, mv_embed_url.indexOf('mv_embed.js'));
1327 }else if(mv_embed_url.indexOf('mwScriptLoader.php')!==-1){
1328 //script load is in the root of mediaWiki so include the default mv_embed extention path (if using the script loader)
1329 mv_embed_path = mv_embed_url.substr(0, mv_embed_url.indexOf('mwScriptLoader.php')) + mediaWiki_mvEmbed_path ;
1330 }else{
1331 mv_embed_path = mv_embed_url.substr(0, mv_embed_url.indexOf('jsScriptLoader.php'));
1332 }
1333 //absolute the url (if relative) (if we don't have mv_embed path)
1334 if( mv_embed_path.indexOf('://') == -1){
1335 var pURL = parseUri( document.URL );
1336 if(mv_embed_path.charAt(0)=='/'){
1337 mv_embed_path = pURL.protocol + '://' + pURL.authority + mv_embed_path;
1338 }else{
1339 //relative:
1340 if(mv_embed_path==''){
1341 mv_embed_path = pURL.protocol + '://' + pURL.authority + pURL.directory + mv_embed_path;
1342 }
1343 }
1344 }
1345 _global['mv_embed_path'] = mv_embed_path;
1346 return mv_embed_path;
1347 }
1348
1349 if (typeof DOMParser == "undefined") {
1350 DOMParser = function () {}
1351 DOMParser.prototype.parseFromString = function (str, contentType) {
1352 if (typeof ActiveXObject != "undefined") {
1353 var d = new ActiveXObject("MSXML.DomDocument");
1354 d.loadXML(str);
1355 return d;
1356 } else if (typeof XMLHttpRequest != "undefined") {
1357 var req = new XMLHttpRequest;
1358 req.open("GET", "data:" + (contentType || "application/xml") +
1359 ";charset=utf-8," + encodeURIComponent(str), false);
1360 if (req.overrideMimeType) {
1361 req.overrideMimeType(contentType);
1362 }
1363 req.send(null);
1364 return req.responseXML;
1365 }
1366 }
1367 }
1368 /*
1369 * utility functions:
1370 */
1371 function js_log(string){
1372 if( window.console ){
1373 window.console.log(string);
1374 }else{
1375 /*
1376 * IE and non-firebug debug:
1377 */
1378 /*var log_elm = document.getElementById('mv_js_log');
1379 if(!log_elm){
1380 document.getElementsByTagName("body")[0].innerHTML = document.getElementsByTagName("body")[0].innerHTML +
1381 '<div style="position:absolute;z-index:500;top:0px;left:0px;right:0px;height:10px;">'+
1382 '<textarea id="mv_js_log" cols="120" rows="5"></textarea>'+
1383 '</div>';
1384
1385 var log_elm = document.getElementById('mv_js_log');
1386 }
1387 if(log_elm){
1388 log_elm.value+=string+"\n";
1389 }*/
1390 }
1391 return false;
1392 }
1393
1394 function checkDefaultMwConfig(){
1395 for(var i in defaultMwConfig){
1396 if(typeof(mwConfig[i])=='undefined'){
1397 mwConfig[i] =defaultMwConfig[i];
1398 }
1399 }
1400 }
1401
1402 function js_error(string){
1403 alert(string);
1404 return false;
1405 }