mirror of
https://github.com/ACSPRI/queXS
synced 2024-04-02 12:12:16 +00:00
241 lines
8.2 KiB
JavaScript
241 lines
8.2 KiB
JavaScript
/**
|
|
* XMLHttpRequest Iframe fallback
|
|
*
|
|
* http://lxr.mozilla.org/seamonkey/source/extensions/xmlextras/tests/ - should work with these
|
|
*
|
|
* @category HTML
|
|
* @package AJAX
|
|
* @author Elizabeth Smith <auroraeosrose@gmail.com>
|
|
* @copyright 2005 Elizabeth Smith
|
|
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
|
*/
|
|
HTML_AJAX_IframeXHR_instances = new Object();
|
|
function HTML_AJAX_IframeXHR()
|
|
{
|
|
this._id = 'HAXHR_iframe_' + new Date().getTime();
|
|
HTML_AJAX_IframeXHR_instances[this._id] = this;
|
|
}
|
|
HTML_AJAX_IframeXHR.prototype = {
|
|
// Data not sent with text/xml Content-Type will only be available via the responseText property
|
|
|
|
// properties available in safari/mozilla/IE xmlhttprequest object
|
|
onreadystatechange: null, // Event handler for an event that fires at every state change
|
|
readyState: 0, // Object status integer: 0 = uninitialized 1 = loading 2 = loaded 3 = interactive 4 = complete
|
|
responseText: '', // String version of data returned from server process
|
|
responseXML: null, // DOM-compatible document object of data returned from server process
|
|
status: 0, // Numeric code returned by server, such as 404 for "Not Found" or 200 for "OK"
|
|
statusText: '', // String message accompanying the status code
|
|
iframe: true, // flag for iframe
|
|
|
|
//these are private properties used internally to keep track of stuff
|
|
_id: null, // iframe id, unique to object(hopefully)
|
|
_url: null, // url sent by open
|
|
_method: null, // get or post
|
|
_async: null, // sync or async sent by open
|
|
_headers: new Object(), //request headers to send, actually sent as form vars
|
|
_response: new Object(), //response headers received
|
|
_phpclass: null, //class to send
|
|
_phpmethod: null, //method to send
|
|
_history: null, // opera has to have history munging
|
|
|
|
// Stops the current request
|
|
abort: function()
|
|
{
|
|
var iframe = document.getElementById(this._id);
|
|
if (iframe) {
|
|
document.body.removeChild(iframe);
|
|
}
|
|
if (this._timeout) {
|
|
window.clearTimeout(this._timeout);
|
|
}
|
|
this.readyState = 1;
|
|
if (typeof(this.onreadystatechange) == "function") {
|
|
this.onreadystatechange();
|
|
}
|
|
},
|
|
|
|
// This will send all headers in this._response and will include lastModified and contentType if not already set
|
|
getAllResponseHeaders: function()
|
|
{
|
|
var string = '';
|
|
for (i in this._response) {
|
|
string += i + ' : ' + this._response[i] + "\n";
|
|
}
|
|
return string;
|
|
},
|
|
|
|
// This will use lastModified and contentType if they're not set
|
|
getResponseHeader: function(header)
|
|
{
|
|
return (this._response[header] ? this._response[header] : null);
|
|
},
|
|
|
|
// Assigns a label/value pair to the header to be sent with a request
|
|
setRequestHeader: function(label, value) {
|
|
this._headers[label] = value;
|
|
return; },
|
|
|
|
// Assigns destination URL, method, and other optional attributes of a pending request
|
|
open: function(method, url, async, username, password)
|
|
{
|
|
if (!document.body) {
|
|
throw('CANNOT_OPEN_SEND_IN_DOCUMENT_HEAD');
|
|
}
|
|
//exceptions for not enough arguments
|
|
if (!method || !url) {
|
|
throw('NOT_ENOUGH_ARGUMENTS:METHOD_URL_REQUIRED');
|
|
}
|
|
//get and post are only methods accepted
|
|
this._method = (method.toUpperCase() == 'POST' ? 'POST' : 'GET');
|
|
this._decodeUrl(url);
|
|
this._async = async;
|
|
if(!this._async && document.readyState && !window.opera) {
|
|
throw('IE_DOES_NOT_SUPPORT_SYNC_WITH_IFRAMEXHR');
|
|
}
|
|
//set status to loading and call onreadystatechange
|
|
this.readyState = 1;
|
|
if(typeof(this.onreadystatechange) == "function") {
|
|
this.onreadystatechange();
|
|
}
|
|
},
|
|
|
|
// Transmits the request, optionally with postable string or DOM object data
|
|
send: function(content)
|
|
{
|
|
//attempt opera history munging
|
|
if (window.opera) {
|
|
this._history = window.history.length;
|
|
}
|
|
//create a "form" for the contents of the iframe
|
|
var form = '<html><body><form method="'
|
|
+ (this._url.indexOf('px=') < 0 ? this._method : 'post')
|
|
+ '" action="' + this._url + '">';
|
|
//tell iframe unwrapper this IS an iframe
|
|
form += '<input name="Iframe_XHR" value="1" />';
|
|
//class and method
|
|
if (this._phpclass != null) {
|
|
form += '<input name="Iframe_XHR_class" value="' + this._phpclass + '" />';
|
|
}
|
|
if (this._phpmethod != null) {
|
|
form += '<input name="Iframe_XHR_method" value="' + this._phpmethod + '" />';
|
|
}
|
|
// fake headers
|
|
for (label in this._headers) {
|
|
form += '<textarea name="Iframe_XHR_headers[]">' + label +':'+ this._headers[label] + '</textarea>';
|
|
}
|
|
// add id
|
|
form += '<textarea name="Iframe_XHR_id">' + this._id + '</textarea>';
|
|
if (content != null && content.length > 0) {
|
|
form += '<textarea name="Iframe_XHR_data">' + content + '</textarea>';
|
|
}
|
|
form += '<input name="Iframe_XHR_HTTP_method" value="' + this._method + '" />';
|
|
form += '<s'+'cript>document.forms[0].submit();</s'+'cript></form></body></html>';
|
|
form = "javascript:document.write('" + form.replace(/\'/g,"\\'") + "');void(0);";
|
|
this.readyState = 2;
|
|
if (typeof(this.onreadystatechange) == "function") {
|
|
this.onreadystatechange();
|
|
}
|
|
// try to create an iframe with createElement and append node
|
|
try {
|
|
var iframe = document.createElement('iframe');
|
|
iframe.id = this._id;
|
|
// display: none will fail on some browsers
|
|
iframe.style.visibility = 'hidden';
|
|
// for old browsers with crappy css
|
|
iframe.style.border = '0';
|
|
iframe.style.width = '0';
|
|
iframe.style.height = '0';
|
|
|
|
if (document.all) {
|
|
// MSIE, opera
|
|
iframe.src = form;
|
|
document.body.appendChild(iframe);
|
|
} else {
|
|
document.body.appendChild(iframe);
|
|
iframe.src = form;
|
|
}
|
|
} catch(exception) {
|
|
// dom failed, write the sucker manually
|
|
var html = '<iframe src="' + form +'" id="' + this._id + '" style="visibility:hidden;border:0;height:0;width:0;"></iframe>';
|
|
document.body.innerHTML += html;
|
|
}
|
|
if (this._async == true) {
|
|
//avoid race state if onload is called first
|
|
if (this.readyState < 3) {
|
|
this.readyState = 3;
|
|
if(typeof(this.onreadystatechange) == "function") {
|
|
this.onreadystatechange();
|
|
}
|
|
}
|
|
} else {
|
|
//we force a while loop for sync, it's ugly but hopefully it works
|
|
while (this.readyState != 4) {
|
|
//just check to see if we can up readyState
|
|
if (this.readyState < 3) {
|
|
this.readyState = 3;
|
|
if(typeof(this.onreadystatechange) == "function") {
|
|
this.onreadystatechange();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
|
|
// attached as an onload function to the iframe to trigger when we're done
|
|
isLoaded: function(headers, data)
|
|
{
|
|
this.readyState = 4;
|
|
//set responseText, Status, StatusText
|
|
this.status = 200;
|
|
this.statusText = 'OK';
|
|
this.responseText = data;
|
|
this._response = headers;
|
|
if (!this._response['Last-Modified']) {
|
|
string += 'Last-Modified : ' + document.getElementById(this._id).lastModified + "\n";
|
|
}
|
|
if (!this._response['Content-Type']) {
|
|
string += 'Content-Type : ' + document.getElementById(this._id).contentType + "\n";
|
|
}
|
|
// if this is xml populate responseXML accordingly
|
|
if (this._response['Content-Type'] == 'application/xml')
|
|
{
|
|
return new DOMParser().parseFromString(this.responseText, 'application/xml');
|
|
}
|
|
//attempt opera history munging in opera 8+ - this is a REGRESSION IN OPERA
|
|
if (window.opera && window.opera.version) {
|
|
//go back current history - old history
|
|
window.history.go(this._history - window.history.length);
|
|
}
|
|
if (typeof(this.onreadystatechange) == "function") {
|
|
this.onreadystatechange();
|
|
}
|
|
document.body.removeChild(document.getElementById(this._id));
|
|
},
|
|
|
|
// strip off the c and m from the url send...yuck
|
|
_decodeUrl: function(querystring)
|
|
{
|
|
//opera 7 is too stupid to do a relative url...go figure
|
|
var url = unescape(location.href);
|
|
url = url.substring(0, url.lastIndexOf("/") + 1);
|
|
var item = querystring.split('?');
|
|
//rip off any path info and append to path above <- relative paths (../) WILL screw this
|
|
this._url = url + item[0].substring(item[0].lastIndexOf("/") + 1,item[0].length);
|
|
if(item[1]) {
|
|
item = item[1].split('&');
|
|
for (i in item) {
|
|
var v = item[i].split('=');
|
|
if (v[0] == 'c') {
|
|
this._phpclass = v[1];
|
|
} else if (v[0] == 'm') {
|
|
this._phpmethod = v[1];
|
|
}
|
|
}
|
|
}
|
|
if (!this._phpclass || !this._phpmethod) {
|
|
var cloc = window.location.href;
|
|
this._url = cloc + (cloc.indexOf('?') >= 0 ? '&' : '?') + 'px=' + escape(HTML_AJAX_Util.absoluteURL(querystring));
|
|
}
|
|
}
|
|
}
|