SitePoint Sponsor

User Tag List

Results 1 to 14 of 14
  1. #1
    SitePoint Addict
    Join Date
    Oct 2003
    Location
    Tenerife, Spain / UK
    Posts
    329
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Reducing the number of AJAX calls

    Hi

    I have a search box which uses AJAX to query a database and return a list of suggestions to the user, it works off the "onkeyup" event on the input textbox.

    Code:
     <input type="text" id="txt1" onkeyup="showHint(this.value)" />
    Obviously this creates an AJAX call for every keypress the user makes and I'd like to make this more efficient by adding a short delay before the AJAX call is made.

    How would I modify my code to make this happen?

    JavaScript code below:

    Code:
    <script type="text/javascript">
    
    function showHint(str)
    {
    var xmlhttp;
    if (str.length==0)
      { 
      document.getElementById("txtHint").innerHTML="";
      return;
      }
    if (window.XMLHttpRequest)
      {// code for IE7+, Firefox, Chrome, Opera, Safari
      xmlhttp=new XMLHttpRequest();
      }
    else
      {// code for IE6, IE5
      xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
      }
    xmlhttp.onreadystatechange=function()
      {
      if (xmlhttp.readyState==4 && xmlhttp.status==200)
        {
        document.getElementById("txtHint").innerHTML=xmlhttp.responseText;
        }
      }
    xmlhttp.open("GET","gethint.asp?q="+str,true);
    xmlhttp.send();
    }
    </script>
    Thanks
    David Parkes
    Nuclear Internet - Windows Web Hosting
    http://www.nuclearinternet.com

  2. #2
    SitePoint Guru
    Join Date
    Sep 2006
    Posts
    731
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Not tested but try:
    Code:
    <script type="text/javascript"> /* Anywhere BELOW the form element */
    
    document.getElementById( "txt1" ).onkeyup = (function()
    {
       var tm;
    
       return function()
       {
         clearTimeout( tm );
    
         tm = setTimeout( function(){ showHint(this.value), 1000 }
       }
    
    })();
    
    </script>
    Tab-indentation is a crime against humanity.

  3. #3
    SitePoint Wizard bronze trophy Immerse's Avatar
    Join Date
    Mar 2006
    Location
    Netherlands
    Posts
    1,661
    Mentioned
    7 Post(s)
    Tagged
    1 Thread(s)
    Another thing you could add is to only start a search after two or three characters have been entered. That, combined with Logic Ali's suggestion above should significantly reduce the number of requests.

  4. #4
    SitePoint Addict
    Join Date
    Oct 2003
    Location
    Tenerife, Spain / UK
    Posts
    329
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Immerse View Post
    Another thing you could add is to only start a search after two or three characters have been entered. That, combined with Logic Ali's suggestion above should significantly reduce the number of requests.
    Yeah that's a great idea and I looked at my code and it was really obvious to implement:

    Code:
    <script type="text/javascript">
    
    function showHint(str)
    {
    var xmlhttp;
    if (str.length<3)
      { 
      document.getElementById("txtHint").innerHTML="";
      return;
      }
    Sadly though Logic Ali's code didn't seem to work, not in Firefox at any rate. Any other suggestions?
    David Parkes
    Nuclear Internet - Windows Web Hosting
    http://www.nuclearinternet.com

  5. #5
    SitePoint Guru
    Join Date
    Sep 2006
    Posts
    731
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by SortedSites View Post

    Sadly though Logic Ali's code didn't seem to work, not in Firefox at any rate. Any other suggestions?
    If you'd used the error console you probably could have fixed the error:
    Code:
    document.getElementById( "txt1" ).onkeyup = (function()
    {
       var tm;
    
       return function()
       {
         clearTimeout( tm );
    
         tm = setTimeout( function(){ showHint(this.value) }, 1000 );
       }
    
    })();
    Tab-indentation is a crime against humanity.

  6. #6
    SitePoint Addict
    Join Date
    Oct 2003
    Location
    Tenerife, Spain / UK
    Posts
    329
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Logic Ali View Post
    If you'd used the error console you probably could have fixed the error:
    Code:
    document.getElementById( "txt1" ).onkeyup = (function()
    {
       var tm;
    
       return function()
       {
         clearTimeout( tm );
    
         tm = setTimeout( function(){ showHint(this.value) }, 1000 );
       }
    
    })();
    The misplaced bracket? Yeah I saw that, but even with the correction I get an error which throws back to the original script... it looks like some kind of incompatibility between your script and my implementation of Immerse's suggestion to wait until at least 3 characters were typed.


    Message: 'length' is null or not an object
    Line: 14
    Char: 1
    Code: 0
    I don't get this error without your delay code in place but its referencing the following line in the main script which makes the Ajax call.:
    Code:
    if (str.length<3)
    Should add, I appreciate your help with this, Javascript has never been my strong point.
    David Parkes
    Nuclear Internet - Windows Web Hosting
    http://www.nuclearinternet.com

  7. #7
    Utopia, Inc. silver trophy
    ScallioXTX's Avatar
    Join Date
    Aug 2008
    Location
    The Netherlands
    Posts
    9,097
    Mentioned
    153 Post(s)
    Tagged
    2 Thread(s)
    <DOMNode>.value probably isn't an instance of the String object, and as such doesn't have a 'length' property.

    Try changing
    Code javascript:
    if (str.length < 3) { ... }

    to

    Code javascript:
    if (String(str).length < 3) { ... }
    Rémon - Hosting Advisor

    SitePoint forums will switch to Discourse soon! Make sure you're ready for it!

    Minimal Bookmarks Tree
    My Google Chrome extension: browsing bookmarks made easy

  8. #8
    SitePoint Addict
    Join Date
    Oct 2003
    Location
    Tenerife, Spain / UK
    Posts
    329
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ScallioXTX View Post
    <DOMNode>.value probably isn't an instance of the String object, and as such doesn't have a 'length' property.

    Try changing
    Code javascript:
    if (str.length < 3) { ... }

    to

    Code javascript:
    if (String(str).length < 3) { ... }
    That seems to implement the delay but messes up the Ajax call, I get no matches on my Ajax query where before I had them. It also seems to cause the Ajax call to happen instantly after 1 second in Internet Explorer, even if no keypress is made.
    David Parkes
    Nuclear Internet - Windows Web Hosting
    http://www.nuclearinternet.com

  9. #9
    Utopia, Inc. silver trophy
    ScallioXTX's Avatar
    Join Date
    Aug 2008
    Location
    The Netherlands
    Posts
    9,097
    Mentioned
    153 Post(s)
    Tagged
    2 Thread(s)
    It executes because of the closure, which fires the function immediately on creation, even when no key has been pressed yet. Remove the stuff in red:

    Code:
    document.getElementById( "txt1" ).onkeyup = (function()
    {
       var tm;
    
       return function()
       {
         clearTimeout( tm );
    
         tm = setTimeout( function(){ showHint(this.value), 1000 }
       }
    
    })();
    I don't know why the AJAX call is messed up though. How is it messed up?
    Rémon - Hosting Advisor

    SitePoint forums will switch to Discourse soon! Make sure you're ready for it!

    Minimal Bookmarks Tree
    My Google Chrome extension: browsing bookmarks made easy

  10. #10
    SitePoint Addict
    Join Date
    Oct 2003
    Location
    Tenerife, Spain / UK
    Posts
    329
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by ScallioXTX View Post
    It executes because of the closure, which fires the function immediately on creation, even when no key has been pressed yet. Remove the stuff in red:

    Code:
    document.getElementById( "txt1" ).onkeyup = (function()
    {
       var tm;
    
       return function()
       {
         clearTimeout( tm );
    
         tm = setTimeout( function(){ showHint(this.value), 1000 }
       }
    
    })();
    I don't know why the AJAX call is messed up though. How is it messed up?
    That fixes the IE instant execution, but I still have the problem with my Ajax call, since I put in the "String(str)" change you suggested, it just doesn't seem to make the call at all.

    Its as if the following condition is always true even though I have typed 3+ letters into the search box.

    Code:
    if (String(str).length<3)
     { 
      document.getElementById("txtHint").innerHTML="";
      return;
      }
    Or I suppose it could be that the timer is not clearing, (those are milliseconds right?) either way I'm just getting nothing from my ajax call even though previously I was.
    David Parkes
    Nuclear Internet - Windows Web Hosting
    http://www.nuclearinternet.com

  11. #11
    SitePoint Guru
    Join Date
    Sep 2006
    Posts
    731
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by SortedSites View Post

    I don't get this error without your delay code in place but its referencing the following line in the main script which makes the Ajax call.:
    Code:
    if (str.length<3)
    It's a scope issue which this should fix:
    Code:
    document.getElementById( "txt1" ).onkeyup = (function()
    {
       var tm;
    
       return function()
       {
         var obj = this;
           
         clearTimeout( tm );
    
         tm = setTimeout( function (){ showHint( obj.value) }, 1000 );
       }
    
    })();
    Tab-indentation is a crime against humanity.

  12. #12
    SitePoint Addict
    Join Date
    Oct 2003
    Location
    Tenerife, Spain / UK
    Posts
    329
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by Logic Ali View Post
    It's a scope issue which this should fix:
    Code:
    document.getElementById( "txt1" ).onkeyup = (function()
    {
       var tm;
    
       return function()
       {
         var obj = this;
           
         clearTimeout( tm );
    
         tm = setTimeout( function (){ showHint( obj.value) }, 1000 );
       }
    
    })();
    Genius! Thank you very much for your help!
    David Parkes
    Nuclear Internet - Windows Web Hosting
    http://www.nuclearinternet.com

  13. #13
    SitePoint Addict
    Join Date
    Oct 2003
    Location
    Tenerife, Spain / UK
    Posts
    329
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sorry to bounce this thread, but I have another query.

    I know we spent a lot of time on this example reducing the number of AJAX calls so there was no more than 1 per second and only after at least 3 characters had been typed into the search box.

    But I now want to hotlink to the page that makes this AJAX call with a pre-defined search parameter in the QueryString, so I need to the script to make the Ajax call as the page first loads (but still only if the search parameter contains at least 3 characters) as well as when there is a change to the search textbox.

    I tried adding:

    <body onload="showHint(<%=Request.QueryString("q")%>);" >

    But this doesn't work.

    Can anyone shed any light on this or am just being dense?
    David Parkes
    Nuclear Internet - Windows Web Hosting
    http://www.nuclearinternet.com

  14. #14
    SitePoint Addict
    Join Date
    Oct 2003
    Location
    Tenerife, Spain / UK
    Posts
    329
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Scrap that I was being dense... I just needed to put quotes around the Querystring parameter I was pushing to the showHint() function. Duh!
    David Parkes
    Nuclear Internet - Windows Web Hosting
    http://www.nuclearinternet.com


Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •