By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,795 Members | 1,242 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,795 IT Pros & Developers. It's quick & easy.

Perfect - unbreakable Ajax Function

Jezternz
100+
P: 145
Ok basicly I want a function where I can enter several parameters, and be able to use this function multiple times. This is an example of what I want, first commented.
Also note i am aiming for high efficiency.
Expand|Select|Wrap|Line Numbers
  1. function QueryUrl(type, url, returnFunction){
  2. // where type is a choice between post and get.
  3. // url is obviously the url you want to retrieve information from
  4. // returnFunction is a function that will be run, and passed across the returned data as a parameter (when it has retrieved the data) 
  5. }
  6.  
It is really the third parameter that is the part I need the most help with.
An example of use is:
Expand|Select|Wrap|Line Numbers
  1. QueryUrl('POST', 'tryregister.php', updateNow);
  2. function updateNow(returnedData){
  3.  document.getElementById('main_content').innerHTML = returnedData;
  4. }
  5.  
So you get the idea, of how I want to be able to use it. The third parameter is a reference to which function to call on retrieval of the data.
Now using bits and pieces of the net. I have an attempt at queryurl.js (this is the part i need help on / my question is on) - this is incomplete and could possibly be more efficient:
Expand|Select|Wrap|Line Numbers
  1. function QueryUrl(type, url, returnFunction){
  2.  var xmlHttp=GetXmlHttpObject();
  3.     if (xmlHttp==null){
  4.         alert ("Browser does not support HTTP Request");
  5.           return;
  6.     }
  7.     xmlHttp.onreadystatechange=stateChanged;
  8.     xmlHttp.open(type,url,true);
  9.     xmlHttp.send(null);
  10.  
  11.  function stateChanged(){ 
  12.     if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete"){ 
  13.         returnFunction(xmlHttp.responseText);
  14.     } 
  15.  }
  16.  
  17.  function GetXmlHttpObject(){
  18.     var xmlHttp=null;
  19.     try{
  20.         xmlHttp=new XMLHttpRequest();
  21.     }catch (e){
  22.         try{
  23.             xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
  24.         }catch (e){
  25.             xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
  26.         }
  27.     }
  28.     return xmlHttp;
  29.  }
  30.  
  31. }
  32.  
I get the feeling the post method wont work, offcourse im rather unsure about most of this.

Thanks in advance, Josh
Oct 31 '08 #1
Share this Question
Share on Google+
11 Replies


Jezternz
100+
P: 145
After a fair bit of messing around, and alot of guessing I think I got something that works, for anyone that wants to test it, or suggest improvements or use it themselves in the future go ahead :).

Expand|Select|Wrap|Line Numbers
  1. function AjaxQuery(type, url, parameters, qfunction){
  2.     if(url == "")return;
  3.     if(parameters == undefined)parameters = "";
  4.  
  5.     var xmlHttp=GetXmlHttpObject();    
  6.     if (xmlHttp==null){alert ("Browser does not support HTTP Request");return;}
  7.  
  8.     xmlHttp.onreadystatechange=function(){
  9.         if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete"){
  10.             if(qfunction != undefined)qfunction(xmlHttp.responseText);
  11.         }            
  12.     }  
  13.     if(type=="GET"){
  14.           xmlHttp.open("GET", url+"?"+parameters, true);
  15.         xmlHttp.send(null);
  16.     } else {
  17.         xmlHttp.open("POST", url, true);
  18.         xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  19.         xmlHttp.setRequestHeader("Content-length", parameters.length);
  20.         xmlHttp.setRequestHeader("Connection", "close");
  21.         xmlHttp.send(parameters);
  22.     }
  23. }
  24. function GetXmlHttpObject(){
  25.     var xmlHttp=null;
  26.     try{
  27.         xmlHttp=new XMLHttpRequest();
  28.     }catch (e){
  29.         try{
  30.             xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
  31.         }catch (e){
  32.             xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
  33.         }
  34.     }
  35.     return xmlHttp;
  36. }
  37.  
Thanks Josh
Nov 1 '08 #2

rnd me
Expert 100+
P: 427
Expand|Select|Wrap|Line Numbers
  1.  
  2.  
  3. function AjaxQuery(url, qfunction, parameters, post ){
  4.     if(!url){return;}
  5.      parameters = parameters || "";
  6.  
  7.     var xmlHttp= !window.XMLHttpRequest ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
  8.  
  9.     if (!xmlHttp){alert ("Browser does not support HTTP Request");return;}
  10.  
  11.     xmlHttp.onreadystatechange=function(){
  12.         if (xmlHttp.readyState==4 || xmlHttp.responseText){
  13.             if(qfunction){ qfunction.apply( xmlHttp, [xmlHttp.responseText, xmlHttp.status]);}
  14.         }            
  15.     }  
  16.  
  17.     if(!post){
  18.           xmlHttp.open("GET", url +"?"+parameters, !!qfunction);
  19.         xmlHttp.send(null);
  20.     } else {
  21.         xmlHttp.open("POST", url, !!qfunction);
  22.         xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  23.         xmlHttp.setRequestHeader("Content-length", parameters.length);
  24.         xmlHttp.setRequestHeader("Connection", "close");
  25.         xmlHttp.send(parameters);
  26.     }
  27. }
  28.  
  29.  
CHANGES:

-turned it into one function.
-killed the global.
-reduced code size by restructuring
-removed the error-hiding try/catch: makes debugging easier.
-defaults to sync, switches to async if callback is used
-added the status as second argument to callback
-"this" in callback refers to xmlhttp object itself
-made type and parameters optional > defaults to "GET"
-re-ordered arguments for most common usage.



it can handle simple or complex usage as needed:
Expand|Select|Wrap|Line Numbers
  1.  
  2. // ARGS:  (url, [qfunction], [parameters], [type])
  3.     alert(AjaxQuery("test.php")); //sync: AjaxQuery function returns text (GET)
  4.     AjaxQuery("test.php", function(a){ alert(a);}); //asynch GET  w/callback
  5.     AjaxQuery("test.php", function(a){ alert(a);}, "name=fred&age=21"); //asynch w/callback w/params (GET)
  6.     AjaxQuery("test.php", function(a){ alert(a);}, "name=fred&age=21", true ); //asynch w/callback w/params (POST)
  7.     AjaxQuery("test.php", function(a){ alert(a);}, "name=fred&age=21", "POST"); //asynch w/callback w/params (POST)
  8.     AjaxQuery("test.php", function(a){ alert(a);}, "name=fred&age=21", 1); //asynch w/callback w/params (POST)
  9.     alert(AjaxQuery("test.php"),"","", true); //sync: AjaxQuery function returns text (POST)
  10.  
  11.  
  12.  
  13.  
Nov 1 '08 #3

Jezternz
100+
P: 145
wow thats awesome, thanks heaps man, looks very efficient.

3 questions:

First, do we need to add a random number parameter to the get statement so that the page is refreshed whenever its called, not just retrieval of a cached page? ie, within the if(!post) statement change it to:
xmlHttp.open("GET", url +"?" + parameters +"&random =" + Math.floor(Math.random() * 9999999), !!qfunction);
I'm not sure about this? maybe you allowed for this?

Second, so can I pass a function as a reference
like this:
AjaxQuery("test.php", myfunction);
instead of this:
AjaxQuery("test.php", function(a){ alert(a);});
because sometimes I expect to have a large function and it seems a bit messy to put it as a parameter.

Third, I don't understand what the !! means in this code, because I thought that just meant not, and two would mean they just cancel each other? and also why pass the function as a parameter to the xmlhttp.open, what is the third parameter for exactly?
xmlHttp.open("POST", url, !!qfunction);

Anyways, thanks heaps, I can tell you know what your doing.
Cheers, Josh
Nov 1 '08 #4

rnd me
Expert 100+
P: 427
3 questions:

First, do we need to add a random number parameter to the get statement so that the page is refreshed whenever its called, not just retrieval of a cached page? ie, within the if(!post) statement change it to:
xmlHttp.open("GET", url +"?" + parameters +"&random =" + Math.floor(Math.random() * 9999999), !!qfunction);
I'm not sure about this? maybe you allowed for this?

that's not a terrible idea. i like using this between open and send to do the same thing
:
Expand|Select|Wrap|Line Numbers
  1. xmlHttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT")
  2.  
Second, so can I pass a function as a reference
like this:
AjaxQuery("test.php", myfunction);
instead of this:
AjaxQuery("test.php", function(a){ alert(a);});
because sometimes I expect to have a large function and it seems a bit messy to put it as a parameter.
yes, functions are functions and names point to functions, so that all works.


Expand|Select|Wrap|Line Numbers
  1. Third, I don't understand what the !! means in this code, because I thought that just meant not, and two would mean they just cancel each other? and also why pass the function as a parameter to the xmlhttp.open, what is the third parameter for exactly?
  2. xmlHttp.open("POST", url, !!qfunction);

in javascript, certain variable value are considered to be "thruthy" and "falsey".
true includes: " ",1,true,!0,[1,2,3],{},/./, and function a(){}.
false includes "",0,false,null, and undefined.

basically non blanks, non-null, non-zero, or object values are all "truthy"

the "!" operator converts a value into its Boolean equivalent.

eg: !5 === false.

not not means convert to Boolean opposite, then the opposite of that.

in the open method, the presence of a call back triggers a true to be passed to the ajax third parameter: forcing it into async mode.

when you omit the callback function, it goes into sync mode, and the AjaxQuery function itself returns the string of the URL. this simplifies coding, but also freezes the browser interface (and script execution) while the file downloads.
Nov 2 '08 #5

Jezternz
100+
P: 145
thanks again rnd-me, I am sure I will be using this function alot in the future.

Just to clarify the final product is:
Expand|Select|Wrap|Line Numbers
  1. function AjaxQuery(url, qfunction, parameters, post ){
  2.     if(!url){return;}
  3.     parameters = parameters || "";
  4.  
  5.     var xmlHttp= !window.XMLHttpRequest ? new ActiveXObject('Microsoft.XMLHTTP') : new XMLHttpRequest();
  6.  
  7.     if (!xmlHttp){alert ("Browser does not support HTTP Request");return;}
  8.  
  9.     xmlHttp.onreadystatechange=function(){
  10.         if (xmlHttp.readyState==4 || xmlHttp.responseText){
  11.             if(qfunction){ qfunction.apply( xmlHttp, [xmlHttp.responseText, xmlHttp.status]);}
  12.         }            
  13.     }  
  14.  
  15.     if(!post){
  16.         xmlHttp.open("GET", url +"?"+parameters, !!qfunction);
  17.         xmlHttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");
  18.         xmlHttp.send(null);
  19.     } else {
  20.         xmlHttp.open("POST", url, !!qfunction);
  21.         xmlHttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
  22.         xmlHttp.setRequestHeader("Content-length", parameters.length);
  23.         xmlHttp.setRequestHeader("Connection", "close");
  24.         xmlHttp.send(parameters);
  25.     }
  26. }
  27.  
-This is your previous code with the "xmlHttp.setRequestHeader("If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT");" added into the GET part (the POST part doesnt need it im guessing??)
Nov 3 '08 #6

rnd me
Expert 100+
P: 427
looks good to me.

i may have to "borrow" this sometime.

cheers!
Nov 3 '08 #7

acoder
Expert Mod 15k+
P: 16,027
Just a note: you may want to encode parameters in case there are any special characters, e.g. & % =

Re. cache busting. A header's good, but if you were using Math.random, I'd have suggested Date.getTime.
Nov 3 '08 #8

Jezternz
100+
P: 145
Thanks for the heads up acoder, i never thought of that.
I will look into encoding % = later in the week, however we cant really do it with & (as i understand it), as it is unknown which parts of the parameter are legit ampersands (to separate parameters) as opposed to which ones are entries (though i am sure you both already know this). Maybe write a function for use when joining the parameters when AjaxQuery is used, maybe VerifyParameter which would return the new formatted string.

Aside from that, half the reason I made this thread was so that, others could come and find it and use it, and not have to make such an important ajax function themselves. Thanks heaps rnd me, you more then anyone should be able to use it.

Cheers, Josh
Nov 3 '08 #9

acoder
Expert Mod 15k+
P: 16,027
Yes, I meant ampersands within the parameter name or value. You can use an object of name/value pairs, e.g. { name: 'fred', age: '21', interests: 'javascript & ajax' } and loop over them to encode them.
Nov 4 '08 #10

Jezternz
100+
P: 145
yeh I understand what you mean, but as I understand it the parameters are currently all stored in a single string like so:
"name=fred&age=21&interests=javascript & ajax" which as you can see, there is no logical way for the script to tell the difference from
a new parameter eg &interests
and a parameter with a ampersand in it eg &interests=javascript & ajax

So another outside function may be required?

cheers, Josh
Nov 5 '08 #11

acoder
Expert Mod 15k+
P: 16,027
Not necessarily. If instead of a string, you passed an object, you could deal with it quite easily within the function. Alternatively, you could just leave it to the user to ensure that they encode strings with special characters before passing in the parameters as strings.
Nov 5 '08 #12

Post your reply

Sign in to post your reply or Sign up for a free account.