text: /* pmxdr: postMessage Cross-Domain Requester
  @version 0.0.6
  @archive http://code.eligrey.com/pmxdr/client/
  @desc Cross-domain HTTP requesting using the postMessage API
  @license GPL v3 and X11/MIT License
  				 http://eligrey.com/about/license/
  @author Elijah Grey, http://eligrey.com
  */
  
  (function() {
  	
  	var window = this;
  
  	if (typeof window.opera != "undefined" && parseInt(window.opera.version()) == 9) // Opera 9.x MessageEvent.origin fix (only for http:, not https:)
  			Event.prototype.__defineGetter__("origin", function(){
  				return "http://" + this.domain;
  			});
  	
  	function pmxdr(host, onload) {
  		var instance = this; // for YUI compressor
  		instance.iFrame	= document.createElement("iframe"); // interface frame
  		instance.iFrame.style.display = "none";
  		instance.origin = host.replace(pmxdr.originRegex, "$1");
  		
  		function onloadHandler() {
  			if (typeof instance.onload == "function")
  				instance.onload();
  		}
  		
  		if (instance.iFrame.addEventListener)
  			instance.iFrame.addEventListener("load", onloadHandler, false);
  		else if (instance.iFrame.attachEvent)
  			instance.iFrame.attachEvent("onload", onloadHandler);
  
  		instance.iFrame.src = instance.origin + "/pmxdr/api";
  		if (typeof onload == "function") {
  			instance.onload = onload;
  			instance.init();
  		}
  	}
  	
  	pmxdr.originRegex = /^([\w-]+:\/*\[?[\w\.:-]+\]?(?::\d+)?).*/; // RegExp.$1 = protocol+host+port (the square brackets are for ipv6)
  	pmxdr.request = function(req) {
  		if (typeof req == "string")
  			return pmxdr.request({uri: req});
  		else if (Object.prototype.toString.call(req) == "[object Array]") { // handle array of requests
  			var requests = [];
  			for (var i=0; i<req.length; i++)
  				requests.push(pmxdr.request(req[i]));
  			return requests;
  		}
  		
  		var pmxdrInstance = new pmxdr(req.uri),
  		callback = req.callback;
  		req.id = pmxdr.getSafeID();
  		
  		req.callback = function(response) {
  			if (typeof callback == "function") callback.call(this, response);
  			this.unload();
  		}
  		
  		pmxdrInstance.onload = function() {
  			this.request(req);
  		}
  
  		pmxdrInstance.init()
  		return {
  			abort: function() {
  				pmxdr.requests.aborted[req.id] = true;
  			}
  		}
  	}
  	// parent for interface frames
  	pmxdr.interfaceFrameParent = document.documentElement||document.getElementsByTagName("head")[0]||document.body||document.getElementsByTagName("body")[0];
  		
  	pmxdr.getSafeID = function() { // generate a random key that doesn't collide with any existing keys
  				var randID = Math.random().toString().substr(2); // Generate a random number, make it a string, and cut off the "0." to make it look nice
  				if (typeof pmxdr.requests[randID] == "undefined") return randID; // key doesn't collide
  				else return safeRandID();
  	}
  	pmxdr.prototype = {
  	
  		init: function(onload) { // load or reload iframe
  			if (typeof onload == "function")
  				this.onload = onload;
  			if (this.iFrame.parentNode) this.unload(); // in case init is being called to re-init
  			pmxdr.interfaceFrameParent.appendChild(this.iFrame);
  		},
  		
  		unload: function() { // remove iframe
  			pmxdr.interfaceFrameParent.removeChild(this.iFrame);
  		},
  		
  		defaultRequestMethod: "GET", // default request method
  		//defaultContentType: "application/x-www-form-urlencoded", default content-type header (ie. POST requests, ect.)
  		//defaultTimeout: 60000, // optional default timeout at which the request recives a TIMEOUT error (60000 ms = 1 minute)
  		
  		request: function(req) { // send a request to a pmxdr host
  			var requests = [], instance = this;
  			
  			if (Object.prototype.toString.call(req) == "[object Array]") { // handle array of requests
  				for (var i=0; i<req.length; i++)
  					requests.push(instance.request(req[i]));
  				return requests;
  			}
  			var
  			id          = (pmxdr.requests[req.id] ? false : req.id) || pmxdr.getSafeID(),
  			method      = req.method      || instance.defaultRequestMethod,
  			timeout     = req.timeout     || instance.defaultTimeout,
  			contentType = req.contentType || instance.defaultContentType;
  			
  			method = method.toUpperCase();
  			
  			pmxdr.requests[id] = {
  				origin: instance.origin,
  				remove: function() {
  					delete pmxdr.requests[id];
  				},
  				callback: function(response) {
  					if (typeof req.callback == "function") req.callback.call(instance, response);
  					pmxdr.requests[id].remove();
  				}
  			};
  	
  			function timeoutCallback() { // give callback a TIMEOUT error
  				if (pmxdr.requests[id] && pmxdr.requests[id].callback)
  					pmxdr.requests[id].callback({
  						pmxdr	: true,
  						id		 : id,
  						error	: "TIMEOUT"
  					})
  			};
  			
  			if (contentType) {
  				if (!req.headers)
  					req.headers = {};
  				req.headers["Content-Type"] = contentType.toString();
  			}
  			
  			instance.iFrame.contentWindow.postMessage(JSON.stringify({
  				pmxdr   : true,
  				method  : method,
  				uri     : req.uri,
  				data    : req.data,
  				headers : req.headers,
  				id      : id
  			}), instance.origin);
  			if (timeout) setTimeout(timeoutCallback, timeout)
  	
  			return {
  				abort: pmxdr.requests[id].remove
  			};
  		}
  	}
  
  	pmxdr.requests = { // requests cache
  		aborted : {},
  		clear   : function() {
  			pmxdr.requests = {
  				aborted : {},
  				clear   : this.clear
  			};
  		},
  	};
  
  	function pmxdrResponseHandler(evt) {
  		var data = JSON.parse(evt.data);
  		if (data.pmxdr == true) { // only handle pmxdr requests
  			if (
  				pmxdr.requests[data.id]
  				&& pmxdr.requests[data.id].origin == evt.origin
  				&& typeof pmxdr.requests[data.id].callback == "function"
  				&& !pmxdr.requests.aborted[data.id]
  			) pmxdr.requests[data.id].callback(data);
  			else if (pmxdr.requests.aborted[data.id]) {
  				delete pmxdr.requests.aborted[data.id];
  				if (data.id in pmxdr.requests)
  					delete pmxdr.requests[data.id];
  			}
  		}
  	}
  
  	if (window.addEventListener) window.addEventListener("message", pmxdrResponseHandler, false);
  	else if (window.attachEvent) window.attachEvent("onmessage", pmxdrResponseHandler);
  
  	pmxdr.destruct = function() {
  		if (window.removeEventListener)
  			window.removeEventListener("message", pmxdrResponseHandler, false);
  		else if (window.detachEvent)
  			window.detachEvent("onmessage", pmxdrResponseHandler);
  		
  		delete window.pmxdr;
  		delete pmxdrResponseHandler;
  	}
  
  	window.pmxdr = pmxdr;
  })();
  
  
  /* the following code block is the json2.js JSON API for if the browser does not natively support it
  	 This code block may look suspicious to you. That's because it's minified and packed.
  	 If you don't trust this code block, replace this block with your own minified http://www.json.org/json2.js
  */
  if (!this.JSON)
  	JSON = {};
  
  if (this.JSON && (!JSON.stringify || !JSON.parse))
  	eval(function(p,a,c,k,e,r){e=function(c){return(c<62?'':e(parseInt(c/62)))+((c=c%62)<36?c.toString(36):String.fromCharCode(c+29))};if('0'.replace(0,e)==0){while(c--)r[e(c)]=k[c];k=[function(e){return r[e]||e}];e=function(){return'\\w{1,2}'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('(3(){3 f(n){6 n<10?"0"+n:n}2(5 1b.w.7!=="3"){1b.w.7=3(a){6 8.getUTCFullYear()+"-"+f(8.getUTCMonth()+1)+"-"+f(8.getUTCDate())+"T"+f(8.getUTCHours())+":"+f(8.getUTCMinutes())+":"+f(8.getUTCSeconds())+"Z"};O.w.7=Number.w.7=Boolean.w.7=3(a){6 8.valueOf()}}y g=/[\\u0000\\R\\Q-\\1i\\1f\\1e\\1c\\1a-\\19\\18-\\17\\15-\\14\\13\\12-\\11]/g,h=/[\\\\\\"\\x00-\\x1f\\x7f-\\x9f\\R\\Q-\\1i\\1f\\1e\\1c\\1a-\\19\\18-\\17\\15-\\14\\13\\12-\\11]/g,l,m,o={"\\b":"\\\\b","\\t":"\\\\t","\\n":"\\\\n","\\f":"\\\\f","\\r":"\\\\r",\'"\':\'\\\\"\',"\\\\":"\\\\\\\\"},p;3 q(b){h.S=0;6 h.I(b)?\'"\'+b.z(h,3(a){y c=o[a];6 5 c==="G"?c:"\\\\u"+("1h"+a.1g(0).P(16)).1d(-4)})+\'"\':\'"\'+b+\'"\'}3 r(a,b){y i,k,v,c,d=l,e,f=b[a];2(f&&5 f==="x"&&5 f.7==="3"){f=f.7(a)}2(5 p==="3"){f=p.H(b,a,f)}switch(5 f){D"G":6 q(f);D"N":6 isFinite(f)?O(f):"C";D"boolean":D"C":6 O(f);D"x":2(!f){6"C"}l+=m;e=[];2(M.w.P.apply(f)==="[x Array]"){c=f.B;A(i=0;i<c;i+=1){e[i]=r(i,f)||"C"}v=e.B===0?"[]":l?"[\\n"+l+e.E(",\\n"+l)+"\\n"+d+"]":"["+e.E(",")+"]";l=d;6 v}2(p&&5 p==="x"){c=p.B;A(i=0;i<c;i+=1){k=p[i];2(5 k==="G"){v=r(k,f);2(v){e.Y(q(k)+(l?": ":":")+v)}}}}J{A(k X f){2(M.W.H(f,k)){v=r(k,f);2(v){e.Y(q(k)+(l?": ":":")+v)}}}}v=e.B===0?"{}":l?"{\\n"+l+e.E(",\\n"+l)+"\\n"+d+"}":"{"+e.E(",")+"}";l=d;6 v}}2(5 9.K!=="3"){9.K=3(a,b,c){y i;l="";m="";2(5 c==="N"){A(i=0;i<c;i+=1){m+=" "}}J{2(5 c==="G"){m=c}}p=b;2(b&&5 b!=="3"&&(5 b!=="x"||5 b.B!=="N")){V U Error("9.K")}6 r("",{"":a})}}2(5 9.L!=="3"){9.L=3(d,e){y j;3 f(a,b){y k,v,c=a[b];2(c&&5 c==="x"){A(k X c){2(M.W.H(c,k)){v=f(c,k);2(v!==undefined){c[k]=v}J{delete c[k]}}}}6 e.H(a,b,c)}g.S=0;2(g.I(d)){d=d.z(g,3(a){6"\\\\u"+("1h"+a.1g(0).P(16)).1d(-4)})}2(/^[\\],:{}\\s]*$/.I(d.z(/\\\\(?:["\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").z(/"[^"\\\\\\n\\r]*"|true|false|C|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g,"]").z(/(?:^|:|,)(?:\\s*\\[)+/g,""))){j=eval("("+d+")");6 5 e==="3"?f({"":j},""):j}V U SyntaxError("9.L")}}})();',[],81,'||if|function||typeof|return|toJSON|this|JSON|||||||||||||||||||||||prototype|object|var|replace|for|length|null|case|join||string|call|test|else|stringify|parse|Object|number|String|toString|u0600|u00ad|lastIndex||new|throw|hasOwnProperty|in|push|||uffff|ufff0|ufeff|u206f|u2060||u202f|u2028|u200f|u200c|Date|u17b5|slice|u17b4|u070f|charCodeAt|0000|u0604'.split('|'),0,{}));
  