1 /* xajax Javascript library :: version 0.2.4 */
3 Array
.prototype.containsValue
= function(valueToCheck
)
5 for (var i
=0;i
<this.length
;i
++) {
6 if (this[i] == valueToCheck
) return true;
13 this.DebugMessage
= function(text
)
15 if (text
.length
> 1000) text
= text
.substr(0,1000)+"...\n[long response]\n...";
17 if (this.debugWindow
== undefined ||
this.debugWindow
.closed
== true) {
18 this.debugWindow
= window
.open('about:blank', 'xajax-debug', 'width=800,height=600,scrollbars=1,resizable,status');
19 this.debugWindow
.document
.write('<html><head><title>Xajax debug output</title></head><body><h2>Xajax debug output</h2><div id="debugTag"></div></body></html>');
21 text
= text
.replace(/&/g
, "&")
22 text
= text
.replace(/</g
, "<")
23 text
= text
.replace(/>/g
, ">")
24 debugTag
= this.debugWindow
.document
.getElementById('debugTag');
25 debugTag
.innerHTML
= ('<b>'+(new Date()).toString()+'</b>: ' + text
+ '<hr/>') + debugTag
.innerHTML
;
27 alert("Xajax Debug:\n " + text
);
31 this.workId
= 'xajaxWork'+ new Date().getTime();
33 this.responseErrorsForAlert
= ["400","401","402","403","404","500","501","502","503"];
35 //Get the XMLHttpRequest Object
36 this.getRequestObject
= function()
38 if (xajaxDebug
) this.DebugMessage("Initializing Request Object..");
40 if (typeof XMLHttpRequest
!= "undefined")
41 req
= new XMLHttpRequest();
42 if (!req
&& typeof ActiveXObject
!= "undefined")
46 req
=new ActiveXObject("Msxml2.XMLHTTP");
52 req
=new ActiveXObject("Microsoft.XMLHTTP");
57 req
=new ActiveXObject("Msxml2.XMLHTTP.4.0");
66 if(!req
&& window
.createRequest
)
67 req
= window
.createRequest();
69 if (!req
) this.DebugMessage("Request Object Instantiation failed.");
74 // xajax.$() is shorthand for document.getElementById()
75 this.$
= function(sId
)
80 var returnObj
= document
.getElementById(sId
);
81 if (!returnObj
&& document
.all
) {
82 returnObj
= document
.all
[sId];
84 if (xajaxDebug
&& !returnObj
&& sId
!= this.workId
) {
85 this.DebugMessage("Element with the id \"" + sId
+ "\" not found.");
90 // xajax.include(sFileName) dynamically includes an external javascript file
91 this.include
= function(sFileName
)
93 var objHead
= document
.getElementsByTagName('head');
94 var objScript
= document
.createElement('script');
95 objScript
.type
= 'text/javascript';
96 objScript
.src
= sFileName
;
97 objHead
[0].appendChild(objScript
);
100 this.stripOnPrefix
= function(sEventName
)
102 sEventName
= sEventName
.toLowerCase();
103 if (sEventName
.indexOf('on') == 0)
105 sEventName
= sEventName
.replace(/on
/,'');
111 this.addOnPrefix
= function(sEventName
)
113 sEventName
= sEventName
.toLowerCase();
114 if (sEventName
.indexOf('on') != 0)
116 sEventName
= 'on' + sEventName
;
122 // xajax.addHandler adds an event handler to an element
123 this.addHandler
= function(sElementId
, sEvent
, sFunctionName
)
125 if (window
.addEventListener
)
127 sEvent
= this.stripOnPrefix(sEvent
);
128 eval("this.$('"+sElementId
+"').addEventListener('"+sEvent
+"',"+sFunctionName
+",false);");
132 sAltEvent
= this.addOnPrefix(sEvent
);
133 eval("this.$('"+sElementId
+"').attachEvent('"+sAltEvent
+"',"+sFunctionName
+",false);");
137 // xajax.removeHandler removes an event handler from an element
138 this.removeHandler
= function(sElementId
, sEvent
, sFunctionName
)
140 if (window
.addEventListener
)
142 sEvent
= this.stripOnPrefix(sEvent
);
143 eval("this.$('"+sElementId
+"').removeEventListener('"+sEvent
+"',"+sFunctionName
+",false);");
147 sAltEvent
= this.addOnPrefix(sEvent
);
148 eval("this.$('"+sElementId
+"').detachEvent('"+sAltEvent
+"',"+sFunctionName
+",false);");
152 // xajax.create creates a new child node under a parent
153 this.create
= function(sParentId
, sTag
, sId
)
155 var objParent
= this.$
(sParentId
);
156 objElement
= document
.createElement(sTag
);
157 objElement
.setAttribute('id',sId
);
159 objParent
.appendChild(objElement
);
162 // xajax.insert inserts a new node before another node
163 this.insert
= function(sBeforeId
, sTag
, sId
)
165 var objSibling
= this.$
(sBeforeId
);
166 objElement
= document
.createElement(sTag
);
167 objElement
.setAttribute('id',sId
);
168 objSibling
.parentNode
.insertBefore(objElement
, objSibling
);
171 // xajax.insertAfter inserts a new node after another node
172 this.insertAfter
= function(sAfterId
, sTag
, sId
)
174 var objSibling
= this.$
(sAfterId
);
175 objElement
= document
.createElement(sTag
);
176 objElement
.setAttribute('id',sId
);
177 objSibling
.parentNode
.insertBefore(objElement
, objSibling
.nextSibling
);
180 this.getInput
= function(sType
, sName
, sId
)
183 if (!window
.addEventListener
)
185 Obj
= document
.createElement('<input type="'+sType
+'" id="'+sId
+'" name="'+sName
+'">');
189 Obj
= document
.createElement('input');
190 Obj
.setAttribute('type',sType
);
191 Obj
.setAttribute('name',sName
);
192 Obj
.setAttribute('id',sId
);
197 // xajax.createInput creates a new input node under a parent
198 this.createInput
= function(sParentId
, sType
, sName
, sId
)
200 var objParent
= this.$
(sParentId
);
201 var objElement
= this.getInput(sType
, sName
, sId
);
202 if (objParent
&& objElement
)
203 objParent
.appendChild(objElement
);
206 // xajax.insertInput creates a new input node before another node
207 this.insertInput
= function(sBeforeId
, sType
, sName
, sId
)
209 var objSibling
= this.$
(sBeforeId
);
210 var objElement
= this.getInput(sType
, sName
, sId
);
211 if (objElement
&& objSibling
&& objSibling
.parentNode
)
212 objSibling
.parentNode
.insertBefore(objElement
, objSibling
);
215 // xajax.insertInputAfter creates a new input node after another node
216 this.insertInputAfter
= function(sAfterId
, sType
, sName
, sId
)
218 var objSibling
= this.$
(sAfterId
);
219 var objElement
= this.getInput(sType
, sName
, sId
);
220 if (objElement
&& objSibling
&& objSibling
.parentNode
) {
221 objSibling
.parentNode
.insertBefore(objElement
, objSibling
.nextSibling
);
225 // xajax.remove deletes an element
226 this.remove
= function(sId
)
228 objElement
= this.$
(sId
);
229 if (objElement
&& objElement
.parentNode
&& objElement
.parentNode
.removeChild
)
231 objElement
.parentNode
.removeChild(objElement
);
235 //xajax.replace searches for text in an attribute of an element and replaces it
236 //with a different text
237 this.replace
= function(sId
,sAttribute
,sSearch
,sReplace
)
239 var bFunction
= false;
241 if (sAttribute
== "innerHTML")
242 sSearch
= this.getBrowserHTML(sSearch
);
244 eval("var txt=this.$('"+sId
+"')."+sAttribute
);
245 if (typeof txt
== "function")
247 txt
= txt
.toString();
250 if (txt
.indexOf(sSearch
)>-1)
253 while (txt
.indexOf(sSearch
) > -1)
255 x
= txt
.indexOf(sSearch
)+sSearch
.length
+1;
256 newTxt
+= txt
.substr(0,x
).replace(sSearch
,sReplace
);
257 txt
= txt
.substr(x
,txt
.length
-x
);
262 eval('this.$("'+sId
+'").'+sAttribute
+'=newTxt;');
264 else if (this.willChange(sId
,sAttribute
,newTxt
))
266 eval('this.$("'+sId
+'").'+sAttribute
+'=newTxt;');
271 // xajax.getFormValues() builds a query string XML message from the elements of a form object
272 // * The first argument is the id of the form
273 // * The second argument (optional) can be set to true if you want to submit disabled elements
274 // * The third argument (optional) allows you to specify a string prefix that a form element
275 // name must contain if you want that element to be submitted
276 this.getFormValues
= function(frm
)
279 var submitDisabledElements
= false;
280 if (arguments
.length
> 1 && arguments
[1] == true)
281 submitDisabledElements
= true;
283 if(arguments
.length
> 2)
284 prefix
= arguments
[2];
286 if (typeof(frm
) == "string")
287 objForm
= this.$
(frm
);
290 var sXml
= "<xjxquery><q>";
291 if (objForm
&& objForm
.tagName
== 'FORM')
293 var formElements
= objForm
.elements
;
294 for( var i
=0; i
< formElements
.length
; i
++)
296 if (!formElements
[i].name
)
298 if (formElements
[i].name
.substring(0, prefix
.length
) != prefix
)
300 if (formElements
[i].type
&& (formElements
[i].type
== 'radio' || formElements
[i].type
== 'checkbox') && formElements
[i].checked
== false)
302 if (formElements
[i].disabled
&& formElements
[i].disabled
== true && submitDisabledElements
== false)
304 var name
= formElements
[i].name
;
307 if (sXml
!= '<xjxquery><q>')
309 if(formElements
[i].type
=='select-multiple')
311 for (var j
= 0; j
< formElements
[i].length
; j
++)
313 if (formElements
[i].options
[j].selected
== true)
314 sXml
+= name
+"="+encodeURIComponent(formElements
[i].options
[j].value
)+"&";
319 sXml
+= name
+"="+encodeURIComponent(formElements
[i].value
);
325 sXml
+="</q></xjxquery>";
330 // Generates an XML message that xajax can understand from a javascript object
331 this.objectToXML
= function(obj
)
333 var sXml
= "<xjxobj>";
338 if (i
== 'constructor')
340 if (obj
[i] && typeof(obj
[i]) == 'function')
345 if (value
&& typeof(value
)=="object" && this.depth
<= 50)
348 value
= this.objectToXML(value
);
352 sXml
+= "<e><k>"+key
+"</k><v>"+value
+"</v></e>";
357 if (xajaxDebug
) this.DebugMessage(e
.name
+": "+e
.message
);
365 // unserializes data structure from xajaxResponse::_buildObjXml()
366 this._nodeToObject
= function(node
) {
367 // parentNode here is weird, have to tune
368 if (node
.nodeName
== '#cdata-section') {
370 for (var j
=0; j
<node
.parentNode
.childNodes
.length
; j
++) {
371 data
+= node
.parentNode
.childNodes
[j].data
;
375 else if (node
.nodeName
== 'xjxobj') {
376 var data
= new Array();
377 for (var j
=0; j
<node
.childNodes
.length
; j
++) {
378 var child
= node
.childNodes
[j];
381 if (child
.nodeName
== 'e') {
382 for (var k
=0; k
<child
.childNodes
.length
; k
++) {
383 if (child
.childNodes
[k].nodeName
== 'k') {
384 key
= child
.childNodes
[k].firstChild
.data
;
386 else if (child
.childNodes
[k].nodeName
== 'v') {
387 value
= this._nodeToObject(child
.childNodes
[k].firstChild
);
390 if (key
!= null && value
!= null) {
400 this.loadingFunction
= function(){};
401 this.doneLoadingFunction
= function(){};
404 // Sends a XMLHttpRequest to call the specified PHP function on the server
405 // * sRequestType is optional -- defaults to POST
406 this.call
= function(sFunction
, aArgs
, sRequestType
)
409 if (document
.body
&& xajaxWaitCursor
)
410 document
.body
.style
.cursor
= 'wait';
411 if (xajaxStatusMessages
== true) window
.status
= 'Sending Request...';
412 clearTimeout(loadingTimeout
);
413 loadingTimeout
= setTimeout("xajax.loadingFunction();",400);
414 if (xajaxDebug
) this.DebugMessage("Starting xajax...");
415 if (sRequestType
== null) {
416 var xajaxRequestType
= xajaxDefinedPost
;
419 var xajaxRequestType
= sRequestType
;
421 var uri
= xajaxRequestUri
;
423 switch(xajaxRequestType
)
425 case xajaxDefinedGet
:{
426 var uriGet
= uri
.indexOf("?")==-1?
"?xajax="+encodeURIComponent(sFunction
):"&xajax="+encodeURIComponent(sFunction
);
428 for (i
= 0; i
<aArgs
.length
; i
++)
431 if (typeof(value
)=="object")
432 value
= this.objectToXML(value
);
433 uriGet
+= "&xajaxargs[]="+encodeURIComponent(value
);
436 uriGet
+= "&xajaxr=" + new Date().getTime();
440 case xajaxDefinedPost
:{
441 postData
= "xajax="+encodeURIComponent(sFunction
);
442 postData
+= "&xajaxr="+new Date().getTime();
444 for (i
= 0; i
<aArgs
.length
; i
++)
447 if (typeof(value
)=="object")
448 value
= this.objectToXML(value
);
449 postData
= postData
+"&xajaxargs[]="+encodeURIComponent(value
);
454 alert("Illegal request type: " + xajaxRequestType
); return false; break;
456 r
= this.getRequestObject();
457 if (!r
) return false;
458 r
.open(xajaxRequestType
==xajaxDefinedGet?
"GET":"POST", uri
, true);
459 if (xajaxRequestType
== xajaxDefinedPost
)
463 r
.setRequestHeader("Method", "POST " + uri
+ " HTTP/1.1");
464 r
.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
468 alert("Your browser does not appear to support asynchronous requests using POST.");
472 r
.onreadystatechange
= function()
474 if (r
.readyState
!= 4)
479 if (xajaxDebug
) xajax
.DebugMessage("Received:\n" + r
.responseText
);
480 if (r
.responseXML
&& r
.responseXML
.documentElement
)
481 xajax
.processResponse(r
.responseXML
);
483 var errorString
= "Error: the XML response that was returned from the server is invalid.";
484 errorString
+= "\nReceived:\n" + r
.responseText
;
485 trimmedResponseText
= r
.responseText
.replace( /^\s
+/g
, "" );// strip leading space
486 trimmedResponseText
= trimmedResponseText
.replace( /\s
+$
/g
, "" );// strip trailing
487 if (trimmedResponseText
!= r
.responseText
)
488 errorString
+= "\nYou have whitespace in your response.";
490 document
.body
.style
.cursor
= 'default';
491 if (xajaxStatusMessages
== true) window
.status
= 'Invalid XML response error';
495 if (xajax
.responseErrorsForAlert
.containsValue(r
.status
)) {
496 var errorString
= "Error: the server returned the following HTTP status: " + r
.status
;
497 errorString
+= "\nReceived:\n" + r
.responseText
;
500 document
.body
.style
.cursor
= 'default';
501 if (xajaxStatusMessages
== true) window
.status
= 'Invalid XML response error';
507 if (xajaxDebug
) this.DebugMessage("Calling "+sFunction
+" uri="+uri
+" (post:"+ postData
+")");
509 if (xajaxStatusMessages
== true) window
.status
= 'Waiting for data...';
514 //Gets the text as it would be if it were being retrieved from
515 //the innerHTML property in the current browser
516 this.getBrowserHTML
= function(html
)
518 tmpXajax
= this.$
(this.workId
);
521 tmpXajax
= document
.createElement("div");
522 tmpXajax
.setAttribute('id',this.workId
);
523 tmpXajax
.style
.display
= "none";
524 tmpXajax
.style
.visibility
= "hidden";
525 document
.body
.appendChild(tmpXajax
);
527 tmpXajax
.innerHTML
= html
;
528 var browserHTML
= tmpXajax
.innerHTML
;
529 tmpXajax
.innerHTML
= '';
534 // Tests if the new Data is the same as the extant data
535 this.willChange
= function(element
, attribute
, newData
)
541 if (attribute
== "innerHTML")
543 newData
= this.getBrowserHTML(newData
);
545 elementObject
= this.$
(element
);
548 eval("oldData=this.$('"+element
+"')."+attribute
);
549 if (newData
!== oldData
)
556 //Returns the source code of the page after it's been modified by xajax
557 this.viewSource
= function()
559 return "<html>"+document
.getElementsByTagName("HTML")[0].innerHTML
+"</html>";
562 //Process XML xajaxResponses returned from the request
563 this.processResponse
= function(xml
)
565 clearTimeout(loadingTimeout
);
566 this.doneLoadingFunction();
567 if (xajaxStatusMessages
== true) window
.status
= 'Processing...';
569 xml
= xml
.documentElement
;
573 var skipCommands
= 0;
574 for (var i
=0; i
<xml
.childNodes
.length
; i
++)
576 if (skipCommands
> 0) {
580 if (xml
.childNodes
[i].nodeName
== "cmd")
589 var objElement
= null;
591 for (var j
=0; j
<xml
.childNodes
[i].attributes
.length
; j
++)
593 if (xml
.childNodes
[i].attributes
[j].name
== "n")
595 cmd
= xml
.childNodes
[i].attributes
[j].value
;
597 else if (xml
.childNodes
[i].attributes
[j].name
== "t")
599 id
= xml
.childNodes
[i].attributes
[j].value
;
601 else if (xml
.childNodes
[i].attributes
[j].name
== "p")
603 property
= xml
.childNodes
[i].attributes
[j].value
;
605 else if (xml
.childNodes
[i].attributes
[j].name
== "c")
607 type
= xml
.childNodes
[i].attributes
[j].value
;
610 if (xml
.childNodes
[i].childNodes
.length
> 1 && xml
.childNodes
[i].firstChild
.nodeName
== "#cdata-section")
613 for (var j
=0; j
<xml
.childNodes
[i].childNodes
.length
; j
++)
615 data
+= xml
.childNodes
[i].childNodes
[j].data
;
618 else if (xml
.childNodes
[i].firstChild
&& xml
.childNodes
[i].firstChild
.nodeName
== 'xjxobj') {
619 data
= this._nodeToObject(xml
.childNodes
[i].firstChild
);
620 objElement
= "XJX_SKIP";
622 else if (xml
.childNodes
[i].childNodes
.length
> 1)
624 for (var j
=0; j
<xml
.childNodes
[i].childNodes
.length
; j
++)
626 if (xml
.childNodes
[i].childNodes
[j].childNodes
.length
> 1 && xml
.childNodes
[i].childNodes
[j].firstChild
.nodeName
== "#cdata-section")
628 var internalData
= "";
629 for (var k
=0; k
<xml
.childNodes
[i].childNodes
[j].childNodes
.length
;k
++)
631 internalData
+=xml
.childNodes
[i].childNodes
[j].childNodes
[k].nodeValue
;
634 var internalData
= xml
.childNodes
[i].childNodes
[j].firstChild
.nodeValue
;
637 if (xml
.childNodes
[i].childNodes
[j].nodeName
== "s")
639 search
= internalData
;
641 if (xml
.childNodes
[i].childNodes
[j].nodeName
== "r")
647 else if (xml
.childNodes
[i].firstChild
)
648 data
= xml
.childNodes
[i].firstChild
.nodeValue
;
652 if (objElement
!= "XJX_SKIP") objElement
= this.$
(id
);
657 cmdFullname
= "addConfirmCommands";
658 var confirmResult
= confirm(data
);
659 if (!confirmResult
) {
665 cmdFullname
= "addAlert";
670 cmdFullname
= "addScript/addRedirect";
675 cmdFullname
= "addScriptCall";
677 if (data
[0] != null) {
679 for (var l
=1; l
<data
.length
; l
++) {
680 scr
+= ',data['+l
+']';
688 cmdFullname
= "addIncludeScript";
693 cmdFullname
= "addAssign/addClear";
694 if (this.willChange(id
,property
,data
))
696 eval("objElement."+property
+"=data;");
701 cmdFullname
= "addAppend";
702 eval("objElement."+property
+"+=data;");
706 cmdFullname
= "addPrepend";
707 eval("objElement."+property
+"=data+objElement."+property
);
711 cmdFullname
= "addReplace";
712 this.replace(id
,property
,search
,data
)
716 cmdFullname
= "addRemove";
721 cmdFullname
= "addCreate";
722 this.create(id
,data
,property
);
726 cmdFullname
= "addInsert";
727 this.insert(id
,data
,property
);
731 cmdFullname
= "addInsertAfter";
732 this.insertAfter(id
,data
,property
);
736 cmdFullname
= "addCreateInput";
737 this.createInput(id
,type
,data
,property
);
741 cmdFullname
= "addInsertInput";
742 this.insertInput(id
,type
,data
,property
);
746 cmdFullname
= "addInsertInputAfter";
747 this.insertInputAfter(id
,type
,data
,property
);
751 cmdFullname
= "addEvent";
752 property
= this.addOnPrefix(property
);
753 eval("this.$('"+id
+"')."+property
+"= function(){"+data
+";}");
757 cmdFullname
= "addHandler";
758 this.addHandler(id
, property
, data
);
762 cmdFullname
= "addRemoveHandler";
763 this.removeHandler(id
, property
, data
);
769 alert("While trying to '"+cmdFullname
+"' (command number "+i
+"), the following error occured:\n"
770 + e
.name
+": "+e
.message
+"\n"
771 + (id
&&!objElement?
"Object with id='"+id
+"' wasn't found.\n":""));
789 document
.body
.style
.cursor
= 'default';
790 if (xajaxStatusMessages
== true) window
.status
= 'Done';
794 var xajax
= new Xajax();