couchdb-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From j..@apache.org
Subject [4/19] git commit: Import browser-request v0.2.1
Date Mon, 11 Feb 2013 13:51:16 GMT
Import browser-request v0.2.1


Project: http://git-wip-us.apache.org/repos/asf/couchdb/repo
Commit: http://git-wip-us.apache.org/repos/asf/couchdb/commit/5ad24876
Tree: http://git-wip-us.apache.org/repos/asf/couchdb/tree/5ad24876
Diff: http://git-wip-us.apache.org/repos/asf/couchdb/diff/5ad24876

Branch: refs/heads/nodejs_couchdb
Commit: 5ad2487692932dd67fd3e0033225cddfd5d2fa71
Parents: 63c59c7
Author: Jason Smith (work) <jhs@iriscouch.com>
Authored: Thu Feb 7 07:12:47 2013 +0000
Committer: Jason Smith (work) <jhs@iriscouch.com>
Committed: Thu Feb 7 07:33:46 2013 +0000

----------------------------------------------------------------------
 share/www/script/request-min.js |   32 ++
 share/www/script/request.js     |  943 ++++++++++++++++++++++++++++++++++
 2 files changed, 975 insertions(+), 0 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/couchdb/blob/5ad24876/share/www/script/request-min.js
----------------------------------------------------------------------
diff --git a/share/www/script/request-min.js b/share/www/script/request-min.js
new file mode 100644
index 0000000..b18c2aa
--- /dev/null
+++ b/share/www/script/request-min.js
@@ -0,0 +1,32 @@
+/**
+* XMLHttpRequest.js Copyright (C) 2011 Sergey Ilinsky (http://www.ilinsky.com)
+*
+* This work is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2.1 of the License, or
+* (at your option) any later version.
+*
+* This work is distributed in the hope that it will be useful,
+* but without any warranty; without even the implied warranty of
+* merchantability or fitness for a particular purpose. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this library; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+// Browser-Request
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy of
+// the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations under
+// the License.
+(function(){function e(){this._object=a&&!d?new a:new window.ActiveXObject("Microsoft.XMLHTTP"),this._listeners=[]}function
f(){return new e}function g(a){a._object.send(a._data);if(b&&!a._async){a.readyState=f.OPENED,j(a);while(a.readyState<f.DONE){a.readyState++,h(a);if(a._aborted)return}}}function
h(a){f.onreadystatechange&&f.onreadystatechange.apply(a),a.dispatchEvent({type:"readystatechange",bubbles:!1,cancelable:!1,timeStamp:new
Date+0})}function i(a){var b=a.responseXML,d=a.responseText;c&&d&&b&&!b.documentElement&&a.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)&&(b=new
window.ActiveXObject("Microsoft.XMLDOM"),b.async=!1,b.validateOnParse=!1,b.loadXML(d));if(b)if(c&&b.parseError!==0||!b.documentElement||b.documentElement&&b.documentElement.tagName=="parsererror")return
null;return b}function j(a){try{a.responseText=a._object.responseText}catch(b){}try{a.responseXML=i(a._object)}catch(b){}try{a.status=a._object.status}catch(b){}try{a.statusText=a._object.statu
 sText}catch(b){}}function k(a){a._object.onreadystatechange=new window.Function}var a=window.XMLHttpRequest,b=!!window.controllers,c=!!window.document.namespaces,d=c&&window.navigator.userAgent.match(/MSIE
7.0/);f.prototype=e.prototype,b&&a.wrapped&&(f.wrapped=a.wrapped),f.UNSENT=0,f.OPENED=1,f.HEADERS_RECEIVED=2,f.LOADING=3,f.DONE=4,f.prototype.UNSENT=f.UNSENT,f.prototype.OPENED=f.OPENED,f.prototype.HEADERS_RECEIVED=f.HEADERS_RECEIVED,f.prototype.LOADING=f.LOADING,f.prototype.DONE=f.DONE,f.prototype.readyState=f.UNSENT,f.prototype.responseText="",f.prototype.responseXML=null,f.prototype.status=0,f.prototype.statusText="",f.prototype.priority="NORMAL",f.prototype.onreadystatechange=null,f.onreadystatechange=null,f.onopen=null,f.onsend=null,f.onabort=null,f.prototype.open=function(a,d,e,g,i){var
l=a.toLowerCase();if(l=="connect"||l=="trace"||l=="track")throw new Error(18);delete this._headers,arguments.length<3&&(e=!0),this._async=e;var
m=this,n=this.readyState,o=null;c&&e&&(o=functi
 on(){n!=f.DONE&&(k(m),m.abort())},window.attachEvent("onunload",o)),f.onopen&&f.onopen.apply(this,arguments),arguments.length>4?this._object.open(a,d,e,g,i):arguments.length>3?this._object.open(a,d,e,g):this._object.open(a,d,e),this.readyState=f.OPENED,h(this),this._object.onreadystatechange=function(){if(b&&!e)return;m.readyState=m._object.readyState,j(m);if(m._aborted){m.readyState=f.UNSENT;return}m.readyState==f.DONE&&(delete
m._data,k(m),c&&e&&window.detachEvent("onunload",o),n!=m.readyState&&h(m),n=m.readyState)}},f.prototype.send=function(a){f.onsend&&f.onsend.apply(this,arguments),arguments.length||(a=null),a&&a.nodeType&&(a=window.XMLSerializer?(new
window.XMLSerializer).serializeToString(a):a.xml,this._headers["Content-Type"]||this._object.setRequestHeader("Content-Type","application/xml")),this._data=a,g(this)},f.prototype.abort=function(){f.onabort&&f.onabort.apply(this,arguments),this.readyState>f.UNSENT&&(this._aborted=!0),this._object.abort(),k(this),this.readyState=f.
 UNSENT,delete this._data},f.prototype.getAllResponseHeaders=function(){return this._object.getAllResponseHeaders()},f.prototype.getResponseHeader=function(a){return
this._object.getResponseHeader(a)},f.prototype.setRequestHeader=function(a,b){return this._headers||(this._headers={}),this._headers[a]=b,this._object.setRequestHeader(a,b)},f.prototype.addEventListener=function(a,b,c){for(var
d=0,e;e=this._listeners[d];d++)if(e[0]==a&&e[1]==b&&e[2]==c)return;this._listeners.push([a,b,c])},f.prototype.removeEventListener=function(a,b,c){for(var
d=0,e;e=this._listeners[d];d++)if(e[0]==a&&e[1]==b&&e[2]==c)break;e&&this._listeners.splice(d,1)},f.prototype.dispatchEvent=function(a){var
b={type:a.type,target:this,currentTarget:this,eventPhase:2,bubbles:a.bubbles,cancelable:a.cancelable,timeStamp:a.timeStamp,stopPropagation:function(){},preventDefault:function(){},initEvent:function(){}};b.type=="readystatechange"&&this.onreadystatechange&&(this.onreadystatechange.handleEvent||this.onreadystat
 echange).apply(this,[b]);for(var c=0,d;d=this._listeners[c];c++)d[0]==b.type&&!d[2]&&(d[1].handleEvent||d[1]).apply(this,[b])},f.prototype.toString=function(){return"[object
XMLHttpRequest]"},f.toString=function(){return"[XMLHttpRequest]"},window.Function.prototype.apply||(window.Function.prototype.apply=function(a,b){b||(b=[]),a.__func=this,a.__func(b[0],b[1],b[2],b[3],b[4]),delete
a.__func}),window.XMLHttpRequest=f})(),!function(){function a(a){if(a==="./xmlhttprequest")return
window&&{XMLHttpRequest:window.XMLHttpRequest};throw new Error("require() unsupported
in the browser build. Use RequireJS or Ender.")}function d(){function f(a,b){if(typeof b!="function")throw
new Error("Bad callback given: "+b);if(!a)throw new Error("No options given");var c=a.onResponse;typeof
a=="string"?a={uri:a}:a=JSON.parse(JSON.stringify(a)),a.onResponse=c,a.url&&(a.uri=a.url,delete
a.url);if(!a.uri&&a.uri!=="")throw new Error("options.uri is a required argument");if(typeof
a.uri!="string")throw new E
 rror("options.uri must be a string");var d=["proxy","_redirectsFollowed","maxRedirects","followRedirect"];for(var
e=0;e<d.length;e++)if(a[d[e]])throw new Error("options."+d[e]+" is not supported");a.callback=b,a.method=a.method||"GET",a.headers=a.headers||{},a.body=a.body||null,a.timeout=a.timeout||f.DEFAULT_TIMEOUT;if(a.headers.host)throw
new Error("Options.headers.host is not supported");return a.json&&(a.headers.accept=a.headers.accept||"application/json",a.method!=="GET"&&(a.headers["content-type"]="application/json"),typeof
a.json!="boolean"?a.body=JSON.stringify(a.json):typeof a.body!="string"&&(a.body=JSON.stringify(a.body))),a.onResponse=a.onResponse||j,a.onResponse===!0&&(a.onResponse=b,a.callback=j),!a.headers.authorization&&a.auth&&(a.headers.authorization="Basic
"+n(a.auth.username+":"+a.auth.password)),h(a)}function h(a){function j(){c=!0;var d=new Error("ETIMEDOUT");return
d.code="ETIMEDOUT",d.duration=a.timeout,f.log.error("Timeout",{id:b._id,milliseconds:a.timeout}),
 a.callback(d,b)}function l(e){if(c)return f.log.debug("Ignoring timed out state change",{state:b.readyState,id:b.id});f.log.debug("State
change",{state:b.readyState,id:b.id,timed_out:c});if(b.readyState===d.OPENED){f.log.debug("Request
started",{id:b.id});for(var g in a.headers)b.setRequestHeader(g,a.headers[g])}else b.readyState===d.HEADERS_RECEIVED?n():b.readyState===d.LOADING?(n(),o()):b.readyState===d.DONE&&(n(),o(),p())}function
n(){if(k.response)return;k.response=!0,f.log.debug("Got response",{id:b.id,status:b.status}),clearTimeout(b.timeoutTimer),b.statusCode=b.status;if(e&&b.statusCode==0){var
c=new Error("CORS request rejected: "+a.uri);return c.cors="rejected",k.loading=!0,k.end=!0,a.callback(c,b)}a.onResponse(null,b)}function
o(){if(k.loading)return;k.loading=!0,f.log.debug("Response body loading",{id:b.id})}function
p(){if(k.end)return;k.end=!0,f.log.debug("Request done",{id:b.id}),b.body=b.responseText;if(a.json)try{b.body=JSON.parse(b.responseText)}catch(c){return
a.ca
 llback(c,b)}a.callback(null,b,b.body)}var b=new d,c=!1,e=m(a.uri),h="withCredentials"in b._object;g+=1,b.seq_id=g,b.id=g+":
"+a.method+" "+a.uri,b._id=b.id;if(e&&!h){var i=new Error("Browser does not support
cross-origin request: "+a.uri);return i.cors="unsupported",a.callback(i,b)}b.timeoutTimer=setTimeout(j,a.timeout);var
k={response:!1,loading:!1,end:!1};return b.onreadystatechange=l,b.open(a.method,a.uri,!0),e&&(b._object.withCredentials=!!a.withCredentials),b.send(a.body),b}function
j(){}function k(){var a={},b=["trace","debug","info","warn","error"],c,d;for(d=0;d<b.length;d++)c=b[d],a[c]=j,typeof
console!="undefined"&&console&&console[c]&&(a[c]=l(console,c));return
a}function l(a,b){function c(c,d){return typeof d=="object"&&(c+=" "+JSON.stringify(d)),a[b].call(a,c)}return
c}function m(a){var b=/^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,c;try{c=location.href}catch(d){c=document.createElement("a"),c.href="",c=c.href}var
e=b.exec(c.toLowerCase())||[],f=b.exec(a.toLowerCase
 ()),g=!(!f||f[1]==e[1]&&f[2]==e[2]&&(f[3]||(f[1]==="http:"?80:443))==(e[3]||(e[1]==="http:"?80:443)));return
g}function n(a){var b="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",c,d,e,f,g,h,i,j,k=0,l=0,m="",n=[];if(!a)return
a;do c=a.charCodeAt(k++),d=a.charCodeAt(k++),e=a.charCodeAt(k++),j=c<<16|d<<8|e,f=j>>18&63,g=j>>12&63,h=j>>6&63,i=j&63,n[l++]=b.charAt(f)+b.charAt(g)+b.charAt(h)+b.charAt(i);while(k<a.length);m=n.join("");switch(a.length%3){case
1:m=m.slice(0,-2)+"==";break;case 2:m=m.slice(0,-1)+"="}return m}var b=a("./xmlhttprequest");if(!b||typeof
b!="object")throw new Error("Could not find ./xmlhttprequest");var d=b.XMLHttpRequest;if(!d)throw
new Error("Bad xmlhttprequest.XMLHttpRequest");if(!("_object"in new d))throw new Error("This
is not portable XMLHttpRequest");c.exports=f,f.XMLHttpRequest=d,f.log=k();var e=18e4,g=0;f.withCredentials=!1,f.DEFAULT_TIMEOUT=e;var
i=["get","put","post","head"];i.forEach(function(a){var b=a.toUpperCase(),c=a.toLowerCase(
 );f[c]=function(a){typeof a=="string"?a={method:b,uri:a}:(a=JSON.parse(JSON.stringify(a)),a.method=b);var
c=[a].concat(Array.prototype.slice.apply(arguments,[1]));return f.apply(this,c)}}),f.couch=function(a,b){function
d(a,c,d){if(a)return b(a,c,d);if((c.statusCode<200||c.statusCode>299)&&d.error){a=new
Error("CouchDB error: "+(d.error.reason||d.error.error));for(var e in d)a[e]=d[e];return b(a,c,d)}return
b(a,c,d)}typeof a=="string"&&(a={uri:a}),a.json=!0,a.body&&(a.json=a.body),delete
a.body,b=b||j;var c=f(a,d);return c}}var b={},c={exports:b};typeof window=="undefined"&&(typeof
console!="undefined"&&console&&console.error&&console.error('Cannot
find global "window" object. Is this a browser?'),window={}),d(),window.request=c.exports}();

http://git-wip-us.apache.org/repos/asf/couchdb/blob/5ad24876/share/www/script/request.js
----------------------------------------------------------------------
diff --git a/share/www/script/request.js b/share/www/script/request.js
new file mode 100644
index 0000000..2ba6585
--- /dev/null
+++ b/share/www/script/request.js
@@ -0,0 +1,943 @@
+/**
+* XMLHttpRequest.js Copyright (C) 2011 Sergey Ilinsky (http://www.ilinsky.com)
+*
+* This work is free software; you can redistribute it and/or modify
+* it under the terms of the GNU Lesser General Public License as published by
+* the Free Software Foundation; either version 2.1 of the License, or
+* (at your option) any later version.
+*
+* This work is distributed in the hope that it will be useful,
+* but without any warranty; without even the implied warranty of
+* merchantability or fitness for a particular purpose. See the
+* GNU Lesser General Public License for more details.
+*
+* You should have received a copy of the GNU Lesser General Public License
+* along with this library; if not, write to the Free Software Foundation, Inc.,
+* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+(function () {
+
+	// Save reference to earlier defined object implementation (if any)
+	var oXMLHttpRequest = window.XMLHttpRequest;
+
+	// Define on browser type
+	var bGecko  = !!window.controllers;
+	var bIE     = !!window.document.namespaces;
+	var bIE7    = bIE && window.navigator.userAgent.match(/MSIE 7.0/);
+
+	// Enables "XMLHttpRequest()" call next to "new XMLHttpRequest()"
+	function fXMLHttpRequest() {
+		this._object  = oXMLHttpRequest && !bIE7 ? new oXMLHttpRequest : new window.ActiveXObject("Microsoft.XMLHTTP");
+		this._listeners = [];
+	}
+
+	// Constructor
+	function cXMLHttpRequest() {
+		return new fXMLHttpRequest;
+	}
+	cXMLHttpRequest.prototype = fXMLHttpRequest.prototype;
+
+	// BUGFIX: Firefox with Firebug installed would break pages if not executed
+	if (bGecko && oXMLHttpRequest.wrapped) {
+		cXMLHttpRequest.wrapped = oXMLHttpRequest.wrapped;
+	}
+
+	// Constants
+	cXMLHttpRequest.UNSENT            = 0;
+	cXMLHttpRequest.OPENED            = 1;
+	cXMLHttpRequest.HEADERS_RECEIVED  = 2;
+	cXMLHttpRequest.LOADING           = 3;
+	cXMLHttpRequest.DONE              = 4;
+
+	// Interface level constants
+	cXMLHttpRequest.prototype.UNSENT            = cXMLHttpRequest.UNSENT;
+	cXMLHttpRequest.prototype.OPENED            = cXMLHttpRequest.OPENED;
+	cXMLHttpRequest.prototype.HEADERS_RECEIVED  = cXMLHttpRequest.HEADERS_RECEIVED;
+	cXMLHttpRequest.prototype.LOADING           = cXMLHttpRequest.LOADING;
+	cXMLHttpRequest.prototype.DONE              = cXMLHttpRequest.DONE;
+
+	// Public Properties
+	cXMLHttpRequest.prototype.readyState    = cXMLHttpRequest.UNSENT;
+	cXMLHttpRequest.prototype.responseText  = '';
+	cXMLHttpRequest.prototype.responseXML   = null;
+	cXMLHttpRequest.prototype.status        = 0;
+	cXMLHttpRequest.prototype.statusText    = '';
+
+	// Priority proposal
+	cXMLHttpRequest.prototype.priority    = "NORMAL";
+
+	// Instance-level Events Handlers
+	cXMLHttpRequest.prototype.onreadystatechange  = null;
+
+	// Class-level Events Handlers
+	cXMLHttpRequest.onreadystatechange  = null;
+	cXMLHttpRequest.onopen              = null;
+	cXMLHttpRequest.onsend              = null;
+	cXMLHttpRequest.onabort             = null;
+
+	// Public Methods
+	cXMLHttpRequest.prototype.open  = function(sMethod, sUrl, bAsync, sUser, sPassword) {
+		// http://www.w3.org/TR/XMLHttpRequest/#the-open-method
+		var sLowerCaseMethod = sMethod.toLowerCase();
+		if (sLowerCaseMethod == "connect" || sLowerCaseMethod == "trace" || sLowerCaseMethod ==
"track") {
+			// Using a generic error and an int - not too sure all browsers support correctly
+			// http://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#securityerror, so, this is
safer
+			// XXX should do better than that, but this is OT to XHR.
+			throw new Error(18);
+		}
+
+		// Delete headers, required when object is reused
+		delete this._headers;
+
+		// When bAsync parameter value is omitted, use true as default
+		if (arguments.length < 3) {
+			bAsync  = true;
+		}
+
+		// Save async parameter for fixing Gecko bug with missing readystatechange in synchronous
requests
+		this._async   = bAsync;
+
+		// Set the onreadystatechange handler
+		var oRequest  = this;
+		var nState    = this.readyState;
+		var fOnUnload = null;
+
+		// BUGFIX: IE - memory leak on page unload (inter-page leak)
+		if (bIE && bAsync) {
+			fOnUnload = function() {
+				if (nState != cXMLHttpRequest.DONE) {
+					fCleanTransport(oRequest);
+					// Safe to abort here since onreadystatechange handler removed
+					oRequest.abort();
+				}
+			};
+			window.attachEvent("onunload", fOnUnload);
+		}
+
+		// Add method sniffer
+		if (cXMLHttpRequest.onopen) {
+			cXMLHttpRequest.onopen.apply(this, arguments);
+		}
+
+		if (arguments.length > 4) {
+			this._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
+		} else if (arguments.length > 3) {
+			this._object.open(sMethod, sUrl, bAsync, sUser);
+		} else {
+			this._object.open(sMethod, sUrl, bAsync);
+		}
+
+		this.readyState = cXMLHttpRequest.OPENED;
+		fReadyStateChange(this);
+
+		this._object.onreadystatechange = function() {
+			if (bGecko && !bAsync) {
+				return;
+			}
+
+			// Synchronize state
+			oRequest.readyState   = oRequest._object.readyState;
+			fSynchronizeValues(oRequest);
+
+			// BUGFIX: Firefox fires unnecessary DONE when aborting
+			if (oRequest._aborted) {
+				// Reset readyState to UNSENT
+				oRequest.readyState = cXMLHttpRequest.UNSENT;
+
+				// Return now
+				return;
+			}
+
+			if (oRequest.readyState == cXMLHttpRequest.DONE) {
+				// Free up queue
+				delete oRequest._data;
+
+				// Uncomment these lines for bAsync
+				/**
+				 * if (bAsync) {
+				 * 	fQueue_remove(oRequest);
+				 * }
+				 */
+
+				fCleanTransport(oRequest);
+
+				// Uncomment this block if you need a fix for IE cache
+				/**
+				 * // BUGFIX: IE - cache issue
+				 * if (!oRequest._object.getResponseHeader("Date")) {
+				 * 	// Save object to cache
+				 * 	oRequest._cached  = oRequest._object;
+				 *
+				 * 	// Instantiate a new transport object
+				 * 	cXMLHttpRequest.call(oRequest);
+				 *
+				 * 	// Re-send request
+				 * 	if (sUser) {
+				 * 		if (sPassword) {
+				 * 			oRequest._object.open(sMethod, sUrl, bAsync, sUser, sPassword);
+				 * 		} else {
+				 * 			oRequest._object.open(sMethod, sUrl, bAsync);
+				 * 		}
+				 *
+				 * 		oRequest._object.setRequestHeader("If-Modified-Since", oRequest._cached.getResponseHeader("Last-Modified")
|| new window.Date(0));
+				 * 		// Copy headers set
+				 * 		if (oRequest._headers) {
+				 * 			for (var sHeader in oRequest._headers) {
+				 * 				// Some frameworks prototype objects with functions
+				 * 				if (typeof oRequest._headers[sHeader] == "string") {
+				 * 					oRequest._object.setRequestHeader(sHeader, oRequest._headers[sHeader]);
+				 * 				}
+				 * 			}
+				 * 		}
+				 * 		oRequest._object.onreadystatechange = function() {
+				 * 			// Synchronize state
+				 * 			oRequest.readyState   = oRequest._object.readyState;
+				 *
+				 * 			if (oRequest._aborted) {
+				 * 				//
+				 * 				oRequest.readyState = cXMLHttpRequest.UNSENT;
+				 *
+				 * 				// Return
+				 * 				return;
+				 * 			}
+				 *
+				 * 			if (oRequest.readyState == cXMLHttpRequest.DONE) {
+				 * 				// Clean Object
+				 * 				fCleanTransport(oRequest);
+				 *
+				 * 				// get cached request
+				 * 				if (oRequest.status == 304) {
+				 * 					oRequest._object  = oRequest._cached;
+				 * 				}
+				 *
+				 * 				//
+				 * 				delete oRequest._cached;
+				 *
+				 * 				//
+				 * 				fSynchronizeValues(oRequest);
+				 *
+				 * 				//
+				 * 				fReadyStateChange(oRequest);
+				 *
+				 * 				// BUGFIX: IE - memory leak in interrupted
+				 * 				if (bIE && bAsync) {
+				 * 					window.detachEvent("onunload", fOnUnload);
+				 * 				}
+				 *
+				 * 			}
+				 * 		};
+				 * 		oRequest._object.send(null);
+				 *
+				 * 		// Return now - wait until re-sent request is finished
+				 * 		return;
+				 * 	};
+				 */
+
+				// BUGFIX: IE - memory leak in interrupted
+				if (bIE && bAsync) {
+					window.detachEvent("onunload", fOnUnload);
+				}
+
+				// BUGFIX: Some browsers (Internet Explorer, Gecko) fire OPEN readystate twice
+				if (nState != oRequest.readyState) {
+					fReadyStateChange(oRequest);
+				}
+
+				nState  = oRequest.readyState;
+			}
+		};
+	};
+
+	cXMLHttpRequest.prototype.send = function(vData) {
+		// Add method sniffer
+		if (cXMLHttpRequest.onsend) {
+			cXMLHttpRequest.onsend.apply(this, arguments);
+		}
+
+		if (!arguments.length) {
+			vData = null;
+		}
+
+		// BUGFIX: Safari - fails sending documents created/modified dynamically, so an explicit
serialization required
+		// BUGFIX: IE - rewrites any custom mime-type to "text/xml" in case an XMLNode is sent
+		// BUGFIX: Gecko - fails sending Element (this is up to the implementation either to standard)
+		if (vData && vData.nodeType) {
+			vData = window.XMLSerializer ? new window.XMLSerializer().serializeToString(vData) : vData.xml;
+			if (!this._headers["Content-Type"]) {
+				this._object.setRequestHeader("Content-Type", "application/xml");
+			}
+		}
+
+		this._data = vData;
+
+		/**
+		 * // Add to queue
+		 * if (this._async) {
+		 * 	fQueue_add(this);
+		 * } else { */
+		fXMLHttpRequest_send(this);
+		 /**
+		 * }
+		 */
+	};
+
+	cXMLHttpRequest.prototype.abort = function() {
+		// Add method sniffer
+		if (cXMLHttpRequest.onabort) {
+			cXMLHttpRequest.onabort.apply(this, arguments);
+		}
+
+		// BUGFIX: Gecko - unnecessary DONE when aborting
+		if (this.readyState > cXMLHttpRequest.UNSENT) {
+			this._aborted = true;
+		}
+
+		this._object.abort();
+
+		// BUGFIX: IE - memory leak
+		fCleanTransport(this);
+
+		this.readyState = cXMLHttpRequest.UNSENT;
+
+		delete this._data;
+
+		/* if (this._async) {
+	 	* 	fQueue_remove(this);
+	 	* }
+	 	*/
+	};
+
+	cXMLHttpRequest.prototype.getAllResponseHeaders = function() {
+		return this._object.getAllResponseHeaders();
+	};
+
+	cXMLHttpRequest.prototype.getResponseHeader = function(sName) {
+		return this._object.getResponseHeader(sName);
+	};
+
+	cXMLHttpRequest.prototype.setRequestHeader  = function(sName, sValue) {
+		// BUGFIX: IE - cache issue
+		if (!this._headers) {
+			this._headers = {};
+		}
+
+		this._headers[sName]  = sValue;
+
+		return this._object.setRequestHeader(sName, sValue);
+	};
+
+	// EventTarget interface implementation
+	cXMLHttpRequest.prototype.addEventListener  = function(sName, fHandler, bUseCapture) {
+		for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) {
+			if (oListener[0] == sName && oListener[1] == fHandler && oListener[2]
== bUseCapture) {
+				return;
+			}
+		}
+
+		// Add listener
+		this._listeners.push([sName, fHandler, bUseCapture]);
+	};
+
+	cXMLHttpRequest.prototype.removeEventListener = function(sName, fHandler, bUseCapture) {
+		for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) {
+			if (oListener[0] == sName && oListener[1] == fHandler && oListener[2]
== bUseCapture) {
+				break;
+			}
+		}
+
+		// Remove listener
+		if (oListener) {
+			this._listeners.splice(nIndex, 1);
+		}
+	};
+
+	cXMLHttpRequest.prototype.dispatchEvent = function(oEvent) {
+		var oEventPseudo  = {
+			'type':             oEvent.type,
+			'target':           this,
+			'currentTarget':    this,
+			'eventPhase':       2,
+			'bubbles':          oEvent.bubbles,
+			'cancelable':       oEvent.cancelable,
+			'timeStamp':        oEvent.timeStamp,
+			'stopPropagation':  function() {},  // There is no flow
+			'preventDefault':   function() {},  // There is no default action
+			'initEvent':        function() {}   // Original event object should be initialized
+		};
+
+		// Execute onreadystatechange
+		if (oEventPseudo.type == "readystatechange" && this.onreadystatechange) {
+			(this.onreadystatechange.handleEvent || this.onreadystatechange).apply(this, [oEventPseudo]);
+		}
+
+
+		// Execute listeners
+		for (var nIndex = 0, oListener; oListener = this._listeners[nIndex]; nIndex++) {
+			if (oListener[0] == oEventPseudo.type && !oListener[2]) {
+				(oListener[1].handleEvent || oListener[1]).apply(this, [oEventPseudo]);
+			}
+		}
+
+	};
+
+	//
+	cXMLHttpRequest.prototype.toString  = function() {
+		return '[' + "object" + ' ' + "XMLHttpRequest" + ']';
+	};
+
+	cXMLHttpRequest.toString  = function() {
+		return '[' + "XMLHttpRequest" + ']';
+	};
+
+	/**
+	 * // Queue manager
+	 * var oQueuePending = {"CRITICAL":[],"HIGH":[],"NORMAL":[],"LOW":[],"LOWEST":[]},
+	 * aQueueRunning = [];
+	 * function fQueue_add(oRequest) {
+	 * 	oQueuePending[oRequest.priority in oQueuePending ? oRequest.priority : "NORMAL"].push(oRequest);
+	 * 	//
+	 * 	setTimeout(fQueue_process);
+	 * };
+	 *
+	 * function fQueue_remove(oRequest) {
+	 * 	for (var nIndex = 0, bFound = false; nIndex < aQueueRunning.length; nIndex++)
+	 * 	if (bFound) {
+	 * 		aQueueRunning[nIndex - 1] = aQueueRunning[nIndex];
+	 * 	} else {
+	 * 		if (aQueueRunning[nIndex] == oRequest) {
+	 * 			bFound  = true;
+	 * 		}
+	 * }
+	 *
+	 * 	if (bFound) {
+	 * 		aQueueRunning.length--;
+	 * 	}
+	 *
+	 *
+	 * 	//
+	 * 	setTimeout(fQueue_process);
+	 * };
+	 *
+	 * function fQueue_process() {
+	 * if (aQueueRunning.length < 6) {
+	 * for (var sPriority in oQueuePending) {
+	 * if (oQueuePending[sPriority].length) {
+	 * var oRequest  = oQueuePending[sPriority][0];
+	 * oQueuePending[sPriority]  = oQueuePending[sPriority].slice(1);
+	 * //
+	 * aQueueRunning.push(oRequest);
+	 * // Send request
+	 * fXMLHttpRequest_send(oRequest);
+	 * break;
+	 * }
+	 * }
+	 * }
+	 * };
+	 */
+
+	// Helper function
+	function fXMLHttpRequest_send(oRequest) {
+		oRequest._object.send(oRequest._data);
+
+		// BUGFIX: Gecko - missing readystatechange calls in synchronous requests
+		if (bGecko && !oRequest._async) {
+			oRequest.readyState = cXMLHttpRequest.OPENED;
+
+			// Synchronize state
+			fSynchronizeValues(oRequest);
+
+			// Simulate missing states
+			while (oRequest.readyState < cXMLHttpRequest.DONE) {
+				oRequest.readyState++;
+				fReadyStateChange(oRequest);
+				// Check if we are aborted
+				if (oRequest._aborted) {
+					return;
+				}
+			}
+		}
+	}
+
+	function fReadyStateChange(oRequest) {
+		// Sniffing code
+		if (cXMLHttpRequest.onreadystatechange){
+			cXMLHttpRequest.onreadystatechange.apply(oRequest);
+		}
+
+
+		// Fake event
+		oRequest.dispatchEvent({
+			'type':       "readystatechange",
+			'bubbles':    false,
+			'cancelable': false,
+			'timeStamp':  new Date + 0
+		});
+	}
+
+	function fGetDocument(oRequest) {
+		var oDocument = oRequest.responseXML;
+		var sResponse = oRequest.responseText;
+		// Try parsing responseText
+		if (bIE && sResponse && oDocument && !oDocument.documentElement
&& oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)) {
+			oDocument = new window.ActiveXObject("Microsoft.XMLDOM");
+			oDocument.async       = false;
+			oDocument.validateOnParse = false;
+			oDocument.loadXML(sResponse);
+		}
+
+		// Check if there is no error in document
+		if (oDocument){
+			if ((bIE && oDocument.parseError !== 0) || !oDocument.documentElement || (oDocument.documentElement
&& oDocument.documentElement.tagName == "parsererror")) {
+				return null;
+			}
+		}
+		return oDocument;
+	}
+
+	function fSynchronizeValues(oRequest) {
+		try { oRequest.responseText = oRequest._object.responseText;  } catch (e) {}
+		try { oRequest.responseXML  = fGetDocument(oRequest._object); } catch (e) {}
+		try { oRequest.status       = oRequest._object.status;        } catch (e) {}
+		try { oRequest.statusText   = oRequest._object.statusText;    } catch (e) {}
+	}
+
+	function fCleanTransport(oRequest) {
+		// BUGFIX: IE - memory leak (on-page leak)
+		oRequest._object.onreadystatechange = new window.Function;
+	}
+
+	// Internet Explorer 5.0 (missing apply)
+	if (!window.Function.prototype.apply) {
+		window.Function.prototype.apply = function(oRequest, oArguments) {
+			if (!oArguments) {
+				oArguments  = [];
+			}
+			oRequest.__func = this;
+			oRequest.__func(oArguments[0], oArguments[1], oArguments[2], oArguments[3], oArguments[4]);
+			delete oRequest.__func;
+		};
+	}
+
+	// Register new object with window
+	window.XMLHttpRequest = cXMLHttpRequest;
+
+})();
+
+
+
+!function() {
+  function require(path) {
+    if(path === './xmlhttprequest')
+      return window && {'XMLHttpRequest':window.XMLHttpRequest}
+    throw new Error('require() unsupported in the browser build. Use RequireJS or Ender.')
+  }
+
+  var exports = {}
+    , module = { 'exports': exports }
+
+  if(typeof window === 'undefined') {
+    if(typeof console !== 'undefined' && console && console.error)
+      console.error('Cannot find global "window" object. Is this a browser?')
+
+    // XXX Global variable
+    window = {}
+  }
+
+  run_module()
+  window["request"] = module.exports
+
+  function run_module() {
+    // Begin CommonJS file
+// Browser Request
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+var xmlhttprequest = require('./xmlhttprequest')
+if(!xmlhttprequest || typeof xmlhttprequest !== 'object')
+  throw new Error('Could not find ./xmlhttprequest')
+
+var XHR = xmlhttprequest.XMLHttpRequest
+if(!XHR)
+  throw new Error('Bad xmlhttprequest.XMLHttpRequest')
+if(! ('_object' in (new XHR)))
+  throw new Error('This is not portable XMLHttpRequest')
+
+module.exports = request
+request.XMLHttpRequest = XHR
+request.log = getLogger()
+
+var DEFAULT_TIMEOUT = 3 * 60 * 1000 // 3 minutes
+
+//
+// request
+//
+
+function request(options, callback) {
+  // The entry-point to the API: prep the options object and pass the real work to run_xhr.
+  if(typeof callback !== 'function')
+    throw new Error('Bad callback given: ' + callback)
+
+  if(!options)
+    throw new Error('No options given')
+
+  var options_onResponse = options.onResponse; // Save this for later.
+
+  if(typeof options === 'string')
+    options = {'uri':options};
+  else
+    options = JSON.parse(JSON.stringify(options)); // Use a duplicate for mutating.
+
+  options.onResponse = options_onResponse // And put it back.
+
+  if(options.url) {
+    options.uri = options.url;
+    delete options.url;
+  }
+
+  if(!options.uri && options.uri !== "")
+    throw new Error("options.uri is a required argument");
+
+  if(typeof options.uri != "string")
+    throw new Error("options.uri must be a string");
+
+  var unsupported_options = ['proxy', '_redirectsFollowed', 'maxRedirects', 'followRedirect']
+  for (var i = 0; i < unsupported_options.length; i++)
+    if(options[ unsupported_options[i] ])
+      throw new Error("options." + unsupported_options[i] + " is not supported")
+
+  options.callback = callback
+  options.method = options.method || 'GET';
+  options.headers = options.headers || {};
+  options.body    = options.body || null
+  options.timeout = options.timeout || request.DEFAULT_TIMEOUT
+
+  if(options.headers.host)
+    throw new Error("Options.headers.host is not supported");
+
+  if(options.json) {
+    options.headers.accept = options.headers.accept || 'application/json'
+    if(options.method !== 'GET')
+      options.headers['content-type'] = 'application/json'
+
+    if(typeof options.json !== 'boolean')
+      options.body = JSON.stringify(options.json)
+    else if(typeof options.body !== 'string')
+      options.body = JSON.stringify(options.body)
+  }
+
+  // If onResponse is boolean true, call back immediately when the response is known,
+  // not when the full request is complete.
+  options.onResponse = options.onResponse || noop
+  if(options.onResponse === true) {
+    options.onResponse = callback
+    options.callback = noop
+  }
+
+  // XXX Browsers do not like this.
+  //if(options.body)
+  //  options.headers['content-length'] = options.body.length;
+
+  // HTTP basic authentication
+  if(!options.headers.authorization && options.auth)
+    options.headers.authorization = 'Basic ' + b64_enc(options.auth.username + ':' + options.auth.password);
+
+  return run_xhr(options)
+}
+
+var req_seq = 0
+function run_xhr(options) {
+  var xhr = new XHR
+    , timed_out = false
+    , is_cors = is_crossDomain(options.uri)
+    , supports_cors = ('withCredentials' in xhr._object)
+
+  req_seq += 1
+  xhr.seq_id = req_seq
+  xhr.id = req_seq + ': ' + options.method + ' ' + options.uri
+  xhr._id = xhr.id // I know I will type "_id" from habit all the time.
+
+  if(is_cors && !supports_cors) {
+    var cors_err = new Error('Browser does not support cross-origin request: ' + options.uri)
+    cors_err.cors = 'unsupported'
+    return options.callback(cors_err, xhr)
+  }
+
+  xhr.timeoutTimer = setTimeout(too_late, options.timeout)
+  function too_late() {
+    timed_out = true
+    var er = new Error('ETIMEDOUT')
+    er.code = 'ETIMEDOUT'
+    er.duration = options.timeout
+
+    request.log.error('Timeout', { 'id':xhr._id, 'milliseconds':options.timeout })
+    return options.callback(er, xhr)
+  }
+
+  // Some states can be skipped over, so remember what is still incomplete.
+  var did = {'response':false, 'loading':false, 'end':false}
+
+  xhr.onreadystatechange = on_state_change
+  xhr.open(options.method, options.uri, true) // asynchronous
+  if(is_cors)
+    xhr._object.withCredentials = !! options.withCredentials
+  xhr.send(options.body)
+  return xhr
+
+  function on_state_change(event) {
+    if(timed_out)
+      return request.log.debug('Ignoring timed out state change', {'state':xhr.readyState,
'id':xhr.id})
+
+    request.log.debug('State change', {'state':xhr.readyState, 'id':xhr.id, 'timed_out':timed_out})
+
+    if(xhr.readyState === XHR.OPENED) {
+      request.log.debug('Request started', {'id':xhr.id})
+      for (var key in options.headers)
+        xhr.setRequestHeader(key, options.headers[key])
+    }
+
+    else if(xhr.readyState === XHR.HEADERS_RECEIVED)
+      on_response()
+
+    else if(xhr.readyState === XHR.LOADING) {
+      on_response()
+      on_loading()
+    }
+
+    else if(xhr.readyState === XHR.DONE) {
+      on_response()
+      on_loading()
+      on_end()
+    }
+  }
+
+  function on_response() {
+    if(did.response)
+      return
+
+    did.response = true
+    request.log.debug('Got response', {'id':xhr.id, 'status':xhr.status})
+    clearTimeout(xhr.timeoutTimer)
+    xhr.statusCode = xhr.status // Node request compatibility
+
+    // Detect failed CORS requests.
+    if(is_cors && xhr.statusCode == 0) {
+      var cors_err = new Error('CORS request rejected: ' + options.uri)
+      cors_err.cors = 'rejected'
+
+      // Do not process this request further.
+      did.loading = true
+      did.end = true
+
+      return options.callback(cors_err, xhr)
+    }
+
+    options.onResponse(null, xhr)
+  }
+
+  function on_loading() {
+    if(did.loading)
+      return
+
+    did.loading = true
+    request.log.debug('Response body loading', {'id':xhr.id})
+    // TODO: Maybe simulate "data" events by watching xhr.responseText
+  }
+
+  function on_end() {
+    if(did.end)
+      return
+
+    did.end = true
+    request.log.debug('Request done', {'id':xhr.id})
+
+    xhr.body = xhr.responseText
+    if(options.json) {
+      try        { xhr.body = JSON.parse(xhr.responseText) }
+      catch (er) { return options.callback(er, xhr)        }
+    }
+
+    options.callback(null, xhr, xhr.body)
+  }
+
+} // request
+
+request.withCredentials = false;
+request.DEFAULT_TIMEOUT = DEFAULT_TIMEOUT;
+
+//
+// HTTP method shortcuts
+//
+
+var shortcuts = [ 'get', 'put', 'post', 'head' ];
+shortcuts.forEach(function(shortcut) {
+  var method = shortcut.toUpperCase();
+  var func   = shortcut.toLowerCase();
+
+  request[func] = function(opts) {
+    if(typeof opts === 'string')
+      opts = {'method':method, 'uri':opts};
+    else {
+      opts = JSON.parse(JSON.stringify(opts));
+      opts.method = method;
+    }
+
+    var args = [opts].concat(Array.prototype.slice.apply(arguments, [1]));
+    return request.apply(this, args);
+  }
+})
+
+//
+// CouchDB shortcut
+//
+
+request.couch = function(options, callback) {
+  if(typeof options === 'string')
+    options = {'uri':options}
+
+  // Just use the request API to do JSON.
+  options.json = true
+  if(options.body)
+    options.json = options.body
+  delete options.body
+
+  callback = callback || noop
+
+  var xhr = request(options, couch_handler)
+  return xhr
+
+  function couch_handler(er, resp, body) {
+    if(er)
+      return callback(er, resp, body)
+
+    if((resp.statusCode < 200 || resp.statusCode > 299) && body.error) {
+      // The body is a Couch JSON object indicating the error.
+      er = new Error('CouchDB error: ' + (body.error.reason || body.error.error))
+      for (var key in body)
+        er[key] = body[key]
+      return callback(er, resp, body);
+    }
+
+    return callback(er, resp, body);
+  }
+}
+
+//
+// Utility
+//
+
+function noop() {}
+
+function getLogger() {
+  var logger = {}
+    , levels = ['trace', 'debug', 'info', 'warn', 'error']
+    , level, i
+
+  for(i = 0; i < levels.length; i++) {
+    level = levels[i]
+
+    logger[level] = noop
+    if(typeof console !== 'undefined' && console && console[level])
+      logger[level] = formatted(console, level)
+  }
+
+  return logger
+}
+
+function formatted(obj, method) {
+  return formatted_logger
+
+  function formatted_logger(str, context) {
+    if(typeof context === 'object')
+      str += ' ' + JSON.stringify(context)
+
+    return obj[method].call(obj, str)
+  }
+}
+
+// Return whether a URL is a cross-domain request.
+function is_crossDomain(url) {
+  var rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/
+
+  // jQuery #8138, IE may throw an exception when accessing
+  // a field from window.location if document.domain has been set
+  var ajaxLocation
+  try { ajaxLocation = location.href }
+  catch (e) {
+    // Use the href attribute of an A element since IE will modify it given document.location
+    ajaxLocation = document.createElement( "a" );
+    ajaxLocation.href = "";
+    ajaxLocation = ajaxLocation.href;
+  }
+
+  var ajaxLocParts = rurl.exec(ajaxLocation.toLowerCase()) || []
+    , parts = rurl.exec(url.toLowerCase() )
+
+  var result = !!(
+    parts &&
+    (  parts[1] != ajaxLocParts[1]
+    || parts[2] != ajaxLocParts[2]
+    || (parts[3] || (parts[1] === "http:" ? 80 : 443)) != (ajaxLocParts[3] || (ajaxLocParts[1]
=== "http:" ? 80 : 443))
+    )
+  )
+
+  //console.debug('is_crossDomain('+url+') -> ' + result)
+  return result
+}
+
+// MIT License from http://phpjs.org/functions/base64_encode:358
+function b64_enc (data) {
+    // Encodes string using MIME base64 algorithm
+    var b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
+    var o1, o2, o3, h1, h2, h3, h4, bits, i = 0, ac = 0, enc="", tmp_arr = [];
+
+    if (!data) {
+        return data;
+    }
+
+    // assume utf8 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;
+}
+
+    // End CommonJS file
+  }
+}();


Mime
View raw message