mirror of
https://github.com/ACSPRI/queXS
synced 2024-04-02 12:12:16 +00:00
521 lines
14 KiB
JavaScript
521 lines
14 KiB
JavaScript
/**
|
|
* 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();
|
|
|