* added textSelection plugin from usability
[lhc/web/wiklou.git] / js2 / mwEmbed / mv_embed.js
index 131e553..7fc146d 100644 (file)
  * (in cases where media will be hosted in a different place than the embedding page)
  *
  */
-// Fix multiple instances of mv_embed (i.e. include twice from two different servers)
-var MV_DO_INIT=true;
-if( MV_EMBED_VERSION ){
-       MV_DO_INIT=false;
+
+/**
+ * AutoLoader paths 
+ * @path The path to the file (or set of files) with ending slash
+ * @gClasses The set of classes
+ *             if it's an array, $j.className becomes jquery.className.js
+ *             if it's an associative object then key => value pairs are used
+ */
+if( typeof mvAutoLoadClasses == 'undefined' )
+       mvAutoLoadClasses = {};
+
+// The script that loads the class set
+function lcPaths( classSet ){
+       for( var i in classSet ) {
+               mvAutoLoadClasses[i] = classSet[i];
+       }
+}
+
+function mvGetClassPath(k){
+       if( mvAutoLoadClasses[k] ) {
+               //js_log('got class path:' + k +  ' : '+ mvClassPaths[k]);
+               return mvAutoLoadClasses[k];
+       } else {
+               js_log('Error:: Could not find path for requested class ' + k );
+               return false;
+       }
+}
+if( typeof mvCssPaths == 'undefined' )
+       mvCssPaths = {};
+
+function lcCssPath( cssSet ) {
+       for( var i in cssSet ) {
+               mvCssPaths[i] = mv_embed_path + cssSet[i];
+       }
 }
-// Used to grab fresh copies of scripts. 
-var MV_EMBED_VERSION = '1.0r20';
 
 /*
- * Configuration variables should be set by extending mwConfigOptions
- * here is the default config: 
+ * --  Load Class Paths --
+ *
+ * MUST BE VALID JSON (NOT JS)
+ * This is used by the script loader to auto-load classes (so we only define
+ * this once for PHP & JavaScript)
+ *
+ * Right now the PHP AutoLoader only reads this mv_embed.js file.
+ * In the future we could have multiple lcPath calls that PHP reads
+ * (if our autoloading class list becomes too long) 
+ * or 
+ * we could support direct file requests to the script loader instead 
+ * of shared class names read from a central location.
  */
-var mwDefaultConfig = {
-       'skin_name': 'mvpcf',
-       'jui_skin': 'redmond',
-       'video_size':'400x300'
-}
+lcPaths({
+       "mv_embed"                      : "mv_embed.js",
+       "window.jQuery"         : "jquery/jquery-1.3.2.js",
+       "$j.fn.pngFix"          : "jquery/plugins/jquery.pngFix.js",
+       "$j.fn.autocomplete": "jquery/plugins/jquery.autocomplete.js",
+       "$j.fn.hoverIntent"     : "jquery/plugins/jquery.hoverIntent.js",
+       "$j.fn.datePicker"      : "jquery/plugins/jquery.datePicker.js",
+       "$j.ui"                         : "jquery/jquery.ui/ui/ui.core.js",
+       "$j.fn.ColorPicker"     : "libClipEdit/colorpicker/js/colorpicker.js",
+       "$j.Jcrop"                      : "libClipEdit/Jcrop/js/jquery.Jcrop.js",
+       "$j.fn.simpleUploadForm" : "libAddMedia/simpleUploadForm.js",
+       
+       "$mw.proxy"             : "libMwApi/mw.proxy.js",
+       
+       "$mw.testLang"  :  "tests/testLang.js",
+       
+       "ctrlBuilder"   : "skins/ctrlBuilder.js",
+       "kskinConfig"   : "skins/kskin/kskin.js",
+       "mvpcfConfig"   : "skins/mvpcf/mvpcf.js",
+
+       "JSON"                          : "libMwApi/json2.js",
+       "$j.cookie"                     : "jquery/plugins/jquery.cookie.js",
+       "$j.contextMenu"        : "jquery/plugins/jquery.contextMenu.js",
+       "$j.fn.suggestions"     : "jquery/plugins/jquery.suggestions.js",
+       "$j.fn.textSelection"   : "jquery/plugins/jquery.textSelection.js",
+
+       "$j.effects.blind"              : "jquery/jquery.ui/ui/effects.blind.js",
+       "$j.effects.drop"               : "jquery/jquery.ui/ui/effects.drop.js",
+       "$j.effects.pulsate"    : "jquery/jquery.ui/ui/effects.pulsate.js",
+       "$j.effects.transfer"   : "jquery/jquery.ui/ui/effects.transfer.js",
+       "$j.ui.droppable"               : "jquery/jquery.ui/ui/ui.droppable.js",
+       "$j.ui.slider"                  : "jquery/jquery.ui/ui/ui.slider.js",
+       "$j.effects.bounce"             : "jquery/jquery.ui/ui/effects.bounce.js",
+       "$j.effects.explode"    : "jquery/jquery.ui/ui/effects.explode.js",
+       "$j.effects.scale"              : "jquery/jquery.ui/ui/effects.scale.js",
+       "$j.ui.datepicker"              : "jquery/jquery.ui/ui/ui.datepicker.js",
+       "$j.ui.progressbar"             : "jquery/jquery.ui/ui/ui.progressbar.js",
+       "$j.ui.sortable"                : "jquery/jquery.ui/ui/ui.sortable.js",
+       "$j.effects.clip"               : "jquery/jquery.ui/ui/effects.clip.js",
+       "$j.effects.fold"               : "jquery/jquery.ui/ui/effects.fold.js",
+       "$j.effects.shake"              : "jquery/jquery.ui/ui/effects.shake.js",
+       "$j.ui.dialog"                  : "jquery/jquery.ui/ui/ui.dialog.js",
+       "$j.ui.resizable"               : "jquery/jquery.ui/ui/ui.resizable.js",
+       "$j.ui.tabs"                    : "jquery/jquery.ui/ui/ui.tabs.js",
+       "$j.effects.core"               : "jquery/jquery.ui/ui/effects.core.js",
+       "$j.effects.highlight"  : "jquery/jquery.ui/ui/effects.highlight.js",
+       "$j.effects.slide"              : "jquery/jquery.ui/ui/effects.slide.js",
+       "$j.ui.accordion"               : "jquery/jquery.ui/ui/ui.accordion.js",
+       "$j.ui.draggable"               : "jquery/jquery.ui/ui/ui.draggable.js",
+       "$j.ui.selectable"              : "jquery/jquery.ui/ui/ui.selectable.js",
+
+       "$j.fn.dragDropFile"            : "libAddMedia/dragDropFile.js",
+       "mvFirefogg"                    : "libAddMedia/mvFirefogg.js",
+       "mvAdvFirefogg"                 : "libAddMedia/mvAdvFirefogg.js",
+       "mvBaseUploadInterface" : "libAddMedia/mvBaseUploadInterface.js",
+       "remoteSearchDriver"    : "libAddMedia/remoteSearchDriver.js",
+       "seqRemoteSearchDriver" : "libSequencer/seqRemoteSearchDriver.js",
+
+       "baseRemoteSearch"              : "libAddMedia/searchLibs/baseRemoteSearch.js",
+       "mediaWikiSearch"               : "libAddMedia/searchLibs/mediaWikiSearch.js",
+       "metavidSearch"                 : "libAddMedia/searchLibs/metavidSearch.js",
+       "archiveOrgSearch"              : "libAddMedia/searchLibs/archiveOrgSearch.js",
+       "flickrSearch"                  : "libAddMedia/searchLibs/flickrSearch.js",
+       "baseRemoteSearch"              : "libAddMedia/searchLibs/baseRemoteSearch.js",
+
+       "mvClipEdit"                    : "libClipEdit/mvClipEdit.js",
+
+       "embedVideo"            : "libEmbedVideo/embedVideo.js",
+       "flashEmbed"            : "libEmbedVideo/flashEmbed.js",
+       "genericEmbed"          : "libEmbedVideo/genericEmbed.js",
+       "htmlEmbed"                     : "libEmbedVideo/htmlEmbed.js",
+       "javaEmbed"                     : "libEmbedVideo/javaEmbed.js",
+       "nativeEmbed"           : "libEmbedVideo/nativeEmbed.js",
+       "quicktimeEmbed"        : "libEmbedVideo/quicktimeEmbed.js",
+       "vlcEmbed"                      : "libEmbedVideo/vlcEmbed.js",
+
+       "mvPlayList"            : "libSequencer/mvPlayList.js",
+       "mvSequencer"           : "libSequencer/mvSequencer.js",
+       "mvFirefoggRender"      : "libSequencer/mvFirefoggRender.js",
+       "mvTimedEffectsEdit": "libSequencer/mvTimedEffectsEdit.js",
+
+       "mvTextInterface"       : "libTimedText/mvTextInterface.js",
+       "mvTimedTextEdit"       : "libTimedText/mvTimedTextEdit.js"
+});
+
+// Dependency mapping for CSS files for self-contained included plugins:
+lcCssPath({
+       '$j.Jcrop'                      : 'libClipEdit/Jcrop/css/jquery.Jcrop.css',
+       '$j.fn.ColorPicker'     : 'libClipEdit/colorpicker/css/colorpicker.css'
+})
 
-// (We install the default config values for anything not set in mwConfig once we know we have jquery)
-if( !mwConfig )
-       var mwConfig = {};
 
 // parseUri 1.2.2
 // (c) Steven Levithan <stevenlevithan.com>
@@ -70,20 +190,19 @@ parseUri.options = {
 // For use when mv_embed with script-loader is in the root MediaWiki path
 var mediaWiki_mvEmbed_path = 'js2/mwEmbed/';
 
-var _global = this; // Global obj
+//The global scope: will be depreciated once we get everything into $mw
+var _global = this; 
 
 /*
-* setup the empty global $mw object 
-* will ensure all our functions are properly namespaced
+* setup the empty global $mw object
+* will ensure all our functions and variables are properly namespaced
+* reducing chance of conflicts
 */
 if(!window['$mw']){
        window['$mw'] = {}
 }
 
 //@@todo move these into $mw
-var mv_init_done = false;
-var global_cb_count = 0;
-var global_player_list = new Array(); // The global player list per page
 var global_req_cb = new Array(); // The global request callback array
 
 // Get the mv_embed location if it has not been set
@@ -91,18 +210,40 @@ if( !mv_embed_path ) {
        var mv_embed_path = getMvEmbedPath();
 }
 /**
-* wrap the global $mw object here:
+* The global $mw object:
 *
 * Any global functions/classes that are not jQuery plugins should make
-* there way into the $mw namespace 
+* there way into the $mw namespace
 */
 (function( $ ) {
+       /*
+        * global config
+        */
+       $.conf = {
+               'skin_name' : 'mvpcf',
+               'jui_skin' : 'redmond',
+               'video_size' : '400x300'        
+       }
+       //list valid skins here:
+       $.valid_skins = ['mvpcf', 'kskin'];
+       // the version of mwEmbed
+       $.version = '1.0r21';
+       
+       /*
+       * some global containers flags 
+       */
+       $.skin_list = new Array();
+       $.init_done = false;
+       $.cb_count = 0;
+       $.player_list = new Array(), // The global player list per page
+       $.req_cb = new Array() // The global request callback array     
+        
        /*
        * Language classes $mw.lang
-       * 
+       *
        * Localized Language support attempts to mirror the functionality of Language.php in MediaWiki
        * It contains methods for loading and transforming msg text
-       * 
+       *
        */
        $.lang = {};
        /**
@@ -110,17 +251,19 @@ if( !mv_embed_path ) {
        */
        var gMsg = {};
        var gRuleSet = {};
+
        /**
        * loadGM function
-       * Loads a set of json messages into the lang object. 
+       * Loads a set of json messages into the lng object.
        *
-       * @param json msgSet The set of msgs to be loaded 
+       * @param json msgSet The set of msgs to be loaded
        */
        $.lang.loadGM = function( msgSet ){
                for( var i in msgSet ) {
                        gMsg[ i ] = msgSet[i];
                }
        },
+
        /**
        * loadRS function
        * Loads a ruleset by given template key ie PLURAL : { //ruleSetObj }
@@ -132,117 +275,188 @@ if( !mv_embed_path ) {
                        gRuleSet[ i ] = ruleSet[ i ];
                }
        }
-       
+
        /**
         * Returns a transformed msg string
         *
         * it take a msg key and array of replacement values of form
-        * $1, $2 and does relevant msgkey transformation returning 
-        * the usser msg. 
+        * $1, $2 and does relevant msgkey transformation returning
+        * the user msg.
         *
         * @param string key The msg key as set by loadGm
         * @param [mixed] args  An array of replacement strings
-        * @return string 
+        * @return string
         */
        $.lang.gM = function( key , args ) {
-               var supportedMagicLang = ['PLURAL'];
-                                               
-               if ( gMsg[ key ] ) {
-                       var ms = '';
-                       //get the messege string:
-                       ms = gMsg[ key ];
-                       
-                       //replace values 
-                       if( typeof args == 'object' || typeof args == 'array' ) {
-                               for( var v in args ) { 
-                                       // Message test replace arguments start at 1 instead of zero:
-                                       var rep = '\$'+ ( parseInt(v) + 1 );
-                                       ms = ms.replace( rep, args[v] );
-                               }
-                       } else if( typeof args =='string' || typeof args =='number' ) {
-                               ms = ms.replace(/\$1/, args);
-                       }
-                       
-                       //a quick check to see if we need to send the msg via the 'parser'
-                       //(we can add more detailed check once we suport more wiki syntax)
-                       if(ms.indexOf('{{')==-1)
-                               return ms;
-                               
-                       //send the msg key through the parser  
-                       pObj = $.parse( ms );
-                       //return the transformed msg
-                       return pObj.getHTML(); 
+               if(! gMsg[ key ])
+                       return '&lt;' + key + '&gt;';// Missing key placeholder
 
-               } else {
-                       // Missing key placeholder
-                       return '&lt;' + key + '&gt;';
+               //swap in the arg values
+               var ms =  $.lang.gMsgSwap( key, args) ;
+               
+               
+               
+               //a quick check to see if we need to send the msg via the 'parser'
+               //(we can add more detailed check once we support more wiki syntax)
+               if( ms.indexOf('{{') === -1 && ms.indexOf('[') === -1){
+                       return ms;
                }
+
+               //make sure we have the lagMagic setup:
+               //@@todo move to init
+               $.lang.magicSetup();
+               //send the msg key through the parser
+               var pObj = $.parser.pNew( ms );         
+               //return the transformed msg
+               return pObj.getHTML();
        }
        /**
-       * Process a special language template (ie PLURAL )
+       * gMsgSwap
+       *
+       * @param string key The msg key as set by loadGm
+       * @param [mixed] args  An array or string to be replaced
+       * @return string
        */
-       $.lang.procLangTemp = function( tObj ){
-       
-               /* local lang templates: */             
-               function procPLURAL(){
-                       //Plural matchRuleTest
-                       function matchRuleTest(cRule, val){
-                               js_log("matchRuleTest:: " + typeof cRule + ' ' + cRule + ' == ' + val );
-                               //check for simple cRule type:
-                               if( typeof cRule == 'number'){                                  
-                                       return ( parseInt( val ) == parseInt( cRule) );                                 
-                               }
-                       }
-                       //maps a given rule Index to template params: 
-                       function getTempParamFromRuleInx( ruleInx ){
-                               //in general this is a one to one mapping:
-                                
-                               js_log('getTempParamFromRuleInx: ruleInx: ' + ruleInx + ' tempParamLength ' + tObj.param.length );
-                               var cat = tObj;
-                               debugger;
-                               return tObj.param[ ruleInx ];
+       $.lang.gMsgSwap = function( key , args ){
+               if(! gMsg[ key ])
+                       return '&lt;' + key + '&gt;';// Missing key placeholder
+               //get the messege string:
+               var ms = gMsg[ key ];
+
+               //replace values
+               if( typeof args == 'object' || typeof args == 'array' ) {
+                       for( var v in args ) {
+                               // Message test replace arguments start at 1 instead of zero:
+                               var rep = new RegExp('\\$'+ ( parseInt(v) + 1 ), 'g');
+                               ms = ms.replace( rep, args[v] );
                        }
-                       
-                       //setup shortcuts
-                       var rs = gRuleSet['PLURAL'];    
-                       var val = tObj.val;             
-                       for(var ruleInx in rs){
-                               cRule = rs[ruleInx];
-                               if( matchRuleTest( cRule, val )){
-                                       js_log("matched rule: " + ruleInx );
-                                       return getTempParamFromRuleInx( ruleInx );                                      
-                               }
-                       }                       
-                       js_log('no match found for: ' + val + ' using last/other : ' +  tObj.param [ tObj.param.length -1 ] );
-                       //return the last /"other" template param 
-                       return tObj.param [ tObj.param.length -1 ];                                     
-               }
-               
-               /*
-               * Master rule switch statement
-               */
-               switch( tObj.n ){
-                       case 'PLURAL':
-                               return procPLURAL();
-                       break;
+               } else if( typeof args =='string' || typeof args =='number' ) {
+                       ms = ms.replace(/\$1/g, args);
                }
+               return ms;
        }
+
        /**
        * gMsgNoTrans
-       * 
+       *
        * @returns string The msg key without transforming it
        */
        $.lang.gMsgNoTrans = function( key ){
                if( gMsg[ key ] )
                        return gMsg[ key ]
-       
+
                // Missing key placeholder
                return '&lt;' + key + '&gt;';
        }
-       
+       /**
+       * Add Supported Magic Words to parser
+       */
+       //set the setupflag to false:
+       $.lang.doneSetup=false;
+       $.lang.magicSetup = function(){
+               if(!$.lang.doneSetup){
+                       $.parser.addMagic ( {
+                               'PLURAL' : $.lang.procPLURAL
+                       })
+
+                       $.lang.doneSetup = true;
+               }
+
+       }
+       /**
+       * Process the PLURAL special language template key:
+       */
+       $.lang.procPLURAL = function( tObj ){
+               //setup shortcuts
+               // (gRuleSet is loaded from script-loader to contains local ruleset)
+               var rs = gRuleSet['PLURAL'];
+
+               /*
+                * Plural matchRuleTest
+                */
+               function matchRuleTest(cRule, val){
+                       //js_log("matchRuleTest:: " + typeof cRule + ' ' + cRule + ' == ' + val );
+
+                       function checkValue(compare, val){
+                               if(typeof compare == 'string'){
+                                       range = compare.split('-');
+                                       if( range.length >= 1 ){
+                                               if( val >= range[0] &&  val <= range[1] )
+                                                       return true;
+                                       }
+                               }
+                               //else do a direct compare
+                               if(compare == val){
+                                       return true;
+                               }
+                               return false;
+                       }
+                       //check for simple cRule type:
+                       if( typeof cRule == 'number'){
+                               return ( parseInt( val ) == parseInt( cRule) );
+                       }else if( typeof cRule == 'object' ){
+                               var cmatch = {};
+                               //if a list we need to match all for rule match
+                               for(var i in  cRule){
+                                       var cr = cRule[i];
+                                       //set cr type
+                                       var crType =  '';
+                                       for( var j in cr ){
+                                               if(j == 'mod')
+                                                       crType = 'mod'
+                                       }
+                                       switch(crType){
+                                               case 'mod':
+                                                       if( cr ['is'] ){
+                                                               if( checkValue( val % cr['mod'], cr ['is'] ) )
+                                                                       cmatch[i] = true;
+                                                       }else if( cr['not']){
+                                                               if( ! checkValue( val % cr['mod'], cr ['not'] ) )
+                                                                       cmatch[i] = true;
+                                                       }
+                                               break;
+                                       }
+                               }
+                               //check all the matches (taking into consideration "or" order)
+                               for(var i in cRule){
+                                       if( ! cmatch[i] )
+                                               return false;
+                               }
+                               return true;
+
+                       }
+               }
+               /**
+                * Maps a given rule Index to template params:
+                *
+                * if index is out of range return last param
+                * @param
+                */
+               function getTempParamFromRuleInx(tObj, ruleInx ){
+                       //js_log('getTempParamFromRuleInx: ruleInx: ' + ruleInx + ' tempParamLength ' + tObj.param.length );
+                       if( ruleInx     >= tObj.param.length )
+                               return  tObj.param[  tObj.param.length -1 ];
+                       //else return the requested index:
+                       return tObj.param[ ruleInx ];
+               }
+               var rCount=0
+               //run the actual rule lookup:
+               for(var ruleInx in rs){
+                       cRule = rs[ruleInx];
+                       if( matchRuleTest( cRule, tObj.arg ) ){
+                               //js_log("matched rule: " + ruleInx );
+                               return getTempParamFromRuleInx(tObj, rCount );
+                       }
+                       rCount ++;
+               }
+               //js_log('no match found for: ' + tObj.arg + ' using last/other : ' +  tObj.param [ tObj.param.length -1 ] );
+               //return the last /"other" template param
+               return tObj.param [ tObj.param.length -1 ];
+       }
+
        /**
         * gMsgLoadRemote loads remote msg strings
-        * 
+        *
         * @param mixed msgSet the set of msg to load remotely
         * @param function callback  the callback to issue once string is ready
         */
@@ -256,7 +470,7 @@ if( !mv_embed_path ) {
                        ammessages += msgSet;
                }
                if( ammessages == '' ) {
-                       js_log( 'gMsgLoadRemote: no message set requested' );           
+                       js_log( 'gMsgLoadRemote: no message set requested' );
                        return false;
                }
                do_api_req({
@@ -310,226 +524,292 @@ if( !mv_embed_path ) {
                var size = Math.round( size * p ) / p;
                //@@todo we need a formatNum and we need to request some special packaged info to deal with that case.
                return gM( msg , size );
+       };
+       
+       $.lang.formatNumber = function( num ){
+               /*
+                       addSeparatorsNF
+               Str: The number to be formatted, as a string or number.         
+               outD: The decimal character for the output, such as ',' for the number 100,2
+               sep: The separator character for the output, such as ',' for the number 1,000.2
+               */ 
+               function addSeparatorsNF(nStr, outD, sep){
+                       nStr += '';
+                       var dpos = nStr.indexOf( '.' );
+                       var nStrEnd = '';
+                       if (dpos != -1) {
+                               nStrEnd = outD + nStr.substring(dpos + 1, nStr.length);
+                               nStr = nStr.substring(0, dpos);
+                       }
+                       var rgx = /(\d+)(\d{3})/;
+                       while (rgx.test(nStr)) {
+                               nStr = nStr.replace(rgx, '$1' + sep + '$2');
+                       }
+                       return nStr + nStrEnd;
+               }               
+               //@@todo read language code and give periods or comas: 
+               return addSeparatorsNF( num, '.', ',');
        }
        
        
+       
        /**
        * MediaWiki wikitext "Parser"
        *
-       * This is not feature complete but we need a way to get at template properties 
+       * This is not feature complete but we need a way to get at template properties
+       *
        *
-       * Template parsing is based in part on Magnus initial version: en:User:Magnus_Manske/tmpl.js
-       *  
        * @param wikiText the wikitext to be parsed
-       * @return parserObj returns a parser object that has methods for getting at 
-       * things you would want 
+       * @return parserObj returns a parser object that has methods for getting at
+       * things you would want
        */
-       $.parse = function( wikiText, opt ){
+       $.parser = {};
+       var pMagicSet = {};
+       /**
+        * parser addMagic
+        *
+        * lets you add a set of magic keys and associated callback functions
+        * callback: @param ( Object Template )
+        * callback: @return the transformed template output
+        *
+        * @param object magicSet key:callback
+        */
+       $.parser.addMagic = function( magicSet ){
+               for(var i in magicSet)
+                       pMagicSet[ i ] = magicSet[i];
+       }
+
+       //actual parse call (returns parser object)
+       $.parser.pNew = function( wikiText, opt ){
                var parseObj = function( wikiText, opt){
                        return this.init( wikiText, opt )
-               }               
+               }
                parseObj.prototype = {
-                       pObj : {}, //the parser object that stores the parsed element structure
-                       pOut : '', //the parser output string container 
+                       //the wikiText "DOM"... stores the parsed wikiText structure
+                       //wtDOM : {}, (not yet supported )
+
+                       pOut : '', //the parser output string container
                        init  :function( wikiText ){
                                this.wikiText = wikiText;
-                               this.parse();
+                       },
+                       updateText : function( wikiText ){
+                               this.wikiText = wikiText;
+                               //invalidate the output (will force a re-parse )
+                               this.pOut = '';
                        },
                        parse : function(){
-                               //basic parser stores wikiText structure in pObj
+                               /*
+                                * quickly recursive / parse out templates:
+                                */
+
+                               // ~ probably a better algorithm out there / should mirror php parser flow ~
+                               //       (we are already running white-space issues ie php parse strips whitespace diffrently)
                                
-                               //tries to mirror Extension:Page Object Model
-                       },
-                       templates : function( name ){
-                               //get template objects (optionally get a set by its name) 
-                               //hard code for plural for now:  
-                               return [{
-                                       'n': 'PLURAL',
-                                       'val': '1',
-                                       'param': ['one','other']
-                               }];                             
+                               // ... but I am having fun with recursion so here it is...
+                               // or at least mirror: http://www.mediawiki.org/wiki/Extension:Page_Object_Model
+                               function rdpp ( txt , cn){                              
+                                       var node = {};                                  
+                                       //inspect each char
+                                       for(var a=0; a < txt.length; a++){
+                                               if( txt[a] == '{' && txt[a+1] == '{' ){
+                                                       a=a+2;
+                                                       node['p'] = node;
+                                                       if(!node['c'])
+                                                               node['c'] = new Array();
+
+                                                       node['c'].push( rdpp( txt.substr( a ), true ) );                                                                                                                                                                                                                                                                                                                                        
+                                               }else if( txt[a] == '}' && txt[a+1] == '}'){                                                    
+                                                       a=a+2;
+                                                       if( !node['p'] ){
+                                                               return node;
+                                                       }                                                       
+                                                       node = node['p'];                                                       
+                                               }
+                                               if(!node['t'])
+                                                       node['t']='';
+                                               //dont put closures into output:
+                                               if( txt[a] &&  txt[a]!='}' )
+                                                               node['t'] += txt[a];
+                                                               
+                                       }
+                                       return node;
+                               }
+                               /**
+                                * parse template text as template name and named params
+                                */
+                               function parseTmplTxt( ts ){                            
+                                       var tObj = {};
+                                       //Get template name:
+                                       tname = ts.split('\|').shift() ;
+                                       tname = tname.split('\{').shift() ;
+                                       tname = tname.replace( /^\s+|\s+$/g, "" ); //trim
+
+                                       //check for arguments:
+                                       if( tname.split(':').length == 1 ){
+                                               tObj["name"] = tname;
+                                       }else{
+                                               tObj["name"] = tname.split(':').shift();
+                                               tObj["arg"] = tname.split(':').pop();
+                                       }
+
+                                       //js_log("TNAME::" + tObj["name"] + ' from:: ' + ts);                                           
+                                       var pSet = ts.split('\|');
+                                       pSet.splice(0,1);                                       
+                                       if( pSet.length ){
+                                               tObj.param = new Array();
+                                               for(var pInx in pSet){                                                  
+                                                       var tStr = pSet[ pInx ];
+                                                       //check for empty param
+                                                       if(tStr==''){
+                                                               tObj.param[ pInx ] = '';
+                                                               continue;
+                                                       }
+                                                       for(var b=0 ; b < tStr.length ; b++){
+                                                               if(tStr[b] == '=' && b>0 && b<tStr.length && tStr[b-1]!='\\'){
+                                                                       //named param
+                                                                       tObj.param[ tStr.split('=').shift() ] = tStr.split('=').pop();
+                                                               }else{
+                                                                       //indexed param
+                                                                       tObj.param[ pInx ] = tStr;
+                                                               }
+                                                       }
+                                               }
+                                       }                                                       
+                                       return tObj;
+                               }
+                               function getMagicTxtFromTempNode( node ){
+                                       node.tObj = parseTmplTxt ( node.t );
+                                       //do magic swap if template key found in pMagicSet
+                                       if( node.tObj.name in pMagicSet){
+                                               var nt = pMagicSet[ node.tObj.name ]( node.tObj );
+                                               return nt;
+                                       }else{
+                                               //don't swap just return text
+                                               return node.t;
+                                       }
+                               }
+                               /**
+                                * recurse_magic_swap
+                                *
+                                * go last child first swap upward: (could probably be integrated above somehow)
+                                */
+                               var pNode = null;
+                               function recurse_magic_swap( node ){
+                                       if( !pNode )
+                                               pNode = node;
+
+                                       if( node['c'] ){
+                                               //swap all the kids:
+                                               for(var i in node['c']){
+                                                       var nt = recurse_magic_swap( node['c'][i] );
+                                                       //swap it into current
+                                                       if( node.t ){
+                                                               node.t = node.t.replace( node['c'][i].t, nt);
+                                                       }
+                                                       //swap into parent
+                                                       pNode.t  = pNode.t.replace( node['c'][i].t, nt);
+                                               }
+                                               //do the current node:
+                                               var nt = getMagicTxtFromTempNode( node );
+                                               pNode.t = pNode.t.replace(node.t , nt);
+                                               //run the swap for the outer most node
+                                               return node.t;
+                                       }else{
+                                               //node.t = getMagicFromTempObj( node.t )
+                                               return getMagicTxtFromTempNode( node );
+                                       }
+                               }
+                               //parse out the template node structure:
+                               this.pNode = rdpp ( this.wikiText );
+                               //strip out the parent from the root    
+                               this.pNode['p'] = null;
+                               
+                               //do the recursive magic swap text:
+                               this.pOut = recurse_magic_swap( this.pNode );
+
                        },
-                       doMagicExpand : function(){
-                               //expand all the templates
-                               tSet = this.templates();
-                               for(var tInx in tSet){
-                                       var tObj = tSet[ tInx ] ;
-                                       //@@todo replace PLURARL with tObj.n                                    
-                                       this.pOut = this.pOut.replace( /\{\{PLURAL[^\}]*\}\}/, 
-                                                               $.lang.procLangTemp(tObj) );                                    
-                               }                       
+                       
+                       /*
+                        * parsed template api ~losely based off of ~POM~
+                        * http://www.mediawiki.org/wiki/Extension:Page_Object_Model
+                        */
+                       
+                       /**
+                        * templates
+                        * 
+                        * gets a requested template from the wikitext (if available)
+                        *  
+                        */
+                       templates: function( tname ){
+                               this.parse();
+                               var tmplSet = new Array();
+                               function getMatchingTmpl( node ){
+                                       if( node['c'] ){
+                                               for(var i in node['c']){
+                                                       getMatchingTmpl( node['c'] );
+                                               }
+                                       }                                       
+                                       if( tname && node.tObj){
+                                               if( node.tObj['name'] == tname )
+                                                       tmplSet.push( node.tObj );
+                                       }else if( node.tObj ){
+                                               tmplSet.push( node.tObj );
+                                       }
+                               }                               
+                               getMatchingTmpl( this.pNode );                          
+                               return tmplSet;                         
                        },
-                       //returns the transformed wikitext
+                       /**
+                        * Returns the transformed wikitext
+                        * 
+                        * Build output from swappable index 
+                        *              (all transforms must be expanded in parse stage and linearly rebuilt)  
+                        * Alternatively we could build output using a place-holder & replace system 
+                        *              (this lets us be slightly more slopy with ordering and indexes, but probably slower)
+                        * 
+                        * Ideal: we build a 'wiki DOM' 
+                        *              When editing you update the data structure directly
+                        *              Then in output time you just go DOM->html-ish output without re-parsing anything                           
+                        */
                        getHTML : function(){
-                               //copy the wikiText into the output (where we will do replaces) 
-                               this.pOut = this.wikiText;
-                               this.doMagicExpand();
-                               return this.pOut;                               
+                               //wikiText updates should invalidate pOut
+                               if( this.pOut == ''){
+                                       this.parse();
+                               }                               
+                               return this.pOut;
                        }
                };
                //return the parserObj
                return new parseObj( wikiText, opt) ;
        }
        
-       
 })(window.$mw);
-//setup legacy global shortcuts: 
+
+//setup legacy global shortcuts:
 var loadGM = $mw.lang.loadGM;
+var loadRS = $mw.lang.loadRS;
 var gM = $mw.lang.gM;
 
-
 // All default messages in [English] should be overwritten by the CMS language message system.
 $mw.lang.loadGM({
-       "mwe-loading_txt" : "loading <blink>...<\/blink>",
-       "mwe-loading_title" : "Loading...",
+       "mwe-loading_txt" : "Loading ...",
        "mwe-size-gigabytes" : "$1 GB",
        "mwe-size-megabytes" : "$1 MB",
        "mwe-size-kilobytes" : "$1 K",
        "mwe-size-bytes" : "$1 B",
-       "mwe-error_load_lib" : "Error: JavaScript $1 was not retrievable or does not define $2"
-});
-
-
-
-/**
- * AutoLoader paths (this should mirror the file: jsAutoloadLocalClasses.php )
- * Any file _not_ listed here won't be auto-loadable
- * @path The path to the file (or set of files) with ending slash
- * @gClasses The set of classes
- *             if it's an array, $j.className becomes jquery.className.js
- *             if it's an associative object then key => value pairs are used
- */
-if( typeof mvAutoLoadClasses == 'undefined' )
-       mvAutoLoadClasses = {};
-
-// The script that loads the class set
-function lcPaths( classSet ){
-       for( var i in classSet ) {
-               mvAutoLoadClasses[i] = classSet[i];
-       }
-}
-
-function mvGetClassPath(k){
-       if( mvAutoLoadClasses[k] ) {
-               //js_log('got class path:' + k +  ' : '+ mvClassPaths[k]);
-               return mvAutoLoadClasses[k];
-       } else {
-               return js_error('could not find path for requested class ' + k );
-       }
-}
-if( typeof mvCssPaths == 'undefined' )
-       mvCssPaths = {};
-
-function lcCssPath( cssSet ) {
-       for( var i in cssSet ) {
-               mvCssPaths[i] = mv_embed_path + cssSet[i];
-       }
-}
-
-/*
- * --  Load Class Paths --
- *
- * MUST BE VALID JSON (NOT JS)
- * This is used by the script loader to auto-load classes (so we only define
- * this once for PHP & JavaScript)
- *
- * This is more verbose than the earlier version that compressed paths
- * but it's all good, gzipping helps compress path strings
- * grouped by directory.
- *
- * Right now the PHP AutoLoader only reads this mv_embed.js file.
- * In the future we could have multiple lcPath calls that PHP reads
- * (if our autoloading class list becomes too long) just have to add those
- * files to the jsAutoLoader file list.
- */
-lcPaths({
-       "mv_embed"                      : "mv_embed.js",
-       "window.jQuery"         : "jquery/jquery-1.3.2.js",
-       "$j.fn.pngFix"          : "jquery/plugins/jquery.pngFix.js",
-       "$j.fn.autocomplete": "jquery/plugins/jquery.autocomplete.js",
-       "$j.fn.hoverIntent"     : "jquery/plugins/jquery.hoverIntent.js",
-       "$j.fn.datePicker"      : "jquery/plugins/jquery.datePicker.js",
-       "$j.ui"                         : "jquery/jquery.ui/ui/ui.core.js",
-       "$j.fn.ColorPicker"     : "libClipEdit/colorpicker/js/colorpicker.js",
-       "$j.Jcrop"                      : "libClipEdit/Jcrop/js/jquery.Jcrop.js",
-       "$j.fn.simpleUploadForm": "libAddMedia/simpleUploadForm.js",
-
-       "ctrlBuilder"   : "skins/ctrlBuilder.js",
-       "kskinConfig"   : "skins/kskin/kskin.js",
-       "mvpcfConfig"   : "skins/mvpcf/mvpcf.js",
-
-       "$j.secureEvalJSON"     : "jquery/plugins/jquery.secureEvalJSON.js",
-       "$j.cookie"                     : "jquery/plugins/jquery.cookie.js",
-       "$j.contextMenu"        : "jquery/plugins/jquery.contextMenu.js",
-       "$j.fn.suggestions"     : "jquery/plugins/jquery.suggestions.js",
-
-       "$j.effects.blind"              : "jquery/jquery.ui/ui/effects.blind.js",
-       "$j.effects.drop"               : "jquery/jquery.ui/ui/effects.drop.js",
-       "$j.effects.pulsate"    : "jquery/jquery.ui/ui/effects.pulsate.js",
-       "$j.effects.transfer"   : "jquery/jquery.ui/ui/effects.transfer.js",
-       "$j.ui.droppable"               : "jquery/jquery.ui/ui/ui.droppable.js",
-       "$j.ui.slider"                  : "jquery/jquery.ui/ui/ui.slider.js",
-       "$j.effects.bounce"             : "jquery/jquery.ui/ui/effects.bounce.js",
-       "$j.effects.explode"    : "jquery/jquery.ui/ui/effects.explode.js",
-       "$j.effects.scale"              : "jquery/jquery.ui/ui/effects.scale.js",
-       "$j.ui.datepicker"              : "jquery/jquery.ui/ui/ui.datepicker.js",
-       "$j.ui.progressbar"             : "jquery/jquery.ui/ui/ui.progressbar.js",
-       "$j.ui.sortable"                : "jquery/jquery.ui/ui/ui.sortable.js",
-       "$j.effects.clip"               : "jquery/jquery.ui/ui/effects.clip.js",
-       "$j.effects.fold"               : "jquery/jquery.ui/ui/effects.fold.js",
-       "$j.effects.shake"              : "jquery/jquery.ui/ui/effects.shake.js",
-       "$j.ui.dialog"                  : "jquery/jquery.ui/ui/ui.dialog.js",
-       "$j.ui.resizable"               : "jquery/jquery.ui/ui/ui.resizable.js",
-       "$j.ui.tabs"                    : "jquery/jquery.ui/ui/ui.tabs.js",
-       "$j.effects.core"               : "jquery/jquery.ui/ui/effects.core.js",
-       "$j.effects.highlight"  : "jquery/jquery.ui/ui/effects.highlight.js",
-       "$j.effects.slide"              : "jquery/jquery.ui/ui/effects.slide.js",
-       "$j.ui.accordion"               : "jquery/jquery.ui/ui/ui.accordion.js",
-       "$j.ui.draggable"               : "jquery/jquery.ui/ui/ui.draggable.js",
-       "$j.ui.selectable"              : "jquery/jquery.ui/ui/ui.selectable.js",
-
-       "mvFirefogg"                    : "libAddMedia/mvFirefogg.js",
-       "mvAdvFirefogg"                 : "libAddMedia/mvAdvFirefogg.js",
-       "mvBaseUploadInterface" : "libAddMedia/mvBaseUploadInterface.js",
-       "remoteSearchDriver"    : "libAddMedia/remoteSearchDriver.js",
-       "seqRemoteSearchDriver" : "libAddMedia/seqRemoteSearchDriver.js",
-
-       "baseRemoteSearch"              : "libAddMedia/searchLibs/baseRemoteSearch.js",
-       "mediaWikiSearch"               : "libAddMedia/searchLibs/mediaWikiSearch.js",
-       "metavidSearch"                 : "libAddMedia/searchLibs/metavidSearch.js",
-       "archiveOrgSearch"              : "libAddMedia/searchLibs/archiveOrgSearch.js",
-       "baseRemoteSearch"              : "libAddMedia/searchLibs/baseRemoteSearch.js",
-
-       "mvClipEdit"                    : "libClipEdit/mvClipEdit.js",
-
-       "embedVideo"            : "libEmbedVideo/embedVideo.js",
-       "flashEmbed"            : "libEmbedVideo/flashEmbed.js",
-       "genericEmbed"          : "libEmbedVideo/genericEmbed.js",
-       "htmlEmbed"                     : "libEmbedVideo/htmlEmbed.js",
-       "javaEmbed"                     : "libEmbedVideo/javaEmbed.js",
-       "nativeEmbed"           : "libEmbedVideo/nativeEmbed.js",
-       "quicktimeEmbed"        : "libEmbedVideo/quicktimeEmbed.js",
-       "vlcEmbed"                      : "libEmbedVideo/vlcEmbed.js",
-
-       "mvPlayList"            : "libSequencer/mvPlayList.js",
-       "mvSequencer"           : "libSequencer/mvSequencer.js",
-       "mvFirefoggRender"      : "libSequencer/mvFirefoggRender.js",
-       "mvTimedEffectsEdit": "libSequencer/mvTimedEffectsEdit.js",
-
-       "mvTextInterface"       : "libTimedText/mvTextInterface.js"
+       "mwe-error_load_lib" : "Error: JavaScript $1 was not retrievable or does not define $2",
+       "mwe-loading-add-media-wiz" : "Loading add media wizard",
+       "mwe-apiproxy-setup" : "Setting up API proxy",
+       "mwe-load-drag-item" : "Loading dragged item",
+       "mwe-ok" : "OK",
+       "mwe-cancel" : "Cancel"
 });
 
-// Dependency mapping for CSS files for self-contained included plugins:
-lcCssPath({
-       '$j.Jcrop'                      : 'libClipEdit/Jcrop/css/jquery.Jcrop.css',
-       '$j.fn.ColorPicker'     : 'libClipEdit/colorpicker/css/colorpicker.css'
-})
-
 
 // Get the loading image
 function mv_get_loading_img( style, class_attr ){
        var style_txt = (style)?style:'';
-       var class_attr = (class_attr)?'class="'+class_attr+'"':'class="mv_loading_img"';
+       var class_attr = (class_attr) ? 'class="' + class_attr + '"' : 'class="mv_loading_img"';
        return '<div '+class_attr+' style="' + style +'"></div>';
 }
 
@@ -542,13 +822,8 @@ function mv_set_loading(target, load_id){
 }
 
 /**
-  * mvJsLoader class handles initialization and js file loads
-  */
-
-// Shortcut
-function mwLoad( loadSet, callback ) {
-       mvJsLoader.doLoad( loadSet, callback );
-}
+* mvJsLoader class handles initialization and js file loads
+*/
 var mvJsLoader = {
        libreq : {},
        libs : {},
@@ -556,7 +831,7 @@ var mvJsLoader = {
        // Base lib flags
        onReadyEvents: new Array(),
        doneReadyEvents: false,
-       jQueryCheckFlag: false,
+       jQuerySetupFlag: false,
 
        // To keep consistency across threads
        ptime: 0,
@@ -569,8 +844,8 @@ var mvJsLoader = {
        missing_path : null,
        doLoad: function( loadLibs, callback ) {
                this.ctime++;
-
                if( loadLibs && loadLibs.length != 0 ) {
+                       //js_log("doLoad setup::" + JSON.stringify( loadLibs ) );
                        // Set up this.libs
                        // First check if we already have this library loaded
                        var all_libs_loaded = true;
@@ -581,7 +856,7 @@ var mvJsLoader = {
                                }
                        }
                        if( all_libs_loaded ) {
-                               js_log( 'All libraries already loaded, skipping load request' );
+                               js_log( 'Libraries ( ' + loadLibs  +  ') already loaded... skipping load request' );
                                callback();
                                return;
                        }
@@ -606,19 +881,18 @@ var mvJsLoader = {
                                                coma = ',';
                                        }
                                }
-                               //Build the url to the scriptServer striping its request paramaters: 
+                               //Build the url to the scriptServer striping its request parameters:
                                var puri = parseUri( getMvEmbedURL() );
                                if( ( getMvEmbedURL().indexOf('://') != -1 )
                                        && puri.host != parseUri( document.URL ).host )
-                               {                                       
+                               {
                                        var scriptPath = puri.protocol + '://' + puri.authority + puri.path;
                                }else{
                                        var scriptPath = puri.path;
                                }
-                               js_log('scriptServer Path is: ' + scriptPath + "\n host script path:" + getMvEmbedURL() );
-                               var dbug_attr = ( puri.queryKey['debug'] ) ? '&debug=true' : '';
+                               //js_log('scriptServer Path is: ' + scriptPath + "\n host script path:" + getMvEmbedURL() );                            
                                this.libs[ last_class ] = scriptPath + '?class=' + class_set +
-                                       '&urid=' + getMvUniqueReqId() + dbug_attr;
+                                       '&' + getMwReqParam();
 
                        } else {
                                // Do many requests
@@ -629,20 +903,21 @@ var mvJsLoader = {
                                                // Do a direct load of the file (pass along unique request id from
                                                // request or mv_embed Version )
                                                var qmark = (libLoc.indexOf( '?' ) !== true) ? '?' : '&';
-                                               this.libs[curLib] = mv_embed_path + libLoc + qmark + 'urid=' + getMvUniqueReqId();
+                                               this.libs[curLib] = mv_embed_path + libLoc + qmark + getMwReqParam();
                                        }
                                }
                        }
                }
+               
                if( callback ) {
                        this.callbacks.push( callback );
                }
                if( this.checkLoading() ) {
-                       //@@todo we should check the <script> Element .onLoad property to 
+                       //@@todo we should check the <script> Element .onLoad property to
                        //make sure its just not a very slow connection
-                        
+                       //(even though the class is not loaded)
                        if( this.load_time++ > 4000 ){ // Time out after ~80 seconds
-                               js_error( gM('mwe-error_load_lib', [mvGetClassPath(this.missing_path),  this.missing_path]) );
+                               js_log( gM('mwe-error_load_lib', [mvGetClassPath(this.missing_path),  this.missing_path]) );
                                this.load_error = true;
                        } else {
                                setTimeout( 'mvJsLoader.doLoad()', 20 );
@@ -719,7 +994,7 @@ var mvJsLoader = {
                        cur_path = (cur_path == '') ? cur_path + objPath[p] : cur_path + '.' + objPath[p];
                        eval( 'var ptest = typeof ( '+ cur_path + ' ); ');
                        if( ptest == 'undefined' ) {
-                               this.missing_path = cur_path;                           
+                               this.missing_path = cur_path;
                                return false;
                        }
                }
@@ -730,42 +1005,45 @@ var mvJsLoader = {
         * checks for jQuery and adds the $j noConflict var
         */
        jQueryCheck: function( callback ) {
-               // Skip stuff if $j is already loaded:
-               if( _global['$j'] && callback )
-                       callback();                                     
+               //js_log( 'jQueryCheck::' );
                var _this = this;
+               // Skip stuff if $j is already loaded:
+               if( _global['$j'] && callback ){
+                       callback();
+                       if( _this.jQuerySetupFlag )
+                               return ;
+               }               
                // Load jQuery
                _this.doLoad([
                        'window.jQuery'
                ], function() {
-                       //only do the $j setup once: 
+                       //only do the $j setup once:
                        if(!_global['$j']){
                                _global['$j'] = jQuery.noConflict();
-                               
-                               //setup our global settings using the (jQuery helper) 
-                               mwConfig = $j.extend( mwDefaultConfig, mwConfig);                                                               
-                               
+                       }
+                       if( _this.jQuerySetupFlag == false){
+                               //js_log('setup mv_embed jQuery bindings');
+                               //setup our global settings using the (jQuery helper)
+
                                // Set up the skin path
-                               _global['mv_jquery_skin_path'] = mv_embed_path + 'jquery/jquery.ui/themes/' +mwConfig['jui_skin'] + '/';
-                               _global['mv_skin_img_path'] = mv_embed_path + 'skins/' + mwConfig['skin_name'] + '/images/';
-                               _global['mv_default_thumb_url'] = mv_skin_img_path + 'vid_default_thumb.jpg';
-                               
-                               //setup skin dependent dependencies 
-                               lcCssPath({'embedVideo'         : 'skins/' + mwConfig['skin_name'] + '/playerSkin.css'});                               
-                               
+                               _global['mv_jquery_skin_path'] = mv_embed_path + 'jquery/jquery.ui/themes/' + $mw.conf['jui_skin'] + '/';
+                               _global['mv_skin_img_path'] = mv_embed_path + 'skins/' + $mw.conf['skin_name'] + '/images/';
+                               _global['mv_default_thumb_url'] = mv_skin_img_path + 'vid_default_thumb.jpg';                   
+
                                // Make sure the skin/style sheets are always available:
                                loadExternalCss( mv_jquery_skin_path + 'jquery-ui-1.7.1.custom.css' );
-                               loadExternalCss( mv_embed_path + 'skins/' + mwConfig['skin_name'] + '/styles.css' );
-                               
+                               loadExternalCss( mv_embed_path + 'skins/' + $mw.conf['skin_name'] + '/styles.css' );
+
                                // Set up AJAX to not send dynamic URLs for loading scripts (we control that with
                                // the scriptLoader)
                                $j.ajaxSetup({
                                        cache: true
                                });
-                               
+
                                js_log( 'jQuery loaded into $j' );
                                // Set up mvEmbed jQuery bindings and config based dependencies
                                mv_jqueryBindings();
+                               _this.jQuerySetupFlag = true;
                        }
                        // Run the callback
                        if( callback ) {
@@ -775,31 +1053,37 @@ var mvJsLoader = {
        },
        embedVideoCheck:function( callback ) {
                var _this = this;
-               js_log( 'embedVideoCheck:' );           
+               js_log( 'embedVideoCheck:' );
                // Make sure we have jQuery
                _this.jQueryCheck( function() {
-                       //set class videonojs to hidden
+                       //set class videonojs to loading
                        $j('.videonojs').html( gM('mwe-loading_txt') );
-                       //Set up the embed video player class request: (include the skin js as well)  
+                       //Set up the embed video player class request: (include the skin js as well)
                        var depReq = [
                                [
                                        '$j.ui',
                                        'embedVideo',
                                        'ctrlBuilder',
-                                       '$j.cookie'                                     
+                                       '$j.cookie'
                                ],
                                [
                                        '$j.ui.slider'
                                ]
-                       ];                                      
-                       //add skin if set: 
-                       if( mwConfig['skin_name'] )
-                               depReq[0].push( mwConfig['skin_name'] + 'Config' );
+                       ];
                        
+                       //add any requested skins (suports multiple skins per single page)
+                       if( $mw.skin_list ){
+                               for(var i in $mw.skin_list  ){
+                                       depReq[0].push( $mw.skin_list[i] + 'Config' );
+                               }
+                       }
+                               
+
                        // Add PNG fix if needed:
                        if( $j.browser.msie || $j.browser.version < 7 )
                                depReq[0].push( '$j.fn.pngFix' );
-                       
+
+                       //load the video libs:
                        _this.doLoadDepMode( depReq, function() {
                                embedTypes.init();
                                callback();
@@ -813,24 +1097,30 @@ var mvJsLoader = {
        // Check the jQuery flag. This way, when remote embedding, we don't load jQuery
        // unless js2AddOnloadHook was used or there is video on the page.
        runQueuedFunctions: function() {
-               var _this = this;
-               this.doneReadyEvents = true;
-               if( this.jQueryCheckFlag ) {
-                       this.jQueryCheck( function() {
-                               _this.runReadyEvents();
-                       });
-               } else {
-                       this.runReadyEvents();
-               }
+               js_log("runQueuedFunctions");           
+               var _this = this;               
+               this.jQueryCheck( function() {                  
+                       _this.runReadyEvents();
+                       _this.doneReadyEvents = true;
+               });
        },
        runReadyEvents: function() {
                js_log( "runReadyEvents" );
-               while( this.onReadyEvents.length ) {
-                       this.onReadyEvents.shift()();
+               while( this.onReadyEvents.length ) {    
+                       var func = this.onReadyEvents.shift();
+                       //js_log('run onReady:: ' + func );
+                       func();
                }
        }
 }
 
+// Shortcut ( @@todo consolidate shortcuts & re-factor mvJsLoader )
+function mwLoad( loadSet, callback ) {
+       mvJsLoader.doLoad( loadSet, callback );
+}
+//$mw.shortcut
+$mw.load = mwLoad;
+
 // Load an external JS file. Similar to jquery .require plugin,
 // but checks for object availability rather than load state.
 
@@ -843,23 +1133,36 @@ var mvJsLoader = {
  * $j(document).ready( function(){ */
 function mwdomReady( force ) {
        js_log( 'f:mwdomReady:' );
-       if( !force && mv_init_done ) {
-               js_log( "mv_init_done already done, do nothing..." );
+       if( !force && $mw.init_done ) {
+               js_log( "mw done, do nothing..." );
                return false;
        }
-       mv_init_done = true;
+       $mw.init_done = true;
        // Handle the execution of queued functions with jQuery "ready"
 
-       // Check if this page has a video or playlist
+       // Check if this page has a video, audio or playlist tag
        var e = [
                document.getElementsByTagName( "video" ),
                document.getElementsByTagName( "audio" ),
                document.getElementsByTagName( "playlist" )
        ];
        if( e[0].length != 0 || e[1].length != 0 || e[2].length != 0 ) {
-               js_log( 'we have items to rewrite' );
-               setSwappableToLoading( e );
-               // Load libs and process them
+               //look for any skin classes we have to load: 
+               for(var j in e){
+                       for(var k in e[j]){
+                               if(e[j][k] && typeof( e[j][k]) == 'object'){
+                                       var     sn = e[j][k].getAttribute('class');                             
+                                       if( sn && sn != ''){
+                                               for(var n=0;n< $mw.valid_skins.length;n++){ 
+                                                       if( sn.indexOf($mw.valid_skins[n]) !== -1){
+                                                               $mw.skin_list.push( $mw.valid_skins[n] );
+                                                       }
+                                               }
+                                       }
+                               }
+                       }
+               }                               
+               // Load libs and process videos
                mvJsLoader.embedVideoCheck( function() {
                        // Run any queued global events:
                        mv_video_embed( function() {
@@ -867,31 +1170,22 @@ function mwdomReady( force ) {
                        });
                });
        } else {
-               // If we already have jQuery, make sure it's loaded into its proper context $j
-               // Run any queued global events
                mvJsLoader.runQueuedFunctions();
        }
 }
-// A quick function that sets the initial text of swappable elements to "loading".
-// jQuery might not be ready. Does not destroy inner elements.
-function setSwappableToLoading( e ) {
-       //for(var i =0)
-       //for(var j = 0; i < j.length; j++){
-       //}
-}
+
 //js2AddOnloadHook: ensure jQuery and the DOM are ready
-function js2AddOnloadHook( func ) {    
-       // If we have already run the DOM-ready function, just run the function directly:
-       if( mvJsLoader.doneReadyEvents ) {
-               // Make sure jQuery is there:
-               mvJsLoader.jQueryCheck( function() {
+function js2AddOnloadHook( func ) {
+       //js_log('js2AddOnloadHook:: jquery:' + typeof window.jQuery + ' $j: ' + typeof $j);    
+       //check for jQuery then add the load event (to run after video tag rewrites (if present) 
+       mvJsLoader.jQueryCheck( function() {
+               if( mvJsLoader.doneReadyEvents ) {
+                       //js_log('run queued event: ' + func);  
                        func();
-               });
-       } else {
-               // If we are using js2AddOnloadHook we need to get jQuery into place (if it's not already included)
-               mvJsLoader.jQueryCheckFlag = true;
-               mvJsLoader.addLoadEvent( func );
-       }
+               } else {                
+                       mvJsLoader.addLoadEvent( func );
+               }
+       });
 }
 // Deprecated mwAddOnloadHook in favor of js2 naming (for clear separation of js2 code from old MW code
 var mwAddOnloadHook = js2AddOnloadHook;
@@ -910,59 +1204,110 @@ function rewrite_by_id( vid_id, ready_callback ) {
 /*********** INITIALIZATION CODE *************
  * set DOM-ready callback to init_mv_embed
  *********************************************/
-// for Mozilla browsers
+// for Mozilla / modern browsers
 if ( document.addEventListener ) {
-       document.addEventListener( "DOMContentLoaded", function(){ mwdomReady() }, false );
-} else {
-       // Use the onload method instead when DOMContentLoaded does not exist
-       window.onload = function() { mwdomReady() };
+       document.addEventListener( "DOMContentLoaded", mwdomReady, false );
 }
-/*
- * Should deprecate and use jquery.ui.dialog instead
- */
-function mv_write_modal( content, speed ) {
-       $j( '#modalbox,#mv_overlay' ).remove();
-       $j( 'body' ).append( 
-               '<div id="modalbox" style="background:#DDD;border:3px solid #666666;font-size:115%;' +
-               'top:30px;left:20px;right:20px;bottom:30px;position:fixed;z-index:100;">' +
-               content +
-               '</div>' +
-               '<div id="mv_overlay" style="background:#000;cursor:wait;height:100%;left:0;position:fixed;' +
-               'top:0;width:100%;z-index:5;filter:alpha(opacity=60);-moz-opacity: 0.6;' +
-               'opacity: 0.6;"/>');
-       $j( '#modalbox,#mv_overlay' ).show( speed );
+var temp_f;
+if( window.onload ) {
+    temp_f = window.onload;
 }
-function mv_remove_modal( speed ) {
-       $j( '#modalbox,#mv_overlay' ).remove( speed );
+// Use the onload method as a backup
+window.onload = function () {
+    if( temp_f )
+        temp_f();
+       mwdomReady();
 }
 
 /*
  * Store all the mwEmbed jQuery-specific bindings
  * (set up after jQuery is available).
- * This lets you call rewrites in a jQuery way
  *
- * @@ eventually we should refactor mwCode over to jQuery style plugins
- *       and mv_embed.js will just handle dependency mapping and loading.
+ * These functions are genneraly are loaders that do the dynamic mapping of
+ * dependencies for a given commponet
+ * 
  *
  */
 function mv_jqueryBindings() {
        js_log( 'mv_jqueryBindings' );
        (function( $ ) {
-               $.fn.addMediaWiz = function( iObj, callback ) {
-                       // First set the cursor for the button to "loading"
-                       $j( this.selector ).css( 'cursor', 'wait' ).attr( 'title', gM( 'mwe-loading_title' ) );
-
-                       iObj['target_invocation'] = this.selector;
+               /*
+               * dragDrop file loader 
+               */
+               $.fn.dragFileUpload = function ( conf ){
+                       if( this.selector ){    
+                               var _this = this;       
+                               //load the dragger and "setup"
+                               $mw.load( ['$j.fn.dragDropFile'], function(){
+                                       $j(_this.selector).dragDropFile();                                                      
+                               }); 
+                       }                                        
+               }
+               /*
+                * apiProxy Loader loader:
+                * 
+                * @param mode is either 'server' or 'client'
+                */                             
+               $.apiProxy = function( mode, pConf, callback ){
+                       js_log('do apiProxy setup');                    
+                       mvJsLoader.doLoad( [
+                               '$mw.proxy',
+                               'JSON'
+                       ], function(){                          
+                               //do the proxy setup or 
+                               if( mode == 'client'){
+                                       //just do the setup (no callbcak for client setup) 
+                                       $mw.proxy.client( pConf );
+                                       if( callback )
+                                               callback();
+                               }else if( mode=='server' ){
+                                       //do the request with the callback
+                                       $mw.proxy.server( pConf , callback );
+                               }
+                       });     
+               }
+               
+               //non selector based add-media-wizard direct invocation with loader
+               $.addMediaWiz = function( iObj, callback ){                     
+                       js_log(".addMediaWiz call");
+                       //check if already loaded:
+                       if( _global['rsdMVRS'] ){
+                               _global['rsdMVRS'].doReDisplay();
+                               if( callback )
+                                       callback( _global['rsdMVRS'] );
+                               return ;
+                       }
+                       //display a loader: 
+                       $.addLoaderDialog( gM('mwe-loading-add-media-wiz') );
+                       //load the addMedia wizard without a target: 
+                       $.fn.addMediaWiz ( iObj, function( amwObj ){
+                               //close the dialog
+                               $.closeLoaderDialog();
+                               //do the add-media-wizard display
+                               amwObj.doInitDisplay();                         
+                               //call the parent callback:
+                               if( callback )
+                                       callback( _global['rsdMVRS'] ); 
+                       });
+               }
+               $.fn.addMediaWiz = function( iObj, callback ) {                 
+                       if( this.selector ){                    
+                               // First set the cursor for the button to "loading"
+                               $j( this.selector ).css( 'cursor', 'wait' ).attr( 'title', gM( 'mwe-loading_txt' ) );
+                               //set the target: 
+                               iObj['target_invocation'] = this.selector;
+                       }
 
                        // Load the mv_embed_base skin:
                        loadExternalCss( mv_jquery_skin_path + 'jquery-ui-1.7.1.custom.css' );
-                       loadExternalCss( mv_embed_path + 'skins/' + mwConfig['skin_name']+'/styles.css' );
+                       loadExternalCss( mv_embed_path + 'skins/' + $mw.conf['skin_name'] + '/styles.css' );
                        // Load all the required libs:
                        mvJsLoader.jQueryCheck( function() {
-                               // Load with staged dependencies (for IE and Safari that don't execute in order)
+                               // Load with staged dependencies (for IE that does not execute in order)
                                mvJsLoader.doLoadDepMode([
                                        [       'remoteSearchDriver',
                                                '$j.cookie',
+                                               '$j.fn.textSelection',
                                                '$j.ui'
                                        ],[
                                                '$j.ui.resizable',
@@ -973,20 +1318,24 @@ function mv_jqueryBindings() {
                                        ]
                                ], function() {
                                        iObj['instance_name'] = 'rsdMVRS';
-                                       _global['rsdMVRS'] = new remoteSearchDriver( iObj );
+                                       if( ! _global['rsdMVRS'] )
+                                               _global['rsdMVRS'] = new remoteSearchDriver( iObj );
                                        if( callback ) {
                                                callback( _global['rsdMVRS'] );
                                        }
                                });
                        });
                }
+               /*
+               * Sequencer loader
+               */
                $.fn.sequencer = function( iObj, callback ) {
                        // Debugger
                        iObj['target_sequence_container'] = this.selector;
                        // Issue a request to get the CSS file (if not already included):
                        loadExternalCss( mv_jquery_skin_path + 'jquery-ui-1.7.1.custom.css' );
-                       loadExternalCss( mv_embed_path + 'skins/' + mwConfig['skin_name'] + '/mv_sequence.css' );
-                       // Make sure we have the required mv_embed libs (they are not loaded when no video 
+                       loadExternalCss( mv_embed_path + 'skins/' + $mw.conf['skin_name'] + '/mv_sequence.css' );
+                       // Make sure we have the required mv_embed libs (they are not loaded when no video
                        // element is on the page)
                        mvJsLoader.embedVideoCheck( function() {
                                // Load the playlist object and then the jQuery UI stuff:
@@ -995,7 +1344,7 @@ function mv_jqueryBindings() {
                                                'mvPlayList',
                                                '$j.ui',
                                                '$j.contextMenu',
-                                               '$j.secureEvalJSON',
+                                               'JSON',
                                                'mvSequencer'
                                        ],
                                        [
@@ -1011,7 +1360,7 @@ function mv_jqueryBindings() {
                                        ]
                                ], function() {
                                        js_log( 'calling new mvSequencer' );
-                                       // Initialise the sequence object (it will take over from there) 
+                                       // Initialise the sequence object (it will take over from there)
                                        // No more than one mvSeq obj for now:
                                        if( !_global['mvSeq'] ) {
                                                _global['mvSeq'] = new mvSequencer( iObj );
@@ -1024,21 +1373,23 @@ function mv_jqueryBindings() {
                /*
                 * The Firefogg jQuery function:
                 * @@note This Firefogg invocation could be made to work more like real jQuery plugins
-                */
+                */             
+               var queuedFirefoggConf = {};
                $.fn.firefogg = function( iObj, callback ) {
                        if( !iObj )
                                iObj = {};
                        // Add the base theme CSS:
                        loadExternalCss( mv_jquery_skin_path + 'jquery-ui-1.7.1.custom.css' );
-                       loadExternalCss( mv_embed_path + 'skins/'+mwConfig['skin_name'] + '/styles.css' );
+                       loadExternalCss( mv_embed_path + 'skins/' + $mw.conf['skin_name'] + '/styles.css' );
 
-                       // Check if we already have Firefogg loaded (the call just updates the element's 
+                       // Check if we already have Firefogg loaded (the call just updates the element's
                        // properties)
                        var sElm = $j( this.selector ).get( 0 );
                        if( sElm['firefogg'] ) {
                                if( sElm['firefogg'] == 'loading' ) {
-                                       js_log( "Error: called firefogg operations on Firefogg selector that is " + 
-                                               "not done loading" );
+                                       js_log( "Queued firefogg operations ( firefogg " +
+                                               "not done loading ) " );
+                                       $j.extend( queuedFirefoggConf, iObj );
                                        return false;
                                }
                                // Update properties
@@ -1078,7 +1429,7 @@ function mv_jqueryBindings() {
                        // Make sure we have everything loaded that we need:
                        mvJsLoader.doLoadDepMode( loadSet, function() {
                                        js_log( 'firefogg libs loaded. target select:' + iObj.selector );
-                                       // Select interface provider based on whether we want to include the 
+                                       // Select interface provider based on whether we want to include the
                                        // encoder interface or not
                                        if( iObj.encoder_interface ) {
                                                var myFogg = new mvAdvFirefogg( iObj );
@@ -1089,6 +1440,11 @@ function mv_jqueryBindings() {
                                                myFogg.doRewrite( callback );
                                                var selectorElement = $j( iObj.selector ).get( 0 );
                                                selectorElement['firefogg'] = myFogg;
+                                               
+                                               js_log('pre:'+ selectorElement['firefogg']['firefogg_form_action'])
+                                               if(queuedFirefoggConf)
+                                                       $j.extend(selectorElement['firefogg'], queuedFirefoggConf);
+                                               js_log('post:'+ selectorElement['firefogg']['firefogg_form_action'])
                                        }
                        });
                }
@@ -1139,15 +1495,15 @@ function mv_jqueryBindings() {
                        var href = (opt.href) ? opt.href : '#';
                        var target_attr = (opt.target) ? ' target="' + opt.target + '" ' : '';
                        var style_attr = (opt.style) ? ' style="' + opt.style + '" ' : '';
-                       return '<a href="' + href + '" ' + target_attr + style_attr + 
+                       return '<a href="' + href + '" ' + target_attr + style_attr +
                                ' class="ui-state-default ui-corner-all ui-icon_link ' +
                                className + '"><span class="ui-icon ui-icon-' + iconId + '" />' +
                                '<span class="btnText">'+ msg +'<span></a>';
                }
                // Shortcut to bind hover state
-               $.fn.btnBind = function() {             
+               $.fn.btnBind = function() {
                        $j( this ).hover(
-                               function() {                                    
+                               function() {
                                        $j( this ).addClass( 'ui-state-hover' );
                                },
                                function() {
@@ -1156,7 +1512,87 @@ function mv_jqueryBindings() {
                        )
                        return this;
                }
-
+               /**
+               * resize the dialog to fit the window
+               */
+               $.fn.dialogFitWindow = function(opt){                   
+                       var opt_default = {'hspace':50,'vspace':50};
+                       if(!opt)
+                               var opt={};                     
+                       $j.extend(opt, opt_default);
+                       $j( this.selector).dialog('option', 'width', $j(window).width() - opt.hspace );
+                       $j( this.selector).dialog('option', 'height', $j(window).height() - opt.vspace );
+                       $j( this.selector).dialog('option', 'position','center');
+                               //update the child position: (some of this should be pushed up-stream via dialog config options
+                       $j( this.selector +'~ .ui-dialog-buttonpane').css({
+                               'position':'absolute',
+                               'left':'0px',
+                               'right':'0px',
+                               'bottom':'0px',
+                       });                     
+               }
+               
+               /**
+               * addLoaderDialog
+               *  small helper for putting a loading dialog box on top of everything
+               * (helps block for request that
+               *
+               * @param msg text text of the loader msg
+               */
+               $.addLoaderDialog = function( msg_txt ){                        
+                       $.addDialog( msg_txt, msg_txt + '<br>' + mv_get_loading_img() );                
+               }                                               
+               
+               $.addDialog = function ( title, msg_txt, btn ){
+                       $('#mwe_tmp_loader').remove();
+                       //append the style free loader ontop: 
+                       $('body').append('<div id="mwe_tmp_loader" style="display:none" title="' + title + '" >' +
+                                       msg_txt +
+                       '</div>');                      
+                       //special btn == ok gives empty give a single "oky" -> "close"
+                       if( btn == 'ok' ){
+                               btn[ gM('mwe-ok') ] = function(){
+                                       $j('#mwe_tmp_loader').close();
+                               }
+                       }
+                       //turn the loader into a real dialog loader: 
+                       mvJsLoader.doLoadDepMode([
+                               [
+                                       '$j.ui'
+                               ],
+                               [
+                                       '$j.ui.dialog'
+                               ]
+                       ], function() {
+                               $('#mwe_tmp_loader').dialog({
+                                       bgiframe: true,
+                                       draggable: false,
+                                       resizable: false,                                       
+                                       modal: true,
+                                       width:400,
+                                       buttons: btn
+                               });
+                       });
+               }
+               $.closeLoaderDialog = function(){               
+                       mvJsLoader.doLoadDepMode([
+                               [
+                                       '$j.ui'
+                               ],
+                               [
+                                       '$j.ui.dialog'
+                               ]
+                       ], function() { 
+                               $j('#mwe_tmp_loader').dialog('close');
+                       });
+               }
+       
+               $.mwProxy = function( apiConf ){
+                       mvJsLoader.doLoad( ['$mw.apiProxy'], 
+                       function(){
+                               $mw.apiProxy( apiConf );
+                       });
+               }
        })(jQuery);
 }
 /*
@@ -1276,7 +1712,7 @@ function do_api_req( options, callback ) {
                return js_error( 'Error: request paramaters must be an object' );
        }
        // Generate the URL if it's missing
-       if( typeof options.url == 'undefined' || options.url === false ) {
+       if( typeof options.url == 'undefined' || !options.url ) {
                if( !wgServer || ! wgScriptPath ) {
                        return js_error('Error: no api url for api request');
                }
@@ -1289,12 +1725,15 @@ function do_api_req( options, callback ) {
        options.data['format'] = 'json';
 
        // If action is not set, assume query
-       if( !options.data['action'] )
+       if( ! options.data['action'] )
                options.data['action'] = 'query';
 
-       // js_log('do api req: ' + options.url +'?' + jQuery.param(options.data) );
-       // Build request string
-       if( parseUri( document.URL ).host == parseUri( options.url ).host ) {
+       // js_log('do api req: ' + options.url +'?' + jQuery.param(options.data) );     
+       if( options.url == 'proxy' && $mw.proxy){
+               //assume the proxy is already "setup" since $mw.proxy is defined.
+               // @@todo we probably integrate that setup into the api call
+               $mw.proxy.doRequest( options.data,  callback);  
+       }else if( parseUri( document.URL ).host == parseUri( options.url ).host ) {
                // Local request: do API request directly
                $j.ajax({
                        type: "POST",
@@ -1322,7 +1761,7 @@ function do_api_req( options, callback ) {
                        req_url += paramAnd + encodeURIComponent( i ) + '=' + encodeURIComponent( options.data[i] );
                        paramAnd = '&';
                }
-               var fname = 'mycpfn_' + ( global_cb_count++ );
+               var fname = 'mycpfn_' + ( $mw.cb_count++ );
                _global[ fname ] = callback;
                req_url += '&' + options.jsonCB + '=' + fname;
                loadExternalJs( req_url );
@@ -1334,36 +1773,6 @@ function mwGetLocalApiUrl( url ) {
        }
        return false;
 }
-// Grab wiki form error for wiki html page processing (should be deprecated because we use api now)
-function grabWikiFormError( result_page ) {
-               var res = {};
-               sp = result_page.indexOf( '<span class="error">' );
-               if( sp != -1 ) {
-                       se = result_page.indexOf( '</span>', sp );
-                       res.error_txt = result_page.substr( sp, sp - se ) + '</span>';
-               } else {
-                       // Look for warning
-                       sp = result_page.indexOf( '<ul class="warning">' )
-                       if( sp != -1 ) {
-                               se = result_page.indexOf( '</ul>', sp );
-                               res.error_txt = result_page.substr( sp, se - sp ) + '</ul>';
-                               // Try to add the ignore form item
-                               sfp = result_page.indexOf( '<form method="post"' );
-                               if( sfp != -1 ) {
-                                       sfe = result_page.indexOf( '</form>', sfp );
-                                       res.form_txt = result_page.substr( sfp, sfe - sfp ) + '</form>';
-                               }
-                       } else {
-                               // One more error type check
-                               sp = result_page.indexOf( 'class="mw-warning-with-logexcerpt">' )
-                               if( sp != -1 ) {
-                                       se = result_page.indexOf( '</div>', sp );
-                                       res.error_txt = result_page.substr( sp, se - sp ) + '</div>';
-                               }
-                       }
-               }
-               return res;
-}
 // Do a "normal" request
 function do_request( req_url, callback ) {
        js_log( 'do_request::req_url:' + req_url + ' != ' +  parseUri( req_url ).host );
@@ -1383,9 +1792,10 @@ function do_request( req_url, callback ) {
        } else {
                // Get data via DOM injection with callback
                global_req_cb.push( callback );
-               // Prepend json_ to feed_format if not already requesting json format (metavid specific) 
+               // Prepend json_ to feed_format if not already requesting json format (metavid specific)
                if( req_url.indexOf( "feed_format=" ) != -1 && req_url.indexOf( "feed_format=json" ) == -1 )
-                       req_url = req_url.replace( /feed_format=/, 'feed_format=json_' );
+                       req_url = req_url.replace( /feed_format=/, 'feed_format=json_' );               
+               
                loadExternalJs( req_url + '&cb=mv_jsdata_cb&cb_inx=' + (global_req_cb.length - 1) );
        }
 }
@@ -1474,7 +1884,7 @@ function loadExternalCss( url ) {
        }
 
        if( url.indexOf('?') == -1 ) {
-               url += '?' + getMvUniqueReqId();
+               url += '?' + getMwReqParam();
        }
        if( !styleSheetPresent( url ) ) {
                js_log( 'load css: ' + url );
@@ -1506,25 +1916,34 @@ function getMvEmbedURL() {
        return false;
 }
 // Get a unique request ID to ensure fresh JavaScript
-function getMvUniqueReqId() {
-       if( _global['urid'] )
-               return _global['urid'];
+function getMwReqParam() {     
+       if( _global['req_param'] )
+               return _global['req_param'];
        var mv_embed_url = getMvEmbedURL();
-       // If we have a URI, return it
-       var urid = parseUri( mv_embed_url ).queryKey['urid']
-       if( urid ) {
-               _global['urid'] = urid;
-               return urid;
-       }
-       // If we're in debug mode, get a fresh unique request key
-       if( parseUri( mv_embed_url ).queryKey['debug'] == 'true' ) {
+       
+       var req_param = '';
+       
+       // If we have a URI, add it to the req
+       var urid = parseUri( mv_embed_url ).queryKey['urid']    
+       // If we're in debug mode, get a fresh unique request key and pass on "debug" param
+       if( parseUri( mv_embed_url ).queryKey['debug'] == 'true' ){
                var d = new Date();
-               var urid = d.getTime();
-               _global['urid'] = urid;
-               return urid;
+               req_param += 'urid=' + d.getTime() + '&debug=true';             
+       }else if( urid ) {
+               // Set from request urid:
+               req_param += 'urid=' + urid;
+       }else{
+               // Otherwise, just use the mv_embed version
+               req_param += 'urid=' + $mw.version;
        }
-       // Otherwise, just return the mv_embed version
-       return MV_EMBED_VERSION;
+       //add the lang param:
+       var langKey = parseUri( mv_embed_url ).queryKey['uselang'];
+       if( langKey )
+               req_param += '&uselang=' + langKey;
+                       
+       _global['req_param'] = req_param;
+               
+       return _global['req_param'];
 }
 /*
  * Set the global mv_embed path based on the script's location
@@ -1537,7 +1956,7 @@ function getMvEmbedPath() {
                mv_embed_path = mv_embed_url.substr( 0, mv_embed_url.indexOf( 'mv_embed.js' ) );
        } else if( mv_embed_url.indexOf( 'mwScriptLoader.php' ) !== -1 ) {
                // Script loader is in the root of MediaWiki, so include the default mv_embed extension path
-               mv_embed_path = mv_embed_url.substr( 0, mv_embed_url.indexOf( 'mwScriptLoader.php' ) ) 
+               mv_embed_path = mv_embed_url.substr( 0, mv_embed_url.indexOf( 'mwScriptLoader.php' ) )
                        + mediaWiki_mvEmbed_path;
        } else {
                mv_embed_path = mv_embed_url.substr( 0, mv_embed_url.indexOf( 'jsScriptLoader.php' ) );
@@ -1581,7 +2000,11 @@ if ( typeof DOMParser == "undefined" ) {
 * Utility functions
 */
 function js_log( string ) {
-       if( window.console ) {
+       ///add any prepend debug strings if nessesary (used for cross browser)
+       if( $mw.conf['debug_pre'] )
+               string = $mw.conf['debug_pre']+ string;
+                       
+       if( window.console ) {                          
                window.console.log( string );
        } else {
                /*