mirror of
https://github.com/ACSPRI/queXS
synced 2024-04-02 12:12:16 +00:00
Import from DCARF SVN
This commit is contained in:
7
include/pear/data/HTML_AJAX/js/Alias.js
Normal file
7
include/pear/data/HTML_AJAX/js/Alias.js
Normal file
@@ -0,0 +1,7 @@
|
||||
// Alias main HTML_AJAX functions to shorter names
|
||||
// See Main.js for License/Author details
|
||||
var $u = HTML_AJAX_Util;
|
||||
var $a = HTML_AJAX;
|
||||
if (!$) {
|
||||
var $ = HTML_AJAX_Util.getElement;
|
||||
}
|
||||
122
include/pear/data/HTML_AJAX/js/Compat.js
Normal file
122
include/pear/data/HTML_AJAX/js/Compat.js
Normal file
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* Compat functions
|
||||
* @category HTML
|
||||
* @package AJAX
|
||||
* @author Joshua Eichorn <josh@bluga.net>
|
||||
* @copyright 2005 Joshua Eichorn
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
*/
|
||||
/**
|
||||
* Functions for compatibility with older browsers
|
||||
*/
|
||||
if (!String.fromCharCode && !String.prototype.fromCharCode) {
|
||||
String.prototype.fromCharCode = function(code)
|
||||
{
|
||||
var h = code.toString(16);
|
||||
if (h.length == 1) {
|
||||
h = '0' + h;
|
||||
}
|
||||
return unescape('%' + h);
|
||||
}
|
||||
}
|
||||
if (!String.charCodeAt && !String.prototype.charCodeAt) {
|
||||
String.prototype.charCodeAt = function(index)
|
||||
{
|
||||
var c = this.charAt(index);
|
||||
for (i = 1; i < 256; i++) {
|
||||
if (String.fromCharCode(i) == c) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// http://www.crockford.com/javascript/remedial.html
|
||||
if (!Array.splice && !Array.prototype.splice) {
|
||||
Array.prototype.splice = function(s, d)
|
||||
{
|
||||
var max = Math.max,
|
||||
min = Math.min,
|
||||
a = [], // The return value array
|
||||
e, // element
|
||||
i = max(arguments.length - 2, 0), // insert count
|
||||
k = 0,
|
||||
l = this.length,
|
||||
n, // new length
|
||||
v, // delta
|
||||
x; // shift count
|
||||
|
||||
s = s || 0;
|
||||
if (s < 0) {
|
||||
s += l;
|
||||
}
|
||||
s = max(min(s, l), 0); // start point
|
||||
d = max(min(typeof d == 'number' ? d : l, l - s), 0); // delete count
|
||||
v = i - d;
|
||||
n = l + v;
|
||||
while (k < d) {
|
||||
e = this[s + k];
|
||||
if (!e) {
|
||||
a[k] = e;
|
||||
}
|
||||
k += 1;
|
||||
}
|
||||
x = l - s - d;
|
||||
if (v < 0) {
|
||||
k = s + i;
|
||||
while (x) {
|
||||
this[k] = this[k - v];
|
||||
k += 1;
|
||||
x -= 1;
|
||||
}
|
||||
this.length = n;
|
||||
} else if (v > 0) {
|
||||
k = 1;
|
||||
while (x) {
|
||||
this[n - k] = this[l - k];
|
||||
k += 1;
|
||||
x -= 1;
|
||||
}
|
||||
}
|
||||
for (k = 0; k < i; ++k) {
|
||||
this[s + k] = arguments[k + 2];
|
||||
}
|
||||
return a;
|
||||
}
|
||||
}
|
||||
if (!Array.push && !Array.prototype.push) {
|
||||
Array.prototype.push = function()
|
||||
{
|
||||
for (var i = 0, startLength = this.length; i < arguments.length; i++) {
|
||||
this[startLength + i] = arguments[i];
|
||||
}
|
||||
return this.length;
|
||||
}
|
||||
}
|
||||
if (!Array.pop && !Array.prototype.pop) {
|
||||
Array.prototype.pop = function()
|
||||
{
|
||||
return this.splice(this.length - 1, 1)[0];
|
||||
}
|
||||
}
|
||||
/*
|
||||
From IE7, version 0.9 (alpha) (2005-08-19)
|
||||
Copyright: 2004-2005, Dean Edwards (http://dean.edwards.name/)
|
||||
*/
|
||||
if (!DOMParser.parseFromString && window.ActiveXObject)
|
||||
{
|
||||
function DOMParser() {/* empty constructor */};
|
||||
DOMParser.prototype = {
|
||||
parseFromString: function(str, contentType) {
|
||||
var xmlDocument = new ActiveXObject('Microsoft.XMLDOM');
|
||||
xmlDocument.loadXML(str);
|
||||
return xmlDocument;
|
||||
}
|
||||
};
|
||||
|
||||
function XMLSerializer() {/* empty constructor */};
|
||||
XMLSerializer.prototype = {
|
||||
serializeToString: function(root) {
|
||||
return root.xml || root.outerHTML;
|
||||
}
|
||||
};
|
||||
}
|
||||
98
include/pear/data/HTML_AJAX/js/Dispatcher.js
Normal file
98
include/pear/data/HTML_AJAX/js/Dispatcher.js
Normal file
@@ -0,0 +1,98 @@
|
||||
/**
|
||||
* Class that is used by generated stubs to make actual AJAX calls
|
||||
*
|
||||
* @category HTML
|
||||
* @package AJAX
|
||||
* @author Joshua Eichorn <josh@bluga.net>
|
||||
* @copyright 2005 Joshua Eichorn
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
*/
|
||||
function HTML_AJAX_Dispatcher(className,mode,callback,serverUrl,serializerType)
|
||||
{
|
||||
this.className = className;
|
||||
this.mode = mode;
|
||||
this.callback = callback;
|
||||
this.serializerType = serializerType;
|
||||
|
||||
if (serverUrl) {
|
||||
this.serverUrl = serverUrl
|
||||
}
|
||||
else {
|
||||
this.serverUrl = window.location;
|
||||
}
|
||||
}
|
||||
|
||||
HTML_AJAX_Dispatcher.prototype = {
|
||||
/**
|
||||
* Queue to use when making a request
|
||||
*/
|
||||
queue: 'default',
|
||||
|
||||
/**
|
||||
* Timeout for async calls
|
||||
*/
|
||||
timeout: 20000,
|
||||
|
||||
/**
|
||||
* Default request priority
|
||||
*/
|
||||
priority: 0,
|
||||
|
||||
/**
|
||||
* Request options
|
||||
*/
|
||||
options: {},
|
||||
|
||||
/**
|
||||
* Make an ajax call
|
||||
*
|
||||
* @param string callName
|
||||
* @param Array args arguments to the report method
|
||||
*/
|
||||
doCall: function(callName,args)
|
||||
{
|
||||
var request = new HTML_AJAX_Request();
|
||||
request.requestUrl = this.serverUrl;
|
||||
request.className = this.className;
|
||||
request.methodName = callName;
|
||||
request.timeout = this.timeout;
|
||||
request.contentType = this.contentType;
|
||||
request.serializer = eval('new HTML_AJAX_Serialize_'+this.serializerType);
|
||||
request.queue = this.queue;
|
||||
request.priority = this.priority;
|
||||
|
||||
for(var i in this.options) {
|
||||
request[i] = this.options[i];
|
||||
}
|
||||
|
||||
for(var i=0; i < args.length; i++) {
|
||||
request.addArg(i,args[i]);
|
||||
};
|
||||
|
||||
if ( this.mode == "async" ) {
|
||||
request.isAsync = true;
|
||||
if (this.callback[callName]) {
|
||||
var self = this;
|
||||
request.callback = function(result) { self.callback[callName](result); }
|
||||
}
|
||||
|
||||
} else {
|
||||
request.isAsync = false;
|
||||
}
|
||||
|
||||
return HTML_AJAX.makeRequest(request);
|
||||
},
|
||||
|
||||
Sync: function()
|
||||
{
|
||||
this.mode = 'sync';
|
||||
},
|
||||
|
||||
Async: function(callback)
|
||||
{
|
||||
this.mode = 'async';
|
||||
if (callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
}
|
||||
};
|
||||
3134
include/pear/data/HTML_AJAX/js/HTML_AJAX.js
Normal file
3134
include/pear/data/HTML_AJAX/js/HTML_AJAX.js
Normal file
File diff suppressed because one or more lines are too long
2798
include/pear/data/HTML_AJAX/js/HTML_AJAX_lite.js
Normal file
2798
include/pear/data/HTML_AJAX/js/HTML_AJAX_lite.js
Normal file
File diff suppressed because one or more lines are too long
269
include/pear/data/HTML_AJAX/js/HttpClient.js
Normal file
269
include/pear/data/HTML_AJAX/js/HttpClient.js
Normal file
@@ -0,0 +1,269 @@
|
||||
/**
|
||||
* XMLHttpRequest Wrapper
|
||||
* @category HTML
|
||||
* @package AJAX
|
||||
* @author Joshua Eichorn <josh@bluga.net>
|
||||
* @copyright 2005 Joshua Eichorn
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
*/
|
||||
function HTML_AJAX_HttpClient() { }
|
||||
HTML_AJAX_HttpClient.prototype = {
|
||||
// request object
|
||||
request: null,
|
||||
|
||||
// timeout id
|
||||
_timeoutId: null,
|
||||
|
||||
callbackComplete: true,
|
||||
|
||||
// has this request been aborted
|
||||
aborted: false,
|
||||
|
||||
// method to initialize an xmlhttpclient
|
||||
init:function()
|
||||
{
|
||||
try {
|
||||
// Mozilla / Safari
|
||||
//this.xmlhttp = new HTML_AJAX_IframeXHR(); //uncomment these two lines to test iframe
|
||||
//return;
|
||||
this.xmlhttp = new XMLHttpRequest();
|
||||
} catch (e) {
|
||||
// IE
|
||||
var XMLHTTP_IDS = new Array(
|
||||
'MSXML2.XMLHTTP.5.0',
|
||||
'MSXML2.XMLHTTP.4.0',
|
||||
'MSXML2.XMLHTTP.3.0',
|
||||
'MSXML2.XMLHTTP',
|
||||
'Microsoft.XMLHTTP' );
|
||||
var success = false;
|
||||
for (var i=0;i < XMLHTTP_IDS.length && !success; i++) {
|
||||
try {
|
||||
this.xmlhttp = new ActiveXObject(XMLHTTP_IDS[i]);
|
||||
success = true;
|
||||
} catch (e) {}
|
||||
}
|
||||
if (!success) {
|
||||
try{
|
||||
this.xmlhttp = new HTML_AJAX_IframeXHR();
|
||||
this.request.iframe = true;
|
||||
} catch(e) {
|
||||
throw new Error('Unable to create XMLHttpRequest.');
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// check if there is a call in progress
|
||||
callInProgress: function()
|
||||
{
|
||||
switch ( this.xmlhttp.readyState ) {
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
// make the request defined in the request object
|
||||
makeRequest: function()
|
||||
{
|
||||
if (!this.xmlhttp) {
|
||||
this.init();
|
||||
}
|
||||
|
||||
try {
|
||||
if (this.request.Open) {
|
||||
this.request.Open();
|
||||
}
|
||||
else if (HTML_AJAX.Open) {
|
||||
HTML_AJAX.Open(this.request);
|
||||
}
|
||||
|
||||
if (this.request.multipart) {
|
||||
if (document.all) {
|
||||
this.iframe = true;
|
||||
} else {
|
||||
this.xmlhttp.multipart = true;
|
||||
}
|
||||
}
|
||||
|
||||
// set onreadystatechange here since it will be reset after a completed call in Mozilla
|
||||
var self = this;
|
||||
this.xmlhttp.open(this.request.requestType,this.request.completeUrl(),this.request.isAsync);
|
||||
if (this.request.customHeaders) {
|
||||
for (i in this.request.customHeaders) {
|
||||
this.xmlhttp.setRequestHeader(i, this.request.customHeaders[i]);
|
||||
}
|
||||
}
|
||||
if (this.request.customHeaders && !this.request.customHeaders['Content-Type']) {
|
||||
var content = this.request.getContentType();
|
||||
//opera is stupid for anything but plain text or xml!!
|
||||
if(window.opera && content != 'application/xml')
|
||||
{
|
||||
this.xmlhttp.setRequestHeader('Content-Type','text/plain; charset=utf-8');
|
||||
this.xmlhttp.setRequestHeader('x-Content-Type', content + '; charset=utf-8');
|
||||
}
|
||||
else
|
||||
{
|
||||
this.xmlhttp.setRequestHeader('Content-Type', content + '; charset=utf-8');
|
||||
}
|
||||
}
|
||||
|
||||
if (this.request.isAsync) {
|
||||
if (this.request.callback) {
|
||||
this.callbackComplete = false;
|
||||
}
|
||||
this.xmlhttp.onreadystatechange = function() { self._readyStateChangeCallback(); }
|
||||
} else {
|
||||
this.xmlhttp.onreadystatechange = function() {}
|
||||
}
|
||||
var payload = this.request.getSerializedPayload();
|
||||
if (payload) {
|
||||
this.xmlhttp.setRequestHeader('Content-Length', payload.length);
|
||||
}
|
||||
this.xmlhttp.send(payload);
|
||||
|
||||
if (!this.request.isAsync) {
|
||||
if ( this.xmlhttp.status == 200 ) {
|
||||
HTML_AJAX.requestComplete(this.request);
|
||||
if (this.request.Load) {
|
||||
this.request.Load();
|
||||
} else if (HTML_AJAX.Load) {
|
||||
HTML_AJAX.Load(this.request);
|
||||
}
|
||||
|
||||
return this._decodeResponse();
|
||||
} else {
|
||||
var e = new Error('['+this.xmlhttp.status +'] '+this.xmlhttp.statusText);
|
||||
e.headers = this.xmlhttp.getAllResponseHeaders();
|
||||
this._handleError(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// setup timeout
|
||||
var self = this;
|
||||
this._timeoutId = window.setTimeout(function() { self.abort(true); },this.request.timeout);
|
||||
}
|
||||
} catch (e) {
|
||||
this._handleError(e);
|
||||
}
|
||||
},
|
||||
|
||||
// abort an inprogress request
|
||||
abort: function (automatic)
|
||||
{
|
||||
if (this.callInProgress()) {
|
||||
this.aborted = true;
|
||||
this.xmlhttp.abort();
|
||||
|
||||
if (automatic) {
|
||||
HTML_AJAX.requestComplete(this.request);
|
||||
this._handleError(new Error('Request Timed Out: time out was '+this.request.timeout+'ms'));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// internal method used to handle ready state changes
|
||||
_readyStateChangeCallback:function()
|
||||
{
|
||||
try {
|
||||
switch(this.xmlhttp.readyState) {
|
||||
// XMLHTTPRequest.open() has just been called
|
||||
case 1:
|
||||
break;
|
||||
// XMLHTTPRequest.send() has just been called
|
||||
case 2:
|
||||
if (this.request.Send) {
|
||||
this.request.Send();
|
||||
} else if (HTML_AJAX.Send) {
|
||||
HTML_AJAX.Send(this.request);
|
||||
}
|
||||
break;
|
||||
// Fetching response from server in progress
|
||||
case 3:
|
||||
if (this.request.Progress) {
|
||||
this.request.Progress();
|
||||
} else if (HTML_AJAX.Progress ) {
|
||||
HTML_AJAX.Progress(this.request);
|
||||
}
|
||||
break;
|
||||
// Download complete
|
||||
case 4:
|
||||
window.clearTimeout(this._timeoutId);
|
||||
if (this.aborted) {
|
||||
if (this.request.Load) {
|
||||
this.request.Load();
|
||||
} else if (HTML_AJAX.Load) {
|
||||
HTML_AJAX.Load(this.request);
|
||||
}
|
||||
}
|
||||
else if (this.xmlhttp.status == 200) {
|
||||
if (this.request.Load) {
|
||||
this.request.Load();
|
||||
} else if (HTML_AJAX.Load ) {
|
||||
HTML_AJAX.Load(this.request);
|
||||
}
|
||||
|
||||
var response = this._decodeResponse();
|
||||
|
||||
if (this.request.callback) {
|
||||
this.request.callback(response);
|
||||
this.callbackComplete = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
var e = new Error('HTTP Error Making Request: ['+this.xmlhttp.status+'] '+this.xmlhttp.statusText);
|
||||
this._handleError(e);
|
||||
}
|
||||
HTML_AJAX.requestComplete(this.request);
|
||||
break;
|
||||
}
|
||||
} catch (e) {
|
||||
this._handleError(e);
|
||||
}
|
||||
},
|
||||
|
||||
// decode response as needed
|
||||
_decodeResponse: function() {
|
||||
//try for x-Content-Type first
|
||||
var content = null;
|
||||
try {
|
||||
content = this.xmlhttp.getResponseHeader('X-Content-Type');
|
||||
} catch(e) {}
|
||||
if(!content || content == null)
|
||||
{
|
||||
content = this.xmlhttp.getResponseHeader('Content-Type');
|
||||
}
|
||||
//strip anything after ;
|
||||
if(content.indexOf(';') != -1)
|
||||
{
|
||||
content = content.substring(0, content.indexOf(';'));
|
||||
}
|
||||
// hook for xml, it doesn't need to be unserialized
|
||||
if(content == 'application/xml')
|
||||
{
|
||||
return this.xmlhttp.responseXML;
|
||||
}
|
||||
var unserializer = HTML_AJAX.serializerForEncoding(content);
|
||||
//alert(this.xmlhttp.getAllResponseHeaders()); // some sort of debug hook is needed here
|
||||
return unserializer.unserialize(this.xmlhttp.responseText);
|
||||
},
|
||||
|
||||
// handle sending an error where it needs to go
|
||||
_handleError: function(e)
|
||||
{
|
||||
HTML_AJAX.requestComplete(this.request,e);
|
||||
if (this.request.onError) {
|
||||
this.request.onError(e);
|
||||
} else if (HTML_AJAX.onError) {
|
||||
HTML_AJAX.onError(e,this.request);
|
||||
}
|
||||
else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
240
include/pear/data/HTML_AJAX/js/IframeXHR.js
Normal file
240
include/pear/data/HTML_AJAX/js/IframeXHR.js
Normal file
@@ -0,0 +1,240 @@
|
||||
/**
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
53
include/pear/data/HTML_AJAX/js/Loading.js
Normal file
53
include/pear/data/HTML_AJAX/js/Loading.js
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Default loading implementation
|
||||
*
|
||||
* @category HTML
|
||||
* @package Ajax
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @copyright 2005 Joshua Eichorn
|
||||
* see Main.js for license Author details
|
||||
*/
|
||||
HTML_AJAX.Open = function(request) {
|
||||
var loading = document.getElementById('HTML_AJAX_LOADING');
|
||||
if (!loading) {
|
||||
loading = document.createElement('div');
|
||||
loading.id = 'HTML_AJAX_LOADING';
|
||||
loading.innerHTML = 'Loading...';
|
||||
|
||||
loading.style.color = '#fff';
|
||||
loading.style.position = 'absolute';
|
||||
loading.style.top = 0;
|
||||
loading.style.right = 0;
|
||||
loading.style.backgroundColor = '#f00';
|
||||
loading.style.border = '1px solid #f99';
|
||||
loading.style.width = '80px';
|
||||
loading.style.padding = '4px';
|
||||
loading.style.fontFamily = 'Arial, Helvetica, sans';
|
||||
loading.count = 0;
|
||||
|
||||
document.body.insertBefore(loading,document.body.firstChild);
|
||||
}
|
||||
else {
|
||||
if (loading.count == undefined) {
|
||||
loading.count = 0;
|
||||
}
|
||||
}
|
||||
loading.count++;
|
||||
if (request.isAsync) {
|
||||
request.loadingId = window.setTimeout(function() { loading.style.display = 'block'; },500);
|
||||
}
|
||||
else {
|
||||
loading.style.display = 'block';
|
||||
}
|
||||
}
|
||||
HTML_AJAX.Load = function(request) {
|
||||
if (request.loadingId) {
|
||||
window.clearTimeout(request.loadingId);
|
||||
}
|
||||
var loading = document.getElementById('HTML_AJAX_LOADING');
|
||||
loading.count--;
|
||||
|
||||
if (loading.count == 0) {
|
||||
loading.style.display = 'none';
|
||||
}
|
||||
}
|
||||
520
include/pear/data/HTML_AJAX/js/Main.js
Normal file
520
include/pear/data/HTML_AJAX/js/Main.js
Normal file
@@ -0,0 +1,520 @@
|
||||
/**
|
||||
* JavaScript library for use with HTML_AJAX
|
||||
*
|
||||
* This library 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 library 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:
|
||||
* Free Software Foundation, Inc.,
|
||||
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
* @category HTML
|
||||
* @package Ajax
|
||||
* @author Joshua Eichorn <josh@bluga.net>
|
||||
* @author Arpad Ray <arpad@php.net>
|
||||
* @author David Coallier <davidc@php.net>
|
||||
* @author Elizabeth Smith <auroraeosrose@gmail.com>
|
||||
* @copyright 2005 Joshua Eichorn, Arpad Ray, David Coallier, Elizabeth Smith
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
*/
|
||||
|
||||
/**
|
||||
* HTML_AJAX static methods, this is the main proxyless api, it also handles global error and event handling
|
||||
*/
|
||||
var HTML_AJAX = {
|
||||
version: '0.5.2',
|
||||
defaultServerUrl: false,
|
||||
defaultEncoding: 'JSON',
|
||||
queues: false,
|
||||
clientPools: {},
|
||||
// get an HttpClient, supply a name to use the pool of that name or the default if it isn't found
|
||||
httpClient: function(name) {
|
||||
if (name) {
|
||||
if (this.clientPools[name]) {
|
||||
return this.clientPools[name].getClient();
|
||||
}
|
||||
}
|
||||
return this.clientPools['default'].getClient();
|
||||
},
|
||||
// Pushing the given request to queue specified by it, in default operation this will immediately make a request
|
||||
// request might be delayed or never happen depending on the queue setup
|
||||
// making a sync request to a non immediate queue will cause you problems so just don't do it
|
||||
makeRequest: function(request) {
|
||||
if (!HTML_AJAX.queues[request.queue]) {
|
||||
var e = new Error('Unknown Queue: '+request.queue);
|
||||
if (HTML_AJAX.onError) {
|
||||
HTML_AJAX.onError(e);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
throw(e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
var qn = request.queue;
|
||||
var q = HTML_AJAX.queues[qn];
|
||||
|
||||
HTML_AJAX.queues[request.queue].addRequest(request);
|
||||
return HTML_AJAX.queues[request.queue].processRequest();
|
||||
}
|
||||
},
|
||||
// get a serializer object for a specific encoding
|
||||
serializerForEncoding: function(encoding) {
|
||||
for(var i in HTML_AJAX.contentTypeMap) {
|
||||
if (encoding == HTML_AJAX.contentTypeMap[i] || encoding == i) {
|
||||
return eval("new HTML_AJAX_Serialize_"+i+";");
|
||||
}
|
||||
}
|
||||
return new HTML_AJAX_Serialize_Null();
|
||||
},
|
||||
fullcall: function(url,encoding,className,method,callback,args, options) {
|
||||
var serializer = HTML_AJAX.serializerForEncoding(encoding);
|
||||
|
||||
var request = new HTML_AJAX_Request(serializer);
|
||||
if (callback) {
|
||||
request.isAsync = true;
|
||||
}
|
||||
request.requestUrl = url;
|
||||
request.className = className;
|
||||
request.methodName = method;
|
||||
request.callback = callback;
|
||||
request.args = args;
|
||||
if (options) {
|
||||
for(var i in options) {
|
||||
request[i] = options[i];
|
||||
}
|
||||
if (options.grab) {
|
||||
if (!request.args || !request.args.length) {
|
||||
request.requestType = 'GET';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HTML_AJAX.makeRequest(request);
|
||||
},
|
||||
callPhpCallback: function(phpCallback, jsCallback, url) {
|
||||
var args = new Array();
|
||||
for (var i = 3; i < arguments.length; i++) {
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
if (HTML_AJAX_Util.getType(phpCallback[0]) == 'object') {
|
||||
jsCallback(phpCallback[0][phpCallback[1]](args));
|
||||
return;
|
||||
}
|
||||
if (!url) {
|
||||
url = HTML_AJAX.defaultServerUrl;
|
||||
}
|
||||
HTML_AJAX.fullcall(url, HTML_AJAX.defaultEncoding,
|
||||
false, false, jsCallback, args, {phpCallback: phpCallback});
|
||||
},
|
||||
call: function(className,method,callback) {
|
||||
var args = new Array();
|
||||
for(var i = 3; i < arguments.length; i++) {
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
return HTML_AJAX.fullcall(HTML_AJAX.defaultServerUrl,HTML_AJAX.defaultEncoding,className,method,callback,args);
|
||||
},
|
||||
grab: function(url,callback,options) {
|
||||
if (!options) {
|
||||
options = {grab:true};
|
||||
}
|
||||
else {
|
||||
options['grab'] = true;
|
||||
}
|
||||
return HTML_AJAX.fullcall(url,'Null',false,null,callback, '', options);
|
||||
},
|
||||
post: function(url,payload,callback,options) {
|
||||
var serializer = 'Null';
|
||||
if (HTML_AJAX_Util.getType(payload) == 'object') {
|
||||
serializer = 'Urlencoded';
|
||||
}
|
||||
return HTML_AJAX.fullcall(url,serializer,false,null,callback, payload, options);
|
||||
},
|
||||
replace: function(id) {
|
||||
var callback = function(result) {
|
||||
HTML_AJAX_Util.setInnerHTML(HTML_AJAX_Util.getElement(id),result);
|
||||
}
|
||||
if (arguments.length == 2) {
|
||||
// grab replacement
|
||||
HTML_AJAX.grab(arguments[1],callback);
|
||||
}
|
||||
else {
|
||||
// call replacement
|
||||
var args = new Array();
|
||||
for(var i = 3; i < arguments.length; i++) {
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
HTML_AJAX.fullcall(HTML_AJAX.defaultServerUrl,HTML_AJAX.defaultEncoding,arguments[1],arguments[2],callback,args, {grab:true});
|
||||
}
|
||||
},
|
||||
append: function(id) {
|
||||
var callback = function(result) {
|
||||
HTML_AJAX_Util.setInnerHTML(HTML_AJAX_Util.getElement(id),result,'append');
|
||||
}
|
||||
if (arguments.length == 2) {
|
||||
// grab replacement
|
||||
HTML_AJAX.grab(arguments[1],callback);
|
||||
}
|
||||
else {
|
||||
// call replacement
|
||||
var args = new Array();
|
||||
for(var i = 3; i < arguments.length; i++) {
|
||||
args.push(arguments[i]);
|
||||
}
|
||||
HTML_AJAX.fullcall(HTML_AJAX.defaultServerUrl,HTML_AJAX.defaultEncoding,arguments[1],arguments[2],callback,args, {grab:true});
|
||||
}
|
||||
},
|
||||
// override to add top level loading notification (start)
|
||||
Open: function(request) {
|
||||
},
|
||||
// override to add top level loading notification (finish)
|
||||
Load: function(request) {
|
||||
},
|
||||
/*
|
||||
// A really basic error handler
|
||||
onError: function(e) {
|
||||
msg = "";
|
||||
for(var i in e) {
|
||||
msg += i+':'+e[i]+"\n";
|
||||
}
|
||||
alert(msg);
|
||||
},
|
||||
*/
|
||||
// Class postfix to content-type map
|
||||
contentTypeMap: {
|
||||
'JSON': 'application/json',
|
||||
'Null': 'text/plain',
|
||||
'Error': 'application/error',
|
||||
'PHP': 'application/php-serialized',
|
||||
'HA' : 'application/html_ajax_action',
|
||||
'Urlencoded': 'application/x-www-form-urlencoded'
|
||||
},
|
||||
// used internally to make queues work, override Load or onError to perform custom events when a request is complete
|
||||
// fires on success and error
|
||||
requestComplete: function(request,error) {
|
||||
for(var i in HTML_AJAX.queues) {
|
||||
if (HTML_AJAX.queues[i].requestComplete) {
|
||||
HTML_AJAX.queues[i].requestComplete(request,error);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// turns a form into a urlencoded string
|
||||
formEncode: function(form, array_format) {
|
||||
form = HTML_AJAX_Util.getElement(form);
|
||||
var el, inpType, value, name;
|
||||
var out = (array_format) ? {} : '';
|
||||
var inputTags = form.getElementsByTagName('INPUT');
|
||||
var selectTags = form.getElementsByTagName('SELECT');
|
||||
var buttonTags = form.getElementsByTagName('BUTTON');
|
||||
var textareaTags = form.getElementsByTagName('TEXTAREA');
|
||||
var arrayRegex = /(.+)%5B%5D/;
|
||||
|
||||
var validElement = function (element) {
|
||||
if (!element || !element.getAttribute) {
|
||||
return false;
|
||||
}
|
||||
el = element;
|
||||
name = HTML_AJAX_Util.encodeUrl(el.getAttribute('name'));
|
||||
if (!name) {
|
||||
// no element name so skip
|
||||
return false;
|
||||
}
|
||||
if (element.disabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!array_format) {
|
||||
value = HTML_AJAX_Util.encodeUrl(el.value);
|
||||
} else {
|
||||
value = el.value;
|
||||
}
|
||||
|
||||
inpType = el.getAttribute('type');
|
||||
return true;
|
||||
}
|
||||
|
||||
inputLoop:
|
||||
for (var i=0; i < inputTags.length; i++) {
|
||||
if (!validElement(inputTags[i])) {
|
||||
continue;
|
||||
}
|
||||
if (inpType == 'checkbox' || inpType == 'radio') {
|
||||
if (!el.checked) {
|
||||
// unchecked radios/checkboxes don't get submitted
|
||||
continue inputLoop;
|
||||
}
|
||||
var arr_var = arrayRegex.exec(name);
|
||||
if (array_format && arr_var) {
|
||||
if (!out[arr_var[1]]) {
|
||||
out[arr_var[1]] = new Array();
|
||||
}
|
||||
out[arr_var[1]].push(value);
|
||||
continue inputLoop;
|
||||
}
|
||||
}
|
||||
// add element to output array
|
||||
if (array_format) {
|
||||
out[name] = value;
|
||||
} else {
|
||||
out += name + '=' + value + '&';
|
||||
}
|
||||
} // end inputLoop
|
||||
|
||||
selectLoop:
|
||||
for (var i=0; i<selectTags.length; i++) {
|
||||
if (!validElement(selectTags[i])) {
|
||||
continue selectLoop;
|
||||
}
|
||||
var options = el.options;
|
||||
for (var z=0; z<options.length; z++){
|
||||
var option=options[z];
|
||||
if(option.selected){
|
||||
if (array_format) {
|
||||
if (el.type == 'select-one') {
|
||||
out[name] = option.value;
|
||||
//only one item can be selected
|
||||
continue selectLoop;
|
||||
} else {
|
||||
if (!out[name]) {
|
||||
out[name] = new Array();
|
||||
}
|
||||
out[name].push(option.value);
|
||||
}
|
||||
} else {
|
||||
out += name + '=' + option.value + '&';
|
||||
if (el.type == 'select-one') {
|
||||
continue selectLoop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // end selectLoop
|
||||
|
||||
buttonLoop:
|
||||
for (var i=0; i<buttonTags.length; i++) {
|
||||
if (!validElement(buttonTags[i])) {
|
||||
continue;
|
||||
}
|
||||
// add element to output array
|
||||
if (array_format) {
|
||||
out[name] = value;
|
||||
} else {
|
||||
out += name + '=' + value + '&';
|
||||
}
|
||||
} // end buttonLoop
|
||||
|
||||
textareaLoop:
|
||||
for (var i=0; i<textareaTags.length; i++) {
|
||||
if (!validElement(textareaTags[i])) {
|
||||
continue;
|
||||
}
|
||||
// add element to output array
|
||||
if (array_format) {
|
||||
out[name] = value;
|
||||
} else {
|
||||
out += name + '=' + value + '&';
|
||||
}
|
||||
} // end textareaLoop
|
||||
|
||||
return out;
|
||||
},
|
||||
// submits a form through ajax. both arguments can be either DOM nodes or IDs, if the target is omitted then the form is set to be the target
|
||||
formSubmit: function (form, target, options)
|
||||
{
|
||||
form = HTML_AJAX_Util.getElement(form);
|
||||
if (!form) {
|
||||
// let the submit be processed normally
|
||||
return false;
|
||||
}
|
||||
|
||||
var out = HTML_AJAX.formEncode(form);
|
||||
target = HTML_AJAX_Util.getElement(target);
|
||||
if (!target) {
|
||||
target = form;
|
||||
}
|
||||
try
|
||||
{
|
||||
var action = form.attributes['action'].value;
|
||||
}
|
||||
catch(e){}
|
||||
if(action == undefined)
|
||||
{
|
||||
action = form.getAttribute('action');
|
||||
}
|
||||
|
||||
var callback = false;
|
||||
if (HTML_AJAX_Util.getType(target) == 'function') {
|
||||
callback = target;
|
||||
}
|
||||
else {
|
||||
callback = function(result) {
|
||||
// result will be undefined if HA_Action is returned, so skip the replace
|
||||
if (typeof result != 'undefined') {
|
||||
HTML_AJAX_Util.setInnerHTML(target,result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var serializer = HTML_AJAX.serializerForEncoding('Null');
|
||||
var request = new HTML_AJAX_Request(serializer);
|
||||
request.isAsync = true;
|
||||
request.callback = callback;
|
||||
|
||||
switch (form.getAttribute('method').toLowerCase()) {
|
||||
case 'post':
|
||||
var headers = {};
|
||||
headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
||||
request.customHeaders = headers;
|
||||
request.requestType = 'POST';
|
||||
request.requestUrl = action;
|
||||
request.args = out;
|
||||
break;
|
||||
default:
|
||||
if (action.indexOf('?') == -1) {
|
||||
out = '?' + out.substr(0, out.length - 1);
|
||||
}
|
||||
request.requestUrl = action+out;
|
||||
request.requestType = 'GET';
|
||||
}
|
||||
|
||||
if(options) {
|
||||
for(var i in options) {
|
||||
request[i] = options[i];
|
||||
}
|
||||
}
|
||||
HTML_AJAX.makeRequest(request);
|
||||
return true;
|
||||
}, // end formSubmit()
|
||||
makeFormAJAX: function(form,target,options) {
|
||||
form = HTML_AJAX_Util.getElement(form);
|
||||
var preSubmit = false;
|
||||
if(typeof form.onsubmit != 'undefined') {
|
||||
preSubmit = form.onsubmit;
|
||||
form.onsubmit = function() {};
|
||||
}
|
||||
form.HAOptions = options;
|
||||
var handler = function(e) {
|
||||
var form = HTML_AJAX_Util.eventTarget(e);
|
||||
|
||||
var valid = true;
|
||||
if (preSubmit) {
|
||||
valid = preSubmit();
|
||||
}
|
||||
if (valid) {
|
||||
HTML_AJAX.formSubmit(form,target,form.HAOptions);
|
||||
}
|
||||
// cancel submission in IE
|
||||
e.returnValue = false;
|
||||
// cancel submission in FF
|
||||
if (e.preventDefault) {
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
HTML_AJAX_Util.registerEvent(form,'submit',handler);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// small classes that I don't want to put in there own file
|
||||
|
||||
function HTML_AJAX_Serialize_Null() {}
|
||||
HTML_AJAX_Serialize_Null.prototype = {
|
||||
contentType: 'text/plain; charset=utf-8',
|
||||
serialize: function(input) {
|
||||
return new String(input).valueOf();
|
||||
},
|
||||
|
||||
unserialize: function(input) {
|
||||
return new String(input).valueOf();
|
||||
}
|
||||
}
|
||||
|
||||
function HTML_AJAX_Serialize_XML() {}
|
||||
HTML_AJAX_Serialize_XML.prototype = {
|
||||
contentType: 'application/xml; charset=utf-8',
|
||||
serialize: function(input) {
|
||||
var xml = '';
|
||||
if(typeof(input) == 'object' && input)
|
||||
{
|
||||
for (var i = 0;i<input.length;i++)
|
||||
{
|
||||
xml += new XMLSerializer().serializeToString(input[i]);
|
||||
}
|
||||
}
|
||||
return xml;
|
||||
},
|
||||
|
||||
unserialize: function(input) {
|
||||
return input;
|
||||
}
|
||||
}
|
||||
|
||||
// serialization class for JSON, wrapper for JSON.stringify in json.js
|
||||
function HTML_AJAX_Serialize_JSON() {}
|
||||
HTML_AJAX_Serialize_JSON.prototype = {
|
||||
contentType: 'application/json; charset=utf-8',
|
||||
serialize: function(input) {
|
||||
return HTML_AJAX_JSON.stringify(input);
|
||||
},
|
||||
unserialize: function(input) {
|
||||
try {
|
||||
return eval('('+input+')');
|
||||
} catch(e) {
|
||||
// sometimes JSON encoded input isn't created properly, if eval of it fails we use the more forgiving but slower parser so will at least get something
|
||||
return HTML_AJAX_JSON.parse(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function HTML_AJAX_Serialize_Error() {}
|
||||
HTML_AJAX_Serialize_Error.prototype = {
|
||||
contentType: 'application/error; charset=utf-8',
|
||||
serialize: function(input) {
|
||||
var ser = new HTML_AJAX_Serialize_JSON();
|
||||
return ser.serialize(input);
|
||||
},
|
||||
unserialize: function(input) {
|
||||
var ser = new HTML_AJAX_Serialize_JSON();
|
||||
var data = new ser.unserialize(input);
|
||||
|
||||
var e = new Error('PHP Error: '+data.errStr);
|
||||
for(var i in data) {
|
||||
e[i] = data[i];
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// Processing Queues
|
||||
|
||||
// simple queue, just processes the request immediately
|
||||
function HTML_AJAX_Queue_Immediate() {}
|
||||
HTML_AJAX_Queue_Immediate.prototype = {
|
||||
request: false,
|
||||
addRequest: function(request) {
|
||||
this.request = request;
|
||||
},
|
||||
processRequest: function() {
|
||||
var client = HTML_AJAX.httpClient();
|
||||
client.request = this.request;
|
||||
return client.makeRequest();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// create a default queue, has to happen after the Queue class has been defined
|
||||
HTML_AJAX.queues = new Object();
|
||||
HTML_AJAX.queues['default'] = new HTML_AJAX_Queue_Immediate();
|
||||
|
||||
236
include/pear/data/HTML_AJAX/js/Queue.js
Normal file
236
include/pear/data/HTML_AJAX/js/Queue.js
Normal file
@@ -0,0 +1,236 @@
|
||||
/**
|
||||
* Various processing queues, use when you want to control how multiple requests are made
|
||||
* @category HTML
|
||||
* @package AJAX
|
||||
* @author Joshua Eichorn <josh@bluga.net>
|
||||
* @copyright 2005 Joshua Eichorn
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
*/
|
||||
|
||||
// Single Buffer queue with interval
|
||||
// works by attempting to send a request every x miliseconds
|
||||
// if an item is currently in the queue when a new item is added it will be replaced
|
||||
// simple queue, just processes the request immediately
|
||||
// the first request starts the interval timer
|
||||
function HTML_AJAX_Queue_Interval_SingleBuffer(interval,singleOutstandingRequest) {
|
||||
this.interval = interval;
|
||||
if (singleOutstandingRequest) {
|
||||
this.singleOutstandingRequest = true;
|
||||
}
|
||||
}
|
||||
HTML_AJAX_Queue_Interval_SingleBuffer.prototype = {
|
||||
request: false,
|
||||
_intervalId: false,
|
||||
singleOutstandingRequest: false,
|
||||
client: false,
|
||||
addRequest: function(request) {
|
||||
this.request = request;
|
||||
},
|
||||
processRequest: function() {
|
||||
if (!this._intervalId) {
|
||||
this.runInterval();
|
||||
this.start();
|
||||
}
|
||||
},
|
||||
start: function() {
|
||||
var self = this;
|
||||
this._intervalId = setInterval(function() { self.runInterval() },this.interval);
|
||||
},
|
||||
stop: function() {
|
||||
clearInterval(this._intervalId);
|
||||
},
|
||||
runInterval: function() {
|
||||
if (this.request) {
|
||||
if (this.singleOutstandingRequest && this.client) {
|
||||
this.client.abort();
|
||||
}
|
||||
this.client = HTML_AJAX.httpClient();
|
||||
this.client.request = this.request;
|
||||
this.request = false;
|
||||
this.client.makeRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Requests return in the same order they were called
|
||||
// this helps handle high latency situations
|
||||
function HTML_AJAX_Queue_Ordered() { }
|
||||
HTML_AJAX_Queue_Ordered.prototype = {
|
||||
request: false,
|
||||
order: 0,
|
||||
current: 0,
|
||||
callbacks: {},
|
||||
interned: {},
|
||||
addRequest: function(request) {
|
||||
request.order = this.order;
|
||||
this.request = request;
|
||||
this.callbacks[this.order] = this.request.callback;
|
||||
var self = this;
|
||||
this.request.callback = function(result) {
|
||||
self.processCallback(result,request.order);
|
||||
}
|
||||
},
|
||||
processRequest: function() {
|
||||
var client = HTML_AJAX.httpClient();
|
||||
client.request = this.request;
|
||||
client.makeRequest();
|
||||
this.order++;
|
||||
},
|
||||
requestComplete: function(request,e) {
|
||||
// something when wrong with the request lets stop waiting for it
|
||||
if (e) {
|
||||
this.current++;
|
||||
}
|
||||
},
|
||||
processCallback: function(result,order) {
|
||||
if (order == this.current) {
|
||||
this.callbacks[order](result);
|
||||
this.current++;
|
||||
}
|
||||
else {
|
||||
this.interned[order] = result;
|
||||
}
|
||||
while (this.interned[this.current]) {
|
||||
this.callbacks[this.current](this.interned[this.current]);
|
||||
this.current++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Make a single request at once, canceling and currently outstanding requests when a new one is made
|
||||
function HTML_AJAX_Queue_Single() {
|
||||
}
|
||||
HTML_AJAX_Queue_Single.prototype = {
|
||||
request: false,
|
||||
client: false,
|
||||
addRequest: function(request) {
|
||||
this.request = request;
|
||||
},
|
||||
processRequest: function() {
|
||||
if (this.request) {
|
||||
if (this.client) {
|
||||
this.client.abort();
|
||||
}
|
||||
this.client = HTML_AJAX.httpClient();
|
||||
this.client.request = this.request;
|
||||
this.request = false;
|
||||
this.client.makeRequest();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Priority queue
|
||||
*
|
||||
* @author Arpad Ray <arpad@php.net>
|
||||
*/
|
||||
function HTML_AJAX_Queue_Priority_Item(item, time) {
|
||||
this.item = item;
|
||||
this.time = time;
|
||||
}
|
||||
HTML_AJAX_Queue_Priority_Item.prototype = {
|
||||
compareTo: function (other) {
|
||||
var ret = this.item.compareTo(other.item);
|
||||
if (ret == 0) {
|
||||
ret = this.time - other.time;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
function HTML_AJAX_Queue_Priority_Simple(interval) {
|
||||
this.interval = interval;
|
||||
this.idleMax = 10; // keep the interval going with an empty queue for 10 intervals
|
||||
this.requestTimeout = 5; // retry uncompleted requests after 5 seconds
|
||||
this.checkRetryChance = 0.1; // check for uncompleted requests to retry on 10% of intervals
|
||||
this._intervalId = 0;
|
||||
this._requests = [];
|
||||
this._removed = [];
|
||||
this._len = 0;
|
||||
this._removedLen = 0;
|
||||
this._idle = 0;
|
||||
}
|
||||
HTML_AJAX_Queue_Priority_Simple.prototype = {
|
||||
isEmpty: function () {
|
||||
return this._len == 0;
|
||||
},
|
||||
addRequest: function (request) {
|
||||
request = new HTML_AJAX_Queue_Priority_Item(request, new Date().getTime());
|
||||
++this._len;
|
||||
if (this.isEmpty()) {
|
||||
this._requests[0] = request;
|
||||
return;
|
||||
}
|
||||
for (i = 0; i < this._len - 1; i++) {
|
||||
if (request.compareTo(this._requests[i]) < 0) {
|
||||
this._requests.splice(i, 1, request, this._requests[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
this._requests.push(request);
|
||||
},
|
||||
peek: function () {
|
||||
return (this.isEmpty() ? false : this._requests[0]);
|
||||
},
|
||||
requestComplete: function (request) {
|
||||
for (i = 0; i < this._removedLen; i++) {
|
||||
if (this._removed[i].item == request) {
|
||||
this._removed.splice(i, 1);
|
||||
--this._removedLen;
|
||||
out('removed from _removed');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
processRequest: function() {
|
||||
if (!this._intervalId) {
|
||||
this._runInterval();
|
||||
this._start();
|
||||
}
|
||||
this._idle = 0;
|
||||
},
|
||||
_runInterval: function() {
|
||||
if (Math.random() < this.checkRetryChance) {
|
||||
this._doRetries();
|
||||
}
|
||||
if (this.isEmpty()) {
|
||||
if (++this._idle > this.idleMax) {
|
||||
this._stop();
|
||||
}
|
||||
return;
|
||||
}
|
||||
var client = HTML_AJAX.httpClient();
|
||||
if (!client) {
|
||||
return;
|
||||
}
|
||||
var request = this.peek();
|
||||
if (!request) {
|
||||
this._requests.splice(0, 1);
|
||||
return;
|
||||
}
|
||||
client.request = request.item;
|
||||
client.makeRequest();
|
||||
this._requests.splice(0, 1);
|
||||
--this._len;
|
||||
this._removed[this._removedLen++] = new HTML_AJAX_Queue_Priority_Item(request, new Date().getTime());
|
||||
},
|
||||
_doRetries: function () {
|
||||
for (i = 0; i < this._removedLen; i++) {
|
||||
if (this._removed[i].time + this._requestTimeout < new Date().getTime()) {
|
||||
this.addRequest(request.item);
|
||||
this._removed.splice(i, 1);
|
||||
--this._removedLen;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
_start: function() {
|
||||
var self = this;
|
||||
this._intervalId = setInterval(function() { self._runInterval() }, this.interval);
|
||||
},
|
||||
_stop: function() {
|
||||
clearInterval(this._intervalId);
|
||||
this._intervalId = 0;
|
||||
}
|
||||
};
|
||||
144
include/pear/data/HTML_AJAX/js/Request.js
Normal file
144
include/pear/data/HTML_AJAX/js/Request.js
Normal file
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
* Class that contains everything needed to make a request
|
||||
* This includes:
|
||||
* The url were calling
|
||||
* If were calling a remote method, the class and method name
|
||||
* The payload, unserialized
|
||||
* The timeout for async calls
|
||||
* The callback method
|
||||
* Optional event handlers: onError, Load, Send
|
||||
* A serializer instance
|
||||
*
|
||||
* @category HTML
|
||||
* @package AJAX
|
||||
* @author Joshua Eichorn <josh@bluga.net>
|
||||
* @copyright 2005 Joshua Eichorn
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
*
|
||||
* See Main.js for author/license details
|
||||
*/
|
||||
function HTML_AJAX_Request(serializer) {
|
||||
this.serializer = serializer;
|
||||
}
|
||||
HTML_AJAX_Request.prototype = {
|
||||
|
||||
// Instance of a serializer
|
||||
serializer: null,
|
||||
|
||||
// Is this an async request
|
||||
isAsync: false,
|
||||
|
||||
// HTTP verb
|
||||
requestType: 'POST',
|
||||
|
||||
// The actual URL the request is sent to
|
||||
requestUrl: '',
|
||||
|
||||
// Remote Class
|
||||
className: null,
|
||||
|
||||
// Remote Method
|
||||
methodName: null,
|
||||
|
||||
// Timeout in milliseconds for requests
|
||||
timeout: 20000,
|
||||
|
||||
// unserialized data, for rpc calls use add args, to send raw data just set this directly
|
||||
args: null,
|
||||
|
||||
// async callback method
|
||||
callback: null,
|
||||
|
||||
// Queue to push this request too
|
||||
queue: 'default',
|
||||
|
||||
// default priority
|
||||
priority: 0,
|
||||
|
||||
// a hash of headers to add to add to this request
|
||||
customHeaders: {'X-Requested-With': 'XMLHttpRequest', 'X-Ajax-Engine': 'HTML_AJAX/0.5.2'},
|
||||
|
||||
// true if this request will be sent using iframes
|
||||
iframe: false,
|
||||
|
||||
// is this a grab request? if so we need to proxy for iframes
|
||||
grab: false,
|
||||
|
||||
// true if this request should expect a multipart response
|
||||
multipart: false,
|
||||
|
||||
// remote callback
|
||||
phpCallback: false,
|
||||
|
||||
/**
|
||||
* Add an argument for the remote method
|
||||
* @param string argument name
|
||||
* @param mixed value
|
||||
* @return void
|
||||
* @throws Error code 1004
|
||||
*/
|
||||
addArg: function(name, value)
|
||||
{
|
||||
if ( !this.args ) {
|
||||
this.args = [];
|
||||
}
|
||||
if (!/[^a-zA-Z_0-9]/.test(name) ) {
|
||||
this.args[name] = value;
|
||||
} else {
|
||||
throw new Error('Invalid parameter name ('+name+')');
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the payload in a serialized manner
|
||||
*/
|
||||
getSerializedPayload: function() {
|
||||
return this.serializer.serialize(this.args);
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the content type
|
||||
*/
|
||||
getContentType: function() {
|
||||
return this.serializer.contentType;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the complete url, adding in any needed get params for rpc
|
||||
*/
|
||||
completeUrl: function() {
|
||||
if (this.className || this.methodName) {
|
||||
this.addGet('c', this.className);
|
||||
this.addGet('m', this.methodName);
|
||||
}
|
||||
if (this.phpCallback) {
|
||||
if (HTML_AJAX_Util.getType(this.phpCallback) == 'array') {
|
||||
this.phpCallback = this.phpCallback.join('.');
|
||||
}
|
||||
this.addGet('cb', this.phpCallback);
|
||||
}
|
||||
if (this.multipart) {
|
||||
this.addGet('multipart', '1');
|
||||
}
|
||||
return this.requestUrl;
|
||||
},
|
||||
|
||||
/**
|
||||
* Compare to another request by priority
|
||||
*/
|
||||
compareTo: function(other) {
|
||||
if (this.priority == other.priority) {
|
||||
return 0;
|
||||
}
|
||||
return (this.priority > other.priority ? 1 : -1);
|
||||
},
|
||||
|
||||
/**
|
||||
* Add a GET argument
|
||||
*/
|
||||
addGet: function(name, value) {
|
||||
var url = new String(this.requestUrl);
|
||||
url += (url.indexOf('?') < 0 ? '?' : '&') + escape(name) + '=' + escape(value);
|
||||
this.requestUrl = url;
|
||||
}
|
||||
}
|
||||
126
include/pear/data/HTML_AJAX/js/behavior/behavior.js
Normal file
126
include/pear/data/HTML_AJAX/js/behavior/behavior.js
Normal file
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
|
||||
ModifiedBehavior v1.0 by Ron Lancaster based on Ben Nolan's Behaviour, June 2005 implementation.
|
||||
Modified to use Dean Edward's CSS Query.
|
||||
|
||||
Description
|
||||
----------
|
||||
|
||||
Uses css selectors to apply javascript Behaviors to enable unobtrusive javascript in html documents.
|
||||
|
||||
Dependencies
|
||||
------------
|
||||
|
||||
Requires [Dean Edwards CSSQuery](http://dean.edwards.name/my/cssQuery/ "CSSQuery").
|
||||
|
||||
Usage
|
||||
------
|
||||
|
||||
Behavior.register(
|
||||
"b.someclass",
|
||||
function(element) {
|
||||
element.onclick = function(){
|
||||
alert(this.innerHTML);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
Behavior.register(
|
||||
"#someid u",
|
||||
function(element) {
|
||||
element.onmouseover = function(){
|
||||
this.innerHTML = "BLAH!";
|
||||
}
|
||||
},
|
||||
getElementByID("parent")
|
||||
);
|
||||
|
||||
Call `Behavior.apply()` to re-apply the rules (if you update the dom, etc).
|
||||
|
||||
License
|
||||
------
|
||||
|
||||
Reproduced under BSD licensed. Same license as Ben Nolan's implementation.
|
||||
|
||||
More information for Ben Nolan's implementation: <http://ripcord.co.nz/behaviour/>
|
||||
|
||||
*/
|
||||
|
||||
var Behavior = {
|
||||
// so to an id to get debug timings
|
||||
debug : false,
|
||||
|
||||
// private data member
|
||||
list : new Array(),
|
||||
|
||||
// private method
|
||||
addLoadEvent : function(func) {
|
||||
var oldonload = window.onload;
|
||||
|
||||
if (typeof window.onload != 'function') {
|
||||
window.onload = func;
|
||||
} else {
|
||||
window.onload = function() {
|
||||
oldonload();
|
||||
func();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// void apply() : Applies the registered ruleset.
|
||||
apply : function() {
|
||||
if (this.debug) {
|
||||
document.getElementById(this.debug).innerHTML += 'Apply: '+new Date()+'<br>';
|
||||
var total = 0;
|
||||
}
|
||||
if (Behavior.list.length > 2) {
|
||||
cssQuery.caching = true;
|
||||
}
|
||||
for (i = 0; i < Behavior.list.length; i++) {
|
||||
var rule = Behavior.list[i];
|
||||
|
||||
if (this.debug) { var ds = new Date() };
|
||||
var tags = cssQuery(rule.selector, rule.from);
|
||||
|
||||
if (this.debug) {
|
||||
var de = new Date();
|
||||
var ts = de.valueOf()-ds.valueOf();
|
||||
document.getElementById(this.debug).innerHTML += 'Rule: '+rule.selector+' - Took: '+ts+' - Returned: '+tags.length+' tags<br>';
|
||||
total += ts;
|
||||
}
|
||||
if (tags) {
|
||||
for (j = 0; j < tags.length; j++) {
|
||||
rule.action(tags[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Behavior.list.length > 2) {
|
||||
cssQuery.caching = false;
|
||||
}
|
||||
|
||||
if (this.debug) {
|
||||
document.getElementById(this.debug).innerHTML += 'Total rule apply time: '+total;
|
||||
}
|
||||
},
|
||||
|
||||
// void register() : register a css selector, and the action (function) to take,
|
||||
// from (optional) is a document, element or array of elements which is filtered by selector.
|
||||
register : function(selector, action, from) {
|
||||
Behavior.list.push(new BehaviorRule(selector, from, action));
|
||||
},
|
||||
|
||||
// void start() : initial application of ruleset at document load.
|
||||
start : function() {
|
||||
Behavior.addLoadEvent(function() {
|
||||
Behavior.apply();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function BehaviorRule(selector, from, action) {
|
||||
this.selector = selector;
|
||||
this.from = from;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
Behavior.start();
|
||||
6
include/pear/data/HTML_AJAX/js/behavior/cssQuery-p.js
Normal file
6
include/pear/data/HTML_AJAX/js/behavior/cssQuery-p.js
Normal file
File diff suppressed because one or more lines are too long
56
include/pear/data/HTML_AJAX/js/clientPool.js
Normal file
56
include/pear/data/HTML_AJAX/js/clientPool.js
Normal file
@@ -0,0 +1,56 @@
|
||||
HTML_AJAX_Client_Pool = function(maxClients, startingClients)
|
||||
{
|
||||
this.maxClients = maxClients;
|
||||
this._clients = [];
|
||||
this._len = 0;
|
||||
while (--startingClients > 0) {
|
||||
this.addClient();
|
||||
}
|
||||
}
|
||||
|
||||
HTML_AJAX_Client_Pool.prototype = {
|
||||
isEmpty: function()
|
||||
{
|
||||
return this._len == 0;
|
||||
},
|
||||
addClient: function()
|
||||
{
|
||||
if (this.maxClients != 0 && this._len > this.maxClients) {
|
||||
return false;
|
||||
}
|
||||
var key = this._len++;
|
||||
this._clients[key] = new HTML_AJAX_HttpClient();
|
||||
return this._clients[key];
|
||||
},
|
||||
getClient: function ()
|
||||
{
|
||||
for (var i = 0; i < this._len; i++) {
|
||||
if (!this._clients[i].callInProgress() && this._clients[i].callbackComplete) {
|
||||
return this._clients[i];
|
||||
}
|
||||
}
|
||||
var client = this.addClient();
|
||||
if (client) {
|
||||
return client;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
removeClient: function (client)
|
||||
{
|
||||
for (var i = 0; i < this._len; i++) {
|
||||
if (!this._clients[i] == client) {
|
||||
this._clients.splice(i, 1);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
clear: function ()
|
||||
{
|
||||
this._clients = [];
|
||||
this._len = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// create a default client pool with unlimited clients
|
||||
HTML_AJAX.clientPools['default'] = new HTML_AJAX_Client_Pool(0);
|
||||
619
include/pear/data/HTML_AJAX/js/dhtmlHistory.js
Normal file
619
include/pear/data/HTML_AJAX/js/dhtmlHistory.js
Normal file
@@ -0,0 +1,619 @@
|
||||
/**
|
||||
Copyright (c) 2005, Brad Neuberg, bkn3@columbia.edu
|
||||
http://codinginparadise.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the "Software"),
|
||||
to deal in the Software without restriction, including without limitation
|
||||
the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
and/or sell copies of the Software, and to permit persons to whom the
|
||||
Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
||||
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
|
||||
OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
|
||||
THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/** An object that provides DHTML history, history data, and bookmarking
|
||||
for AJAX applications. */
|
||||
window.dhtmlHistory = {
|
||||
/** Initializes our DHTML history. You should
|
||||
call this after the page is finished loading. */
|
||||
/** public */ initialize: function() {
|
||||
// only Internet Explorer needs to be explicitly initialized;
|
||||
// other browsers don't have its particular behaviors.
|
||||
// Basicly, IE doesn't autofill form data until the page
|
||||
// is finished loading, which means historyStorage won't
|
||||
// work until onload has been fired.
|
||||
if (this.isInternetExplorer() == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if this is the first time this page has loaded...
|
||||
if (historyStorage.hasKey("DhtmlHistory_pageLoaded") == false) {
|
||||
this.fireOnNewListener = false;
|
||||
this.firstLoad = true;
|
||||
historyStorage.put("DhtmlHistory_pageLoaded", true);
|
||||
}
|
||||
// else if this is a fake onload event
|
||||
else {
|
||||
this.fireOnNewListener = true;
|
||||
this.firstLoad = false;
|
||||
}
|
||||
},
|
||||
|
||||
/** Adds a history change listener. Note that
|
||||
only one listener is supported at this
|
||||
time. */
|
||||
/** public */ addListener: function(callback) {
|
||||
this.listener = callback;
|
||||
|
||||
// if the page was just loaded and we
|
||||
// should not ignore it, fire an event
|
||||
// to our new listener now
|
||||
if (this.fireOnNewListener == true) {
|
||||
this.fireHistoryEvent(this.currentLocation);
|
||||
this.fireOnNewListener = false;
|
||||
}
|
||||
},
|
||||
|
||||
/** public */ add: function(newLocation, historyData) {
|
||||
// most browsers require that we wait a certain amount of time before changing the
|
||||
// location, such as 200 milliseconds; rather than forcing external callers to use
|
||||
// window.setTimeout to account for this to prevent bugs, we internally handle this
|
||||
// detail by using a 'currentWaitTime' variable and have requests wait in line
|
||||
var self = this;
|
||||
var addImpl = function() {
|
||||
// indicate that the current wait time is now less
|
||||
if (self.currentWaitTime > 0)
|
||||
self.currentWaitTime = self.currentWaitTime - self.WAIT_TIME;
|
||||
|
||||
// remove any leading hash symbols on newLocation
|
||||
newLocation = self.removeHash(newLocation);
|
||||
|
||||
// IE has a strange bug; if the newLocation
|
||||
// is the same as _any_ preexisting id in the
|
||||
// document, then the history action gets recorded
|
||||
// twice; throw a programmer exception if there is
|
||||
// an element with this ID
|
||||
var idCheck = document.getElementById(newLocation);
|
||||
if (idCheck != undefined || idCheck != null) {
|
||||
var message =
|
||||
"Exception: History locations can not have "
|
||||
+ "the same value as _any_ id's "
|
||||
+ "that might be in the document, "
|
||||
+ "due to a bug in Internet "
|
||||
+ "Explorer; please ask the "
|
||||
+ "developer to choose a history "
|
||||
+ "location that does not match "
|
||||
+ "any HTML id's in this "
|
||||
+ "document. The following ID "
|
||||
+ "is already taken and can not "
|
||||
+ "be a location: "
|
||||
+ newLocation;
|
||||
|
||||
throw message;
|
||||
}
|
||||
|
||||
// store the history data into history storage
|
||||
historyStorage.put(newLocation, historyData);
|
||||
|
||||
// indicate to the browser to ignore this upcomming
|
||||
// location change
|
||||
self.ignoreLocationChange = true;
|
||||
|
||||
// indicate to IE that this is an atomic location change
|
||||
// block
|
||||
this.ieAtomicLocationChange = true;
|
||||
|
||||
// save this as our current location
|
||||
self.currentLocation = newLocation;
|
||||
|
||||
// change the browser location
|
||||
window.location.hash = newLocation;
|
||||
|
||||
// change the hidden iframe's location if on IE
|
||||
if (self.isInternetExplorer())
|
||||
self.iframe.src = "blank.html?" + newLocation;
|
||||
|
||||
// end of atomic location change block
|
||||
// for IE
|
||||
this.ieAtomicLocationChange = false;
|
||||
};
|
||||
|
||||
// now execute this add request after waiting a certain amount of time, so as to
|
||||
// queue up requests
|
||||
window.setTimeout(addImpl, this.currentWaitTime);
|
||||
|
||||
// indicate that the next request will have to wait for awhile
|
||||
this.currentWaitTime = this.currentWaitTime + this.WAIT_TIME;
|
||||
},
|
||||
|
||||
/** public */ isFirstLoad: function() {
|
||||
if (this.firstLoad == true) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/** public */ isInternational: function() {
|
||||
return false;
|
||||
},
|
||||
|
||||
/** public */ getVersion: function() {
|
||||
return "0.05";
|
||||
},
|
||||
|
||||
/** Gets the current hash value that is in the browser's
|
||||
location bar, removing leading # symbols if they are present. */
|
||||
/** public */ getCurrentLocation: function() {
|
||||
var currentLocation = this.removeHash(window.location.hash);
|
||||
|
||||
return currentLocation;
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** Our current hash location, without the "#" symbol. */
|
||||
/** private */ currentLocation: null,
|
||||
|
||||
/** Our history change listener. */
|
||||
/** private */ listener: null,
|
||||
|
||||
/** A hidden IFrame we use in Internet Explorer to detect history
|
||||
changes. */
|
||||
/** private */ iframe: null,
|
||||
|
||||
/** Indicates to the browser whether to ignore location changes. */
|
||||
/** private */ ignoreLocationChange: null,
|
||||
|
||||
/** The amount of time in milliseconds that we should wait between add requests.
|
||||
Firefox is okay with 200 ms, but Internet Explorer needs 400. */
|
||||
/** private */ WAIT_TIME: 200,
|
||||
|
||||
/** The amount of time in milliseconds an add request has to wait in line before being
|
||||
run on a window.setTimeout. */
|
||||
/** private */ currentWaitTime: 0,
|
||||
|
||||
/** A flag that indicates that we should fire a history change event
|
||||
when we are ready, i.e. after we are initialized and
|
||||
we have a history change listener. This is needed due to
|
||||
an edge case in browsers other than Internet Explorer; if
|
||||
you leave a page entirely then return, we must fire this
|
||||
as a history change event. Unfortunately, we have lost
|
||||
all references to listeners from earlier, because JavaScript
|
||||
clears out. */
|
||||
/** private */ fireOnNewListener: null,
|
||||
|
||||
/** A variable that indicates whether this is the first time
|
||||
this page has been loaded. If you go to a web page, leave
|
||||
it for another one, and then return, the page's onload
|
||||
listener fires again. We need a way to differentiate
|
||||
between the first page load and subsequent ones.
|
||||
This variable works hand in hand with the pageLoaded
|
||||
variable we store into historyStorage.*/
|
||||
/** private */ firstLoad: null,
|
||||
|
||||
/** A variable to handle an important edge case in Internet
|
||||
Explorer. In IE, if a user manually types an address into
|
||||
their browser's location bar, we must intercept this by
|
||||
continiously checking the location bar with an timer
|
||||
interval. However, if we manually change the location
|
||||
bar ourselves programmatically, when using our hidden
|
||||
iframe, we need to ignore these changes. Unfortunately,
|
||||
these changes are not atomic, so we surround them with
|
||||
the variable 'ieAtomicLocationChange', that if true,
|
||||
means we are programmatically setting the location and
|
||||
should ignore this atomic chunked change. */
|
||||
/** private */ ieAtomicLocationChange: null,
|
||||
|
||||
/** Creates the DHTML history infrastructure. */
|
||||
/** private */ create: function() {
|
||||
// get our initial location
|
||||
var initialHash = this.getCurrentLocation();
|
||||
|
||||
// save this as our current location
|
||||
this.currentLocation = initialHash;
|
||||
|
||||
// write out a hidden iframe for IE and
|
||||
// set the amount of time to wait between add() requests
|
||||
if (this.isInternetExplorer()) {
|
||||
document.write("<iframe style='border: 0px; width: 1px; "
|
||||
+ "height: 1px; position: absolute; bottom: 0px; "
|
||||
+ "right: 0px; visibility: visible;' "
|
||||
+ "name='DhtmlHistoryFrame' id='DhtmlHistoryFrame' "
|
||||
+ "src='blank.html?" + initialHash + "'>"
|
||||
+ "</iframe>");
|
||||
// wait 400 milliseconds between history
|
||||
// updates on IE, versus 200 on Firefox
|
||||
this.WAIT_TIME = 400;
|
||||
}
|
||||
|
||||
// add an unload listener for the page; this is
|
||||
// needed for Firefox 1.5+ because this browser caches all
|
||||
// dynamic updates to the page, which can break some of our
|
||||
// logic related to testing whether this is the first instance
|
||||
// a page has loaded or whether it is being pulled from the cache
|
||||
var self = this;
|
||||
window.onunload = function() {
|
||||
self.firstLoad = null;
|
||||
};
|
||||
|
||||
// determine if this is our first page load;
|
||||
// for Internet Explorer, we do this in
|
||||
// this.iframeLoaded(), which is fired on
|
||||
// page load. We do it there because
|
||||
// we have no historyStorage at this point
|
||||
// in IE, which only exists after the page
|
||||
// is finished loading for that browser
|
||||
if (this.isInternetExplorer() == false) {
|
||||
if (historyStorage.hasKey("DhtmlHistory_pageLoaded") == false) {
|
||||
this.ignoreLocationChange = true;
|
||||
this.firstLoad = true;
|
||||
historyStorage.put("DhtmlHistory_pageLoaded", true);
|
||||
}
|
||||
else {
|
||||
// indicate that we want to pay attention
|
||||
// to this location change
|
||||
this.ignoreLocationChange = false;
|
||||
// For browser's other than IE, fire
|
||||
// a history change event; on IE,
|
||||
// the event will be thrown automatically
|
||||
// when it's hidden iframe reloads
|
||||
// on page load.
|
||||
// Unfortunately, we don't have any
|
||||
// listeners yet; indicate that we want
|
||||
// to fire an event when a listener
|
||||
// is added.
|
||||
this.fireOnNewListener = true;
|
||||
}
|
||||
}
|
||||
else { // Internet Explorer
|
||||
// the iframe will get loaded on page
|
||||
// load, and we want to ignore this fact
|
||||
this.ignoreLocationChange = true;
|
||||
}
|
||||
|
||||
if (this.isInternetExplorer()) {
|
||||
this.iframe = document.getElementById("DhtmlHistoryFrame");
|
||||
}
|
||||
|
||||
// other browsers can use a location handler that checks
|
||||
// at regular intervals as their primary mechanism;
|
||||
// we use it for Internet Explorer as well to handle
|
||||
// an important edge case; see checkLocation() for
|
||||
// details
|
||||
var self = this;
|
||||
var locationHandler = function() {
|
||||
self.checkLocation();
|
||||
};
|
||||
setInterval(locationHandler, 100);
|
||||
},
|
||||
|
||||
/** Notify the listener of new history changes. */
|
||||
/** private */ fireHistoryEvent: function(newHash) {
|
||||
// extract the value from our history storage for
|
||||
// this hash
|
||||
var historyData = historyStorage.get(newHash);
|
||||
|
||||
// call our listener
|
||||
this.listener.call(null, newHash, historyData);
|
||||
},
|
||||
|
||||
/** Sees if the browsers has changed location. This is the primary history mechanism
|
||||
for Firefox. For Internet Explorer, we use this to handle an important edge case:
|
||||
if a user manually types in a new hash value into their Internet Explorer location
|
||||
bar and press enter, we want to intercept this and notify any history listener. */
|
||||
/** private */ checkLocation: function() {
|
||||
// ignore any location changes that we made ourselves
|
||||
// for browsers other than Internet Explorer
|
||||
if (this.isInternetExplorer() == false
|
||||
&& this.ignoreLocationChange == true) {
|
||||
this.ignoreLocationChange = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// if we are dealing with Internet Explorer
|
||||
// and we are in the middle of making a location
|
||||
// change from an iframe, ignore it
|
||||
if (this.isInternetExplorer() == false
|
||||
&& this.ieAtomicLocationChange == true) {
|
||||
return;
|
||||
}
|
||||
|
||||
// get hash location
|
||||
var hash = this.getCurrentLocation();
|
||||
|
||||
// see if there has been a change
|
||||
if (hash == this.currentLocation)
|
||||
return;
|
||||
|
||||
// on Internet Explorer, we need to intercept users manually
|
||||
// entering locations into the browser; we do this by comparing
|
||||
// the browsers location against the iframes location; if they
|
||||
// differ, we are dealing with a manual event and need to
|
||||
// place it inside our history, otherwise we can return
|
||||
this.ieAtomicLocationChange = true;
|
||||
|
||||
if (this.isInternetExplorer()
|
||||
&& this.getIFrameHash() != hash) {
|
||||
this.iframe.src = "blank.html?" + hash;
|
||||
}
|
||||
else if (this.isInternetExplorer()) {
|
||||
// the iframe is unchanged
|
||||
return;
|
||||
}
|
||||
|
||||
// save this new location
|
||||
this.currentLocation = hash;
|
||||
|
||||
this.ieAtomicLocationChange = false;
|
||||
|
||||
// notify listeners of the change
|
||||
this.fireHistoryEvent(hash);
|
||||
},
|
||||
|
||||
/** Gets the current location of the hidden IFrames
|
||||
that is stored as history. For Internet Explorer. */
|
||||
/** private */ getIFrameHash: function() {
|
||||
// get the new location
|
||||
var historyFrame = document.getElementById("DhtmlHistoryFrame");
|
||||
var doc = historyFrame.contentWindow.document;
|
||||
var hash = new String(doc.location.search);
|
||||
|
||||
if (hash.length == 1 && hash.charAt(0) == "?")
|
||||
hash = "";
|
||||
else if (hash.length >= 2 && hash.charAt(0) == "?")
|
||||
hash = hash.substring(1);
|
||||
|
||||
|
||||
return hash;
|
||||
},
|
||||
|
||||
/** Removes any leading hash that might be on a location. */
|
||||
/** private */ removeHash: function(hashValue) {
|
||||
if (hashValue == null || hashValue == undefined)
|
||||
return null;
|
||||
else if (hashValue == "")
|
||||
return "";
|
||||
else if (hashValue.length == 1 && hashValue.charAt(0) == "#")
|
||||
return "";
|
||||
else if (hashValue.length > 1 && hashValue.charAt(0) == "#")
|
||||
return hashValue.substring(1);
|
||||
else
|
||||
return hashValue;
|
||||
},
|
||||
|
||||
/** For IE, says when the hidden iframe has finished loading. */
|
||||
/** private */ iframeLoaded: function(newLocation) {
|
||||
// ignore any location changes that we made ourselves
|
||||
if (this.ignoreLocationChange == true) {
|
||||
this.ignoreLocationChange = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// get the new location
|
||||
var hash = new String(newLocation.search);
|
||||
if (hash.length == 1 && hash.charAt(0) == "?")
|
||||
hash = "";
|
||||
else if (hash.length >= 2 && hash.charAt(0) == "?")
|
||||
hash = hash.substring(1);
|
||||
|
||||
// move to this location in the browser location bar
|
||||
// if we are not dealing with a page load event
|
||||
if (this.pageLoadEvent != true) {
|
||||
window.location.hash = hash;
|
||||
}
|
||||
|
||||
// notify listeners of the change
|
||||
this.fireHistoryEvent(hash);
|
||||
},
|
||||
|
||||
/** Determines if this is Internet Explorer. */
|
||||
/** private */ isInternetExplorer: function() {
|
||||
var userAgent = navigator.userAgent.toLowerCase();
|
||||
if (document.all && userAgent.indexOf('msie')!=-1) {
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/** An object that uses a hidden form to store history state
|
||||
across page loads. The chief mechanism for doing so is using
|
||||
the fact that browser's save the text in form data for the
|
||||
life of the browser and cache, which means the text is still
|
||||
there when the user navigates back to the page. See
|
||||
http://codinginparadise.org/weblog/2005/08/ajax-tutorial-saving-session-across.html
|
||||
for full details. */
|
||||
window.historyStorage = {
|
||||
/** If true, we are debugging and show the storage textfield. */
|
||||
/** public */ debugging: false,
|
||||
|
||||
/** Our hash of key name/values. */
|
||||
/** private */ storageHash: new Object(),
|
||||
|
||||
/** If true, we have loaded our hash table out of the storage form. */
|
||||
/** private */ hashLoaded: false,
|
||||
|
||||
/** public */ put: function(key, value) {
|
||||
this.assertValidKey(key);
|
||||
|
||||
// if we already have a value for this,
|
||||
// remove the value before adding the
|
||||
// new one
|
||||
if (this.hasKey(key)) {
|
||||
this.remove(key);
|
||||
}
|
||||
|
||||
// store this new key
|
||||
this.storageHash[key] = value;
|
||||
|
||||
// save and serialize the hashtable into the form
|
||||
this.saveHashTable();
|
||||
},
|
||||
|
||||
/** public */ get: function(key) {
|
||||
this.assertValidKey(key);
|
||||
|
||||
// make sure the hash table has been loaded
|
||||
// from the form
|
||||
this.loadHashTable();
|
||||
|
||||
var value = this.storageHash[key];
|
||||
|
||||
if (value == undefined)
|
||||
return null;
|
||||
else
|
||||
return value;
|
||||
},
|
||||
|
||||
/** public */ remove: function(key) {
|
||||
this.assertValidKey(key);
|
||||
|
||||
// make sure the hash table has been loaded
|
||||
// from the form
|
||||
this.loadHashTable();
|
||||
|
||||
// delete the value
|
||||
delete this.storageHash[key];
|
||||
|
||||
// serialize and save the hash table into the
|
||||
// form
|
||||
this.saveHashTable();
|
||||
},
|
||||
|
||||
/** Clears out all saved data. */
|
||||
/** public */ reset: function() {
|
||||
this.storageField.value = "";
|
||||
this.storageHash = new Object();
|
||||
},
|
||||
|
||||
/** public */ hasKey: function(key) {
|
||||
this.assertValidKey(key);
|
||||
|
||||
// make sure the hash table has been loaded
|
||||
// from the form
|
||||
this.loadHashTable();
|
||||
|
||||
if (typeof this.storageHash[key] == "undefined")
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
},
|
||||
|
||||
/** Determines whether the key given is valid;
|
||||
keys can only have letters, numbers, the dash,
|
||||
underscore, spaces, or one of the
|
||||
following characters:
|
||||
!@#$%^&*()+=:;,./?|\~{}[] */
|
||||
/** public */ isValidKey: function(key) {
|
||||
// allow all strings, since we don't use XML serialization
|
||||
// format anymore
|
||||
return (typeof key == "string");
|
||||
|
||||
/*
|
||||
if (typeof key != "string")
|
||||
key = key.toString();
|
||||
|
||||
|
||||
var matcher =
|
||||
/^[a-zA-Z0-9_ \!\@\#\$\%\^\&\*\(\)\+\=\:\;\,\.\/\?\|\\\~\{\}\[\]]*$/;
|
||||
|
||||
return matcher.test(key);*/
|
||||
},
|
||||
|
||||
|
||||
|
||||
|
||||
/** A reference to our textarea field. */
|
||||
/** private */ storageField: null,
|
||||
|
||||
/** private */ init: function() {
|
||||
// write a hidden form into the page
|
||||
var styleValue = "position: absolute; top: -1000px; left: -1000px;";
|
||||
if (this.debugging == true) {
|
||||
styleValue = "width: 30em; height: 30em;";
|
||||
}
|
||||
|
||||
var newContent =
|
||||
"<form id='historyStorageForm' "
|
||||
+ "method='GET' "
|
||||
+ "style='" + styleValue + "'>"
|
||||
+ "<textarea id='historyStorageField' "
|
||||
+ "style='" + styleValue + "'"
|
||||
+ "left: -1000px;' "
|
||||
+ "name='historyStorageField'></textarea>"
|
||||
+ "</form>";
|
||||
document.write(newContent);
|
||||
|
||||
this.storageField = document.getElementById("historyStorageField");
|
||||
},
|
||||
|
||||
/** Asserts that a key is valid, throwing
|
||||
an exception if it is not. */
|
||||
/** private */ assertValidKey: function(key) {
|
||||
if (this.isValidKey(key) == false) {
|
||||
throw "Please provide a valid key for "
|
||||
+ "window.historyStorage, key= "
|
||||
+ key;
|
||||
}
|
||||
},
|
||||
|
||||
/** Loads the hash table up from the form. */
|
||||
/** private */ loadHashTable: function() {
|
||||
if (this.hashLoaded == false) {
|
||||
// get the hash table as a serialized
|
||||
// string
|
||||
var serializedHashTable = this.storageField.value;
|
||||
|
||||
if (serializedHashTable != "" &&
|
||||
serializedHashTable != null) {
|
||||
// destringify the content back into a
|
||||
// real JavaScript object
|
||||
this.storageHash = eval('(' + serializedHashTable + ')');
|
||||
}
|
||||
|
||||
this.hashLoaded = true;
|
||||
}
|
||||
},
|
||||
|
||||
/** Saves the hash table into the form. */
|
||||
/** private */ saveHashTable: function() {
|
||||
this.loadHashTable();
|
||||
|
||||
// serialized the hash table
|
||||
var serializedHashTable = HTML_AJAX_JSON.stringify(this.storageHash);
|
||||
|
||||
// save this value
|
||||
this.storageField.value = serializedHashTable;
|
||||
}
|
||||
};
|
||||
|
||||
/** Initialize all of our objects now. */
|
||||
window.historyStorage.init();
|
||||
window.dhtmlHistory.create();
|
||||
152
include/pear/data/HTML_AJAX/js/serializer/JSON.js
Normal file
152
include/pear/data/HTML_AJAX/js/serializer/JSON.js
Normal file
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
Copyright (c) 2005 JSON.org
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The Software shall be used for Good, not Evil.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
The global object JSON contains two methods.
|
||||
|
||||
JSON.stringify(value) takes a JavaScript value and produces a JSON text.
|
||||
The value must not be cyclical.
|
||||
|
||||
JSON.parse(text) takes a JSON text and produces a JavaScript value. It will
|
||||
throw a 'JSONError' exception if there is an error.
|
||||
*/
|
||||
var HTML_AJAX_JSON = {
|
||||
copyright: '(c)2005 JSON.org',
|
||||
license: 'http://www.crockford.com/JSON/license.html',
|
||||
/*
|
||||
Stringify a JavaScript value, producing a JSON text.
|
||||
*/
|
||||
stringify: function (v) {
|
||||
var a = [];
|
||||
|
||||
/*
|
||||
Emit a string.
|
||||
*/
|
||||
function e(s) {
|
||||
a[a.length] = s;
|
||||
}
|
||||
|
||||
/*
|
||||
Convert a value.
|
||||
*/
|
||||
function g(x) {
|
||||
var c, i, l, v;
|
||||
|
||||
switch (typeof x) {
|
||||
case 'object':
|
||||
if (x) {
|
||||
if (x instanceof Array) {
|
||||
e('[');
|
||||
l = a.length;
|
||||
for (i = 0; i < x.length; i += 1) {
|
||||
v = x[i];
|
||||
if (typeof v != 'undefined' &&
|
||||
typeof v != 'function') {
|
||||
if (l < a.length) {
|
||||
e(',');
|
||||
}
|
||||
g(v);
|
||||
}
|
||||
}
|
||||
e(']');
|
||||
return;
|
||||
} else if (typeof x.valueOf == 'function') {
|
||||
e('{');
|
||||
l = a.length;
|
||||
for (i in x) {
|
||||
v = x[i];
|
||||
if (typeof v != 'undefined' &&
|
||||
typeof v != 'function' &&
|
||||
(!v || typeof v != 'object' ||
|
||||
typeof v.valueOf == 'function')) {
|
||||
if (l < a.length) {
|
||||
e(',');
|
||||
}
|
||||
g(i);
|
||||
e(':');
|
||||
g(v);
|
||||
}
|
||||
}
|
||||
return e('}');
|
||||
}
|
||||
}
|
||||
e('null');
|
||||
return;
|
||||
case 'number':
|
||||
e(isFinite(x) ? +x : 'null');
|
||||
return;
|
||||
case 'string':
|
||||
l = x.length;
|
||||
e('"');
|
||||
for (i = 0; i < l; i += 1) {
|
||||
c = x.charAt(i);
|
||||
if (c >= ' ') {
|
||||
if (c == '\\' || c == '"') {
|
||||
e('\\');
|
||||
}
|
||||
e(c);
|
||||
} else {
|
||||
switch (c) {
|
||||
case '\b':
|
||||
e('\\b');
|
||||
break;
|
||||
case '\f':
|
||||
e('\\f');
|
||||
break;
|
||||
case '\n':
|
||||
e('\\n');
|
||||
break;
|
||||
case '\r':
|
||||
e('\\r');
|
||||
break;
|
||||
case '\t':
|
||||
e('\\t');
|
||||
break;
|
||||
default:
|
||||
c = c.charCodeAt();
|
||||
e('\\u00' + Math.floor(c / 16).toString(16) +
|
||||
(c % 16).toString(16));
|
||||
}
|
||||
}
|
||||
}
|
||||
e('"');
|
||||
return;
|
||||
case 'boolean':
|
||||
e(String(x));
|
||||
return;
|
||||
default:
|
||||
e('null');
|
||||
return;
|
||||
}
|
||||
}
|
||||
g(v);
|
||||
return a.join('');
|
||||
},
|
||||
/*
|
||||
Parse a JSON text, producing a JavaScript value.
|
||||
*/
|
||||
parse: function (text) {
|
||||
return
|
||||
(/^(\s+|[,:{}\[\]]|"(\\["\\\/bfnrtu]|[^\x00-\x1f"\\]+)*"|-?\d+(\.\d*)?([eE][+-]?\d+)?|true|false|null)+$/.test(text))
|
||||
&&
|
||||
eval('(' + text + ')');
|
||||
}
|
||||
};
|
||||
145
include/pear/data/HTML_AJAX/js/serializer/UrlSerializer.js
Normal file
145
include/pear/data/HTML_AJAX/js/serializer/UrlSerializer.js
Normal file
@@ -0,0 +1,145 @@
|
||||
// {{{ HTML_AJAX_Serialize_Urlencoded
|
||||
/**
|
||||
* URL-encoding serializer
|
||||
*
|
||||
* This class can be used to serialize and unserialize data in a
|
||||
* format compatible with PHP's handling of HTTP query strings.
|
||||
* Due to limitations of the format, all input is serialized as an
|
||||
* array or a string. See examples/serialize.url.examples.php
|
||||
*
|
||||
* @version 0.0.1
|
||||
* @copyright 2005 Arpad Ray <arpad@php.net>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
*
|
||||
* See Main.js for Author/license details
|
||||
*/
|
||||
function HTML_AJAX_Serialize_Urlencoded() {}
|
||||
HTML_AJAX_Serialize_Urlencoded.prototype = {
|
||||
contentType: 'application/x-www-form-urlencoded; charset=UTF-8',
|
||||
base: '_HTML_AJAX',
|
||||
_keys: [],
|
||||
error: false,
|
||||
message: "",
|
||||
cont: "",
|
||||
// {{{ serialize
|
||||
/**
|
||||
* Serializes a variable
|
||||
*
|
||||
* @param mixed inp the variable to serialize
|
||||
* @return string a string representation of the input,
|
||||
* which can be reconstructed by unserialize()
|
||||
*/
|
||||
serialize: function(input, _internal) {
|
||||
if (typeof input == 'undefined') {
|
||||
return '';
|
||||
}
|
||||
if (!_internal) {
|
||||
this._keys = [];
|
||||
}
|
||||
var ret = '', first = true;
|
||||
for (i = 0; i < this._keys.length; i++) {
|
||||
ret += (first ? HTML_AJAX_Util.encodeUrl(this._keys[i]) : '[' + HTML_AJAX_Util.encodeUrl(this._keys[i]) + ']');
|
||||
first = false;
|
||||
}
|
||||
ret += '=';
|
||||
switch (HTML_AJAX_Util.getType(input)) {
|
||||
case 'string':
|
||||
case 'number':
|
||||
ret += HTML_AJAX_Util.encodeUrl(input.toString());
|
||||
break;
|
||||
case 'boolean':
|
||||
ret += (input ? '1' : '0');
|
||||
break;
|
||||
case 'array':
|
||||
case 'object':
|
||||
ret = '';
|
||||
for (i in input) {
|
||||
this._keys.push(i);
|
||||
ret += this.serialize(input[i], true) + '&';
|
||||
this._keys.pop();
|
||||
}
|
||||
ret = ret.substr(0, ret.length - 1);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
// }}}
|
||||
// {{{ unserialize
|
||||
/**
|
||||
* Reconstructs a serialized variable
|
||||
*
|
||||
* @param string inp the string to reconstruct
|
||||
* @return array an array containing the variable represented by the input string, or void on failure
|
||||
*/
|
||||
unserialize: function(input) {
|
||||
if (!input.length || input.length == 0) {
|
||||
// null
|
||||
return;
|
||||
}
|
||||
if (!/^(\w+(\[[^\[\]]*\])*=[^&]*(&|$))+$/.test(input)) {
|
||||
this.raiseError("invalidly formed input", input);
|
||||
return;
|
||||
}
|
||||
input = input.split("&");
|
||||
var pos, key, keys, val, _HTML_AJAX = [];
|
||||
if (input.length == 1) {
|
||||
return HTML_AJAX_Util.decodeUrl(input[0].substr(this.base.length + 1));
|
||||
}
|
||||
for (var i in input) {
|
||||
pos = input[i].indexOf("=");
|
||||
if (pos < 1 || input[i].length - pos - 1 < 1) {
|
||||
this.raiseError("input is too short", input[i]);
|
||||
return;
|
||||
}
|
||||
key = HTML_AJAX_Util.decodeUrl(input[i].substr(0, pos));
|
||||
val = HTML_AJAX_Util.decodeUrl(input[i].substr(pos + 1));
|
||||
key = key.replace(/\[((\d*\D+)+)\]/g, '["$1"]');
|
||||
keys = key.split(']');
|
||||
for (j in keys) {
|
||||
if (!keys[j].length || keys[j].length == 0) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
if (eval('typeof ' + keys[j] + ']') == 'undefined') {
|
||||
var ev = keys[j] + ']=[];';
|
||||
eval(ev);
|
||||
}
|
||||
} catch (e) {
|
||||
this.raiseError("error evaluating key", ev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
try {
|
||||
eval(key + '="' + val + '";');
|
||||
} catch (e) {
|
||||
this.raiseError("error evaluating value", input);
|
||||
return;
|
||||
}
|
||||
}
|
||||
return _HTML_AJAX;
|
||||
},
|
||||
// }}}
|
||||
// {{{ getError
|
||||
/**
|
||||
* Gets the last error message
|
||||
*
|
||||
* @return string the last error message from unserialize()
|
||||
*/
|
||||
getError: function() {
|
||||
return this.message + "\n" + this.cont;
|
||||
},
|
||||
// }}}
|
||||
// {{{ raiseError
|
||||
/**
|
||||
* Raises an eror (called by unserialize().)
|
||||
*
|
||||
* @param string message the error message
|
||||
* @param string cont the remaining unserialized content
|
||||
*/
|
||||
raiseError: function(message, cont) {
|
||||
this.error = 1;
|
||||
this.message = message;
|
||||
this.cont = cont;
|
||||
}
|
||||
// }}}
|
||||
}
|
||||
// }}}
|
||||
301
include/pear/data/HTML_AJAX/js/serializer/haSerializer.js
Normal file
301
include/pear/data/HTML_AJAX/js/serializer/haSerializer.js
Normal file
@@ -0,0 +1,301 @@
|
||||
/**
|
||||
* HTML_AJAX_Serialize_HA - custom serialization
|
||||
*
|
||||
* This class is used with the JSON serializer and the HTML_AJAX_Action php class
|
||||
* to allow users to easily write data handling and dom manipulation related to
|
||||
* ajax actions directly from their php code
|
||||
*
|
||||
* See Main.js for Author/license details
|
||||
*/
|
||||
function HTML_AJAX_Serialize_HA() { }
|
||||
HTML_AJAX_Serialize_HA.prototype =
|
||||
{
|
||||
/**
|
||||
* Takes data from JSON - which should be parseable into a nice array
|
||||
* reads the action to take and pipes it to the right method
|
||||
*
|
||||
* @param string payload incoming data from php
|
||||
* @return true on success, false on failure
|
||||
*/
|
||||
unserialize: function(payload)
|
||||
{
|
||||
var actions = eval(payload);
|
||||
for(var i = 0; i < actions.length; i++)
|
||||
{
|
||||
var action = actions[i];
|
||||
switch(action.action)
|
||||
{
|
||||
case 'prepend':
|
||||
this._prependAttr(action.id, action.attributes);
|
||||
break;
|
||||
case 'append':
|
||||
this._appendAttr(action.id, action.attributes);
|
||||
break;
|
||||
case 'assign':
|
||||
this._assignAttr(action.id, action.attributes);
|
||||
break;
|
||||
case 'clear':
|
||||
this._clearAttr(action.id, action.attributes);
|
||||
break;
|
||||
case 'create':
|
||||
this._createNode(action.id, action.tag, action.attributes, action.type);
|
||||
break;
|
||||
case 'replace':
|
||||
this._replaceNode(action.id, action.tag, action.attributes);
|
||||
break;
|
||||
case 'remove':
|
||||
this._removeNode(action.id);
|
||||
break;
|
||||
case 'script':
|
||||
this._insertScript(action.data);
|
||||
break;
|
||||
case 'alert':
|
||||
this._insertAlert(action.data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
/* Dispatch Methods */
|
||||
_prependAttr: function(id, attributes)
|
||||
{
|
||||
var node = document.getElementById(id);
|
||||
this._setAttrs(node, attributes, 'prepend');
|
||||
},
|
||||
_appendAttr: function(id, attributes)
|
||||
{
|
||||
var node = document.getElementById(id);
|
||||
this._setAttrs(node, attributes, 'append');
|
||||
},
|
||||
_assignAttr: function(id, attributes)
|
||||
{
|
||||
var node = document.getElementById(id);
|
||||
this._setAttrs(node, attributes);
|
||||
},
|
||||
_clearAttr: function(id, attributes)
|
||||
{
|
||||
var node = document.getElementById(id);
|
||||
for(var i = 0; i < attributes.length; i++)
|
||||
{
|
||||
if(attributes[i] == 'innerHTML')
|
||||
{
|
||||
HTML_AJAX_Util.setInnerHTML(node, '');
|
||||
}
|
||||
// value can't be removed
|
||||
else if(attributes[i] == 'value')
|
||||
{
|
||||
node.value = '';
|
||||
}
|
||||
// I'd use hasAttribute first but IE is stupid stupid stupid
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
node.removeAttribute(attributes[i]);
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
node[i] = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_createNode: function(id, tag, attributes, type)
|
||||
{
|
||||
var newnode = document.createElement(tag);
|
||||
this._setAttrs(newnode, attributes);
|
||||
switch(type)
|
||||
{
|
||||
case 'append':
|
||||
document.getElementById(id).appendChild(newnode);
|
||||
break
|
||||
case 'prepend':
|
||||
var parent = document.getElementById(id);
|
||||
var sibling = parent.firstChild;
|
||||
parent.insertBefore(newnode, sibling);
|
||||
break;
|
||||
case 'insertBefore':
|
||||
var sibling = document.getElementById(id);
|
||||
var parent = sibling.parentNode;
|
||||
parent.insertBefore(newnode, sibling);
|
||||
break;
|
||||
//this one is tricky, if it's the last one we use append child...ewww
|
||||
case 'insertAfter':
|
||||
var sibling = document.getElementById(id);
|
||||
var parent = sibling.parentNode;
|
||||
var next = sibling.nextSibling;
|
||||
if(next == null)
|
||||
{
|
||||
parent.appendChild(newnode);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.insertBefore(newnode, next);
|
||||
}
|
||||
break;
|
||||
}
|
||||
},
|
||||
_replaceNode: function(id, tag, attributes)
|
||||
{
|
||||
var node = document.getElementById(id);
|
||||
var parent = node.parentNode;
|
||||
var newnode = document.createElement(tag);
|
||||
this._setAttrs(newnode, attributes);
|
||||
parent.replaceChild(newnode, node);
|
||||
},
|
||||
_removeNode: function(id)
|
||||
{
|
||||
var node = document.getElementById(id);
|
||||
if(node)
|
||||
{
|
||||
var parent = node.parentNode;
|
||||
parent.removeChild(node);
|
||||
}
|
||||
},
|
||||
_insertScript: function(data)
|
||||
{
|
||||
eval(data);
|
||||
},
|
||||
_insertAlert: function(data)
|
||||
{
|
||||
alert(data);
|
||||
},
|
||||
/* Helper Methods */
|
||||
// should we move this to HTML_AJAX_Util???, just does the - case which we need for style
|
||||
_camelize: function(instr)
|
||||
{
|
||||
var p = instr.split('-');
|
||||
var out = p[0];
|
||||
for(var i = 1; i < p.length; i++) {
|
||||
out += p[i].charAt(0).toUpperCase()+p[i].substring(1);
|
||||
}
|
||||
return out;
|
||||
},
|
||||
_setAttrs: function(node, attributes, type)
|
||||
{
|
||||
switch(type)
|
||||
{
|
||||
case 'prepend':
|
||||
for (var i in attributes)
|
||||
{
|
||||
// innerHTML is extremely flakey - use util method for it
|
||||
if(i == 'innerHTML')
|
||||
{
|
||||
HTML_AJAX_Util.setInnerHTML(node, attributes[i], 'append');
|
||||
}
|
||||
//IE doesn't support setAttribute on style so we need to break it out and set each property individually
|
||||
else if(i == 'style')
|
||||
{
|
||||
var styles = [];
|
||||
if(attributes[i].indexOf(';'))
|
||||
{
|
||||
styles = attributes[i].split(';');
|
||||
}
|
||||
else
|
||||
{
|
||||
styles.push(attributes[i]);
|
||||
}
|
||||
for(var i = 0; i < styles.length; i++)
|
||||
{
|
||||
var r = styles[i].match(/^\s*(.+)\s*:\s*(.+)\s*$/);
|
||||
if(r)
|
||||
{
|
||||
node.style[this._camelize(r[1])] = r[2] + node.style[this._camelize(r[1])];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
node[i] = attributes[i] + node[i];
|
||||
}
|
||||
catch(e){}
|
||||
node.setAttribute(i, attributes[i] + node[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'append':
|
||||
{
|
||||
for (var i in attributes)
|
||||
{
|
||||
// innerHTML is extremely flakey - use util method for it
|
||||
if(i == 'innerHTML')
|
||||
{
|
||||
HTML_AJAX_Util.setInnerHTML(node, attributes[i], 'append');
|
||||
}
|
||||
//IE doesn't support setAttribute on style so we need to break it out and set each property individually
|
||||
else if(i == 'style')
|
||||
{
|
||||
var styles = [];
|
||||
if(attributes[i].indexOf(';'))
|
||||
{
|
||||
styles = attributes[i].split(';');
|
||||
}
|
||||
else
|
||||
{
|
||||
styles.push(attributes[i]);
|
||||
}
|
||||
for(var i = 0; i < styles.length; i++)
|
||||
{
|
||||
var r = styles[i].match(/^\s*(.+)\s*:\s*(.+)\s*$/);
|
||||
if(r)
|
||||
{
|
||||
node.style[this._camelize(r[1])] = node.style[this._camelize(r[1])] + r[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
node[i] = node[i] + attributes[i];
|
||||
}
|
||||
catch(e){}
|
||||
node.setAttribute(i, node[i] + attributes[i]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
for (var i in attributes)
|
||||
{
|
||||
//innerHTML hack bailout
|
||||
if(i == 'innerHTML')
|
||||
{
|
||||
HTML_AJAX_Util.setInnerHTML(node, attributes[i]);
|
||||
}
|
||||
else if(i == 'style')
|
||||
{
|
||||
var styles = [];
|
||||
if(attributes[i].indexOf(';'))
|
||||
{
|
||||
styles = attributes[i].split(';');
|
||||
}
|
||||
else
|
||||
{
|
||||
styles.push(attributes[i]);
|
||||
}
|
||||
for(var i = 0; i < styles.length; i++)
|
||||
{
|
||||
var r = styles[i].match(/^\s*(.+)\s*:\s*(.+)\s*$/);
|
||||
if(r)
|
||||
{
|
||||
node.style[this._camelize(r[1])] = r[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
try
|
||||
{
|
||||
node[i] = attributes[i];
|
||||
}
|
||||
catch(e){}
|
||||
node.setAttribute(i, attributes[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
244
include/pear/data/HTML_AJAX/js/serializer/phpSerializer.js
Normal file
244
include/pear/data/HTML_AJAX/js/serializer/phpSerializer.js
Normal file
@@ -0,0 +1,244 @@
|
||||
// {{{ HTML_AJAX_Serialize_PHP
|
||||
/**
|
||||
* PHP serializer
|
||||
*
|
||||
* This class can be used to serialize and unserialize data in a
|
||||
* format compatible with PHP's native serialization functions.
|
||||
*
|
||||
* @version 0.0.3
|
||||
* @copyright 2005 Arpad Ray <arpad@php.net>
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
*
|
||||
* See Main.js for Author/license details
|
||||
*/
|
||||
|
||||
function HTML_AJAX_Serialize_PHP() {}
|
||||
HTML_AJAX_Serialize_PHP.prototype = {
|
||||
error: false,
|
||||
message: "",
|
||||
cont: "",
|
||||
defaultEncoding: 'UTF-8',
|
||||
contentType: 'application/php-serialized; charset: UTF-8',
|
||||
// {{{ serialize
|
||||
/**
|
||||
* Serializes a variable
|
||||
*
|
||||
* @param mixed inp the variable to serialize
|
||||
* @return string a string representation of the input,
|
||||
* which can be reconstructed by unserialize()
|
||||
* @author Arpad Ray <arpad@rajeczy.com>
|
||||
* @author David Coallier <davidc@php.net>
|
||||
*/
|
||||
serialize: function(inp) {
|
||||
var type = HTML_AJAX_Util.getType(inp);
|
||||
var val;
|
||||
switch (type) {
|
||||
case "undefined":
|
||||
val = "N";
|
||||
break;
|
||||
case "boolean":
|
||||
val = "b:" + (inp ? "1" : "0");
|
||||
break;
|
||||
case "number":
|
||||
val = (Math.round(inp) == inp ? "i" : "d") + ":" + inp;
|
||||
break;
|
||||
case "string":
|
||||
val = "s:" + inp.length + ":\"" + inp + "\"";
|
||||
break;
|
||||
case "array":
|
||||
val = "a";
|
||||
case "object":
|
||||
if (type == "object") {
|
||||
var objname = inp.constructor.toString().match(/(\w+)\(\)/);
|
||||
if (objname == undefined) {
|
||||
return;
|
||||
}
|
||||
objname[1] = this.serialize(objname[1]);
|
||||
val = "O" + objname[1].substring(1, objname[1].length - 1);
|
||||
}
|
||||
var count = 0;
|
||||
var vals = "";
|
||||
var okey;
|
||||
for (key in inp) {
|
||||
okey = (key.match(/^[0-9]+$/) ? parseInt(key) : key);
|
||||
vals += this.serialize(okey) +
|
||||
this.serialize(inp[key]);
|
||||
count++;
|
||||
}
|
||||
val += ":" + count + ":{" + vals + "}";
|
||||
break;
|
||||
}
|
||||
if (type != "object" && type != "array") val += ";";
|
||||
return val;
|
||||
},
|
||||
// }}}
|
||||
// {{{ unserialize
|
||||
/**
|
||||
* Reconstructs a serialized variable
|
||||
*
|
||||
* @param string inp the string to reconstruct
|
||||
* @return mixed the variable represented by the input string, or void on failure
|
||||
*/
|
||||
unserialize: function(inp) {
|
||||
this.error = 0;
|
||||
if (inp == "" || inp.length < 2) {
|
||||
this.raiseError("input is too short");
|
||||
return;
|
||||
}
|
||||
var val, kret, vret, cval;
|
||||
var type = inp.charAt(0);
|
||||
var cont = inp.substring(2);
|
||||
var size = 0, divpos = 0, endcont = 0, rest = "", next = "";
|
||||
|
||||
switch (type) {
|
||||
case "N": // null
|
||||
if (inp.charAt(1) != ";") {
|
||||
this.raiseError("missing ; for null", cont);
|
||||
}
|
||||
// leave val undefined
|
||||
rest = cont;
|
||||
break;
|
||||
case "b": // boolean
|
||||
if (!/[01];/.test(cont.substring(0,2))) {
|
||||
this.raiseError("value not 0 or 1, or missing ; for boolean", cont);
|
||||
}
|
||||
val = (cont.charAt(0) == "1");
|
||||
rest = cont.substring(1);
|
||||
break;
|
||||
case "s": // string
|
||||
val = "";
|
||||
divpos = cont.indexOf(":");
|
||||
if (divpos == -1) {
|
||||
this.raiseError("missing : for string", cont);
|
||||
break;
|
||||
}
|
||||
size = parseInt(cont.substring(0, divpos));
|
||||
if (size == 0) {
|
||||
if (cont.length - divpos < 4) {
|
||||
this.raiseError("string is too short", cont);
|
||||
break;
|
||||
}
|
||||
rest = cont.substring(divpos + 4);
|
||||
break;
|
||||
}
|
||||
if ((cont.length - divpos - size) < 4) {
|
||||
this.raiseError("string is too short", cont);
|
||||
break;
|
||||
}
|
||||
if (cont.substring(divpos + 2 + size, divpos + 4 + size) != "\";") {
|
||||
this.raiseError("string is too long, or missing \";", cont);
|
||||
}
|
||||
val = cont.substring(divpos + 2, divpos + 2 + size);
|
||||
rest = cont.substring(divpos + 4 + size);
|
||||
break;
|
||||
case "i": // integer
|
||||
case "d": // float
|
||||
var dotfound = 0;
|
||||
for (var i = 0; i < cont.length; i++) {
|
||||
cval = cont.charAt(i);
|
||||
if (isNaN(parseInt(cval)) && !(type == "d" && cval == "." && !dotfound++)) {
|
||||
endcont = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!endcont || cont.charAt(endcont) != ";") {
|
||||
this.raiseError("missing or invalid value, or missing ; for int/float", cont);
|
||||
}
|
||||
val = cont.substring(0, endcont);
|
||||
val = (type == "i" ? parseInt(val) : parseFloat(val));
|
||||
rest = cont.substring(endcont + 1);
|
||||
break;
|
||||
case "a": // array
|
||||
if (cont.length < 4) {
|
||||
this.raiseError("array is too short", cont);
|
||||
return;
|
||||
}
|
||||
divpos = cont.indexOf(":", 1);
|
||||
if (divpos == -1) {
|
||||
this.raiseError("missing : for array", cont);
|
||||
return;
|
||||
}
|
||||
size = parseInt(cont.substring(0, divpos));
|
||||
cont = cont.substring(divpos + 2);
|
||||
val = new Array();
|
||||
if (cont.length < 1) {
|
||||
this.raiseError("array is too short", cont);
|
||||
return;
|
||||
}
|
||||
for (var i = 0; i < size; i++) {
|
||||
kret = this.unserialize(cont, 1);
|
||||
if (this.error || kret[0] == undefined || kret[1] == "") {
|
||||
this.raiseError("missing or invalid key, or missing value for array", cont);
|
||||
return;
|
||||
}
|
||||
vret = this.unserialize(kret[1], 1);
|
||||
if (this.error) {
|
||||
this.raiseError("invalid value for array", cont);
|
||||
return;
|
||||
}
|
||||
val[kret[0]] = vret[0];
|
||||
cont = vret[1];
|
||||
}
|
||||
if (cont.charAt(0) != "}") {
|
||||
this.raiseError("missing ending }, or too many values for array", cont);
|
||||
return;
|
||||
}
|
||||
rest = cont.substring(1);
|
||||
break;
|
||||
case "O": // object
|
||||
divpos = cont.indexOf(":");
|
||||
if (divpos == -1) {
|
||||
this.raiseError("missing : for object", cont);
|
||||
return;
|
||||
}
|
||||
size = parseInt(cont.substring(0, divpos));
|
||||
var objname = cont.substring(divpos + 2, divpos + 2 + size);
|
||||
if (cont.substring(divpos + 2 + size, divpos + 4 + size) != "\":") {
|
||||
this.raiseError("object name is too long, or missing \":", cont);
|
||||
return;
|
||||
}
|
||||
var objprops = this.unserialize("a:" + cont.substring(divpos + 4 + size), 1);
|
||||
if (this.error) {
|
||||
this.raiseError("invalid object properties", cont);
|
||||
return;
|
||||
}
|
||||
rest = objprops[1];
|
||||
var objout = "function " + objname + "(){";
|
||||
for (key in objprops[0]) {
|
||||
objout += "this." + key + "=objprops[0]['" + key + "'];";
|
||||
}
|
||||
objout += "}val=new " + objname + "();";
|
||||
eval(objout);
|
||||
break;
|
||||
default:
|
||||
this.raiseError("invalid input type", cont);
|
||||
}
|
||||
return (arguments.length == 1 ? val : [val, rest]);
|
||||
},
|
||||
// }}}
|
||||
// {{{ getError
|
||||
/**
|
||||
* Gets the last error message
|
||||
*
|
||||
* @return string the last error message from unserialize()
|
||||
*/
|
||||
getError: function() {
|
||||
return this.message + "\n" + this.cont;
|
||||
},
|
||||
// }}}
|
||||
// {{{ raiseError
|
||||
/**
|
||||
* Raises an eror (called by unserialize().)
|
||||
*
|
||||
* @param string message the error message
|
||||
* @param string cont the remaining unserialized content
|
||||
*/
|
||||
raiseError: function(message, cont) {
|
||||
this.error = 1;
|
||||
this.message = message;
|
||||
this.cont = cont;
|
||||
}
|
||||
// }}}
|
||||
}
|
||||
// }}}
|
||||
|
||||
407
include/pear/data/HTML_AJAX/js/util.js
Normal file
407
include/pear/data/HTML_AJAX/js/util.js
Normal file
@@ -0,0 +1,407 @@
|
||||
/**
|
||||
* Utility methods
|
||||
*
|
||||
* @category HTML
|
||||
* @package Ajax
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
*
|
||||
* See Main.js for author/license details
|
||||
*/
|
||||
// {{{ HTML_AJAX_Util
|
||||
/**
|
||||
* All the utilities we will be using thorough the classes
|
||||
*/
|
||||
var HTML_AJAX_Util = {
|
||||
// Set the element event
|
||||
registerEvent: function(element, event, handler)
|
||||
{
|
||||
element = this.getElement(element);
|
||||
if (typeof element.addEventListener != "undefined") { //Dom2
|
||||
element.addEventListener(event, handler, false);
|
||||
} else if (typeof element.attachEvent != "undefined") { //IE 5+
|
||||
element.attachEvent("on" + event, handler);
|
||||
} else {
|
||||
if (element["on" + event] != null) {
|
||||
var oldHandler = element["on" + event];
|
||||
element["on" + event] = function(e) {
|
||||
oldHander(e);
|
||||
handler(e);
|
||||
};
|
||||
} else {
|
||||
element["on" + event] = handler;
|
||||
}
|
||||
}
|
||||
},
|
||||
// get the target of an event, automatically checks window.event for ie
|
||||
eventTarget: function(event)
|
||||
{
|
||||
if (!event) var event = window.event;
|
||||
if (event.target) return event.target; // w3c
|
||||
if (event.srcElement) return event.srcElement; // ie 5
|
||||
},
|
||||
// gets the type of a variable or its primitive equivalent as a string
|
||||
getType: function(inp)
|
||||
{
|
||||
var type = typeof inp, match;
|
||||
if(type == 'object' && !inp)
|
||||
{
|
||||
return 'null';
|
||||
}
|
||||
if (type == "object") {
|
||||
if(!inp.constructor)
|
||||
{
|
||||
return 'object';
|
||||
}
|
||||
var cons = inp.constructor.toString();
|
||||
if (match = cons.match(/(\w+)\(/)) {
|
||||
cons = match[1].toLowerCase();
|
||||
}
|
||||
var types = ["boolean", "number", "string", "array"];
|
||||
for (key in types) {
|
||||
if (cons == types[key]) {
|
||||
type = types[key];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return type;
|
||||
},
|
||||
// repeats the input string the number of times given by multiplier. exactly like PHP's str_repeat()
|
||||
strRepeat: function(inp, multiplier) {
|
||||
var ret = "";
|
||||
while (--multiplier > 0) ret += inp;
|
||||
return ret;
|
||||
},
|
||||
// encode a string allowing it to be used in a query string of a url
|
||||
encodeUrl: function(input) {
|
||||
return encodeURIComponent(input);
|
||||
},
|
||||
// decode a url encoded string
|
||||
decodeUrl: function(input) {
|
||||
return decodeURIComponent(input);
|
||||
},
|
||||
// recursive variable dumper similar in output to PHP's var_dump(), the differences being: this function displays JS types and type names; JS doesn't provide an object number like PHP does
|
||||
varDump: function(inp, printFuncs, _indent, _recursionLevel)
|
||||
{
|
||||
if (!_recursionLevel) _recursionLevel = 0;
|
||||
if (!_indent) _indent = 1;
|
||||
var tab = this.strRepeat(" ", ++_indent);
|
||||
var type = this.getType(inp), out = type;
|
||||
var consrx = /(\w+)\(/;
|
||||
consrx.compile();
|
||||
if (++_recursionLevel > 6) {
|
||||
return tab + inp + "Loop Detected\n";
|
||||
}
|
||||
switch (type) {
|
||||
case "boolean":
|
||||
case "number":
|
||||
out += "(" + inp.toString() + ")";
|
||||
break;
|
||||
case "string":
|
||||
out += "(" + inp.length + ") \"" + inp + "\"";
|
||||
break;
|
||||
case "function":
|
||||
if (printFuncs) {
|
||||
out += inp.toString().replace(/\n/g, "\n" + tab);
|
||||
}
|
||||
break;
|
||||
case "array":
|
||||
case "object":
|
||||
var atts = "", attc = 0;
|
||||
try {
|
||||
for (k in inp) {
|
||||
atts += tab + "[" + (/\D/.test(k) ? "\"" + k + "\"" : k)
|
||||
+ "]=>\n" + tab + this.varDump(inp[k], printFuncs, _indent, _recursionLevel);
|
||||
++attc;
|
||||
}
|
||||
} catch (e) {}
|
||||
if (type == "object") {
|
||||
var objname, objstr = inp.toString();
|
||||
if (objname = objstr.match(/^\[object (\w+)\]$/)) {
|
||||
objname = objname[1];
|
||||
} else {
|
||||
try {
|
||||
objname = inp.constructor.toString().match(consrx)[1];
|
||||
} catch (e) {
|
||||
objname = 'unknown';
|
||||
}
|
||||
}
|
||||
out += "(" + objname + ") ";
|
||||
}
|
||||
out += "(" + attc + ") {\n" + atts + this.strRepeat(" ", _indent - 1) +"}";
|
||||
break;
|
||||
}
|
||||
return out + "\n";
|
||||
},
|
||||
// non resursive simple debug printer
|
||||
quickPrint: function(input,sep) {
|
||||
if (!sep) {
|
||||
var sep = "\n";
|
||||
}
|
||||
var type = HTML_AJAX_Util.getType(input);
|
||||
switch (type) {
|
||||
case 'string':
|
||||
return input;
|
||||
case 'array':
|
||||
var ret = "";
|
||||
for(var i = 0; i < input.length; i++) {
|
||||
ret += i+':'+input[i]+sep;
|
||||
}
|
||||
return ret;
|
||||
default:
|
||||
var ret = "";
|
||||
for(var i in input) {
|
||||
ret += i+':'+input[i]+sep;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
//compat function for stupid browsers in which getElementsByTag with a * dunna work
|
||||
getAllElements: function(parentElement)
|
||||
{
|
||||
//check for idiot browsers
|
||||
if( document.all)
|
||||
{
|
||||
if(!parentElement) {
|
||||
var allElements = document.all;
|
||||
}
|
||||
else
|
||||
{
|
||||
var allElements = [], rightName = new RegExp( parentElement, 'i' ), i;
|
||||
for( i=0; i<document.all.length; i++ ) {
|
||||
if( rightName.test( document.all[i].parentElement ) )
|
||||
allElements.push( document.all[i] );
|
||||
}
|
||||
}
|
||||
return allElements;
|
||||
}
|
||||
//real browsers just do this
|
||||
else
|
||||
{
|
||||
if (!parentElement) { parentElement = document.body; }
|
||||
return parentElement.getElementsByTagName('*');
|
||||
}
|
||||
},
|
||||
getElementsByProperty: function(property, regex, parentElement) {
|
||||
var allElements = HTML_AJAX_Util.getAllElements(parentElement);
|
||||
var items = [];
|
||||
for(var i=0,j=allElements.length; i<j; i++)
|
||||
{
|
||||
if(regex.test(allElements[i][property]))
|
||||
{
|
||||
items.push(allElements[i]);
|
||||
}
|
||||
}
|
||||
return items;
|
||||
},
|
||||
getElementsByClassName: function(className, parentElement) {
|
||||
return HTML_AJAX_Util.getElementsByProperty('className',new RegExp('(^| )' + className + '( |$)'),parentElement);
|
||||
},
|
||||
getElementsById: function(id, parentElement) {
|
||||
return HTML_AJAX_Util.getElementsByProperty('id',new RegExp(id),parentElement);
|
||||
},
|
||||
getElementsByCssSelector: function(selector,parentElement) {
|
||||
return cssQuery(selector,parentElement);
|
||||
},
|
||||
htmlEscape: function(inp) {
|
||||
var div = document.createElement('div');
|
||||
var text = document.createTextNode(inp);
|
||||
div.appendChild(text);
|
||||
return div.innerHTML;
|
||||
},
|
||||
// return the base of the given absolute url, or the filename if the second argument is true
|
||||
baseURL: function(absolute, filename) {
|
||||
var qPos = absolute.indexOf('?');
|
||||
if (qPos >= 0) {
|
||||
absolute = absolute.substr(0, qPos);
|
||||
}
|
||||
var slashPos = Math.max(absolute.lastIndexOf('/'), absolute.lastIndexOf('\\'));
|
||||
if (slashPos < 0) {
|
||||
return absolute;
|
||||
}
|
||||
return (filename ? absolute.substr(slashPos + 1) : absolute.substr(0, slashPos + 1));
|
||||
},
|
||||
// return the query string from a url
|
||||
queryString: function(url) {
|
||||
var qPos = url.indexOf('?');
|
||||
if (qPos >= 0) {
|
||||
return url.substr(qPos+1);
|
||||
}
|
||||
},
|
||||
// return the absolute path to the given relative url
|
||||
absoluteURL: function(rel, absolute) {
|
||||
if (/^https?:\/\//i.test(rel)) {
|
||||
return rel;
|
||||
}
|
||||
if (!absolute) {
|
||||
var bases = document.getElementsByTagName('base');
|
||||
for (i in bases) {
|
||||
if (bases[i].href) {
|
||||
absolute = bases[i].href;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!absolute) {
|
||||
absolute = window.location.href;
|
||||
}
|
||||
}
|
||||
if (rel == '') {
|
||||
return absolute;
|
||||
}
|
||||
if (rel.substr(0, 2) == '//') {
|
||||
// starts with '//', replace everything but the protocol
|
||||
var slashesPos = absolute.indexOf('//');
|
||||
if (slashesPos < 0) {
|
||||
return 'http:' + rel;
|
||||
}
|
||||
return absolute.substr(0, slashesPos) + rel;
|
||||
}
|
||||
var base = this.baseURL(absolute);
|
||||
var absParts = base.substr(0, base.length - 1).split('/');
|
||||
var absHost = absParts.slice(0, 3).join('/') + '/';
|
||||
if (rel.substr(0, 1) == '/') {
|
||||
// starts with '/', append it to the host
|
||||
return absHost + rel;
|
||||
}
|
||||
if (rel.substr(0, 1) == '.' && rel.substr(1, 1) != '.') {
|
||||
// starts with '.', append it to the base
|
||||
return base + rel.substr(1);
|
||||
}
|
||||
// remove everything upto the path and beyond
|
||||
absParts.splice(0, 3);
|
||||
var relParts = rel.split('/');
|
||||
var loopStart = relParts.length - 1;
|
||||
relParts = absParts.concat(relParts);
|
||||
for (i = loopStart; i < relParts.length;) {
|
||||
if (relParts[i] == '..') {
|
||||
if (i == 0) {
|
||||
return absolute;
|
||||
}
|
||||
relParts.splice(i - 1, 2);
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return absHost + relParts.join('/');
|
||||
},
|
||||
// sets the innerHTML of an element. the third param decides how to write, it replaces by default, others are append|prepend
|
||||
setInnerHTML: function(node, innerHTML, type)
|
||||
{
|
||||
node = this.getElement(node);
|
||||
|
||||
if (type != 'append') {
|
||||
if (type == 'prepend') {
|
||||
var oldHtml = node.innerHTML;
|
||||
}
|
||||
node.innerHTML = '';
|
||||
}
|
||||
var good_browser = (window.opera || navigator.product == 'Gecko');
|
||||
var regex = /^([\s\S]*?)<script([\s\S]*?)>([\s\S]*?)<\/script>([\s\S]*)$/i;
|
||||
var regex_src = /src=["'](.*?)["']/i;
|
||||
var matches, id, script, output = '', subject = innerHTML;
|
||||
var scripts = [];
|
||||
|
||||
while (true) {
|
||||
matches = regex.exec(subject);
|
||||
if (matches && matches[0]) {
|
||||
subject = matches[4];
|
||||
id = 'ih_' + Math.round(Math.random()*9999) + '_' + Math.round(Math.random()*9999);
|
||||
|
||||
var startLen = matches[3].length;
|
||||
script = matches[3].replace(/document\.write\(([\s\S]*?)\)/ig,
|
||||
'document.getElementById("' + id + '").innerHTML+=$1');
|
||||
|
||||
output += matches[1];
|
||||
if (startLen != script.length) {
|
||||
output += '<span id="' + id + '"></span>';
|
||||
}
|
||||
|
||||
output += '<script' + matches[2] + '>' + script + '</script>';
|
||||
if (good_browser) {
|
||||
continue;
|
||||
}
|
||||
if (script) {
|
||||
scripts.push(script);
|
||||
}
|
||||
if (regex_src.test(matches[2])) {
|
||||
var script_el = document.createElement("SCRIPT");
|
||||
var atts_regex = /(\w+)=["'](.*?)["']([\s\S]*)$/;
|
||||
var atts = matches[2];
|
||||
for (var i = 0; i < 5; i++) {
|
||||
var atts_matches = atts_regex.exec(atts);
|
||||
if (atts_matches && atts_matches[0]) {
|
||||
script_el.setAttribute(atts_matches[1], atts_matches[2]);
|
||||
atts = atts_matches[3];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
scripts.push(script_el);
|
||||
}
|
||||
} else {
|
||||
output += subject;
|
||||
break;
|
||||
}
|
||||
}
|
||||
innerHTML = output;
|
||||
|
||||
if (good_browser) {
|
||||
var el = document.createElement('span');
|
||||
el.innerHTML = innerHTML;
|
||||
|
||||
for(var i = 0; i < el.childNodes.length; i++) {
|
||||
node.appendChild(el.childNodes[i].cloneNode(true));
|
||||
}
|
||||
}
|
||||
else {
|
||||
node.innerHTML += innerHTML;
|
||||
}
|
||||
|
||||
if (oldHtml) {
|
||||
node.innerHTML += oldHtml;
|
||||
}
|
||||
|
||||
if (!good_browser) {
|
||||
for(var i = 0; i < scripts.length; i++) {
|
||||
if (HTML_AJAX_Util.getType(scripts[i]) == 'string') {
|
||||
scripts[i] = scripts[i].replace(/^\s*<!(\[CDATA\[|--)|((\/\/)?--|\]\])>\s*$/g, '');
|
||||
window.eval(scripts[i]);
|
||||
}
|
||||
else {
|
||||
node.appendChild(scripts[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
},
|
||||
classSep: '(^|$| )',
|
||||
hasClass: function(o, className) {
|
||||
var o = this.getElement(o);
|
||||
var regex = new RegExp(this.classSep + className + this.classSep);
|
||||
return regex.test(o.className);
|
||||
},
|
||||
addClass: function(o, className) {
|
||||
var o = this.getElement(o);
|
||||
if(!this.hasClass(o, className)) {
|
||||
o.className += " " + className;
|
||||
}
|
||||
},
|
||||
removeClass: function(o, className) {
|
||||
var o = this.getElement(o);
|
||||
var regex = new RegExp(this.classSep + className + this.classSep);
|
||||
o.className = o.className.replace(regex, " ");
|
||||
},
|
||||
replaceClass: function(o, oldClass, newClass) {
|
||||
var o = this.getElement(o);
|
||||
var regex = new RegExp(this.classSep + oldClass + this.classSep);
|
||||
o.className = o.className.replace(regex, newClass);
|
||||
},
|
||||
getElement: function(el) {
|
||||
if (typeof el == 'string') {
|
||||
return document.getElementById(el);
|
||||
}
|
||||
return el;
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
Reference in New Issue
Block a user