/* - Dynamic script framework "dsf" - */
var dsf = {
  version: "00037",
	environment: "production", // default environment
	
	/* plugins */	
	comments: {
	  loaded: false,
		
		development_url: "http://10.0.0.1:8080/php/ultracomments/javascripts/dsf_comments.js",             /* 8< */
		testing_url:     "http://multimedia.ekstrabladet.dk/eb/archive/00409/dsf_comments_409845a.js",     /* 8< */
		production_url:  "http://multimedia.ekstrabladet.dk/eb/archive/00409/dsf_comments_409845a.js"
	},
	
	/* unified "ultralogin" login */
	login: {
	  loaded: true,
	  callback_que: [],
	  require_reload: false,
	  status: {
	    mhid: -1,
	    fbid: -1,
	    fbstatus: 'not_yet_set',
	    mhstatus: 'not_yet_set'
	  },
	  urls: {
	    development: "http://10.0.0.1:8080/php/ultralogin/",
	    testing:     "http://ytterbium.lp.ekstrabladet.dk/php/ultralogin/",
	    production:  "http://ekstrabladet.dk/php/ultralogin/"
	  },
	  
	  // pop's up thickbox with login/fbconnect
	  ultralogin: function( o ){
	    var href = dsf.login.urls[ dsf.environment ] + "?page=login.ajax&height=432&width=731";
	    var data = null;
	    if(o && o.n_source){ href+="&n_source="+o.n_source; }
	    if(o && o.n_origin){ href+="&n_origin="+o.n_origin; }
	    if(o && o.n_campaign){ href+="&n_campaign="+o.n_campaign; }
	    if(o && o.n_returnurl){ 
	      href+="&n_returnurl="+o.n_returnurl; 
	    } else {
	      href+="&n_returnurl="+dsf.url.encode( window.location.href ); 
	    }
	    if(o && o.n_returnname){ 
	      href+="&n_returnname="+o.n_returnurl; 
	    } else {
	      href+="&n_returnname=" + document.title; 
	    }
	    if(o && o.data){ data = o.data; }
	    return dsf.tb.extend.open( { title: 'Log ind', href: href, rel: null, data: data } );
	  },
	  
	  add_callback: function( callback, reload ){      
	    if( reload ){
	      this.require_reload = reload;
	    } else {
	      this.callback_que.push( callback );
	    }
	  },
	  trigger: function( action, callback ){    
	    if( this.require_reload ){
	      var r = this.require_reload;
	      setTimeout(function(){
	        if( r === true){
	          window.location.reload();
	        } else {
	          window.location.href = r;
	        }
	      }, 10);
	      return false;
	    } else {
	      for( var index in this.callback_que ){
          this.callback_que[index]( action );
        }

  	    if( callback )
  	      callback();
  	    
  	    dsf.tb.extend.close();  
        // _({f:['tb', 'close']});
	    }
	  },
	  
	  /* --- */
	  __trigger_backend_user_updating_and_mirroring: function( callback ){
	    $.ajax({
        dataType: 'json',
        timeout: 3000,
        type: "POST",
        url: dsf.login.urls[ dsf.environment ] + "?page=update.fb.json",
        data: {
				},
				beforeSend: function(){ 
				  dsf.tb.extend.show_spinner();
				},
        success: function(data){
					if(data.status == true){
					  callback(true);
					} else if( data.message ) {
					  callback(false, data.message);
					} else {
            callback( false );
					}
        }
        // , 
        // complete: function(){ 
        //   _({f:['tb', 'close']});
        // }
      });  
	  },
	  /* --- */
	  
	  connect_with_facebook: function( o ){
	    if(!window.FB) { return; }
	    
  	  FB.ensureInit(function(){
        try {
          FB.Connect.requireSession(function(){
              // Does the round-trip so the ultralogin can mirror this user to MH
              dsf.login.__trigger_backend_user_updating_and_mirroring(function(status, message){
                if(o.callback)
                  o.callback( status );
                  
                if(status)
                  dsf.login.trigger('login');
              });
    	    });
  	    } catch(e) { }
      });
      setTimeout(function(){ dsf.tb.extend.close(); }, 100);
      return false;	  
	  },
	  	  
	  get_status: function( callback, mh_only ){
	    if(dsf.cookie.read('mh_mail') && dsf.cookie.read('mh_pass')){
	      dsf.login.status.mhstatus = 'logged_in';
	    } else {
	      dsf.login.status.mhstatus = 'logged_out';
	    }
	    
	    if(mh_only){
	      dsf.login.status.fbstatus = 'unknown';
	      callback( dsf.login.status );
	      return;
	    }
	    
	    if(window.FB){
	      FB.ensureInit(function(){
          FB_RequireFeatures(["Connect"], function(){
            FB.Connect.get_status().waitUntilReady(function( status ){
              if( status == FB.ConnectState.connected        && dsf.login.status.fbstatus != "connected" ||
                  status == FB.ConnectState.appNotAuthorized && dsf.login.status.fbstatus != "app_not_authorized" || 
                  status == FB.ConnectState.userNotLoggedIn  && dsf.login.status.fbstatus != "user_not_logged_in"){
                switch ( status ) {
                  case FB.ConnectState.connected:
                    dsf.login.status.fbstatus = 'connected';
                    dsf.login.status.fbid = FB.Facebook.apiClient.get_session();
                    callback( dsf.login.status );
                  break;
                  case FB.ConnectState.appNotAuthorized:
                    dsf.login.status.fbstatus = 'app_not_authorized';
                    callback( dsf.login.status );
                  break;
                  case FB.ConnectState.userNotLoggedIn:
                    dsf.login.status.fbstatus = 'user_not_logged_in';
                    callback( dsf.login.status );
                  break;
                  }              
                } else {
                  callback( dsf.login.status );
                }
            });
          });
        });
        return false;
	    } 
      callback( dsf.login.status );
	  },
	  
	  /* this can eventually be rewritten to work through jsonp */
	  custom_login_button_click: function( options ){
      var form   = $( options.form ),
          button = $( options._this),
          original_button_text = button.val();
      
      $.ajax({
        dataType: 'json',
        timeout: 3000,
        type: "POST",
        url: dsf.login.urls[ dsf.environment ] + "?page=login.json",
        data: {
					username:    form.find('input[name="username"]:first').val(),
					password:    form.find('input[name="password"]:first').val(),
					remember_me: form.find('input[name="remember_me"]:first').attr('checked')
				},
				beforeSend: function(){
          // button.attr('disabled', 'disabled');
          _({f:['tb', 'show_spinner']});
				  button.attr('value', 'Logger ind...');
				  form.find('input').attr('disabled', 'disabled');
				},
        success: function(data){
					if(data.status == true){
						dsf.login.trigger( 'login', function(){
							dsf.tb.extend.close();
						});
					} else if( data.message ) {
						alert( data.message );
					}
        }, 
        complete: function(){
				  form.find('input').attr('disabled', '');
          button.attr('value', original_button_text);
          dsf.tb.extend.close();
        }
      });
      return false;
	  },
	  custom_logout_button_click: function( options ){
	    var form   = $( options.form ),
          button = $( options._this);
      
	      $.ajax({
          dataType: 'json',
          timeout: 3000,
          type: "POST",
          url: dsf.login.urls[ dsf.environment ] + "?page=logout.json",
          data: {
            logout: 'true'
          },
  				beforeSend: function(){
  				  _({f:['tb', 'show_spinner']});
  				  button.attr('disabled', 'disabled');
  				},
          success: function(data){
  					if(data.status == true){
  					  var delayed = function(){
  					    dsf.login.trigger( 'logout', function(){
    							dsf.tb.extend.close();
    						});
  					  }

  					  dsf.login.get_status(function( status ){  					    
                if(status.fbstatus == "connected"){
                  FB.Connect.logout(function(){ delayed(); });
                } else {
                  delayed();
                }
          		});
  					} else if( data.message ) {
  						alert( data.message );
  					}
          }, 
          complete: function(){
            setTimeout(function(){ _({f:['tb', 'hide_spinner']}); }, 20000);
            button.attr('disabled', '');
          }
        });
        
	    return false;
	  },
	  
    obtain_permission: function( options, callback  ){
      dsf.tb.extend.show_spinner();
      
      var cleanup = function( callback ){
        dsf.tb.extend.close();
        if( callback )
          callback();
      }
    
      try {  
        switch(options.name){
          case 'email':
            var delayed = function( options ){
              FB.ensureInit(function(){ 
                  $('#TB_load').hide();
                  FB.Connect.showPermissionDialog('email', function(o){
                    if(o == 'email'){
                       options.success();
                    } else {
                       options.failure();
                    }
                  });
              });
            };
        
            delayed({ 
              success: function(){
                // Does the update-ajax-call
                dsf.login.__trigger_backend_user_updating_and_mirroring(function(){
                  cleanup( function(){ 
                    callback( { status: true } );
                  });
                });
              }, 
              failure: function(){
                if( options.required ){
                  if( options.error_text )
                    window.alert( options.error_text );
                  dsf.login.obtain_permission( options, callback );
                } else {
                  callback( { status: false } );
                }
              }
            });
            break;
    
          default: 
            callback( { status: false } );
            return;
        }
      } catch(e) { }
    }
  },
	
	/* thickbox */
	tb: {
	  loaded: true,
	  prefixes: {
  	  development: "http://10.0.0.1:8080/php/ultracomments/",
  	  testing:     "http://ekstrabladet.dk/php/ultrasocial/",
  	  production:  "http://ekstrabladet.dk/php/ultrasocial/" 
  	},
  	extend: {
  	  show_spinner: function(){
  	    try {
  	      if (typeof document.body.style.maxHeight === "undefined") {//if IE 6
           $("body","html").css({height: "100%", width: "100%"});
           $("html").css("overflow","hidden");
           if (document.getElementById("TB_HideSelect") === null) {//iframe to hide select elements in ie6
             $("body").append("<iframe id='TB_HideSelect'></iframe><div id='TB_overlay'></div><div id='TB_window'></div>");
           }
          } else { //all others
           if(document.getElementById("TB_overlay") === null){
             $("body").append("<div id=\"TB_overlay\"></div><div id='TB_window'></div>");
           }
           $("#TB_overlay").click(this.close);
          }
          $("object,embed").hide();
  	    } catch(e) { /* Nothing here */ } 
  	    
  	    if( $('#TB_load').length < 1 ){
  	      imgLoader = new Image();
          imgLoader.src = dsf.tb.prefixes[dsf.environment] + "images/loadingAnimation.gif";
          $('body').append("<div id='TB_load'><img src='" + imgLoader.src + "' /></div>");
  	    }
        $('#TB_load').fadeIn('fast');
  	  },
  	  hide_spinner: function(){
  	    if( $('#TB_load').length > 0 )
  	      $('#TB_load').hide();
  	  },
  	  open: function( o ){
        this.show_spinner();
        
        dsf.load_script('jquery_thickbox', function(){
          dsf.load_script('jquery_form', function(){
              if( o._this ){
                var _t = $(o._this);
                var t = _t.attr('title') || _t.attr('name') || null;
                var a = _t.attr('href')  || _t.attr('alt');
                var g = _t.attr('rel')   || false;
                tb_show(t, a, g, (o.data || false));
                _t.blur(); 
              } else {
                tb_show( o.title, o.href, ( o.rel || false ), ( o.data || false ) );
              }
          });
        });
        return false;
  	  },
  	  
  	  close: function(){
        // if( typeof tb_remove == 'function' ){
        //   tb_remove();
        // } else {
	      $("#TB_imageOff").unbind("click");
      	$("#TB_closeWindowButton").unbind("click");
      	
      	$("#TB_overlay").fadeOut('fast', function(){
      	  $("#TB_window").fadeOut('fast', function(){
        	  $('#TB_window, #TB_overlay, #TB_HideSelect').trigger("unload").unbind().remove();
        	  $("object,embed").show();
        	});
      	});
      	
      	dsf.tb.extend.hide_spinner();
      	if (typeof document.body.style.maxHeight == "undefined") {//if IE 6
      		$("body","html").css({height: "auto", width: "auto"});
      		$("html").css("overflow","");
      	}
      	document.onkeydown = "";
      	document.onkeyup = "";
      	return false;
        // }
  	  }
  	}
	},
	
	jquery_form: {
	  loaded: false,
	  
	  development_url: "http://10.0.0.1:8080/php/ultracomments/javascripts/jquery_form.js",              /* 8< */
		testing_url:     "http://multimedia.ekstrabladet.dk/eb/archive/00409/jquery_form_409857a.js",     /* 8< */
		production_url:  "http://multimedia.ekstrabladet.dk/eb/archive/00409/jquery_form_409857a.js"
	},
	
	jquery_thickbox: {
	  loaded: false,
	  development_url: "http://10.0.0.1:8080/php/ultracomments/javascripts/thickbox_3_1.js",             /* 8< */
		testing_url:     "http://multimedia.ekstrabladet.dk/eb/archive/00409/thickbox_3_1_409856a.js",     /* 8< */
		production_url:  "http://multimedia.ekstrabladet.dk/eb/archive/00409/thickbox_3_1_409856a.js"
	},
	
	tv_right_box: { 
		loaded: false,
		
		development_url:  "javascripts/tv_right_box.js",                                                /* 8< */
		testing_url:      "http://multimedia.ekstrabladet.dk/eb/archive/00382/tv_right_box_382057a.js", /* 8< */
		production_url:   "http://multimedia.ekstrabladet.dk/eb/archive/00382/tv_right_box_382057a.js",
		
		extend: null,
		target: null,
		
		preload:   function( a ){ 
			this.target = $(".boxid2").css('opacity', 0.4);
		},
		afterload: function( a ){ 
			this.target.css('opacity', 1);
		}
	},
	
	tv_box41: {
		loaded: false,
		
		development_url: "javascripts/tv_box41.js",                                                 /* 8< */
		testing_url:     "http://multimedia.ekstrabladet.dk/eb/archive/00382/tv_box41_382056a.js",  /* 8< */
		production_url:  "http://multimedia.ekstrabladet.dk/eb/archive/00382/tv_box41_382056a.js",
		
		extend: null,
		target: null,
		
		preload:  function( a ){ 
			this.target = $("#eb_main div.boxid41:first").css('opacity', 0.4);
		},
		afterload: function( a ){ 
			this.target.css('opacity', 1);
		}
	},
	
	tv_box42: {
		loaded: false,
		
		development_url: "javascripts/tv_box42.js",                                                 /* 8< */
		testing_url:     "http://multimedia.ekstrabladet.dk/eb/archive/00382/tv_box42_382350a.js",  /* 8< */
		production_url:  "http://multimedia.ekstrabladet.dk/eb/archive/00382/tv_box42_382350a.js",
		
		extend: null,
		target: null,
		
		preload:  function( a ){ 
			this.target = $("div.boxid42:first").css('opacity', 0.4);
		},
		afterload: function( a ){ 
		  this.target.css('opacity', 1);
		}
	},
	
	tv_quicksearch :{
		loaded: false,
		
		development_url: "http://10.0.0.1:8080/EkstraBladet/redesign/javascripts/tv_quicksearch.js",     /* 8< */
		testing_url:     "http://multimedia.ekstrabladet.dk/eb/archive/00382/tv_quicksearch_382058a.js", /* 8< */
		production_url:  "http://multimedia.ekstrabladet.dk/eb/archive/00382/tv_quicksearch_382058a.js"
	},
		
	tv_box106: {
		loaded: false,
		
		development_url: "http://10.0.0.1:8080/EkstraBladet/redesign/javascripts/tv_box106.js",         /* 8< */
		testing_url:     "http://multimedia.ekstrabladet.dk/eb/archive/00382/tv_box106_382049a.js",     /* 8< */
		production_url:  "http://multimedia.ekstrabladet.dk/eb/archive/00382/tv_box106_382049a.js",
		
		preload:   function( a ){  
			this.target = $(".boxid106:first").css('opacity', 0.4);
		},
		afterload: function( a ){  
			this.target.css('opacity', 1);
		}
	},
	
	livesports: {
	  loaded: false,
	  development_url: "http://10.0.0.1:8080/EkstraBladet/php/livesportoversigt/javascripts/dsf_livesports.js", /* 8< */
	  testing_url:     "http://multimedia.ekstrabladet.dk/eb/archive/00455/dsf_livesports_455817a.js",          /* 8< */
	  production_url:  "http://multimedia.ekstrabladet.dk/eb/archive/00455/dsf_livesports_455817a.js"               
	},
	
	quicksearch :{
	  loaded: false,
	  development_url: "http://10.0.0.1:8080/EkstraBladet/redesign/javascripts/quicksearch.js",     /* 8< */
		testing_url:     "http://multimedia.ekstrabladet.dk/eb/archive/00394/quicksearch_394498a.js", /* 8< */
		production_url:  "http://multimedia.ekstrabladet.dk/eb/archive/00394/quicksearch_394498a.js"
	},
		
	/* core */
	std_tabbed_box: {
	  /* standart single tabbed box */
    d: function( options ){
      var element = $(options._this);
    	var target = $(options.target);
    	var current_class = (!options.current_class)? 'current' : options.current_class;
    	
      element.parent().parent().find("." + current_class).removeClass(current_class);
			target.css('opacity', 0.4);
			
    	$.ajax({
    		type: "GET",
    		dataType: "html",
    		url: options.url,
    		cache: false,
    		complete: function(){ target.css('opacity', 1); },
    		success: function(data){
    			element.parent().addClass(current_class);
    			$(target).html(data);
    		}
    	});
    	
    	return false;
    },
    
    /* standart double tabbed box */
    double_d: function(options){
      if(!this.selected_subtab){
        this.selected_subtab = [1,1,1,1,1,1,1,1,1,1,1];
      }
      
      var supertabs = $(options.supertabs);
      var subgroups = $(options.subgroups);
      var target    = $(options.target);
      
      if(!options.current_class || options.current_class == null){
        options.current_class = "current";
      }
      
      if(!options.subtab || options.subtab == null){
        options.subtab = this.selected_subtab[options.supertab - 1];
      } else {
        this.selected_subtab[options.supertab - 1] = options.subtab;
      }
      
      options.data.supertab = options.supertab;
      options.data.subtab = options.subtab;
      
      $.ajax({
        type: "GET",
        dataType: "html",
        url: options.url,
        data: options.data,
        beforeSend: function(){
          target.css('opacity', 0.4);
        },
        success: function(data){
          supertabs.removeClass(options.current_class);
          supertabs.eq(options.supertab - 1).addClass(options.current_class);
          subgroups.hide();
          subgroups.eq(options.supertab - 1).show();
          var subtabs = subgroups.eq(options.supertab-1).find("li");
          subtabs.removeClass(options.current_class);
          subtabs.eq(options.subtab - 1).addClass(options.current_class);
          target.html(data);
          target.css('opacity', 1);
        }
      });
    }
  },
	
	load_script: function( script , callback ){
		if(this[ script ].loaded == true){
			callback();
		} else {
		  var url = dsf[script][dsf.environment + "_url"];
		  if(dsf.environment != "production"){
		    url = url + "?" + Math.random();
		  }
		  $.ajax({
      		type: "GET",
    			url: url,
    			success: function(){
    			  setTimeout(function(){
    			    callback();
    			  }, 1000);
    			},	
    			dataType: "script",
    			cache: (dsf.environment == "production")? true : false,
    			data: null
    	});
		}
	},
	
	forwarded_load: function( element, e ){
		if(this[element['module']].loaded == true){
			this[ element['module'] ][ 'extend' ][ element['method'] ]( element, e );
		} else {
			$.ajax({ 
				dataType: "script", 
				type: "GET",
				async: false,
				url: this[element['module']][ this.environment + "_url"] + "?" + this['version'], 
				complete: function(){ 
					dsf[ element['module'] ][ 'extend' ][ element['method'] ]( element, e );
				},
				cache: (this.environment == "production" || $.browser == "msie")? true : false
			}); 
		}
	},
	
	/* modules */
		
	url: {
	  decode: function(str){
	    var histogram = {}, histogram_r = {}, code = 0, str_tmp = [];
      var ret = str.toString();

      var replacer = function(search, replace, str) {
          var tmp_arr = [];
          tmp_arr = str.split(search);
          return tmp_arr.join(replace);
      };
      
      histogram['!']   = '%21'; histogram['%20'] = '+';

      for (replace in histogram) {
          search = histogram[replace];
          ret = replacer(search, replace, ret);
      }
      return decodeURIComponent(ret);
	  },
	  encode: function(str){
	    return encodeURIComponent( str );
	  }
	},
	
	cookie: { 
	  create: function(name, value, days) {
    	if (days) {
    		var date = new Date();
    		date.setTime(date.getTime()+(days*24*60*60*1000));
    		var expires = "; expires="+date.toGMTString();
    	}
    	else var expires = "";
    	document.cookie = name+"="+value+expires+"; path=/";
    },

    read: function(name) {
    	var nameEQ = name + "=";
    	var ca = document.cookie.split(';');
    	for(var i=0;i < ca.length;i++) {
    		var c = ca[i];
    		while (c.charAt(0)==' ') c = c.substring(1,c.length);
    		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    	}
    	return null;
    },

    erase: function(name) {
    	this.create(name,"",-1);
    }
	},
	
	bookmark: {
	  create: function(title,url,obj){
      if ($.browser.msie) {
         obj.setHomePage(url);
      } else {
         if (window.sidebar)
             window.sidebar.addPanel(title, url, "");
         else if(window.opera && window.print){
             var elem = document.createElement('a');
             elem.setAttribute('href',url);
             elem.setAttribute('title',title);
             elem.setAttribute('rel','sidebar');
             elem.click();
         } 
         else if(document.all)
             window.external.AddFavorite(url, title);
      }
	  }
	},
	
	object: {
	  // http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_serialize/
	  serialize: function( mixed_value ) { 
        var _getType = function( inp ) {
            var type = typeof inp, match;
            var key;
            if (type == 'object' && !inp) {
                return 'null';
            }
            if (type == "object") {
                if (!inp.constructor) {
                    return 'object';
                }
                var cons = inp.constructor.toString();
                match = cons.match(/(\w+)\(/);
                if (match) {
                    cons = match[1].toLowerCase();
                }
                var types = ["boolean", "number", "string", "array"];
                for (key in types) {
                    if (cons == types[key]) {
                        type = types[key];
                        break;
                    }
                }
            }
            return type;
        };
        var type = _getType(mixed_value);
        var val, ktype = '';

        switch (type) {
            case "function": 
                val = ""; 
                break;
            case "boolean":
                val = "b:" + (mixed_value ? "1" : "0");
                break;
            case "number":
                val = (Math.round(mixed_value) == mixed_value ? "i" : "d") + ":" + mixed_value;
                break;
            case "string":
                val = "s:" + encodeURIComponent(mixed_value).replace(/%../g, 'x').length + ":\"" + mixed_value + "\"";
                break;
            case "array":
            case "object":
                val = "a";
                var count = 0;
                var vals = "";
                var okey;
                var key;
                for (key in mixed_value) {
                    ktype = _getType(mixed_value[key]);
                    if (ktype == "function") { 
                        continue; 
                    }

                    okey = (key.match(/^[0-9]+$/) ? parseInt(key, 10) : key);
                    vals += dsf.object.serialize(okey) +
                            dsf.object.serialize(mixed_value[key]);
                    count++;
                }
                val += ":" + count + ":{" + vals + "}";
                break;
            case "undefined": // Fall-through
            default: // if the JS object has a property which contains a null value, the string cannot be unserialized by PHP
                val = "N";
                break;
        }
        if (type != "object" && type != "array") {
            val += ";";
        }
        return val;
    },
    
    // http://kevin.vanzonneveld.net/techblog/article/javascript_equivalent_for_phps_unserialize/
	  unserialize: function(data){
        var error = function (type, msg, filename, line){throw new this.window[type](msg, filename, line);};
        var read_until = function (data, offset, stopchr){
            var buf = [];
            var chr = data.slice(offset, offset + 1);
            var i = 2;
            while (chr != stopchr) {
                if ((i+offset) > data.length) {
                    error('Error', 'Invalid');
                }
                buf.push(chr);
                chr = data.slice(offset + (i - 1),offset + i);
                i += 1;
            }
            return [buf.length, buf.join('')];
        };
        var read_chrs = function (data, offset, length){
            var buf;

            buf = [];
            for(var i = 0;i < length;i++){
                var chr = data.slice(offset + (i - 1),offset + i);
                buf.push(chr);
            }
            return [buf.length, buf.join('')];
        };
        var _unserialize = function (data, offset){
            var readdata;
            var readData;
            var chrs = 0;
            var ccount;
            var stringlength;
            var keyandchrs;
            var keys;

            if(!offset) {offset = 0;}
            var dtype = (data.slice(offset, offset + 1)).toLowerCase();

            var dataoffset = offset + 2;
            var typeconvert = new Function('x', 'return x');

            switch(dtype){
                case 'i':
                    typeconvert = function (x) {return parseInt(x, 10);};
                    readData = read_until(data, dataoffset, ';');
                    chrs = readData[0];
                    readdata = readData[1];
                    dataoffset += chrs + 1;
                break;
                case 'b':
                    typeconvert = function (x) {return parseInt(x, 10) !== 0;};
                    readData = read_until(data, dataoffset, ';');
                    chrs = readData[0];
                    readdata = readData[1];
                    dataoffset += chrs + 1;
                break;
                case 'd':
                    typeconvert = function (x) {return parseFloat(x);};
                    readData = read_until(data, dataoffset, ';');
                    chrs = readData[0];
                    readdata = readData[1];
                    dataoffset += chrs + 1;
                break;
                case 'n':
                    readdata = null;
                break;
                case 's':
                    ccount = read_until(data, dataoffset, ':');
                    chrs = ccount[0];
                    stringlength = ccount[1];
                    dataoffset += chrs + 2;

                    readData = read_chrs(data, dataoffset+1, parseInt(stringlength, 10));
                    chrs = readData[0];
                    readdata = readData[1];
                    dataoffset += chrs + 2;
                    if(chrs != parseInt(stringlength, 10) && chrs != readdata.length){
                        error('SyntaxError', 'String length mismatch');
                    }
                break;
                case 'a':
                    readdata = {};

                    keyandchrs = read_until(data, dataoffset, ':');
                    chrs = keyandchrs[0];
                    keys = keyandchrs[1];
                    dataoffset += chrs + 2;

                    for(var i = 0;i < parseInt(keys, 10);i++){
                        var kprops = _unserialize(data, dataoffset);
                        var kchrs = kprops[1];
                        var key = kprops[2];
                        dataoffset += kchrs;

                        var vprops = _unserialize(data, dataoffset);
                        var vchrs = vprops[1];
                        var value = vprops[2];
                        dataoffset += vchrs;

                        readdata[key] = value;
                    }

                    dataoffset += 1;
                break;
                default:
                    error('SyntaxError', 'Unknown / Unhandled data type(s): ' + dtype);
                break;
            }
            return [dtype, dataoffset - offset, typeconvert(readdata)];
        };
        return _unserialize((data+''), 0)[2];
    }
	},
		
	/* 8< */ set_env: function (){
	/* 8< */	if( document.URL.substring(0,8) == "http://1" ){
	/* 8< */		this.environment = "development";
	/* 8< */	} else if( document.URL.substring(0,10) == "http://ytt" || 
	/* 8< */	           document.URL.substring(0,10) == "http://erb" ){
	/* 8< */		this.environment = "testing";
	/* 8< */	}
	/* 8< */ },
	
	_: function(){ }
}; 

dsf.set_env(); /* 8< */

if(!console){
  var console = {
    log: function( what_to_log ){
      if( dsf.environment == "testing" || dsf.environment == "development")
        window.alert( what_to_log );
    }
  }
}

function dispatch( invoke_string, element ){
	var invoke = invoke_string.split("->", 3);

	element['module'] = invoke[0];
	element['method'] = invoke[1];
	element['param']  = invoke[2];
	
	dsf.load_script(invoke[0], function(){
		if( dsf[ invoke[0] ][ 'preload' ] ){ dsf[ invoke[0] ][ 'preload' ]( element ); }
		dsf[ invoke[0] ][ 'extend'  ][ invoke[1] ]( element, function(){ 
		  if( dsf[ invoke[0] ]['afterload'] ){ dsf[ invoke[0] ]['afterload'](element); } 
		});
	});
		
	return false;
}

function d( invoke_string, element, event ){
	var invoke = invoke_string.split("->", 3);

	element['module'] = invoke[0];
	element['method'] = invoke[1];
	element['param']  = invoke[2];

	dsf.forwarded_load(element, event);
		
	return false;
}

/* magic function */

function _( options ){
  if(options.f && options.f instanceof Array && options.f[0] && options.f[1]){
    
    if(dsf[options.f[0]].loaded){
      if(options.f.length == 2){
        dsf[options.f[0]]['extend'][options.f[1]](options);
      } else if(options.f.length == 3){
        dsf[options.f[0]]['extend'][options.f[1]][options.f[2]](options);
      }
    } else {
      dsf.load_script(options.f[0], function(){
        if(dsf[options.f[0]]['preload']){
          dsf[options.f[0]]['preload'](options);
        }

        try {
          if(options.f.length == 2){
            dsf[options.f[0]]['extend'][options.f[1]](options);
          } else if(options.f.length == 3){
            dsf[options.f[0]]['extend'][options.f[1]][options.f[2]](options);
          }
        } catch(err) { }

        if(dsf[options.f[0]]['afterload']){
          dsf[options.f[0]]['afterload'](options);
        }
      });
    }    
  }
  
  return false;
}