Hi Tom,

Thanks for the ideas. Unfortunately there is a fundamental issue with
my JSON file that I returning and how the autocomplete plugin handles
input.

The JSON file is an object. Jorn's autocomplete plugin only handles
arrays (see here:http://docs.jquery.com/Plugins/Autocomplete). Notice
this sentence in particular:

"For local autocomplete, just pass the data as an array to the
autocomplete plugin."

Passing autocomplete a complex object (such as my JSON file) causes
the browser to hang with multiple queries, due to how autocomplete
automagically parses the information it is given to a URL string, and
it expects an array. I checked a couple of times, and the console log
just spins wildly! :)

It is not the fault of the plugin - it is just me putting the wrong
data type into it.

So, I got around this by creating another JSON file that is just an
array of station names. Autocomplete now parses this just fine, and my
first field is completed. The next part was more tricky - how to
populate the second input field based on the number of report types (I
actually ended up using a <select> element with the <option> list
populated with the reports available. My solution is pretty inelegant,
but uses a nice option in Jorns plugin, the result() option (http://
docs.jquery.com/Plugins/Autocomplete/result#handler). Using this, I
can get the match from the first autocomplete call, and write a
callback function that then goes via AJAX to my original complex JSON
object to just get the matching stations object. It is a little long
winded (I iterate over every station in the original JSON object) and
I am sure John Resig would write it much much more nicely, but it
works in about 20ms!

Here is the code:

$(function(){
    $.ajax({
        type: "GET",
        url: "/path/to/simple_array_of_station_names.json",
        dataType: "json",
        global: false,
        success: function(data) {
            $.each(data, function() {
                $("#stacode").autocomplete(this).result( function
( event, data, mysta ) {
                    $("#dynamicReport").html( "" ) ;
                    // Check I am getting the correct station as
selected by autocomplete plugin
                    // console.log( mysta ) ;
                    // Use that in the larger JSON object that has all
the report types and times
                    $.ajax({
                        type: "GET",
                        url: "/path/to/reports.json",
                        dataType: "json",
                        global: false,
                        success: function( reports ) {
                            /*
                           NOTE:
                           Not sure why $.each(reports.stations.mysta,
function( repSta,repStaObj ) {} ) ;
                           does not work - any ideas anyone? It is a
valid way to get the matching station
                           in the JSON structure, right? Oh well, lets
just iterate over the whole thing with $.each()....
                            */
                            $.each(reports.stations, function
( repSta,repStaObj ) {
                                // The matching station
                                if( repSta === mysta ) {
                                    // Quick and dirty DOM markup,
purists look away
                                    var selection =
'&nbsp;&nbsp;&nbsp;<label for="reportType">Report </label><select
id="reportType">' ;
                                    $.each(repStaObj, function
( repStaRepsTypes, repStaRepsTimes ) {
                                        console.log( "Type is:
"+repStaRepsTypes+" Time is: "+repStaRepsTimes );
                                        selection +=
"<option>"+repStaRepsTypes+"</option>" ;
                                    });
                                    selection += '</
select>&nbsp;&nbsp;&nbsp;<input type="submit" value="Go!" />' ;
                                    // Update the <span> element with
the select box
                                    $("#dynamicReport").html
( selection ) ;
                                }
                            });
                        },
                        error: function() {
                            alert( "Could not load the available
report list" ) ;
                        }
                    });
                });
            });
        },
        error: function() {
            alert( "Could not load station list for form
autocomplete" ) ;
        }
    });
});

The inline HTML looks like:

<div id="form_autocomplete" style="none">
    <form id="autorep" autocomplete="off">
        <p><strong>Shortcut to view a stations reports:</strong>
        <label for="stacode">Stacode </label>
        <input id="stacode" type="text" class="auto" maxlength="4"
size="8"/>
        <span id="dynamicReport"></span>
        </p>
    </form>
</div>

So that is my solution. Not pretty. But it works. If anyone would like
to pipe in and tell me where I could improve it, I am all ears!!!

Thanks for the ideas and feedback.

On Apr 15, 5:40 pm, Tom Worster <f...@thefsb.org> wrote:
> i have an ajax backend onto a mysql table with about 25 million rows,
> including three searchable indexed text columns. i want a form with three
> text input fields, each with autocomplete.
>
> 1) if all fields are blank when the user starts to type into one of them
> then normal autocomplete happens on that field, independent of the others.
>
> 2) but if the user focuses on an empty field after an autocomplete selection
> has been made in one or both of the other fields then a list of all distinct
> values in that column of the big table, constrained by the selection(s)
> already made, is immediately displayed without any typing.
>
> each of the three fields has class 'auto' and there are three blocks like
> this one:
>
> $('#field1').autocomplete('suggest.php', {
>   extraParams: {
>     p: 'field1',
>     field2: function() { return $('#field2').data('chosen')
>         ? $('#field2').val() : ''; },
>     field3: function() { return $('#field3').data('chosen')
>         ? $('#field3').val() : ''; } } });
>
> so the back end can figure what's being looked for and what the constraints
> are, if any.
>
> to make a list of suggestions display on focus for 2) i have:
>
> var lastfocus = '';
> $('.auto').setOptions({ minChars: 2}).focus(function(){
>
>   if ( lastfocus != $(this).attr('id')
>        && $(this).val() == ''
>        && ( $('#field').data('chosen')
>             || $('#field2').data('chosen')
>             || $('#field3').data('chosen') ) )
>     $(this).data('chosen', false).setOptions(
>       {minChars: 0}).trigger('click').trigger('click');
>   else
>     $(this).setOptions({minChars: 2});
>   lastfocus = $(this).attr('id');}).change(function(){
>
>   $(this).data('chosen', false);
>   lastfocus = $(this).attr('id');}).result(function(){
>
>   $(this).data('chosen', true);
>
> });
>
> lastfocus is a hack: the focus event on a field triggers after a selection
> is made by clicking. i.e. with mouse selection focus moves to the list and
> then back to the text field. lastfocus deals with that.
>
> the 'chosen' data on each field indicates if the value in that field is one
> selected from the big table.
>
> two clicks are needed after setting minChars to 0 to display the list of
> suggestions. this is a quirk of the plugin.
>
> this is my first version of a script that seems to work in a way that
> wouldn't be too surprising to an unprepared user. i haven't given it much
> testing yet. comments and improvements would be welcomed.
>
> tom

Reply via email to