views:

117

answers:

2

I'm using Jorn Zaefferer's Autocomplete plugin on a couple of different pages. In both instances, the order of displayed strings is a little bit messed up.

Example 1: array of strings: basically they are in alphabetical order except for General Knowledge which has been pushed to the top:

General Knowledge,Art and Design,Business Studies,Citizenship,Design and Technology,English,Geography,History,ICT,Mathematics,MFL French,MFL German,MFL Spanish,Music,Physical Education,PSHE,Religious Education,Science,Something Else

Displayed strings:

General Knowledge,Geography,Art and Design,Business Studies,Citizenship,Design and Technology,English,History,ICT,Mathematics,MFL French,MFL German,MFL Spanish,Music,Physical Education,PSHE,Religious Education,Science,Something Else

Note that Geography has been pushed to be the second item, after General Knowledge. The rest are all fine.

Example 2: array of strings: as above but with Cross-curricular instead of General Knowledge.

Cross-curricular,Art and Design,Business Studies,Citizenship,Design and Technology,English,Geography,History,ICT,Mathematics,MFL French,MFL German,MFL Spanish,Music,Physical Education,PSHE,Religious Education,Science,Something Else

Displayed strings:

Cross-curricular,Citizenship,Art and Design,Business Studies,Design and Technology,English,Geography,History,ICT,Mathematics,MFL French,MFL German,MFL Spanish,Music,Physical Education,PSHE,Religious Education,Science,Something Else

Here, Citizenship has been pushed to the number 2 position.

I've experimented a little, and it seems like there's a bug saying "put things that start with the same letter as the first item after the first item and leave the rest alone". Kind of mystifying. I've tried a bit of debugging by triggering alerts inside the autocomplete plugin code but everywhere i can see, it's using the correct order. it seems to be just when its rendered out that it goes wrong.

Any ideas anyone? max

EDIT - reply to Clint

Thanks for pointing me at the relevant bit of code btw. To make diagnosis simpler i changed the array of values to ["carrot", "apple", "cherry"], which autocomplete re-orders to ["carrot", "cherry", "apple"].

Here's the array that it generates for stMatchSets:

stMatchSets = ({'':[#1={value:"carrot", data:["carrot"], result:"carrot"}, #3={value:"apple", data:["apple"], result:"apple"}, #2={value:"cherry", data:["cherry"], result:"cherry"}], c:[#1#, #2#], a:[#3#]})

So, it's collecting the first letters together into a map, which makes sense as a first-pass matching strategy. What i'd like it to do though, is to use the given array of values, rather than the map, when it comes to populating the displayed list. I can't quite get my head around what's going on with the cache inside the guts of the code (i'm not very experienced with javascript).

SOLVED - i fixed this by hacking the javascript in the plugin.
On line 549 (or 565) we return a variable csub which is an object holding the matching data. Before it's returned, I reorder this so that the order matches the original array of value we were given, ie that we used to build the index in the first place, which i had put into another variable:

csub = csub.sort(function(a,b){ return originalData.indexOf(a.value) > originalData.indexOf(b.value); })

hacky but it works. Personally i think that this behaviour (possibly coded more cleanly) should be the default behaviour of the plugin: ie, the order of results should match the original passed array of possible values. That way the user can sort their array alphabetically if they want (which is trivial) to get the results in alphabetical order, or they can preserve their own 'custom' order.

+1  A: 

I'm not sure about this autocomplete plugin in particular, but are you sure it's not just trying to give you the best match possible? My autocomplete plugin does some heuristics and does reordering of that nature.

Which brings me to my other answer: there are a million jQuery autocomplete plugins out there. If this one doesn't satisfy you, I'm sure there is another that will.

edit: In fact, I'm completely certain that's what it's doing. Take a look around line 474:

// loop through the array and create a lookup structure
for ( var i = 0, ol = options.data.length; i < ol; i++ ) {
    /* some code */

    var firstChar = value.charAt(0).toLowerCase();
    // if no lookup array for this character exists, look it up now
    if( !stMatchSets[firstChar] )

and so on. So, it's a feature.

Clint Tseng
Thanks clint, i'm not sure i follow you though. When the text field is empty, the list displays all of the options given to it. Why would it re-order them to be different, and in such an odd way? ie"the first given item, other given items which start with the same letter, all the others". In what way is that a feature? I'm not having a go, i'm genuinely seeking enlightenment. thanks, max.Also, apart from this odd behaviour i really like jorn's autocomplete and would rather stick with it and fix this rather than start again with something else.
Max Williams
i edited my post rather than comment more here due to stackoverflow not having linebreaks in the comments.
Max Williams
Do you have matchContains set to true? If so, try turning that off. If that doesn't get you the desired behavior, you will have to modify the plugin code itself.
Clint Tseng
Yes, i have matchContains set to true, which i need. I think you're right, maybe i will have to just try a different plugin. I had a little play around with how autocomplete works and i don't think i could easily change it to do what i want. thanks
Max Williams
Did a bit of hacking and fixed this (see main post) - thanks for the prod.
Max Williams
+1  A: 

What I did instead of your solution was to add

if (!q && data[q]){return data[q];}

just above

var csub = [];

found in line ~535.

What this does, if I understood correctly, is to fetch the cached data for when the input is empty, specified in line ~472: stMatchSets[""] = []. Assuming that the cached data for when the input is empty are the first data you provided to begin with, then its all good.

snz3
Thanks snz3, that works perfectly. cheers, max
Max Williams