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