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