-
Notifications
You must be signed in to change notification settings - Fork 116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added functionality to override default autoComplete item rendering via options #3
Conversation
Sounds interesting. I'm just not sure how/where it could be used. Can you provide a short example or describe some use cases? I guess I do understand, but a small snippet can help a lot :-) One of the main reasons for this autocompleter plugin is to provide a really minimalistic choice. So all options should also be useful for a significant part of users. Thanks in any case for your contribution! |
I am creating a directory list. So, you type in something and a list of people drop down. In the row object (div) I show the persons name, an image of the person (or default image), the status of the person in the system (away, idle, busy, etc.). As well as if the person is associated with any groups. The list of people who appear in the list comes from an $.ajax request, but many of the properties such as their status and groups comes from other data source. With this I can combine multiple data sources into a single object and render complex row objects fairly easily.
Status indicator on left, then image, then name and group |
Here is my implementation: input.autoComplete({
minChars: 1,
source: function (term, suggest) {
$.ajax({
url: dateUrl,
data: 'term=' + term,
method: "GET",
dataType: "jsonp",
success: function (data, textStatus, jqXhr) {
suggest(data);
}
});
},
renderItem: function (item, search) {
var userInfo = userStore.get(item.user_id) || {},
tpl = {
status: userInfo.status || 'none',
photo: item.photo || defaultImagePath,
name: item.label || 'Unknown',
groups: userInfo.group || ''
};
return '<div class="autocomplete-suggestion" data-val="' + tpl.name + '">' +
'<div class="status status-' + tpl.status + '"></div>' +
'<div class="image"><img src="' + tpl.photo + '"></div>' +
'<div class="info">' +
'<div class="name">' + tpl.name + '</div>' +
'<div class="groups">' + tpl.groups + '</div>' +
'</div>' +
'</div>';
}
}); |
That sounds really useful! We'll most likely include it. It'll probably take a few days, because I'm kept very busy right now with another project. |
No problem. I also have a change today which I made where I added that.fixPosition() just before the dropdown is shows. When the input initializes (not the drop down) it has a 'display:none'. The width() value used at this time is invalid and the drop down appears in the wrong location (until you resize your window). |
There a timeout call after init, which should catch this problem: Could you try to increase the delay value there (maybe to 200+ ms) and try again? Just to see if that's the issue ... I'd prefer not to include fixPosition() inside fixScroll(), just for preventing some overhead. |
I think I was slightly incorrect earlier. Basically how the you get to the input on my screens is from the main panel:
So, the width actually is 0 until the button is clicked. I tried adding a resize callback to the input and it worked: setTimeout(that.fixPosition, 100);
$(window).on('resize.autocomplete', that.fixPosition);
that.on('resize.autocomplete', that.fixPosition); |
Hmm, interesting ... maybe your event is enough and the first two calls could be obsolete now. That would be great. I'll check that also. Or if you can confirm - that would also be great. Thanks :) |
I ran some tests and the lines are needed or the demo.html fails. When resizing the window on demo.html the input resize doesn't fire off. I think this is because the width of the input is 100%, so the input is not registering changes. My feeling on the subject is you probably want to calculate before each render. Since you are storying the inputDomObject in a variable and not looking it up off the DOM each time, your overhead isn't going to bad. The reason I recommend this is because in order to be assured we have the correct data [width/top/left] for the dropdown. We must know 1) a valid point in time to gather accurate data, and 2) be informed of updates/changes to the data. I order to do this via events we will need to attach to every event which could possibly alter the data for the dropdown and check if the data needs to be updated. So, this means the 'that.resize' event and 'window.resize' event are both needed as window can change the data for the input without causing the 'that.resize' to fire off. This should also be true for every parent DOM object between the input and the window objects. In addition to the .resize event for every DOM object between input and window, we must consider all other events that could fire off and change the data for the dropdown. So, in order to get full coverage then the number of event we must cover are: (2+N) * T 2 for 'window' and 'that' So, what we currently have is the absolute minimal. Which is N = 0 and T = 1 (resize). Honestly, this will probably cover most situation most of the time. But, the dropdown will have unexpected behavior in any edge cases where the DOM elements in-between are resized and the input has 100% width. |
I agree - it should be calculated whenever the dropdown is shown. Sorry for the rather slow process - I'm just kept extremely busy for a few days. I'll certainly include this in the next release, which will be soon. |
If you want I can add the changes onto this branch as I have already made the change on my project version of the file. |
I've rewritten several parts based on your suggestions. Also included a public settings object and did some minor renaming for better readability of the code. I couldn't find any bugs, so I hope it's working as expected :-) Thanks for these great tips, amcnea! I think that's a very useful improvement that didn't come with significant overhead. |
Minified Version Updated
ReadMe Updated
With this change one no longer needs to pass in an array of strings into the suggest() function. This is still the default behavior, but now one may override the 'autocomplete-suggestion' item render to allow one to render any data item passed into the suggest() function.
This is handled by overriding the renderItem() function in the options variable. The renderItem() function takes 2 parameters 'item' and 'search'. Where item is an item in the suggest array and search is the search term used.
Below is a patch that will alter demo.html to use an array of objects instead of an array of strings. Each string can now be found in data[i].name instead of data[i]