SitePoint Sponsor

User Tag List

Results 1 to 14 of 14

Thread: AJAX Search Box

Hybrid View

  1. #1
    SitePoint Addict
    Join Date
    Sep 2006
    Posts
    334
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    AJAX Search Box

    Hi all... I have seen it a million times but can't seem to find out how to do it, I am a total total noob to AJAX. When a new customer signs up on my website, they can pick a store which is closest to them. If they don't know which store that is, I want to have a textfield, which when they input their zip code into the name of the store associated with that zip code is written underneath the search box... I don't want them to have to click search just type in the zip code on the on the final number the result displays... I've set up a table in my databases which is called 'tblstorezip' and next to each zip is the appropriate store... If anyone can help of point me in the right direction would be much appreciated!

  2. #2
    SitePoint Wizard cranial-bore's Avatar
    Join Date
    Jan 2002
    Location
    Australia
    Posts
    2,634
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    This is the basis of what you want. It uses the Yahoo User Interface Library (YUI) for Event handling, and managing the (Ajax) connection.
    Code HTML:
    <html>
    <head>
     
    <script src="http://yui.yahooapis.com/2.2.2/build/yahoo-dom-event/yahoo-dom-event.js" type="text/javascript"></script>
    <script src="http://yui.yahooapis.com/2.2.2/build/connection/connection-min.js" type="text/javascript"></script>
    <script type="text/javascript">
    var $D = YAHOO.util.Dom;     //YAHOO DOM
    var $E = YAHOO.util.Event; //YAHOO Event
    var $C = YAHOO.util.Connect; //YAHOO connection manager
     
    function init() {
        $E.on('zip', 'keyup', chkZip);
    }
     
    //See if zip code is fully entered (5 digits)
    function chkZip(e) {
        var zipCode = $E.getTarget(e).value;
        if(zipCode.length < 5) return; //Ignore if not complete
     
        var storeSpan = document.getElementById('store'); //Element to put store name into
        var AjaxObj = {
            success: function(o) {
                storeSpan.innerHTML = o.responseText;
            },
            failure: function(o) {
                storeSpan.innerHTML = "<em>Error - Please try again</em>";
            },
            timeout: 5000
        }
        $C.asyncRequest('GET', 'find-store.php?zipCode=' + encodeURIComponent(zipCode), AjaxObj);
     
    }
    $E.onDOMReady(init);
    </script>
    </head>
    <body>
     
    <form method="post" action="find-store.php">
    <input type="text" name="zip" id="zip"><span id="store"></span>
    </form>
     
    </body>
    </html>

    After each keypress in the text field the script checks the value length. If 5 or more chars it will send an Ajax request to find-store.php with a GET parameter, zipCode.

    The server side script should then return the store name (or appropriate message if none found) as the only response text. E.g Kansas City

    It will put that return value as the content of the #store element.

    You may want to improve the keypress code, so that it doesn't fire on arrow presses, or other irrelevant events, but this should certainly get you started.

  3. #3
    SitePoint Evangelist hexburner's Avatar
    Join Date
    Jan 2007
    Location
    Belgium
    Posts
    591
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I would suggest using Google Maps for this, and a table with the location of the stores. Then you can query the database to give a number of stores closest to any location in the world without having to enter all the distances and zipcodes yourself.

    The AJAX part: add an onkeydown and onkeyup event to the input box.
    When the onkeyup event fires, you stop an existing timer and set a new timer with setTimeout for about 1 second.
    In the function that fires onkeydown you stop the timer.
    This way you can search automatically.

    Example:
    Code JavaScript:
    /* addEvent by Scott Andrew */
    window.addEvent = function (e,ev,f,c) { 
        if (e.addEventListener) {
            e.addEventListener(ev,f,c);
        } else if (e.attachEvent) {
            var r=e.attachEvent('on'+ev,f);
            return r;
        } else {
            e['on'+ev]=f;
        }
    }
     
    var timer = null;
     
    function keyDown(e) {
        clearInterval(timer);
    }
     
    function keyUp(e) {
        clearInterval(timer);
        timer = setTimeout(1000, function() {AjaxSearch(this)});
    }
     
    function AjaxSearch(el) {
        var query = el.value;
        /* Do your XMLHttpRequest here, the Ajax stuff... */
    }
     
    function init() {
        var s = document.getElementById('SearchBox');
        window.addEvent(s, 'keyup', keyUp, false);
        window.addEvent(s, 'keydown', keyDown, false);
    }
     
    window.addEvent(window, 'load', init, false);

    Code HTML4Strict:
    <input type="text" name="SearchBox" id="SearchBox" value="Type your search query here..."/>
    FOR SALE: 1 set of morals, never used, will sell cheap

  4. #4
    SitePoint Addict
    Join Date
    Sep 2006
    Posts
    334
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Guys they both look great... I like the Google maps idea but I was hoping once I got the initial AJAX search done I could apply it to other things in the database, so just a simple table search is fine I think... So with find-store.php what do I need to add to that file? Is it just a simple query? I don't really understand on that page what I need to do...

  5. #5
    SitePoint Wizard cranial-bore's Avatar
    Join Date
    Jan 2002
    Location
    Australia
    Posts
    2,634
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, assuming all US zip codes are numeric your find-store.php would look something like this:
    PHP Code:
    if(!isset($_GET['zipCode']) OR !preg_match('/^[0-9]{5}$/')) exit('Invalid zip code');

    //Connect to database here (mysql_connect)

    $query "SELECT storeName FROM `tblstorezip` WHERE zip = '" $_GET['zipCode'] . "'";

    $result mysql_query($query);
    while(
    $r mysql_fetch_assoc($result)) {
      exit(
    $r['storeName']);
    }
    exit(
    'No store found'); 
    Change storeName (both instances) to whatever that field in your DB is called.
    If you have multiple stores in a single zip the first will be returned.

  6. #6
    SitePoint Addict
    Join Date
    Sep 2006
    Posts
    334
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi cranial-bore... Thanks for your help! I have been trying to play around with it, but am not having much luck... I changed the idea a bit, someone types in a code and it checks if that code is in the database, if so it gives them a 'NBR' this number is associated with a name in the database... I'll get to the name later but I can't get it to even return the number... This is what I've edited...

    testPostcode.htm
    Code:
    <html>
    <head>
     
    <script src="http://yui.yahooapis.com/2.2.2/build/yahoo-dom-event/yahoo-dom-event.js" type="text/javascript"></script>
    <script src="http://yui.yahooapis.com/2.2.2/build/connection/connection-min.js" type="text/javascript"></script>
    <script type="text/javascript">
    var $D = YAHOO.util.Dom;     //YAHOO DOM
    var $E = YAHOO.util.Event; //YAHOO Event
    var $C = YAHOO.util.Connect; //YAHOO connection manager
     
    function init() {
        $E.on('Code', 'keyup', chkZip);
    }
     
    //See if code is fully entered (8 digits)
    function chkZip(e) {
        var zipCode = $E.getTarget(e).value;
        if(zipCode.length < 8) return; //Ignore if not complete
        
        var storeSpan = document.getElementById('store'); //Element to put store name into
        var AjaxObj = {
            success: function(o) {
                storeSpan.innerHTML = o.responseText;
            },
            failure: function(o) {
                storeSpan.innerHTML = "<em>Error - Please try again</em>";
            },
            timeout: 5000
        }
        $C.asyncRequest('GET', 'testFindStore.php?zipCode=' + encodeURIComponent(zipCode), AjaxObj);
                
    }
    $E.onDOMReady(init);
    </script>
    </head>
    <body>
     
    <form method="post" action="testFindStore.php">
    <input type="text" name="Code" id="Code"><span id="store"></span>
    </form>
     
    </body>
    </html>
    testFindStore.php
    PHP Code:
    <?php

    if(!isset($_GET['zipCode']) OR !preg_match('/^[0-9A-Za-z]{10}$/')) exit('Invalid Code code');

    //connect to db
    include 'library/config.php';
    include 
    'library/opendb.php';

    $query "SELECT `NBR` FROM `tblcodes` WHERE `Code` = '" $_GET['zipCode'] . "'";

    $result mysql_query($query);
    while(
    $r mysql_fetch_assoc($result)) {
      exit(
    $r['NBR']);
    }
    exit(
    'No store found');

    include 
    'library/closedb.php'

    ?>
    I think I changed the !preg_match correctly so it could accept an 8 digit code like this 7gdTs8jd or JHG7fys2, now when I run it ths is my inital error...

    Warning: preg_match() expects at least 2 parameters, 1 given in /home/html/admin/testFindStore.php on line 3
    Invalid Code
    Thanks for your help so far!

  7. #7
    SitePoint Addict
    Join Date
    Sep 2006
    Posts
    334
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Anyone?

  8. #8
    SitePoint Member
    Join Date
    Sep 2005
    Posts
    1
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    preg_match also needs to know what to match the regex with, so add $_GET['zipCode'] as the second parameter to preg_match.

    PHP Code:
    <?php

    if(!isset($_GET['zipCode']) OR !preg_match('/^[0-9A-Za-z]{10}$/'$_GET['zipCode'])) exit('Invalid Code code');

    //connect to db
    include 'library/config.php';
    include 
    'library/opendb.php';

    $query "SELECT `NBR` FROM `tblcodes` WHERE `Code` = '" $_GET['zipCode'] . "'";

    $result mysql_query($query);
    while(
    $r mysql_fetch_assoc($result)) {
      exit(
    $r['NBR']);
    }
    exit(
    'No store found');

    include 
    'library/closedb.php'

    ?>

  9. #9
    SitePoint Addict
    Join Date
    Sep 2006
    Posts
    334
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hoagster congrats on your first post! Well you did it my friend that was it! Works perfectly... The only issue I have is that how can I stop if you hit return on the keyboard it launches the php file actually in a new page...

  10. #10
    SitePoint Addict
    Join Date
    Sep 2006
    Posts
    334
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Guys how can I disable the enter button? Currently the code works beautifully but if the user hit's enter it runs the page and loads the php page...

  11. #11
    SitePoint Wizard cranial-bore's Avatar
    Join Date
    Jan 2002
    Location
    Australia
    Posts
    2,634
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Sorry about the preg_match error, I forgot the second parameter in my example.

    To cancel the form submission do the following.
    1. Give your form an ID. Let's say findStore
    2. Change your JS init function to this:
    Code Javascript:
    function init() {
        $E.on('Code', 'keyup', chkZip);
        $E.on('findStore', 'submit', function(e) {$E.stopEvent(e);});
    }

    This will "capture" the submit event of the form and cancel it.
    Beauty is that the form will still submit for users with JS disabled so it can fallback to a script so they get the same functionality without Ajax.

  12. #12
    SitePoint Addict
    Join Date
    Sep 2006
    Posts
    334
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hey cranial-bore worked a treat! Thanks! Out of interest sake, not sure if I haven't added something correctly but when I remove that line and hit enter it always outputs 'invalid Postcode', the AJAX part works perfectly, when I type in the postcode on the 4th key stroke I get the result, just not if I hit enter any ideas?

    testFindStore.php
    PHP Code:
    <?php

    if(!isset($_GET['postCode']) OR !preg_match('/^[0-9]{4}$/'$_GET['postCode'])) exit('Invalid Postcode'); 

    //connect to db
    include 'library/config.php';
    include 
    'library/opendb.php';

    $query "SELECT * FROM stores WHERE `PostCode` = '" $_GET['postCode'] . "'";

    $result mysql_query($query);
    while(
    $r mysql_fetch_assoc($result)) {
      exit(
    $r['StoreName']." ".$r['StoreOwner']);
    }
    exit(
    'Area Not Covered');

    include 
    'library/closedb.php'

    ?>
    testPostcode.htm
    PHP Code:
    <html>
    <
    head>
     
    <
    script src="http://yui.yahooapis.com/2.2.2/build/yahoo-dom-event/yahoo-dom-event.js" type="text/javascript"></script>
    <script src="http://yui.yahooapis.com/2.2.2/build/connection/connection-min.js" type="text/javascript"></script>
    <script type="text/javascript">
    var $D = YAHOO.util.Dom;     //YAHOO DOM
    var $E = YAHOO.util.Event; //YAHOO Event
    var $C = YAHOO.util.Connect; //YAHOO connection manager
     
    function init() {
        $E.on('Code', 'keyup', chkZip);
        //$E.on('findStore', 'submit', function(e) {$E.stopEvent(e);});
    }
     
    //See if code is fully entered (4 digits)
    function chkZip(e) {
        var postCode = $E.getTarget(e).value;
        if(postCode.length < 4) return; //Ignore if not complete
        
        var storeSpan = document.getElementById('store'); //Element to put store name into
        var AjaxObj = {
            success: function(o) {
                storeSpan.innerHTML = o.responseText;
            },
            failure: function(o) {
                storeSpan.innerHTML = "<em>Error - Please try again</em>";
            },
            timeout: 5000
        }
        $C.asyncRequest('GET', 'testFindStore.php?postCode=' + encodeURIComponent(postCode), AjaxObj);
                
    }
    $E.onDOMReady(init);
    </script>
    </head>
    <body>
     
    <form action="testFindStore.php" method="post" name="findStore" id="findStore">
    <input type="text" name="Code" id="Code"><span id="store"></span>
    </form>
     
    </body>
    </html> 

  13. #13
    SitePoint Addict
    Join Date
    Sep 2006
    Posts
    334
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi guys... Also guys I am trying to integrate it into another form which obviously has a different post and a whole lot of JavaScript... This form code is below, I only showed the section obviously which I need to fix, but the run down of the form is it's broken up into 5 sections, my postcode search will be in section 5 which is the last section then it get's posted to lastpage.php. So I guess what I need to achieve is testFindStore.php get's checked, then the javascript is run for section 5 and the form is posted to lastpage.php... Hopefully this makes some sense?


    HTML Code:
    <head>
    <script language="JavaScript" type="text/JavaScript">
    if(section == "section5")
        {
            // Check the fields are valid from page 5
            validateSection5EmptyFields();
            validateSection5NumericFields();
            validateSection5CheckTerms();
            error = printErrorMessage();
            if(error == false)
                document.formObject.lastpage.value = "true"; // set the variable to true because we are ready to submit to database
            return evaluateError(error, "section5");
        }                
    }
    //-->
    </script>
    </head>
    <form name="formObject" action="lastpage.php" method="post">
    <input type="hidden" value="" name="toSectionForward">
    <input type="hidden" value="" name="toSectionBackward">
    <input name="Code" type="text" class="fields" id="Code">
    <input type="hidden" name="lastpage" value="false">
    <input name="Submit25" onClick="return checkFieldsValidForward('section5')" type="submit" class="submit" value="Submit">

  14. #14
    SitePoint Addict
    Join Date
    Sep 2006
    Posts
    334
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hello does anyone have any idea how I can do this???


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
  •