Files
simrs-jatim/include/ajax.js
2024-04-19 14:04:41 +07:00

1268 lines
42 KiB
JavaScript

/**
* @fileoverview
* Ajax Javascript Library<br/>
* (c)2006 LAMATEK, Inc.<br/>
* @author Tom Cole tcole@lamatek.com
* @version 2.0
*/
/**
* Factory class for handling multiple Ajax Requests. Allows you to create and
* identify AjaxRequests via a user defined string.
*/
var AjaxFactory = function () {
/**Array that stores all AjaxRequest objects */
var requests = {};
/**
* Creates a new request and adds it to the queue.
*/
this.createRequest = function (id) {
var request = new AjaxRequest();
requests[id] = request;
return request;
}
/**
* Attempts to return the value from the specified request id, if
* it exists.
*/
this.getRequest = function (id) {
var request = requests[id];
if (request) {
return request;
}
else {
return null;
}
}
/**
* Removes a request from the queue.
*/
this.deleteRequest = function (id) {
requests[id] = null;
}
}
/**
* Cross-browser implementation to obtain and process a XMLHttpRequest instance.
* It removes the need to worry about cross-browser implementation issues and provides
* a simple, consistent interface to XMLHttpRequests. It also provides a simple API
* that automatically converts the response to the expected data type (text, xml
* or JSON) and gives a simple way to parse values from XML responses.
*/
var AjaxRequest = function () {
/**Current debugging status. */
var debug = false;
/**Handle to a loading display div.*/
var async = true;
/**The resulting value (either a String or DOM object based on request type.*/
var value = null;
/**The resulting value as a String, regardless of request type.*/
var valueString = null;
/**The XMLHttpRequest used to send & receive data.*/
var xmlhttp = null;
/**The method that will get called on a successful request.*/
var handler = null;
/**Secondary handler used in autoSubmitAndLoad___Request methods. */
var handler2 = null;
/**Attempts to hold browser type. Only works after an AjaxRequest has been created.*/
var browser = (navigator.appName.indexOf('Microsoft') >= 0);
/**The text to display while requests are processing.*/
var message = "Please wait...";
/**Holds the last request type.*/
var type = "text";
/**Holds the active parnt form element. Used in the submit___Request methods.*/
var form;
/**Denotes whether the user is providing style elements him/herself*/
var isStyled = false;
/**Denotes whether or not unique id generated is desired.*/
var uniqueID = false;
/**Denotes the timeout limit for requests.*/
var timeout = null;
/**Denotes the method to call if a timeout occurs.*/
var timeouthandler = null;
/**The timeout object. Kept as a reference so we can clear it if not needed.*/
var timer = null;
/**Denotes whether a request has been completed. Used by timeoutRequest.*/
var completed = false;
/**Denotes that the request was aborted.*/
var aborted = false;
/**Array of set request header values.*/
var headers = new Array();
/**Denotes that this request is cross domain.*/
var crossDomain = false;
/**Provides DOM based drag capabilities for the log window.
*
* This script found at http://boring.youngpup.net/2001/domdrag.
*/
var Drag = {
obj : null,
init : function(o, oRoot, minX, maxX, minY, maxY, bSwapHorzRef, bSwapVertRef, fXMapper, fYMapper) {
o.onmousedown = Drag.start;
o.hmode = bSwapHorzRef ? true : false ;
o.vmode = bSwapVertRef ? false : true ;
o.root = oRoot && oRoot != null ? oRoot : o ;
if (o.hmode && isNaN(parseInt(o.root.style.left ))) o.root.style.left = "0px";
if (o.vmode && isNaN(parseInt(o.root.style.top ))) o.root.style.top = "0px";
if (!o.hmode && isNaN(parseInt(o.root.style.right ))) o.root.style.right = "0px";
if (!o.vmode && isNaN(parseInt(o.root.style.bottom))) o.root.style.bottom = "0px";
o.minX = typeof minX != 'undefined' ? minX : null;
o.minY = typeof minY != 'undefined' ? minY : null;
o.maxX = typeof maxX != 'undefined' ? maxX : null;
o.maxY = typeof maxY != 'undefined' ? maxY : null;
o.xMapper = fXMapper ? fXMapper : null;
o.yMapper = fYMapper ? fYMapper : null;
o.root.onDragStart = new Function();
o.root.onDragEnd = new Function();
o.root.onDrag = new Function();
},
start : function(e) {
var o = Drag.obj = this;
e = Drag.fixE(e);
var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom);
var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
o.root.onDragStart(x, y);
o.lastMouseX = e.clientX;
o.lastMouseY = e.clientY;
if (o.hmode) {
if (o.minX != null) o.minMouseX = e.clientX - x + o.minX;
if (o.maxX != null) o.maxMouseX = o.minMouseX + o.maxX - o.minX;
} else {
if (o.minX != null) o.maxMouseX = -o.minX + e.clientX + x;
if (o.maxX != null) o.minMouseX = -o.maxX + e.clientX + x;
}
if (o.vmode) {
if (o.minY != null) o.minMouseY = e.clientY - y + o.minY;
if (o.maxY != null) o.maxMouseY = o.minMouseY + o.maxY - o.minY;
} else {
if (o.minY != null) o.maxMouseY = -o.minY + e.clientY + y;
if (o.maxY != null) o.minMouseY = -o.maxY + e.clientY + y;
}
document.onmousemove = Drag.drag;
document.onmouseup = Drag.end;
return false;
},
drag : function(e) {
e = Drag.fixE(e);
var o = Drag.obj;
var ey = e.clientY;
var ex = e.clientX;
var y = parseInt(o.vmode ? o.root.style.top : o.root.style.bottom);
var x = parseInt(o.hmode ? o.root.style.left : o.root.style.right );
var nx, ny;
if (o.minX != null) ex = o.hmode ? Math.max(ex, o.minMouseX) : Math.min(ex, o.maxMouseX);
if (o.maxX != null) ex = o.hmode ? Math.min(ex, o.maxMouseX) : Math.max(ex, o.minMouseX);
if (o.minY != null) ey = o.vmode ? Math.max(ey, o.minMouseY) : Math.min(ey, o.maxMouseY);
if (o.maxY != null) ey = o.vmode ? Math.min(ey, o.maxMouseY) : Math.max(ey, o.minMouseY);
nx = x + ((ex - o.lastMouseX) * (o.hmode ? 1 : -1));
ny = y + ((ey - o.lastMouseY) * (o.vmode ? 1 : -1));
if (o.xMapper) nx = o.xMapper(y)
else if (o.yMapper) ny = o.yMapper(x)
Drag.obj.root.style[o.hmode ? "left" : "right"] = nx + "px";
Drag.obj.root.style[o.vmode ? "top" : "bottom"] = ny + "px";
Drag.obj.lastMouseX = ex;
Drag.obj.lastMouseY = ey;
Drag.obj.root.onDrag(nx, ny);
return false;
},
end : function() {
document.onmousemove = null;
document.onmouseup = null;
Drag.obj.root.onDragEnd( parseInt(Drag.obj.root.style[Drag.obj.hmode ? "left" : "right"]),
parseInt(Drag.obj.root.style[Drag.obj.vmode ? "top" : "bottom"]));
Drag.obj = null;
},
fixE : function(e){
if (typeof e == 'undefined') e = window.event;
if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
return e;
}
};
/**
* This internal method resets the completed and aborted status for the next request
* and setups the client callback handler.
* @param {Function} method The end-user defined method that will be called upon successful completion of the request.
*/
var generateRequest = function (method) {
complete = false;
aborted = false;
log("----Registering client callback method...",0);
handler = method;
xmlhttp = getRequest();
if (xmlhttp) {
xmlhttp.onreadystatechange = parseResponse;
}
}
/**
* This internal method is a cross-browser implementation to obtain an
* XMLHttpRequest object.
* @type XMLHttpRequest
*/
var getRequest = function () {
var xml;
/*@cc_on
@if (@_jscript_version >= 5)
try {
xml = new ActiveXObject("Msxml2.XMLHTTP");
browser = true;
}
catch (e) {
try {
xml = new ActiveXObject("Microsoft.XMLHTTP");
browser = true;
}
catch (E) {
xml = false;
}
}
@else
xml = false;
@end @*/
if (!xml && typeof XMLHttpRequest != 'undefined') {
try {
xml = new XMLHttpRequest();
browser = false;
}
catch (e) {
xml = false;
browser = false;
}
}
if (! xml) {
this.log("------Unable to create XmlHTTPRequest.", 3);
}
return xml;
}
/**
* This internal method reads the text response from the xmlhttp request, attempts to create
* the appropriate data type out of it (based on the type) and calls the registered handler method.
*/
var parseResponse = function () {
headers = new Array(); //reset headers so they aren't used on subsequent calls.
if (xmlhttp && !aborted) {
if (xmlhttp.readyState == 4) {
clearTimeout(timer);
completed = true;
log("------XmlHTTPRequest readystate is OK...");
if (xmlhttp.status == 200) {
valueString = xmlhttp.responseText;
log("------XmlHTTPRequest status is OK...");
log("");
log("------Response received:<br/><blockquote><pre>" + valueString.replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</pre></blockquote>",1);
try {
switch (type) {
case 'json':
value = eval('(' + xmlhttp.responseText + ')');
break;
case 'xml':
value = xmlhttp.responseXML;
break;
default:
value = xmlhttp.responseText;
}
}
catch(e) {
log("------Error occurred assigning response to value: " + e.message + "...", 3);
value = null
}
if (handler) {
if (! form && ! handler2)
log("Forwarding control to client handler:<br/><blockquote><pre>" + handler.toString().replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</pre></blockquote>", 1);
handler.call(this);
}
}
else {
log("------XmlHTTPRequest status returned " + xmlhttp.status + "...", 3);
value = null;
}
if (document.getElementById('loadingDiv')) {
document.body.removeChild(document.getElementById('loadingDiv'));
}
delete xmlhttp.onreadystatechange;
}
else {
log("------XmlHTTPRequest readystate is " + xmlhttp.readyState + "...", 2);
}
}
}
/**
* This internal method generates and sends the XMLHttpRequest.
* @param url The relative or absolute url of the server side resource receiving the request
* @param method The request method to use (GET, POST or HEAD)
* @param parameters The parameter list to send to the server (name=value&name2=value...)
* @param callback The javascript method to call upon a successful response
* @param asynchronous True or false
* @param responseType The expected server response data-type "text", "xml" or "json"
*/
var initiateRequest = function (url, method, parameters, callback, asynchronous, responseType) {
type = responseType;
if (url) {
var defMethod = "GET";
if (method) {
defMethod = method;
}
defMethod = defMethod.toUpperCase();
if (uniqueID) {
var uid = (new Date()).getTime();
if (parameters) {
parameters += "&uniqueid=" + uid;
}
else {
parameters = "uniqueid=" + uid;
}
}
if (defMethod == "GET") {
url += "?" + parameters;
parameters = null;
}
log("--Request method set to " + defMethod + "...");
async = true;
if (! asynchronous) {
async = asynchronous;
}
log("--Request set to asynchronous: " + async + "...");
showLoadingDiv();
generateRequest(callback);
xmlhttp.open(defMethod, url, async);
if (parameters) {
xmlhttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
for (var i = 0; i < headers.length; i++) {
xmlhttp.setRequestHeader(headers[i].name, headers[i].value);
alert("Set " + headers[i].name + " to " + headers[i].value);
}
}
else {
parameters = null;
}
for (var i = 0; i < headers.length; i++) {
xmlhttp.setRequestHeader(headers[i].name, headers[i].value);
}
log("--Sending request...");
if (timeout) {
timer = setTimeout(doTimeout, timeout);
}
completed = false;
xmlhttp.send(parameters);
}
else {
log("--Request URL is not set. Unable to process request.", 3);
}
}
/**
* This internal method is called once the user set timeout limit is hit.
* If the request has not completed, it attempts to abort the request.
*/
var doTimeout = function () {
if (xmlhttp && (! completed)) {
log("--Request has hit timeout limit. Aborting request.", 2);
aborted = true;
xmlhttp.abort();
if (timeouthandler) {
log("--Calling client timeout handler.");
timeouthandler.call(this);
}
completed = true;
if (document.getElementById('loadingDiv')) {
document.body.removeChild(document.getElementById('loadingDiv'));
}
xmlhttp = null;
}
}
/**
* This internal method creates a floating window (if necessary) and adds a
* message ine to the log.
* @param message A message to add to the log window.
*/
var log = function (message, severity) {
if (debug) {
var bg = "#ffffff";
if (severity) {
switch (severity) {
case 3:
bg = "#ff0000";
break;
case 2:
bg = "#ffb500";
break;
case 1:
bg = "#ffff00";
break;
default:
bg = "#ffffff";
}
}
if (! document.getElementById("loggerDiv")) {
var logger = document.createElement("div");
logger.id = "loggerDiv";
if (browser) {
logger.style.position = "absolute";
}
else {
logger.style.position = "fixed";
}
logger.style.top = "25px";
logger.style.right = "25px";
logger.style.display = "inline";
logger.style.width = "400";
logger.style.height = "400";
logger.style.border = "1px solid #000000";
logger.style.background = "#cccccc";
var loggerBar = document.createElement("div");
loggerBar.id = "loggerBar";
loggerBar.style.height = 22;
loggerBar.style.textAlign = "right";
loggerBar.innerHTML = "<span width=\"100%\"><input type=\"button\" value=\"Clear\" onclick=\"document.getElementById('loggerStatusDetails').removeChild(document.getElementById('loggingDetailLines'));\"/><input type=\"button\" value=\"X\" onclick=\"document.body.removeChild(document.getElementById('loggerDiv'));\"/></span>";
logger.appendChild(loggerBar);
var loggerStatus = document.createElement("div");
loggerStatus.style.overflow = "auto";
loggerStatus.id = "loggerStatusDetails";
loggerStatus.style.background = "#ffffff";
loggerStatus.style.width = "100%";
loggerStatus.style.height = 378;
logger.appendChild(loggerStatus);
document.body.insertBefore(logger, document.body.firstChild);
}
if (! document.getElementById('loggingDetailLines')) {
var loggerDiv = document.getElementById("loggerStatusDetails");
var loggingDiv = document.createElement("div");
loggingDiv.id = "loggingDetailLines";
loggerDiv.appendChild(loggingDiv);
}
var loggingDiv = document.getElementById('loggingDetailLines');
var logLine = document.createElement("div");
logLine.style.borderTop = "1px solid #cccccc";
logLine.innerHTML = message;
logLine.style.background = bg;
loggingDiv.appendChild(logLine);
Drag.init(document.getElementById('loggerBar'), document.getElementById('loggerDiv'));
}
}
/**
* This internal method displays a "loading" div message for asynchronous requests.
*/
var showLoadingDiv = function () {
if (message) {
if (! document.getElementById('loadingDiv')) {
var loading = document.createElement("div");
loading.id = 'loadingDiv';
loading.innerHTML = message;
if (browser) {
loading.style.position = 'absolute';
}
else {
loading.style.position = 'fixed';
}
if (! isStyled) {
loading.style.background = '#cc0000';
loading.style.color = '#ffffff';
loading.style.top = 2;
loading.style.right = 2;
loading.style.paddingLeft = 5;
loading.style.paddingRight = 5;
loading.style.fontFamily = "Arial";
loading.style.fontSize = "12";
}
loading.className = 'loading';
document.body.appendChild(loading);
}
}
}
/**
* This internal method automatically builds the parameter list from any form elements inside the given
* form node as if submitted by the given submitBy element. This method does not work for multipart/form-data enctypes.
* @param {String} form The id of the form node to submit.
* @param {Object} submitBy The element that is submitting the form.
* @type {String} returns a parameter list for the specified form submitted by the specified submittor.
*/
var getFormData = function (form, submitBy) {
try {
var parameters = "";
for (var i = 0; i < form.getElementsByTagName('input').length; i++) {
var element = form.getElementsByTagName('input')[i];
var name = null;
if (element.name)
name = element.name;
else if (element.id)
name = element.id;
if (name) {
switch (element.type) {
case 'check':
if (element.checked)
parameters += name + "=" + element.value + "&";
else
parameters += name + "=&";
break;
case 'radio':
if (element.checked)
parameters += name + "=" + element.value + "&";
break;
case 'submit': //ignore these, handled by submitBy
break;
case 'button': //ignore these, handled by submitBy
break;
default:
parameters += name + "=" + element.value + "&";
}
}
}
for (var i = 0; i < form.getElementsByTagName('select').length; i++) {
var element = form.getElementsByTagName('select')[i];
var name = null;
if (element.name)
name = element.name;
else if (element.id)
name = element.id;
if (name) {
if (element.type == 'select-one') {
parameters += name + "=" + element.options[element.selectedIndex].value + "&";
}
else if (element.type == 'select-multiple') {
for (var j = 0; j < element.options.length; j++) {
if (element.options[j].selected)
parameters += name + "=" + element.options[j].value + "&";
}
}
}
}
for (var i = 0; i < form.getElementsByTagName('textarea').length; i++) {
var element = form.getElementsByTagName('textarea')[i];
var name = null;
if (element.name)
name = element.name;
else if (element.id)
name = element.id;
if (name) {
parameters += name + "=" + element.value + "&";
}
}
if (submitBy) {
var name = null;
if (submitBy.name)
name = submitBy.name;
else if (submitBy.id)
name = submitBy.id;
if (name) {
parameters += name + "=" + submitBy.value;
}
}
return parameters;
}
catch(e) {
return null;
}
}
var setElement = function (element, rValue) {
switch(element.tagName) {
case 'INPUT':
switch(element.typeName) {
case 'check': case 'radio':
if (element.value == rValue) {
element.checked = true;
}
break;
default:
try {
element.value = rValue;
}
catch(e) {
log("Error attempting to assign value to element " + rName + ". Skipping it.", 1);
}
}
break;
case 'TEXTAREA':
element.innerHTML = rValue;
break;
case 'SELECT':
for (var j = 0; j < element.options.length; j++) {
if (element.options[j].value == rValue) {
element.options[j].selected = true;
break;
}
}
break;
default:
try {
element.innerHTML = rValue;
}
catch(e) {
log("Error assigning value to unidentified element " + rName + ". Skipping it.", 1);
}
}
}
/**
* This internal method takes the current value object as a CSV string and parses
* through it for all names. It attempts to find screen elements with id's that
* match each name, and if it finds one, sets it's value to that name's value.
*/
var populateFormFromText = function () {
try {
if (form) {
for (var i = 0; i < value.split(',').length; i++) {
var child = value.split(',')[i];
try {
var rName = child.split("=")[0];
var rValue = child.split("=")[1] || '';
var element = document.getElementById(rName);
if (element) {
setElement(element, rValue);
}
else {
element = document.getElementsByName(rName);
if (element) {
for (var j = 0; j < element.length; j++) {
setElement(element[j], rValue);
}
}
}
}
catch(e) {
}
}
}
else {
log("Error attempting to populate form. The current form is null.", 3);
}
}
catch(e) {
log("An error occured attempting to populate the form.<blockquote><pre>" + e.message + "</pre></blockquote>", 3);
}
if (handler2) {
log("Forwarding control to client handler:<br/><blockquote><pre>" + handler2.toString().replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</pre></blockquote>", 1);
handler2.call();
}
}
/**
* This internal method takes the current value object as JSON and parses through
* the values array..
* It attempts to find screen elements with id's that match each "name", and if
* it finds one, sets it's value to "value".
*/
var populateFormFromJSON = function () {
try {
if (form) {
var root = value;
for (var i = 0; i < root.values.length; i++) {
var rName = root.values[i].name;
var rValue = root.values[i].value;
var element = document.getElementById(rName);
if (element) {
setElement(element, rValue);
}
else {
element = document.getElementsByName(rName);
if (element) {
for (var j = 0; j < element.length; j++) {
setElement(element[j], rValue);
}
}
}
}
}
else {
log("Error attempting to populate form. The current form is null.", 3);
}
}
catch(e) {
log("An error occured attempting to populate the form.<blockquote><pre>" + e.message + "</pre></blockquote>", 3);
}
if (handler2) {
log("Forwarding control to client handler:<br/><blockquote><pre>" + handler2.toString().replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</pre></blockquote>", 1);
handler2.call();
}
}
/**
* This internal method takes the current value object as XML and parses through
* it for all nodes. It attempts to find screen elements with id's that match
* each nodeName, and if it finds one, sets it's value to that node's value.
*/
var populateFormFromXML = function () {
try {
if (form) {
var root = value.documentElement;
for (var i = 0; i < root.childNodes.length; i++) {
var child = root.childNodes[i];
var rName = child.nodeName;
var rValue = child.firstChild.data;
var element = document.getElementById(rName);
if (element) {
setElement(element, rValue);
}
else {
element = document.getElementsByName(rName);
if (element) {
for (var j = 0; j < element.length; j++) {
setElement(element[j], rValue);
}
}
}
}
}
else {
log("Error attempting to populate form. The current form is null.", 3);
}
}
catch(e) {
log("An error occured attempting to populate the form.<blockquote><pre>" + e.message + "</pre></blockquote>", 3);
}
if (handler2) {
log("Forwarding control to client handler:<br/><blockquote><pre>" + handler2.toString().replace(/</g, "&lt;").replace(/>/g, "&gt;") + "</pre></blockquote>", 1);
handler2.call();
}
}
/**
*This public method makes a JSON request, reads the response and attempts
* to load any document elements with the given values. It assumes that the
* response will be a valid JSON string in the given format:
*
* { values [
* {"name": "name1", "value": "value1},
* {"name": "name1", "value": "value1}
* ] }
*
* Where any element with an id or name of 'name1' will be assigned the value (or innerHTML)
* of 'value1'.
*/
this.autoSubmitAndLoadJSONRequest = function (element, callback) {
handler2 = callback;
this.submitJSONRequest(element, populateFormFromJSON, true);
}
/**
* This public method initiates a request that is expected to return
* a JSON text string that is to be converted into a JSON object. Parameter data,
* url and call method are retrieved from the given form object.
* The resulting object will be stored in the value variable and
* can be retrieved using getValue();
* @param {String} form The form DOM object fro which to pull form data. (REQUIRED)
* @param {Object} submitBy The element that is initiating the form submission. (OPTIONAL)
* @param {Function} callback The end-user defined method that will be called upon successful completion of the request. Default is null. (OPTIONAL)
* @param {Boolean} asynchronous. Set to true if the request is to be asynchronous, false if not. Default is true. (OPTIONAL)
*/
this.submitJSONRequest = function (element, callback, asynchronous) {
try {
form = element;
while (! (form.tagName == 'FORM')) {
form = form.parentNode;
}
if (form) {
this.doJSONRequest(form.action, form.method || "GET", getFormData(form, element), callback, asynchronous);
}
else {
log("Error processing Ajax form submission. Form " + form + " is not valid");
}
}
catch(e) {
log("Error generating Ajax request in submitJSONRequest. " + e.message);
}
}
/**
* This public method initiates a request that is expected to return
* a JSON text string that is to be converted into a JSON object.
* The resulting object will be stored in the value variable and
* can be retrieved using getValue();
* @param {String} url The url to the server resource that will handle the request. (REQUIRED)
* @param {String} method The HTTP method to send the request. Must be "GET" or "POST". Default is "GET" (OPTIONAL)
* @param {String} parameters A url formatted list of parameter names and values. Parameters are specified as name=value&name=value.... Default is null. (OPTIONAL)
* @param {Function} callback The end-user defined method that will be called upon successful completion of the request. Default is null. (OPTIONAL)
* @param {Boolean} asynchronous. Set to true if the request is to be asynchronous, false if not. Default is true. (OPTIONAL)
*/
this.doJSONRequest = function (url, method, parameters, callback, asynchronous) {
log("Beginning new JSON request...");
initiateRequest(url, method, parameters, callback, asynchronous, "json");
}
/**
*This public method makes an XML request, reads the response and attempts
* to load any document elements with the given values. It assumes that the
* response will be a valid XML document in the given format:
*
* <?xml version="1.0" encoding="UTF-8" ?>
* <documentElement>
* <name>value<name>
* <name2>value2</name2>
* ...
* </documentElement>
*
* Where any element with an id or name of 'name' will be assigned the value (or innerHTML)
* of 'value'.
*/
this.autoSubmitAndLoadXMLRequest = function (element, callback) {
handler2 = callback;
this.submitXMLRequest(element, populateFormFromXML, true);
}
/**
* This public method initiates a request that is expected to return
* an XML text string that is to be converted into a XML DOM object. Parameter data,
* url and call method are retrieved from the given form object.
* The resulting object will be stored in the value variable and
* can be retrieved using getValue();
* @param {Object} form The form DOM object fro which to pull form data. (REQUIRED)
* @param {Object} submitBy The element that is initiating the form submission. (OPTIONAL)
* @param {Function} callback The end-user defined method that will be called upon successful completion of the request. Default is null. (OPTIONAL)
* @param {Boolean} asynchronous. Set to true if the request is to be asynchronous, false if not. Default is true. (OPTIONAL)
*/
this.submitXMLRequest = function (element, callback, asynchronous) {
try {
form = element;
while (! (form.tagName == 'FORM')) {
form = form.parentNode;
}
if (form) {
this.doXMLRequest(form.action, form.method || "GET", getFormData(form, element), callback, asynchronous);
}
else {
log("Error processing Ajax form submission. Form " + form + " is not valid");
}
}
catch(e) {
log("Error generating Ajax request in submitXMLRequest. " + e.message);
}
}
/**
* This public method initiates a request that is expected to return
* an XML document. The resulting DOM object will be stored in the value variable and
* can be retrieved using getValue();
* @param {String} url The url to the server resource that will handle the request. (REQUIRED)
* @param {String} method The HTTP method to send the request. Must be "GET" or "POST". Default is "GET" (OPTIONAL)
* @param {String} parameters A url formatted list of parameter names and values. Parameters are specified as name=value&name=value.... Default is null. (OPTIONAL)
* @param {Function} callback The end-user defined method that will be called upon successful completion of the request. Default is null. (OPTIONAL)
* @param {Boolean} asynchronous. Set to true if the request is to be asynchronous, false if not. Default is true. (OPTIONAL)
*/
this.doXMLRequest = function (url, method, parameters, callback, asynchronous) {
log("Beginning new XML request...");
initiateRequest(url, method, parameters, callback, asynchronous, "xml");
}
/**
*This public method makes a text request, reads the response and attempts
* to load any document elements with the given values. It assumes that the
* response will be a valid CSV string in the given format:
*
* name=value,name1=value1,name2=value2,name3=value3...
*
* Where any element with an id or name of 'name' will be assigned the value (or innerHTML)
* of 'value'.
*/
this.autoSubmitAndLoadTextRequest = function (element, callback) {
handler2 = callback;
this.submitTextRequest(element, populateFormFromText, true);
}
/**
* This public method initiates a request that is expected to return
* a text string or an XML/JSON request where the response should not be converted
* into an object. Parameter data,
* url and call method are retrieved from the given form object.
* The resulting object will be stored in the value variable and
* can be retrieved using getValue();
* @param {Object} form The form DOM object fro which to pull form data. (REQUIRED)
* @param {Object} submitBy The element that is initiating the form submission. (OPTIONAL)
* @param {Function} callback The end-user defined method that will be called upon successful completion of the request. Default is null. (OPTIONAL)
* @param {Boolean} asynchronous. Set to true if the request is to be asynchronous, false if not. Default is true. (OPTIONAL)
*/
this.submitTextRequest = function (element, callback, asynchronous) {
try {
form = element;
while (! (form.tagName == 'FORM')) {
form = form.parentNode;
}
if (form) {
this.doTextRequest(form.action, form.method || "GET", getFormData(form, element), callback, asynchronous);
}
else {
log("Error processing Ajax form submission. Form " + form + " is not valid");
}
}
catch(e) {
log("Error generating Ajax request in submitTextRequest. " + e.message);
}
}
/**
* This public method initiates a request that is expected to return
* a text string OR a request that returns an XML document that is desired as a string,
* rather than a DOM object. The resulting string will be stored in the value variable and
* can be retrieved using getValue();
* @param {String} url The url to the server resource that will handle the request. (REQUIRED)
* @param {String} method The HTTP method to send the request. Must be "GET" or "POST". Default is "GET" (OPTIONAL)
* @param {String} parameters A url formatted list of parameter names and values. Parameters are specified as name=value&name=value.... Default is null. (OPTIONAL)
* @param {Function} callback The end-user defined method that will be called upon successful completion of the request. Default is null. (OPTIONAL)
* @param {Boolean} asynchronous. Set to true if the request is to be asynchronous, false if not. Default is true. (OPTIONAL)
*/
this.doTextRequest = function (url, method, parameters, callback, asynchronous) {
log("Beginning new Text request...");
initiateRequest(url, method, parameters, callback, asynchronous, "text");
}
/**
* Public method that returns the value returned by the request.
* Returns - a String or XML DOM Object or Javascript Object
* based on the type of request made.
* @type Variant
*/
this.getValue = function () {
return value;
}
/**
* Public function that returns the value returned by the request as
* a String, regardless of the type of request made.
* Returns - a String that contains the server response.
* @type String
*/
this.getValueAsString = function () {
return valueString;
}
/**
* Public function that transforms the current XML DOM value
* based on the XSL file specified in the url, and places it's contents in
* the suggested DOM element.
* Returns - a transformed XML string or null if the XSL could not be found.
* @param {String} url The url of the XSL document to use for transformation.
* @type XML DOM Object
*/
this.transformValueInto = function (url, element) {
if (type == "xml") {
if (value && url && element) {
if (typeof XSLTProcessor != 'undefined') {
var processor = new XSLTProcessor();
var request = getRequest();
if (request) {
request.open("GET", url, false);
request.send(null);
var xsl = request.responseXML;
processor.importStylesheet(xsl);
var fragment = processor.transformToFragment(value, document);
if (element)
element.appendChild(fragment);
}
else {
return;
}
}
else {
var stylesheet = new ActiveXObject("Msxml2.DOMDocument.3.0");
if (stylesheet) {
stylesheet.async = false;
stylesheet.load(url);
var results = new ActiveXObject("Msxml2.DOMDocument.3.0");
results.async = false;
results.validateOnParse = true;
value.transformNodeToObject(stylesheet, results);
if (element)
element.innerHTML = results.documentElement.xml;
}
else {
return;
}
}
}
}
else if (type == "text") {
if (element && value) {
element.innerHTML = value;
}
}
else if (type == "json") {
if (element && value) {
element.append(value);
}
}
else {
return;
}
}
/**
* Public function that attempts to retrieve the number of XML elements
* with the given name that exist in the current value object. This assumes that
* the value is an XML DOM object
* Returns - the number of nodes with the given name or 0 if none exist.
* @param {String} nodeName The node name to search for.
* @type int
*/
this.getNodeCount = function (nodeName) {
try {
var root = value.documentElement;
return root.getElementsByTagName(nodeName).length;
}
catch (e) {
return 0;
}
}
/**
* Public function that attempts to retrieve an XML DOMNode from the value
* variable if:
* 1. It is an XML DOM object
* 2. It has at least one tag with the given name.
* Otherwise, results are inconsistent.
* Returns - The DOMNode of the 'index' instance of 'nodeName' or null if it doesn't exist.
* @param {String} nodeName The name of the node.
* @param {int} index The index. i.e. If there are expected to be 3 nodes with the name
* 'item', then you would enter 0 for the first instance, 1 for the
* second instance and 2 for the third instance. If no index is provided
* then 0 is assumed.
* @type DOMNode
*/
this.getNode = function (nodeName, index) {
if (! index)
index = 0;
try {
var root = value.documentElement;
var node = root.getElementsByTagName(nodeName)[index];
return node;
}
catch (e) {
return null;
}
}
/**
* Public function that attempts to retrieve an XML value from the value
* variable if:
* 1. It is an XML DOM object
* 2. It has at least one tag with the given name.
* Otherwise, results are inconsistent.
* Returns - The value of the 'index' instance of 'nodeName' or null if it doesn't exist.
* @param {String} nodeName The name of the node
* @param {int} index The index. i.e. If there are expected to be 3 nodes with the name
* 'item', then you would enter 0 for the first instance, 1 for the
* second instance and 2 for the third instance. If no index is provided
* then 0 is assumed.
* @type String
*/
this.getValueForNode = function (nodeName, index) {
if (! index)
index = 0;
try {
var root = value.documentElement;
var nodeValue = root.getElementsByTagName(nodeName)[index].firstChild.data;
return nodeValue;
}
catch (e) {
return null;
}
}
/**
* Public function that attempts to retrieve the number of XML elements
* with the given name that exist under the parent node. This assumes that
* the value is an XML DOM object
* Returns - the number of nodes with the given name or 0 if none exist.
* @param {String} nodeName The node name to search for.
* @type int
*/
this.getNodeCountByParent = function (parentNode, nodeName) {
try {
return parentNode.getElementsByTagName(nodeName).length;
}
catch (e) {
return 0;
}
}
/**
* Public function that attempts to retrieve an XML value from the value
* variable if:
* 1. It is an XML DOM object
* 2. It has at least one tag with the given name.
* Otherwise, results are inconsistent.
* Returns - DOMNode of the 'index' instance of 'nodeName' with 'parentNode' as it's parent, or null if it doesn't exist.
* @param {DomNode} parentNode The parent DOMNode under which the child node should be found.
* See #getNode
* @param {String} nodeName The name of the node
* @param {int} index The index. i.e. If there are expected to be 3 nodes with the name
* 'item', then you would enter 0 for the first instance, 1 for the
* second instance and 2 for the third instance. If no index is provided
* then 0 is assumed.
* @type DOMNode
*/
this.getNodeByParent = function (parentNode, nodeName, index) {
if (! index) {
index = 0;
}
try {
var node = parentNode.getElementsByTagName(nodeName)[index];
return node;
}
catch (e) {
return null;
}
}
/**
* Public function that attempts to retrieve an XML value from the value
* variable if:
* 1. It is an XML DOM object
* 2. It has at least one tag with the given name.
* Otherwise, results are inconsistent.
* Returns - The value of the 'index' instance of 'nodeName' or null if it doesn't exist.
* @param {DomNode} parentNode The parent DOMNode under which the child node should be found.
* See #getNode
* @param {String} nodeName The name of the node
* @param {int} index The index. i.e. If there are expected to be 3 nodes with the name
* 'item', then you would enter 0 for the first instance, 1 for the
* second instance and 2 for the third instance. If no index is provided
* then 0 is assumed.
* @type String
*/
this.getValueForNodeByParent = function (parentNode, nodeName, index) {
if (! index) {
index = 0;
}
try {
var nodeValue = parentNode.getElementsByTagName(nodeName)[index].firstChild.data;
return nodeValue;
}
catch (e) {
return null;
}
}
/**
* Public method that creates a floating window (if necessary) and adds a message to the log.
* Provides public access to the private method log(message).
* @param message A message to add to the log window.
*/
this.log = function (message, severity) {
log(message, severity);
}
/**
* Public method that sets the display message that is presented while an
* AjaxRequest is processing.
* @param text The message to display.
*/
this.setDisplayMessage = function (text) {
message = text;
}
/**
* Public method that lets the user specify whether or not they are controlling
* the display message using CSS. Prevents the internal code from trying to
* set the style programmatically.
* @param styled True if the client is using CSS to style the message. False otherwise.
*/
this.setIsStyled = function (styled) {
isStyled = styled;
}
/**
* Public method that turns the debugging window on or off.
* @param show True shows the log window, false hides it.
*/
this.setDebugging = function (show) {
debug = show;
}
/**
* Public method that turns unique request ID generation on or off.
* UniqueID generation will append a parameter value with the name
* uniqueid to the end of your request. This helps to ensure that
* IE doesn't cache the request.
* @param generate True to append uniqueid to the url, false to not.
*/
this.generateUniqueID = function (generate) {
uniqueID = generate;
}
/**
* Public method that sets a timeout limit for requests and the method
* to call if a timeout occurs.
* @param milliseconds Milliseconds to wait for a request to complete before aborting.
* @param callback The method to call if a timeout occurs.
*/
this.setTimeoutInterval = function(milliseconds, callback) {
timeout = milliseconds;
if (callback)
timeouthandler = callback;
else
timeouthandler = null;
}
/**
* Public method that sets an HTTP request header value for the next
* Ajax request.
* @param headerName The HTTP header name to set.
* @param headerValue The value to set the HTTP header to.
*/
this.setHeader = function (headerName, headerValue) {
headers.push({"name": headerName, "value": headerValue});
}
/**
* Public method that sets the request as a cross domain request. If your
* Ajax request is set to cross domain (true), it uses an invisible iframe to
* send the data and read the response.
* @param cross True if the next Ajax request will be cross domain, false if not. Default is false.
*/
this.setCrossDomain = function (cross) {
crossDomain = cross;
}
}