• Given
  • Have a form with 3 fields: Zip(text field), City(text field), State(dropdown field).

  • Problem description
  • The user fills in the Zip. Then, when starting to fill the City, AutoComplete appear (from those that have filled Zip). When/If one is selected the Stateis filled automatically.

  • Solution
  • Nowadays there are many solutions for AJAX AutoComplete but i choosed the jQuery plugin from devbridge.com. It seem to work very well and on the site are given details on how to use it.
    So after incuding the library with
    <script type="text/javascript" src="js/jquery.autocomplete.js"></script>
    creating the form:
    <form name="frm" action="someactionhere" method="post"><strong>Zip:</strong>?<input size="5" name="Zip" id="Zip" type="Text" value="#Zip#">
    ?<strong>City:</strong>?<input size="30" name="City" id="City" type="Text" value="#City#">
    ?<strong>State:</strong>?
    <select name="State" id="State"><option value=""<cfif State eq "">selected</cfif>><cfloop query="getStates"><option value="#stateCode#"<cfif State eq stateCode>selected</cfif>>#stateName#
    </cfloop></select></form>

    and ading the JS:
    <script language="JavaScript" type="text/javascript"><!--
    var options, a;
    jQuery(function(){
    options =
    {
    serviceUrl:'index.cfm?action=buyers.getCity&loadContent=true&Zip='+$('##Zip').val()
    , maxHeight:150
    }
    a = $('##City').autocomplete(options);
    });
    //--></script>

    i started to test it in order to move farther.

    And of course issues started. First problem was that the value from the Zip field was not passed to index.cfm?action=buyers.getCity. Instead of the value just entered was passed the one that was in the field at the start, so it wasn't exactly what i needed. Maybe there exist an easier way, i don't know, but after quite long playing with it i came to the following solution. I created a new JS function doAutoSuggest()and moved existing code into it and then made the call to it from City's onclick
    <form name="frm" action="someactionhere" method="post"><strong>Zip:</strong>?<input size="5" name="Zip" id="Zip" type="Text" value="#Zip#">
    ?<strong>City:</strong>?<input size="30" name="City" id="City" onclick="doAutoSuggest();" type="Text" value="#City#">
    ?<strong>State:</strong>?
    <select name="State" id="State"><option value=""<cfif State eq "">selected</cfif>><cfloop query="getStates"><option value="#stateCode#"<cfif State eq stateCode>selected</cfif>>#stateName#
    </cfloop></select></form><script language="JavaScript" type="text/javascript"><!--
    function doAutoSuggest()
    {
    options =
    {
    serviceUrl:'index.cfm?action=buyers.getCity&loadContent=true&Zip='+$('##Zip').val()
    , maxHeight:150
    };
    $('##City').autocomplete(options);
    }
    //--></script>

    The script that retrieves cities data and pass it back on the AJAX call is:
    <cfsetting showdebugoutput="No" enablecfoutputonly="Yes"><cfsilent><cfparam name="query" default=""><cfparam name="Zip" default=""><cfquery name="getCities" datasource="#application.dsn#">
    Select distinct top 50 City + ', ' + st as ct, City + '|' + st as ct2
    From zips
    Where City like '#query#%'
    <cfif Len(Zip)>
    and zip = <cfqueryparam cfsqltype="CF_SQL_VARCHAR" value="#Zip#"></cfif>
    Order by ct asc
    </cfquery><cfset items = QuotedValueList(getCities.ct, ",")><cfset items2 = QuotedValueList(getCities.ct2, ",")></cfsilent><cfoutput>{ query:'#query#',suggestions:[#items#],data:[#items2#] }</cfoutput>

    Note that the Zipmay not be entered and so there may be Citywith same name for different State. Because of it, in the suggestionsi return city, statepairs and in datai place same pairs but without the blank after the comma so that it to can be used for later easy processing.
    What is left now is to make sure the Cityand Stateform fields are filled with the right values when something is selected in the AutoComplete dropdown.
    Because the data come in a city,stateformat we can split it and so onSelectto place it in needed form fields. But because the Stateis a dropdown element you can't just place the right value into it, you need to change the current selection. So, i created a JS function that taking as attribute the new value, will set it AND make the right selection.
    function getOptionInde<img src="images/smiles/14.gif" border="0">opt)
    {
    document.frm.State.value=opt;
    return document.getElementById('State').selectedIndex;
    }

    And so, the final code is as follow
    <form name="frm" action="someactionhere" method="post"><strong>Zip:</strong>?<input size="5" name="Zip" id="Zip" type="Text" value="#Zip#">
    ?<strong>City:</strong>?<input size="30" name="City" id="City" onclick="doAutoSuggest();" type="Text" value="#City#">
    ?<strong>State:</strong>?
    <select name="State" id="State"><option value=""<cfif State eq "">selected</cfif>><cfloop query="getStates"><option value="#stateCode#"<cfif State eq stateCode>selected</cfif>>#stateName#
    </cfloop></select></form><script language="JavaScript" type="text/javascript"><!--
    function doAutoSuggest()
    {
    options =
    {
    serviceUrl:'index.cfm?action=buyers.getCity&loadContent=true&Zip='+$('##Zip').val()
    , maxHeight:150
    , onSelect: function(value, data){ qwe=data.split("|");document.frm.City.value=qwe[0];document.frm.State.selectedIndex=getOptionInde<img src="images/smiles/14.gif" border="0">qwe[1]); }
    };
    $('##City').autocomplete(options);
    }
    function getOptionInde<img src="images/smiles/14.gif" border="0">opt)
    {
    document.frm.State.value=opt;
    return document.getElementById('State').selectedIndex;
    }
    //--></script>

    Enjoy!