var B81AjaxFrame = new Class({
	overlayFrame:			null,
	
	refreshContainer: 		null,
	ajx_senderContainer:  	null,
	ajx_singleSenders:    	null,
	alt_senderContainer:  	null,
	alt_singleSenders:    	null,
	external_functions:     null,
	
	tempScripts: 	  		null,
	usedHeadScripts:  		null,
	usedCSS:			null,
	
	actualOldHREF:			null,
	actualNewHREF:			null,
	
	actualHash:				null,
	hashCheckInt:			null,
	
	responseData:			null,
	parsedData:				null,
	
	messageQueue:			null,
	
	processing:				null,


	
	getOptions: function(){
		return {
			ieVersion:					null,
			host: 						null,
			tmplScope:					null,
			secure: 					0,
			b81TemplatePluginValue: 	'',
			hashCheckTime:				500,
			useSwapFx: 					true,
			showLoader: 				1,
		    loaderText: 				'LOADING DATA',
			loaderAnimation: 			'',
			loaderOpacity : 			0.8,
		    loaderInTime : 				1000,
		    loaderOutTime : 			1000,
			linkExcludeBlank: 			1,
			linkExcludeRelKey: 			'noScript',
			parseForms: 				1,
			isSEF: 						0,
			debugMode: 					'none', // none, all, scripts, errors, response
			jmessages:					1,
			jmessage_mode:				'overlay',
			jmessage_inject_el:			'',
			jmessage_overlay_opac:		0.8
		};
	},
	//* inittialize *//
	initialize: function(refr, ajx_cont, ajx_single, alt_cont, alt_single, xtfunc, options){
		this.setOptions(this.getOptions(), options);
		
		this.refreshContainer 		= refr;
		this.ajx_senderContainer  	= ajx_cont;
		this.ajx_singleSenders    	= ajx_single;
		this.alt_senderContainer  	= alt_cont;
		this.alt_singleSenders    	= alt_single;
		this.external_functions    	= xtfunc;
		this.tempScripts 			= new Array();
		this.usedHeadScripts		= new Array();
		this.usedCSS			= new Array();
		
		
		//setup events
		this.addEvent('onInit', this.onInitHandler); //event sent on initiation
		this.addEvent('onAddressChange', this.onAddressChangeHandler); //event sent on initiation
		this.addEvent('onRequest', this.onRequestHandler); //event sent on starting request
		this.addEvent('onBasicDataParsed', this.onBasicDataParsedHandler); //event sent after parsed the response (json, pagetitle, scripts)
		this.addEvent('onDataComplete', this.onDataCompleteHandler); //event sent after parsed the refresh content
		this.addEvent('onFrameworkComplete', this.onFrameworkCompleteHandler); //event sent after framework has completed the procedure
		
		
		//setup 
		this.initAddressHandling();
		
		//setup external ajax-calls
		this.setupExternalCalls();
		
		//event sent after framework has completed the procedure
		this.fireEvent('onInit');
	},
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////// 
	////////////////////////////////// EVENT HANDLER
	////////////////////////////////////////////////////////////////////////////////////////////////////// 
	onInitHandler: function() {		
		this.processing = false;
		
		//setup outside functionality
		this.runExternalScripts('onInit');
		
		//collect already existing headscripts (JS&CSS)
		this.collectHeadScripts();
		
		//find and parse all senders
		this.parseSenders(false);
		
		//delete script tags for security
		if(this.options.secure) {
			$('b81ajaxframe').remove();
			$('b81ajaxframe_init').remove();
		}
	},
	
	onAddressChangeHandler: function() {
		var href = this.getUrlFromHash();
		this.doRequest(href);
	},
	
	onRequestHandler: function() {
		this.processing = true;
		
		//setup outside functionality
		this.runExternalScripts('onRequest');
		
		//show loader GXF
		if(this.options.showLoader) {
			var loader = this.setupLoader();
			this.showLoader(loader);
		}
	},
	
	onBasicDataParsedHandler: function() {
		//setup outside functionality
		//outside aditional data handlers
		this.runExternalScripts('responseDataHandler');
		
		//outside refresh handler function(class, contentdata, refreshcontainer[, xtraparams]);
		//have to return an event class.fireEvent('onDataComplete');
		var external = this.runExternalScripts('contentDataHandler');

		//do basic internal refresh
		if(!external) {
			this.doBasicRefreshContent(this.parsedData);
		}
	},
	
	onDataCompleteHandler: function() {
		//search and parse senders in loaded content
		this.parseSenders(true);
		
		//eval collected respone-scripts
		this.doTempScripts();
		
		//hide loadergfx
		if(this.options.showLoader) {
			this.hideLoader();
		}
		
		//setup outside functionality
		this.runExternalScripts('onDataComplete');
		this.fireEvent('onFrameworkComplete');
	},
	
	onFrameworkCompleteHandler: function() {
		//setup outside functionality
 		this.runExternalScripts('onFrameworkComplete');		
		
		actualOldHREF = null;
		actualNewHREF = null;
		responseData = null;
		parsedData = null;
		
		this.processing = false;
		
		//setup messages
		if(this.messageQueue != null) {
			switch(this.options.jmessage_mode) {
				case'overlay':
					this.doMessagesOverlay();
				break;
				case'inject':
					this.doMessagesInject();
				break;
				case'external':
				break;
			}
		}
	},
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////// 
	////////////////////////////////// AJAX CORE FUNCTIONS
	////////////////////////////////////////////////////////////////////////////////////////////////////// 
	
	// -----------------------------------------------------> collect, rewrite & prepare
	collectHeadScripts: function() {
		var head = document.getElements('head');
		var js_head = head[0].getElements('script');
		js_head.each(function(el, i) {
						
						var ident = this.getScriptIdent(el, true);
						
						this.usedHeadScripts.push(ident); 
						if(this.options.debugMode == 'all' || this.options.debugMode == 'scripts') {
							alert('found existing script ' + ident);
						}
					}, this);
		var css_head = head.getElements('link');
		css_head.each(function(el, i) {
						if(el.rel=='stylesheet') {
							var iStart = this.strrpos(el.href,'/')+1;
							var ident = this.substr(el.href, iStart);
							if(this.options.debugMode == 'all' || this.options.debugMode == 'scripts') {
								alert('found existing stylesheet ' + ident);
							}
							this.usedCSS.push(ident); 
						}
					}, this);
	},
	
	parseSenders: function(onlyRefresh) {
		if(!onlyRefresh) {
			//ajx_container_senders
			if(this.ajx_senderContainer.length > 0) {
				for(var c=0; c < this.ajx_senderContainer.length; c++) {
					$$('#'+	this.ajx_senderContainer[c] + ' a').each( function(el,i) { this.rewriteLink(el); }.bind(this) );
					if(this.options.parseForms == 1) {
						$$('#'+	this.ajx_senderContainer[c] + ' form').each( function(el,i) { this.rewriteForm(el); }.bind(this) );
					}
				}
			}
			//ajx_single_senders
			if(this.ajx_singleSenders.length > 0) {
				for(var s=0; s < this.singleSenders.length; s++) {
					var ajx_single = $(this.singleSenders[s]);
					if(ajx_single && ajx_single.href) {
						this.rewriteLink(ajx_single);
					} else if(ajx_single && ajx_single.action && this.options.parseForms == 1) {
						this.rewriteForm(ajx_single);
					}
				}
			}
			//alt_container_senders
			if(this.alt_senderContainer.length > 0) {
				for(var c=0; c < this.alt_senderContainer.length; c++) {
					$$('#'+	this.alt_senderContainer[c] + ' a').each( function(el,i) { this.rewriteLink(el, true); }.bind(this) );
					if(this.options.parseForms == 1) {
						$$('#'+	this.alt_senderContainer[c] + ' form').each( function(el,i) { this.rewriteForm(el, true); }.bind(this) );
					}
				}
			}
			//alt_single_senders
			if(this.alt_singleSenders.length > 0) {
				for(var s=0; s < this.alt_singleSenders.length; s++) {
					var alt_single = $(this.alt_singleSenders[s]);
					if(alt_single && alt_single.href) {
						this.rewriteLink(alt_single, true);
					} else if(alt_single && alt_single.action && this.options.parseForms == 1) {
						this.rewriteForm(alt_single, true);
					}
				}
			}
		} else {
			for(var r=0; r < this.refreshContainer.length; r++) {
				$$('#'+	this.refreshContainer[r] + ' a').each( function(el,i) { this.rewriteLink(el); }.bind(this) );
				if(this.options.parseForms == 1) {
					$$('#'+	this.refreshContainer[r] + ' form').each( function(el,i) { this.rewriteForm(el); }.bind(this) );
				}
			}
		}
	},
	
	rewriteLink: function(element, alternate) {
		var ajaxLink = false;
		if(!alternate){
			if((!element.target || element.target.toLowerCase() != '_blank' || !this.options.linkExcludeBlank) 
				&& (!element.rel || element.rel != this.options.linkExcludeRelKey)) {
				ajaxLink = true;
			}
		}
		//force ajax_senders to an ajax-request
		if(ajaxLink) {
			element.onclick = function() { return false; };
			element.addEvent('click', function(e) { 
								var elem = new Event(e).target;
								if(window.ie) {
									while(elem.tagName != 'A' && elem.parentElement)  var elem = elem.parentElement;
								} else {
									while(elem.tagName != 'A' && elem.getParent())  var elem = elem.getParent();
								}
							  	var oldHref = elem.href;
							  	var newHref = this.reparseHref(oldHref);
								
								this.actualOldHREF = oldHref;
								
								this.setupRequest(newHref);
							  }.bind(this) 
							);
		}
		//force alternates to do an alternate request
		if(alternate){
			element.onclick = function() { return false; };
			element.addEvent('click', function(e) { 
								var elem = new Event(e).target;
								if(window.ie) {
									while(elem.tagName != 'A' && elem.parentElement)  var elem = elem.parentElement;
								} else {
									while(elem.tagName != 'A' && elem.getParent())  var elem = elem.getParent();
								}
							  	var oldHref = elem.href;
								this.doAlternateRequest(oldHref);
							  }.bind(this) 
							);
		}
	},
	
	rewriteForm: function(element, alternate) {
		if(!alternate){
			element.onsubmit = function() { return false; };
			element.addEvent('submit', function(e) { 
								var elem = new Event(e).target;
							  	var oldAction = elem.action;
							  	elem.action = this.reparseHref(oldAction);
								
								this.setupFormRequest(elem, oldAction);
							  }.bind(this) 
							);
		}
	},
	
	reparseHref: function(oldHref) {
		//check for first divider
		if(!this.strpos(oldHref,'?')) {
			var qd1 = '?';	
		} else {
			var qd1 = '&';		
		}
		
		var newHref = oldHref;
		
		if(newHref == this.options.host) {
			newHref = newHref+'index.php';
		}
		
		if(this.options.b81TemplatePluginValue != '') {
			newHref = newHref+qd1+'usetmpl='+this.options.b81TemplatePluginValue;
		}
		//check for second divider
		if(!this.strpos(newHref,'?')) {
			var qd2 = '?';	
		} else {
			var qd2 = '&';		
		}

		newHref = newHref+qd2+"aj=1&tmplscope="+this.options.tmplScope;
		
		return newHref;
	},

	// -----------------------------------------------------> request
	setupRequest: function(newHref) {
		if(this.processing == false) {
			this.setAddress(newHref);
			this.doRequest(newHref);
		}
	},
	
	setupFormRequest: function(form, oldAction) {
		if(this.processing == false) {
			this.doFormRequest(form, oldAction);
		}
	},
	
	doRequest: function(newHref) {
		this.fireEvent('onRequest');
		var success  = function(r) { 
			/* try to parse the entry */
			try {
				this.responseData = r;
				this.parseResultBasicData( r );
			} catch(e) {
				if(this.options.debugMode == 'all' || this.options.debugMode == 'errors' || this.options.debugMode == 'response') {
					var errmsg = 'Error handling Response \n';
					for(var ie in e) {
						errmsg += ie+': '+e[ie]+'\n';
					}
					alert(errmsg);	
				}
				this.doAlternateRequest( this.actualOldHREF );
			}
		}.bind(this);
		
		var failure  = function(){ 
			this.doAlternateRequest( this.actualOldHREF );
		}.bind(this);
		
		//add the AJ-VAR to sign the AJAX-request
		if(this.options.debugMode == 'all') {
			alert("link to: " + newHref);	
		}
		
		var AJAX = new Ajax(newHref, {
						  method: 'get',
						  onComplete:success,
						  onFailure:failure
						  }).request();
	},
	
	doFormRequest: function(form, oldAction) {
		this.fireEvent('onRequest');
		var success  = function(r) { 
			/* try to parse the entry */
			try {
				this.responseData = r;
				this.parseResultBasicData( r );
			} catch(e) {
				if(this.options.debugMode == 'all' || this.options.debugMode == 'errors' || this.options.debugMode == 'response') {
					var errmsg = 'Error handling Form Response \n';
					for(var ie in e) {
						errmsg += ie+': '+e[ie]+'\n';
					}
					alert(errmsg);	
				}
				this.doAlternateFormRequest(form, oldAction );
			}
		}.bind(this);
		
		var failure  = function(){ 
			this.doAlternateFormRequest(form, oldAction );
		}.bind(this);
		
		//add the AJ-VAR to sign the AJAX-request
		if(this.options.debugMode == 'all') {
			alert("Form "+ form.id +" send to: " + form.action);	
		}
		
		form.send({onComplete:success, onFailure:failure});
	},
	
	doAlternateRequest: function(oldHref) {
		if(this.options.isSEF || !this.strpos(oldHref,'?')) {
			var qd = '?';	
		} else {
			var qd = '&';		
		}
		var reqUrl = oldHref+qd+"aj=0";
		if(this.options.debugMode == 'all') {
			alert("alternate link to: " + reqUrl);	
		}
		document.location.href = reqUrl;
	},
	
	doAlternateFormRequest: function(form, oldAction) {
		if(this.options.isSEF || !this.strpos(oldAction,'?')) {
			var qd = '?';	
		} else {
			var qd = '&';		
		}
		var action = oldAction+qd+"aj=0";
		if(this.options.debugMode == 'all') {
			alert("alternate Form send to: " + action);	
		}
		
		form.action = action;
		form.submit();
	},
	
	// -----------------------------------------------------> parse data and run scripts
	parseResultBasicData:function(result) {
		//parse the result and return the content
		this.parsedData = Json.evaluate(result);
		
		this.setPageTitle(this.parsedData);
		this.doResultScripts(this.parsedData);
		
		if(this.options.jmessages) {
			this.getMessagedata(this.parsedData);	
		}
		
		this.fireEvent('onBasicDataParsed');
	},
	
	setPageTitle: function(data) {
		//set pagetitle
		document.title = data.pagedata.title;
	},
	
	getMessagedata: function(data) {
		//messagedata[i].message / messagedata[i].type
		if(data.messagedata.length > 0) {
			this.messageQueue = data.messagedata;	
		} else {
			this.messageQueue = null;
		}
	},
	
	doResultScripts: function(data) {
		if(this.options.debugMode == 'all' || this.options.debugMode == 'response') {
			alert(data.fullcontentdata);
		}
		
		try {
			var head =  document.getElements('head')[0];
		} catch(e) {
			if(this.options.debugMode == 'errors') {
				alert('head for for script- or css-insertion not found');
			}
		}
		
		//do the headscripts!
		for(var hs=0; hs<data.headScriptsdata.length; hs++) {
			var headscript = data.headScriptsdata[hs];
			if(!this.in_array(headscript.ident, this.usedHeadScripts)) {
				this.usedHeadScripts.push(headscript.ident);
				try {
					var script = new Element("script");
					script.type = "text/javascript";
  					script.id = headscript.ident;
					head.appendChild(script);
					script.text = headscript.script;
				} catch(e) {
					if(this.options.debugMode == 'all' || this.options.debugMode == 'scripts' || this.options.debugMode == 'errors') {
						var errmsg = 'Error inject HeadScript: \n' + 'ident: ' + headscript.ident +'\n';
						for(var ie in e) {
							errmsg += ie+': '+e[ie]+'\n';
						}
						alert(errmsg);	
					}
				}
				if(this.options.debugMode == 'all' || this.options.debugMode == 'scripts' || this.options.debugMode == 'response') {
					alert('headscript ' + headscript.ident + ' injected in head');	
				}
			}
		}
		
		//inject the CSS in head!
		//relations
		for(var hcr=0; hcr<data.cssReldata.length; hcr++) {
			var cssRel = data.cssReldata[hcr];
			if(!this.in_array(cssRel.ident, this.usedCSS)) {
				try {
					var relcss = new Element("link");
					relcss.id = cssRel.ident;
					relcss.type = "text/css";
					relcss.rel = "stylesheet";
					relcss.href = cssRel.href;
					if(cssRel.media) {
						relcss.media = cssRel.media;
					}
					head.appendChild(relcss);
					
					this.usedCSS.push(cssRel.ident);
				} catch(e) {
					if(this.options.debugMode == 'all' || this.options.debugMode == 'scripts' || this.options.debugMode == 'errors') {
						var errmsg = 'Error inject CSS-Relation: \n' + 'ident: ' + cssRel.ident +'\n';
						for(var ie in e) {
							errmsg += ie+': '+e[ie]+'\n';
						}
						alert(errmsg);	
					}
				}
				
				if(this.options.debugMode == 'all' || this.options.debugMode == 'scripts' || this.options.debugMode == 'response') {
					alert('CSS-Relation ' + cssRel.ident + ' injected');	
				}
			}
		}
		//direct styles
		for(var hcd=0; hcd<data.cssStyledata.length; hcd++) {
			var cssStyle = data.cssStyledata[hc];
			if(!this.in_array(cssStyle.ident, this.usedCSS)) {
				try {
					var style = new Element("style");
					style.id = cssStyle.ident;
					style.type = "text/css";
					if(cssStyle.media) {
						style.media = cssStyle.media;
					}
					style.text = cssStyle.styles;
					head.appendChild(style);
					
					this.usedCSS.push(cssStyle.ident);
				} catch(e) {
					if(this.options.debugMode == 'all' || this.options.debugMode == 'scripts' || this.options.debugMode == 'errors') {
						var errmsg = 'Error inject CSS-Style: \n' + 'ident: ' + cssStyle.ident +'\n';
						for(var ie in e) {
							errmsg += ie+': '+e[ie]+'\n';
						}
						alert(errmsg);	
					}
				}
				
				if(this.options.debugMode == 'all' || this.options.debugMode == 'scripts' || this.options.debugMode == 'response') {
					alert('CSS-Style ' + cssStyle.ident + ' injected');	
				}
			}
		}
		
		
		//collect the bodycripts to inject them at the end of the procedures!
		for(var bs=0; bs<data.bodyScriptsdata.length; bs++) {
			var bodyscript = data.bodyScriptsdata[bs];
			this.tempScripts.push(bodyscript);
			if(this.options.debugMode == 'all' || this.options.debugMode == 'scripts' || this.options.debugMode == 'response') {
				alert('BodyScript found \n\n' + bodyscript + '\n\n stored for later injection');	
			}
		}
	},
	
	doBasicRefreshContent: function(data) {
		var cscope  = data.rcdata;
		for(var rc=0; rc < this.refreshContainer.length; rc++) {
			var rc_name = this.refreshContainer[rc];
			var rc_elem = $(rc_name);
			
			if(!rc_elem) {
				if(this.options.debugMode == 'errors') {
					alert('No element for Refreshcontainer "'+rc_name+'" found in document!!');
				}
				continue;
			}
			if(!cscope[rc_name]) {
				if(this.options.debugMode == 'errors' || this.options.debugMode == 'response') {
					alert('No data for Refreshcontainer "'+rc_name+'" in Response!!');
				}
				continue;
			}
			//cleanup refreshcontainer
			while(rc_elem.getFirst()) rc_elem.getFirst().remove();
			
			//set new content
			rc_elem.innerHTML = cscope[rc_name];
		}
		this.fireEvent('onDataComplete');
	},
		
	doTempScripts: function() {
		for(var s=0; s<this.tempScripts.length; s++) {
			try {
				var scriptContent = this.tempScripts[s];
				if(this.options.debugMode == 'all' || this.options.debugMode == 'scripts' || this.options.debugMode == 'response') {
					alert("inject script: " + scriptContent);	
				}
				
				var ident = this.getScriptIdent(scriptContent, false);
				if($(ident)) {
					$(ident).remove();
				}
				var bdy =  document.getElements('body')[0];
				var script = new Element("script");
				script.type = "text/javascript";
				script.id = ident;
				bdy.appendChild(script);
				script.text = scriptContent;
			} catch(e) {
				if(this.options.debugMode == 'all' || this.options.debugMode == 'scripts' || this.options.debugMode == 'errors') {
					var errmsg = 'Error inject BodyScript '+ident+': \n';
					for(var ie in e) {
						errmsg += ie+': '+e[ie]+'\n';
					}
					alert(errmsg);	
				}
			}
		}
		
		//clean tempScripts
		this.tempScripts.length = 0;
		
		//init scripts that using 'domready' to init
		window.fireEvent('domready');
	},
	

	////////////////////////////////////////////////////////////////////////////////////////////////////// 
	////////////////////////////////// ADDRESSHANDLING & HISTORY
	////////////////////////////////////////////////////////////////////////////////////////////////////// 
	initAddressHandling: function() {
		//if its an old Opera (Op < 9) set history-mode for hash-navigation
		if (window.opera) {
			history.navigationMode = 'compatible';
		}
		
		this.actualHash				= '';
		
		//if an initial hash is set preset the iframe for old ie
		if((this.options.ieVersion != null && this.options.ieVersion < 8) && !window.opera) {
			if(this.strpos(window.location.href, '#')) {
				this.setIframe(this.substr(window.location.href, this.strpos(window.location.href, '#')+1));
			}
		}
		
		this.hashCheckInt = this.ceckForAddressChange.periodical(this.options.hashCheckTime, this);
	},
	
	setAddress: function(href) {
		var hashValue = this.parseHashValue(href);
		this.setHash(hashValue);
	},
	
	parseHashValue: function(url) {
		var hashValue = this.substr(url, this.strpos(url, 'index.php')-1);
		return hashValue;
	},
	
	setHash: function(hashValue) {
		//use iframe-solution older ie
		if((this.options.ieVersion != null && this.options.ieVersion < 8) && !window.opera) {
			this.setIframe(hashValue);
		}
		
		window.location.hash = hashValue;
		this.actualHash = '#'+hashValue;
	},
	
	setIframe: function(hashValue) {
		var frame = $('b81_old_ie_addressframe');
		var doc = frame.contentWindow.document;
		doc.open("javascript:'<html></html>'");
		doc.write("<html><body>" + '#'+hashValue + "</body></html>");
        doc.close();
	},
	
	getUrlFromHash: function() {
		if((this.options.ieVersion != null && this.options.ieVersion < 8) || window.opera) {
			var hashValue = window.location.href;
			hashValue =  this.substr(hashValue, this.strpos(hashValue, '#'));
		} else {
			var hashValue = window.location.hash;
		}
		
		if(!this.strpos(hashValue, 'index.php')) {
			var url = this.reparseHref(this.options.host + 'index.php');
		} else {
			var url = this.options.host + this.substr(hashValue,2);
		}
		return url;
	},
	
	ceckForAddressChange:function() {
		var hashValue = ''
		//old IE
		if((this.options.ieVersion != null && this.options.ieVersion < 8) && !window.opera) {
			hashValue = $('b81_old_ie_addressframe').contentWindow.document.body.innerText;
			if(this.actualHash != hashValue) {
				window.location.hash = hashValue;
			}
			
		//Opera
		} else if(window.opera) {
			if(window.location.hash != ''){
				var hashValue = window.location.href;
				hashValue =  this.substr(hashValue, this.strpos(hashValue, '#'));
			}
		//all the nice browser
		} else {
			var hashValue = window.location.hash;
		}
		if(hashValue != this.urldecode(this.actualHash)) {
			this.actualHash = hashValue;
			this.fireEvent('onAddressChange');
		}
	},
	

	////////////////////////////////////////////////////////////////////////////////////////////////////// 
	////////////////////////////////// EXTERNAL functionality
	////////////////////////////////////////////////////////////////////////////////////////////////////// 
	setupExternalCalls: function() {
		window.callB81Ajax = function(url, del) {
			var newHref = this.reparseHref(url);
			if(del) {
				this.setupRequest(newHref, url);
			} else {
				this.setupRequest(newHref, url);
			}
		}.bind(this)
	},
	
	runExternalScripts: function(typeval) {
		var foundScripts = false;
		var scopeScripts = this.external_functions[typeval];
		if(scopeScripts && scopeScripts.length > 0) {
			foundScripts = true;
			for(var xts=0; xts < scopeScripts.length; xts++) {
					var fobj = scopeScripts[xts];
					
					var call = '';
					if(fobj.scriptscope) {
						call = call + fobj.scriptscope+".";
					}
					call = call+fobj.functionname
					
					//prepare callparams
					var xtsparams = '';
					if(fobj.xtparams != '') {
						xtsparams = ','+fobj.xtparams;						 
					}
					
					var classcopy = this;
					
					var callparams = 'classcopy';
					
					switch(typeval){
						case'responseDataHandler':
							callparams = '('+callparams+',this.parsedData'+xtsparams+')';
						break;
						
						case'contentDataHandler':
							callparams = '('+callparams+',this.parsedData.rcdata,this.refreshContainer'+xtsparams+')';
						break;
						
						default:
							callparams = '('+callparams+xtsparams+')';
						break;
					}
					
					call = call+callparams;
					eval(call);
			}
		}
		return foundScripts;
	},


	////////////////////////////////////////////////////////////////////////////////////////////////////// 
	////////////////////////////////// LOADER-GFX
	////////////////////////////////////////////////////////////////////////////////////////////////////// 
	setupLoader: function() {
		if(!$('b81_ajaxloader') || this.loader == null) {
			var tgt = document.getElements('body')[0];
			this.loader = new Element('div', { 
									  'id': 'b81_ajaxloader', 
									  'class': 'b81_ajaxloader', 
									  'styles': {
												  'position':'fixed',
												  'width':'300px',
												  'height':'100px',
												  'background-image': 'url('+this.options.loaderAnimation+')',
												  'background-repeat': 'no-repeat',
												  'background-position': 'center center',
												  'top':((window.getHeight() / 2) -100) +'px',
												  'left':((window.getWidth() / 2) -300) +'px',
												  'z-index':'1000'
											  }
									  } );
			var loadertext = new Element('div', {
										 'id': 'b81_ajaxloader_text', 
										 'class': 'b81_ajaxloader_text',
										 'styles': {
												  'position':'absolute',
												  'width':'250px',
												  'left':'50%',
												  'margin-left':'-125px',
												  'margin-top':'60px',
												  'text-align':'center'
												}
										 } );
			loadertext.setHTML(this.options.loaderText);
			loadertext.injectInside(this.loader);
			this.loader.injectInside(tgt);
			this.loader.setOpacity(0);
			
		} else {
			this.loader.setStyles ({
									  'top':((window.getHeight() / 2) -100) +'px',
									  'left':((window.getWidth() / 2) -300) +'px'
								   });
		}
	},
	
	showLoader: function() {
		if(this.loader.fx && this.loader.fx != null) {
			this.loader.fx.stop();	
		}
		this.loader.fx = new Fx.Style(this.loader, 'opacity', {
										duration: this.options.loaderInTime, 
										transition: Fx.Transitions.Cubic.easeInOut,
										onComplete: function() { this.loader.fx = null }.bind(this)
										}).start(0, this.options.loaderOpacity);
	},
	
	hideLoader: function() {
		if(this.loader.fx && this.loader.fx != null) {
			this.loader.fx.stop();	
		}
		this.loader.fx = new Fx.Style(this.loader, 'opacity', {
										duration: this.options.loaderInTime, 
										transition: Fx.Transitions.Cubic.easeInOut,
										onComplete: function() { this.loader.fx = null; }.bind(this)
										}).start(this.options.loaderOpacity, 0);
	},
	
	
	////////////////////////////////////////////////////////////////////////////////////////////////////// 
	////////////////////////////////// JMESSAGE-HANDLING
	//////////////////////////////////////////////////////////////////////////////////////////////////////
	buildMessageContent: function() {
		var msgUL = new Element('ul', { 'id': 'jmessages', 'class': 'jmessages_list' });
		for(m=0; m<this.messageQueue.length; m++) {
			var msgObj = this.messageQueue[m];
			var msgLI = new Element('li', {
										'id': 'jmessages_message_'+m,
										'class': 'jmessages_message '+msgObj.type
									});
			msgLI.innerHTML = msgObj.message;
			
			msgLI.injectInside(msgUL);
		}
		return msgUL;
	},
	
	doMessagesInject: function() {
		var content = this.buildMessageContent();
		var tgt = $(this.options.jmessage_inject_el);
		if(tgt) {
			//cleanup refreshcontainer
			while(tgt.getFirst()) tgt.getFirst().remove();	
			content.injectInside(tgt);
		}
	},
	
	doMessagesOverlay: function() {
		if(this.overlayFrame == null) {
			var opt = {
					opacity: this.options.jmessage_overlay_opac,	 
					transition: Fx.Transitions.linear,			
					duration: 500,
					content_width: 400,
					classadd: 'jmessages'
				}
			this.overlayFrame = new B81OverlayFrame(opt);
		}
		var content = this.buildMessageContent();
		this.overlayFrame.setOverlay(content, 'js_element');
	},

	
	////////////////////////////////////////////////////////////////////////////////////////////////////// 
	////////////////////////////////// HELPER
	//////////////////////////////////////////////////////////////////////////////////////////////////////
	getScriptIdent: function(el, isElement) {
		if(isElement && el.id) {
			var ident = el.id;
		} else if(isElement && el.src) {
			var iStart = this.strrpos(el.src,'/')+1;
			var ident = this.substr(el.src, iStart);
		} else {
			var ident = this.md5(el.innerHTML);	
		}
		return ident;
	},
	
	////////////////////////////////////////////////////////////////////////////////////////////////////// 
	////////////////////////////////// PHP.JS Essential Functions
	////////////////////////////////// thanks alot to kevin and his developers!!!
	//////////////////////////////////////////////////////////////////////////////////////////////////////
	in_array: function(needle, haystack, argStrict) {
		// http://kevin.vanzonneveld.net
		// +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// *     example 1: in_array('van', ['Kevin', 'van', 'Zonneveld']);
		// *     returns 1: true
	 
		var found = false, key, strict = !!argStrict;
	 
		for (key in haystack) {
			if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
				found = true;
				break;
			}
		}
	 
		return found;
	}, 	
	substr: function( f_string, f_start, f_length ) {
		// http://kevin.vanzonneveld.net
		// +     original by: Martijn Wieringa
		// +     bugfixed by: T.Wild
		// +      tweaked by: Onno Marsman
		// *       example 1: substr('abcdef', 0, -1);
		// *       returns 1: 'abcde'
		// *       example 2: substr(2, 0, -6);
		// *       returns 2: ''
	 
		f_string += '';
	 
		if(f_start < 0) {
			f_start += f_string.length;
		}
	 
		if(f_length == undefined) {
			f_length = f_string.length;
		} else if(f_length < 0){
			f_length += f_string.length;
		} else {
			f_length += f_start;
		}
	 
		if(f_length < f_start) {
			f_length = f_start;
		}
	 
		return f_string.substring(f_start, f_length);
	},
	strpos: function( haystack, needle, offset){
		// http://kevin.vanzonneveld.net
		// +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +   improved by: Onno Marsman    
	 
		var i = (haystack+'').indexOf( needle, offset ); 
		return i===-1 ? false : i;
	},
	strrpos: function( haystack, needle, offset){
		// http://kevin.vanzonneveld.net
		// +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +   bugfixed by: Onno Marsman
		// *     example 1: strrpos('Kevin van Zonneveld', 'e');
		// *     returns 1: 16
	 
		var i = (haystack+'').lastIndexOf( needle, offset ); // returns -1
		return i >= 0 ? i : false;
	},
	str_replace: function(search, replace, subject) {
		// http://kevin.vanzonneveld.net
		// +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +   improved by: Gabriel Paderni
		// +   improved by: Philip Peterson
		// +   improved by: Simon Willison (http://simonwillison.net)
		// +    revised by: Jonas Raoni Soares Silva (http://www.jsfromhell.com)
		// +   bugfixed by: Anton Ongson
		// +      input by: Onno Marsman
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +    tweaked by: Onno Marsman
	 
		var f = search, r = replace, s = subject;
		var ra = r instanceof Array, sa = s instanceof Array, f = [].concat(f), r = [].concat(r), i = (s = [].concat(s)).length;
	 
		while (j = 0, i--) {
			if (s[i]) {
				while (s[i] = s[i].split(f[j]).join(ra ? r[j] || "" : r[0]), ++j in f){};
			}
		};
	 
		return sa ? s : s[0];
	},
	urlencode: function( str ) {
		// http://kevin.vanzonneveld.net
		// +   original by: Philip Peterson
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +      input by: AJ
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +   improved by: Brett Zamir (http://brettz9.blogspot.com)
		// +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +      input by: travc
		// +      input by: Brett Zamir (http://brettz9.blogspot.com)
		// +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +   improved by: Lars Fischer
		// %          note 1: info on what encoding functions to use from: http://xkr.us/articles/javascript/encode-compare/
		// *     example 1: urlencode('Kevin van Zonneveld!');
		// *     returns 1: 'Kevin+van+Zonneveld%21'
		// *     example 2: urlencode('http://kevin.vanzonneveld.net/');
		// *     returns 2: 'http%3A%2F%2Fkevin.vanzonneveld.net%2F'
		// *     example 3: urlencode('http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a');
		// *     returns 3: 'http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a'
								 
		var histogram = {}, unicodeStr='', hexEscStr='';
		var ret = (str+'').toString();
		
		var replacer = function(search, replace, str) {
			var tmp_arr = [];
			tmp_arr = str.split(search);
			return tmp_arr.join(replace);
		};
		
		// The histogram is identical to the one in urldecode.
		histogram["'"]   = '%27';
		histogram['(']   = '%28';
		histogram[')']   = '%29';
		histogram['*']   = '%2A';
		histogram['~']   = '%7E';
		histogram['!']   = '%21';
		histogram['%20'] = '+';
		histogram['\u00DC'] = '%DC';
		histogram['\u00FC'] = '%FC';
		histogram['\u00C4'] = '%D4';
		histogram['\u00E4'] = '%E4';
		histogram['\u00D6'] = '%D6';
		histogram['\u00F6'] = '%F6';
		histogram['\u00DF'] = '%DF';
		histogram['\u20AC'] = '%80';
		histogram['\u0081'] = '%81';
		histogram['\u201A'] = '%82';
		histogram['\u0192'] = '%83';
		histogram['\u201E'] = '%84';
		histogram['\u2026'] = '%85';
		histogram['\u2020'] = '%86';
		histogram['\u2021'] = '%87';
		histogram['\u02C6'] = '%88';
		histogram['\u2030'] = '%89';
		histogram['\u0160'] = '%8A';
		histogram['\u2039'] = '%8B';
		histogram['\u0152'] = '%8C';
		histogram['\u008D'] = '%8D';
		histogram['\u017D'] = '%8E';
		histogram['\u008F'] = '%8F';
		histogram['\u0090'] = '%90';
		histogram['\u2018'] = '%91';
		histogram['\u2019'] = '%92';
		histogram['\u201C'] = '%93';
		histogram['\u201D'] = '%94';
		histogram['\u2022'] = '%95';
		histogram['\u2013'] = '%96';
		histogram['\u2014'] = '%97';
		histogram['\u02DC'] = '%98';
		histogram['\u2122'] = '%99';
		histogram['\u0161'] = '%9A';
		histogram['\u203A'] = '%9B';
		histogram['\u0153'] = '%9C';
		histogram['\u009D'] = '%9D';
		histogram['\u017E'] = '%9E';
		histogram['\u0178'] = '%9F';
		
		// Begin with encodeURIComponent, which most resembles PHP's encoding functions
		ret = encodeURIComponent(ret);
	 
		for (unicodeStr in histogram) {
			hexEscStr = histogram[unicodeStr];
			ret = replacer(unicodeStr, hexEscStr, ret); // Custom replace. No regexing
		}
		
		// Uppercase for full PHP compatibility
		return ret.replace(/(\%([a-z0-9]{2}))/g, function(full, m1, m2) {
			return "%"+m2.toUpperCase();
		});
	},
	urldecode: function( str ) {
		// http://kevin.vanzonneveld.net
		// +   original by: Philip Peterson
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +      input by: AJ
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +   improved by: Brett Zamir (http://brett-zamir.me)
		// +      input by: travc
		// +      input by: Brett Zamir (http://brett-zamir.me)
		// +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +   improved by: Lars Fischer
		// +      input by: Ratheous
		// %          note 1: info on what encoding functions to use from: http://xkr.us/articles/javascript/encode-compare/
		// *     example 1: urldecode('Kevin+van+Zonneveld%21');
		// *     returns 1: 'Kevin van Zonneveld!'
		// *     example 2: urldecode('http%3A%2F%2Fkevin.vanzonneveld.net%2F');
		// *     returns 2: 'http://kevin.vanzonneveld.net/'
		// *     example 3: urldecode('http%3A%2F%2Fwww.google.nl%2Fsearch%3Fq%3Dphp.js%26ie%3Dutf-8%26oe%3Dutf-8%26aq%3Dt%26rls%3Dcom.ubuntu%3Aen-US%3Aunofficial%26client%3Dfirefox-a');
		// *     returns 3: 'http://www.google.nl/search?q=php.js&ie=utf-8&oe=utf-8&aq=t&rls=com.ubuntu:en-US:unofficial&client=firefox-a'
		
		var hash_map = {}, ret = str.toString(), unicodeStr='', hexEscStr='';
		
		var replacer = function(search, replace, str) {
			var tmp_arr = [];
			tmp_arr = str.split(search);
			return tmp_arr.join(replace);
		};
		
		// The hash_map is identical to the one in urlencode.
		hash_map["'"]   = '%27';
		hash_map['(']   = '%28';
		hash_map[')']   = '%29';
		hash_map['*']   = '%2A';
		hash_map['~']   = '%7E';
		hash_map['!']   = '%21';
		hash_map['%20'] = '+';
		hash_map['\u00DC'] = '%DC';
		hash_map['\u00FC'] = '%FC';
		hash_map['\u00C4'] = '%D4';
		hash_map['\u00E4'] = '%E4';
		hash_map['\u00D6'] = '%D6';
		hash_map['\u00F6'] = '%F6';
		hash_map['\u00DF'] = '%DF';
		hash_map['\u20AC'] = '%80';
		hash_map['\u0081'] = '%81';
		hash_map['\u201A'] = '%82';
		hash_map['\u0192'] = '%83';
		hash_map['\u201E'] = '%84';
		hash_map['\u2026'] = '%85';
		hash_map['\u2020'] = '%86';
		hash_map['\u2021'] = '%87';
		hash_map['\u02C6'] = '%88';
		hash_map['\u2030'] = '%89';
		hash_map['\u0160'] = '%8A';
		hash_map['\u2039'] = '%8B';
		hash_map['\u0152'] = '%8C';
		hash_map['\u008D'] = '%8D';
		hash_map['\u017D'] = '%8E';
		hash_map['\u008F'] = '%8F';
		hash_map['\u0090'] = '%90';
		hash_map['\u2018'] = '%91';
		hash_map['\u2019'] = '%92';
		hash_map['\u201C'] = '%93';
		hash_map['\u201D'] = '%94';
		hash_map['\u2022'] = '%95';
		hash_map['\u2013'] = '%96';
		hash_map['\u2014'] = '%97';
		hash_map['\u02DC'] = '%98';
		hash_map['\u2122'] = '%99';
		hash_map['\u0161'] = '%9A';
		hash_map['\u203A'] = '%9B';
		hash_map['\u0153'] = '%9C';
		hash_map['\u009D'] = '%9D';
		hash_map['\u017E'] = '%9E';
		hash_map['\u0178'] = '%9F';
	 
		for (unicodeStr in hash_map) {
			hexEscStr = hash_map[unicodeStr]; // Switch order when decoding
			ret = replacer(hexEscStr, unicodeStr, ret); // Custom replace. No regexing
		}
		// End with decodeURIComponent, which most resembles PHP's encoding functions
		ret = decodeURIComponent(ret);
	 
		return ret;
	},
	base64_encode: function( data ) {
		// http://kevin.vanzonneveld.net
		// +   original by: Tyler Akins (http://rumkin.com)
		// +   improved by: Bayron Guevara
		// +   improved by: Thunder.m
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +   bugfixed by: Pellentesque Malesuada
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// -    depends on: utf8_encode
		// *     example 1: base64_encode('Kevin van Zonneveld');
		// *     returns 1: 'S2V2aW4gdmFuIFpvbm5ldmVsZA=='
	 
		// mozilla has this native
		// - but breaks in 2.0.0.12!
		//if (typeof this.window['atob'] == 'function') {
		//    return atob(data);
		//}
			
		var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
		var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc="", tmp_arr = [];
	 
		if (!data) {
			return data;
		}
	 
		data = this.utf8_encode(data+'');
		
		do { // pack three octets into four hexets
			o1 = data.charCodeAt(i++);
			o2 = data.charCodeAt(i++);
			o3 = data.charCodeAt(i++);
	 
			bits = o1<<16 | o2<<8 | o3;
	 
			h1 = bits>>18 & 0x3f;
			h2 = bits>>12 & 0x3f;
			h3 = bits>>6 & 0x3f;
			h4 = bits & 0x3f;
	 
			// use hexets to index into b64, and append result to encoded string
			tmp_arr[ac++] = b64.charAt(h1) + b64.charAt(h2) + b64.charAt(h3) + b64.charAt(h4);
		} while (i < data.length);
		
		enc = tmp_arr.join('');
		
		switch( data.length % 3 ){
			case 1:
				enc = enc.slice(0, -2) + '==';
			break;
			case 2:
				enc = enc.slice(0, -1) + '=';
			break;
		}
	 
		return enc;
	},
	base64_decode: function( data ) {
		// http://kevin.vanzonneveld.net
		// +   original by: Tyler Akins (http://rumkin.com)
		// +   improved by: Thunder.m
		// +      input by: Aman Gupta
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +   bugfixed by: Onno Marsman
		// +   bugfixed by: Pellentesque Malesuada
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +      input by: Brett Zamir (http://brett-zamir.me)
		// +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// -    depends on: utf8_decode
		// *     example 1: base64_decode('S2V2aW4gdmFuIFpvbm5ldmVsZA==');
		// *     returns 1: 'Kevin van Zonneveld'
	 
		// mozilla has this native
		// - but breaks in 2.0.0.12!
		//if (typeof this.window['btoa'] == 'function') {
		//    return btoa(data);
		//}
	 
		var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
		var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, dec = "", tmp_arr = [];
	 
		if (!data) {
			return data;
		}
	 
		data += '';
	 
		do {  // unpack four hexets into three octets using index points in b64
			h1 = b64.indexOf(data.charAt(i++));
			h2 = b64.indexOf(data.charAt(i++));
			h3 = b64.indexOf(data.charAt(i++));
			h4 = b64.indexOf(data.charAt(i++));
	 
			bits = h1<<18 | h2<<12 | h3<<6 | h4;
	 
			o1 = bits>>16 & 0xff;
			o2 = bits>>8 & 0xff;
			o3 = bits & 0xff;
	 
			if (h3 == 64) {
				tmp_arr[ac++] = String.fromCharCode(o1);
			} else if (h4 == 64) {
				tmp_arr[ac++] = String.fromCharCode(o1, o2);
			} else {
				tmp_arr[ac++] = String.fromCharCode(o1, o2, o3);
			}
		} while (i < data.length);
	 
		dec = tmp_arr.join('');
		dec = this.utf8_decode(dec);
	 
		return dec;
	},
	utf8_encode: function( argString ) {
		// http://kevin.vanzonneveld.net
		// +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +   improved by: sowberry
		// +    tweaked by: Jack
		// +   bugfixed by: Onno Marsman
		// +   improved by: Yves Sucaet
		// +   bugfixed by: Onno Marsman
		// *     example 1: utf8_encode('Kevin van Zonneveld');
		// *     returns 1: 'Kevin van Zonneveld'
	 
		var string = (argString+'').replace(/\r\n/g, "\n").replace(/\r/g, "\n");
	 
		var utftext = "";
		var start, end;
		var stringl = 0;
	 
		start = end = 0;
		stringl = string.length;
		for (var n = 0; n < stringl; n++) {
			var c1 = string.charCodeAt(n);
			var enc = null;
	 
			if (c1 < 128) {
				end++;
			} else if((c1 > 127) && (c1 < 2048)) {
				enc = String.fromCharCode((c1 >> 6) | 192) + String.fromCharCode((c1 & 63) | 128);
			} else {
				enc = String.fromCharCode((c1 >> 12) | 224) + String.fromCharCode(((c1 >> 6) & 63) | 128) + String.fromCharCode((c1 & 63) | 128);
			}
			if (enc !== null) {
				if (end > start) {
					utftext += string.substring(start, end);
				}
				utftext += enc;
				start = end = n+1;
			}
		}
	 
		if (end > start) {
			utftext += string.substring(start, string.length);
		}
	 
		return utftext;
	},
	utf8_decode: function( str_data ) {
		// http://kevin.vanzonneveld.net
		// +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
		// +      input by: Aman Gupta
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +   improved by: Norman "zEh" Fuchs
		// +   bugfixed by: hitwork
		// +   bugfixed by: Onno Marsman
		// +      input by: Brett Zamir (http://brett-zamir.me)
		// +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// *     example 1: utf8_decode('Kevin van Zonneveld');
		// *     returns 1: 'Kevin van Zonneveld'
	 
		var tmp_arr = [], i = 0, ac = 0, c1 = 0, c2 = 0, c3 = 0;
		
		str_data += '';
		
		while ( i < str_data.length ) {
			c1 = str_data.charCodeAt(i);
			if (c1 < 128) {
				tmp_arr[ac++] = String.fromCharCode(c1);
				i++;
			} else if ((c1 > 191) && (c1 < 224)) {
				c2 = str_data.charCodeAt(i+1);
				tmp_arr[ac++] = String.fromCharCode(((c1 & 31) << 6) | (c2 & 63));
				i += 2;
			} else {
				c2 = str_data.charCodeAt(i+1);
				c3 = str_data.charCodeAt(i+2);
				tmp_arr[ac++] = String.fromCharCode(((c1 & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
				i += 3;
			}
		}
	 
		return tmp_arr.join('');
	},
	
	md5: function(str) {
		// http://kevin.vanzonneveld.net
		// +   original by: Webtoolkit.info (http://www.webtoolkit.info/)
		// + namespaced by: Michael White (http://getsprink.com)
		// +    tweaked by: Jack
		// +   improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +      input by: Brett Zamir (http://brett-zamir.me)
		// +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// -    depends on: utf8_encode
		// *     example 1: md5('Kevin van Zonneveld');
		// *     returns 1: '6e658d4bfcb59cc13f96c14450ac40b9'
	 
		var xl;
	 
		var rotateLeft = function (lValue, iShiftBits) {
			return (lValue<<iShiftBits) | (lValue>>>(32-iShiftBits));
		};
	 
		var addUnsigned = function (lX,lY) {
			var lX4,lY4,lX8,lY8,lResult;
			lX8 = (lX & 0x80000000);
			lY8 = (lY & 0x80000000);
			lX4 = (lX & 0x40000000);
			lY4 = (lY & 0x40000000);
			lResult = (lX & 0x3FFFFFFF)+(lY & 0x3FFFFFFF);
			if (lX4 & lY4) {
				return (lResult ^ 0x80000000 ^ lX8 ^ lY8);
			}
			if (lX4 | lY4) {
				if (lResult & 0x40000000) {
					return (lResult ^ 0xC0000000 ^ lX8 ^ lY8);
				} else {
					return (lResult ^ 0x40000000 ^ lX8 ^ lY8);
				}
			} else {
				return (lResult ^ lX8 ^ lY8);
			}
		};
	 
		var _F = function (x,y,z) { return (x & y) | ((~x) & z); };
		var _G = function (x,y,z) { return (x & z) | (y & (~z)); };
		var _H = function (x,y,z) { return (x ^ y ^ z); };
		var _I = function (x,y,z) { return (y ^ (x | (~z))); };
	 
		var _FF = function (a,b,c,d,x,s,ac) {
			a = addUnsigned(a, addUnsigned(addUnsigned(_F(b, c, d), x), ac));
			return addUnsigned(rotateLeft(a, s), b);
		};
	 
		var _GG = function (a,b,c,d,x,s,ac) {
			a = addUnsigned(a, addUnsigned(addUnsigned(_G(b, c, d), x), ac));
			return addUnsigned(rotateLeft(a, s), b);
		};
	 
		var _HH = function (a,b,c,d,x,s,ac) {
			a = addUnsigned(a, addUnsigned(addUnsigned(_H(b, c, d), x), ac));
			return addUnsigned(rotateLeft(a, s), b);
		};
	 
		var _II = function (a,b,c,d,x,s,ac) {
			a = addUnsigned(a, addUnsigned(addUnsigned(_I(b, c, d), x), ac));
			return addUnsigned(rotateLeft(a, s), b);
		};
	 
		var convertToWordArray = function (str) {
			var lWordCount;
			var lMessageLength = str.length;
			var lNumberOfWords_temp1=lMessageLength + 8;
			var lNumberOfWords_temp2=(lNumberOfWords_temp1-(lNumberOfWords_temp1 % 64))/64;
			var lNumberOfWords = (lNumberOfWords_temp2+1)*16;
			var lWordArray=new Array(lNumberOfWords-1);
			var lBytePosition = 0;
			var lByteCount = 0;
			while ( lByteCount < lMessageLength ) {
				lWordCount = (lByteCount-(lByteCount % 4))/4;
				lBytePosition = (lByteCount % 4)*8;
				lWordArray[lWordCount] = (lWordArray[lWordCount] | (str.charCodeAt(lByteCount)<<lBytePosition));
				lByteCount++;
			}
			lWordCount = (lByteCount-(lByteCount % 4))/4;
			lBytePosition = (lByteCount % 4)*8;
			lWordArray[lWordCount] = lWordArray[lWordCount] | (0x80<<lBytePosition);
			lWordArray[lNumberOfWords-2] = lMessageLength<<3;
			lWordArray[lNumberOfWords-1] = lMessageLength>>>29;
			return lWordArray;
		};
	 
		var wordToHex = function (lValue) {
			var wordToHexValue="",wordToHexValue_temp="",lByte,lCount;
			for (lCount = 0;lCount<=3;lCount++) {
				lByte = (lValue>>>(lCount*8)) & 255;
				wordToHexValue_temp = "0" + lByte.toString(16);
				wordToHexValue = wordToHexValue + wordToHexValue_temp.substr(wordToHexValue_temp.length-2,2);
			}
			return wordToHexValue;
		};
	 
		var x=[],
			k,AA,BB,CC,DD,a,b,c,d,
			S11=7, S12=12, S13=17, S14=22,
			S21=5, S22=9 , S23=14, S24=20,
			S31=4, S32=11, S33=16, S34=23,
			S41=6, S42=10, S43=15, S44=21;
	 
		str = this.utf8_encode(str);
		x = convertToWordArray(str);
		a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476;
		
		xl = x.length;
		for (k=0;k<xl;k+=16) {
			AA=a; BB=b; CC=c; DD=d;
			a=_FF(a,b,c,d,x[k+0], S11,0xD76AA478);
			d=_FF(d,a,b,c,x[k+1], S12,0xE8C7B756);
			c=_FF(c,d,a,b,x[k+2], S13,0x242070DB);
			b=_FF(b,c,d,a,x[k+3], S14,0xC1BDCEEE);
			a=_FF(a,b,c,d,x[k+4], S11,0xF57C0FAF);
			d=_FF(d,a,b,c,x[k+5], S12,0x4787C62A);
			c=_FF(c,d,a,b,x[k+6], S13,0xA8304613);
			b=_FF(b,c,d,a,x[k+7], S14,0xFD469501);
			a=_FF(a,b,c,d,x[k+8], S11,0x698098D8);
			d=_FF(d,a,b,c,x[k+9], S12,0x8B44F7AF);
			c=_FF(c,d,a,b,x[k+10],S13,0xFFFF5BB1);
			b=_FF(b,c,d,a,x[k+11],S14,0x895CD7BE);
			a=_FF(a,b,c,d,x[k+12],S11,0x6B901122);
			d=_FF(d,a,b,c,x[k+13],S12,0xFD987193);
			c=_FF(c,d,a,b,x[k+14],S13,0xA679438E);
			b=_FF(b,c,d,a,x[k+15],S14,0x49B40821);
			a=_GG(a,b,c,d,x[k+1], S21,0xF61E2562);
			d=_GG(d,a,b,c,x[k+6], S22,0xC040B340);
			c=_GG(c,d,a,b,x[k+11],S23,0x265E5A51);
			b=_GG(b,c,d,a,x[k+0], S24,0xE9B6C7AA);
			a=_GG(a,b,c,d,x[k+5], S21,0xD62F105D);
			d=_GG(d,a,b,c,x[k+10],S22,0x2441453);
			c=_GG(c,d,a,b,x[k+15],S23,0xD8A1E681);
			b=_GG(b,c,d,a,x[k+4], S24,0xE7D3FBC8);
			a=_GG(a,b,c,d,x[k+9], S21,0x21E1CDE6);
			d=_GG(d,a,b,c,x[k+14],S22,0xC33707D6);
			c=_GG(c,d,a,b,x[k+3], S23,0xF4D50D87);
			b=_GG(b,c,d,a,x[k+8], S24,0x455A14ED);
			a=_GG(a,b,c,d,x[k+13],S21,0xA9E3E905);
			d=_GG(d,a,b,c,x[k+2], S22,0xFCEFA3F8);
			c=_GG(c,d,a,b,x[k+7], S23,0x676F02D9);
			b=_GG(b,c,d,a,x[k+12],S24,0x8D2A4C8A);
			a=_HH(a,b,c,d,x[k+5], S31,0xFFFA3942);
			d=_HH(d,a,b,c,x[k+8], S32,0x8771F681);
			c=_HH(c,d,a,b,x[k+11],S33,0x6D9D6122);
			b=_HH(b,c,d,a,x[k+14],S34,0xFDE5380C);
			a=_HH(a,b,c,d,x[k+1], S31,0xA4BEEA44);
			d=_HH(d,a,b,c,x[k+4], S32,0x4BDECFA9);
			c=_HH(c,d,a,b,x[k+7], S33,0xF6BB4B60);
			b=_HH(b,c,d,a,x[k+10],S34,0xBEBFBC70);
			a=_HH(a,b,c,d,x[k+13],S31,0x289B7EC6);
			d=_HH(d,a,b,c,x[k+0], S32,0xEAA127FA);
			c=_HH(c,d,a,b,x[k+3], S33,0xD4EF3085);
			b=_HH(b,c,d,a,x[k+6], S34,0x4881D05);
			a=_HH(a,b,c,d,x[k+9], S31,0xD9D4D039);
			d=_HH(d,a,b,c,x[k+12],S32,0xE6DB99E5);
			c=_HH(c,d,a,b,x[k+15],S33,0x1FA27CF8);
			b=_HH(b,c,d,a,x[k+2], S34,0xC4AC5665);
			a=_II(a,b,c,d,x[k+0], S41,0xF4292244);
			d=_II(d,a,b,c,x[k+7], S42,0x432AFF97);
			c=_II(c,d,a,b,x[k+14],S43,0xAB9423A7);
			b=_II(b,c,d,a,x[k+5], S44,0xFC93A039);
			a=_II(a,b,c,d,x[k+12],S41,0x655B59C3);
			d=_II(d,a,b,c,x[k+3], S42,0x8F0CCC92);
			c=_II(c,d,a,b,x[k+10],S43,0xFFEFF47D);
			b=_II(b,c,d,a,x[k+1], S44,0x85845DD1);
			a=_II(a,b,c,d,x[k+8], S41,0x6FA87E4F);
			d=_II(d,a,b,c,x[k+15],S42,0xFE2CE6E0);
			c=_II(c,d,a,b,x[k+6], S43,0xA3014314);
			b=_II(b,c,d,a,x[k+13],S44,0x4E0811A1);
			a=_II(a,b,c,d,x[k+4], S41,0xF7537E82);
			d=_II(d,a,b,c,x[k+11],S42,0xBD3AF235);
			c=_II(c,d,a,b,x[k+2], S43,0x2AD7D2BB);
			b=_II(b,c,d,a,x[k+9], S44,0xEB86D391);
			a=addUnsigned(a,AA);
			b=addUnsigned(b,BB);
			c=addUnsigned(c,CC);
			d=addUnsigned(d,DD);
		}
	 
		var temp = wordToHex(a)+wordToHex(b)+wordToHex(c)+wordToHex(d);
	 
		return temp.toLowerCase();
	}

});
B81AjaxFrame.implement(new Options);
B81AjaxFrame.implement(new Events);

