|
Perfect..... Thanks for all your help Dmitry. My requirement is fullfilled. Now I have to fit this in my project. Hope everything goes well. Thanks again and Wish you all the best
Priyatam K
|
|
|
|
|
Hi Dmitry,
Just found a small bug in positioning suggestions div. I was creating a textbox dynamically and adding it to a panel (C#). After generating the control, if I scroll down the page and then type in the textbox, suggestions position is being displayed from actual top position(top positoin before scrolling). I have used the following function to get top and left positions.... and it works fine now.
function findPos(obj) {
var curleft = curtop = 0;
if (obj.offsetParent) {
curleft = obj.offsetLeft
curtop = obj.offsetTop
while (obj = obj.offsetParent) {
curleft += obj.offsetLeft
curtop += obj.offsetTop
}
}
return [curleft,curtop];
}
Thanks,
Priyatam
|
|
|
|
|
Hi Dimitry,
I had the immediate need of some additional fixes/features:
- Ability to display the list programmatically from outside code, e.g. a combo box dropdown button
- In addition to matching at beginning of string, also support matching at begging of words in the string
- If the minimum number of characters is 0, the list should be allowed to display when the text is blank, and should display all items (up to the specified max)
- The list gets re-ordered each time it is searched
- Issue with tabbing out of control when no item is selected
- Other minor issues with the list not showing or hiding consistently in different browsers
- Desire for more developer-friendly names for the “public” properties (e.g. the “actb_” prefix is unnecessary)
- zichun's original code was needlessly complex
Partly to address these issues and partly to make the code easier to understand so that I could more easily tweak the behavior, I have largely re-worked it. If you're interested I can send you the code. The downside to my changes for existing users is that I have changed the property names to make them clearer, so existing code would need to be modified to work with my changes.
Just thought I would let you know, and keep up the good work. I have voted for your article already!
Greg Bahns
-- modified at 1:18 Thursday 11th October, 2007
|
|
|
|
|
Hi Greg,
I'd be very grateful if you send your modification to me. All your changes look sweet
Thanks a lot,
Dmitry.
-------------------------
Listen up! "Teamwork" means staying out of my way! (Seifer, Final Fantasy 8).
|
|
|
|
|
Hi all!
Auto-suggest control is close to it's maturity, and I'm thinking (supported by multiple requests) to create an ASP.NET control out of this code. I'll also publish a webservice code (probably, as a separate article), that can be used with it.
What I'm asking is your advice. What features do you need? What should I add/omit/be aware of? I'm not so proficient in ASP.NET (I'm learning it intensively now), so I hope you'll give me some guidelines
Best regards & thank you for your support,
- Dmitry.
P.S. the updated article and code were sent to CP yesterday - a bit overdue, sorry. It will be available in a day or so.
-------------------------
Listen up! "Teamwork" means staying out of my way! (Seifer, Final Fantasy 8).
|
|
|
|
|
I fixed a positioning problem in IE6 when using this control nested inside other objects:
<code>
actb_clear: function() {
var msie = (document.all && !window.opera) ? true : false;
var event = window.event;
var doblur = true;
if (msie && event && this.cur_h) {
var x = event.offsetX;
var y = event.offsetY;
if (((x>0) && (x<(this.cur_w+18))) && ((y>0) && (y<(this.cur_h+18)))) {
this.actb_curr.focus();
doblur = false;
}
}
if (doblur) {
actb_RemoveEvent(document, "keydown", this.funcCheck);
actb_RemoveEvent(this.actb_curr, "blur", this.funcClear);
actb_RemoveEvent(document, "keypress", this.funcPress);
this.actb_removedisp();
}
},
</code>
You'll want to tweak this for other browsers. The "+18" is necessary to make sure the dropdown doesn't clear when the user tries to use the scrollbar. Again, you'll want to try various settings to work it out for all configurations.
|
|
|
|
|
The original actb was called like this:
new actb(document.getElementById('tb1'),customarray2);
The new one is called like this:
new actb('tb1',customarray2);
It might be helpful to include something in the instructions for those who simply want to drop this into their old code without modifying their old code.
|
|
|
|
|
You mean zichun's code -> new code? Will do it.
-------------------------
Listen up! "Teamwork" means staying out of my way! (Seifer, Final Fantasy 8).
|
|
|
|
|
That would be really great.
-- modified at 14:00 Tuesday 9th October, 2007
This would be needed for beckward compability:
this.actb_suggesturl = ( url || suggesturl )+ "?str="
|
|
|
|
|
|
Hi Dmitry,
Excellent work, thank you for doing it. Props to zichun also despite his disappearance.
I noticed that with your control there is a delay after typing before the list is updated. Zichun's original control did not exhibit this delay. It could be a design decision and I would guess if you're doing ajax calls it is appropriate to wait a second to see if the user stops typing before hitting the server, but when you have client-side lists it would be preferable to have instantaneous feedback.
Another problem I noticed is that although one of the stated goals of zichun's original control was to solve the problem where the user wants to type "apple" when "apple cart" is in the list. When the user hits ENTER or TAB, it auto-compltes to "apple cart". Not even hitting DELETE, as alluded to in zichun's article, avoids this result. Oddly, I don't think I've seen any posts about this problem. Am I missing something?
Another idea that I've had is that rather than first_only being true/false, it would be nice to have three options, say "anywhere", "first_of_text", and "first_of_word", where first_of_word would match any string starting at the beginning or after a space. For example, this would be useful in a list of full names, where the user could beginning typing either a first name or a last name.
One more idea I'm pondering is to include an optional dropdown arrow like you see with the traditional SELECT control to allow the user to just select from this list without typing anything. This would allow for a good hybrid where the user can go either route.
Lastly, for use in my projects I plan to turn this into a resuable .NET control. I envision using your code as is so that it would be easy to update my control with your latest whenever you come out with updates. If you don't object I may eventually post my .NET control in a separate article with a reference back to yours.
Thanks again for the great work and congratulations on the awards.
Greg
|
|
|
|
|
I noticed that ESC allows the user to close the list without auto-completing from the list. That's good.
However I discovered another problem. The list is displayed when you hit any key that is not explicitly checked for. For example, SHIFT, CTRL, ALT, left & right arrow, home, end, etc. I think it should only display when the user changes the string, and perhaps for certain pre-defined keystrokes. For example, with a standard dropdown list, ALT-DownArrow displays the list. I would also suggest that up & down arrow should display the list... currently if you have hidden the list by hitting ESC, then the up & down arrows don't seem to do anything.
Since it's complicated to determine which key codes change the text and which don't, I would simply track the value of the textbox named oldvalue, and only update the filter and display the list when oldvalue != value (i.e. the value has actually changed).
Back to the delay issue I mentioned in my previous post... to address this I changed this line:
obj.actb_toid = setTimeout(function() { obj.actb_tocomplete.call(obj, code) }, 500);
to this:
obj.actb_toid = setTimeout(function() { obj.actb_tocomplete(code) }, obj.actb_suggesturl.length ? 500 : 5);
So it only delays the half-second if you're using ajax. (Note: I tried to make it just call the function directly rather than using a 5ms timer, but the way it's implemented this did not work because it ended up filtering by the old value rather than the new value.)
Greg
|
|
|
|
|
I Greg,
Thanks for all your comments & bugreports (+ fixes) - I will fix/implement it in a future release.
I'll post a more detailed answer to your propositions later today, because I've worked all night and too tired now, sorry
- Dmitry.
-------------------------
Listen up! "Teamwork" means staying out of my way! (Seifer, Final Fantasy 8).
|
|
|
|
|
gbahns wrote: Since it's complicated to determine which key codes change the text and which don't, I would simply track the value of the textbox named oldvalue, and only update the filter and display the list when oldvalue != value (i.e. the value has actually changed).
Thanks! I'll add it to the control.
As for the delay issue - I'll examine it, thanks for the tips.
- Dmitry.
-------------------------
Listen up! "Teamwork" means staying out of my way! (Seifer, Final Fantasy 8).
|
|
|
|
|
So, here is the detailed answer.
gbahns wrote: It could be a design decision and I would guess if you're doing ajax calls it is appropriate to wait a second to see if the user stops typing before hitting the server...
Exactly.
gbahns wrote: ...but when you have client-side lists it would be preferable to have instantaneous feedback.
You're right. When I created this control, my attention was fixed at the AJAX part. I'll move the (now-hardcoded) response time to a variable.
gbahns wrote: Another problem I noticed is that although one of the stated goals of zichun's original control was to solve the problem where the user wants to type "apple" when "apple cart" is in the list. When the user hits ENTER or TAB, it auto-compltes to "apple cart". Not even hitting DELETE, as alluded to in zichun's article, avoids this result. Oddly, I don't think I've seen any posts about this problem. Am I missing something?
I don't understand it. Can you explain more in detail please?
gbahns wrote: Another idea that I've had is that rather than first_only being true/false, it would be nice to have three options, say "anywhere", "first_of_text", and "first_of_word", where first_of_word would match any string starting at the beginning or after a space. For example, this would be useful in a list of full names, where the user could beginning typing either a first name or a last name.
This issue was risen in the recent LTSpeed's post; it will be solved in the next release.
gbahns wrote: One more idea I'm pondering is to include an optional dropdown arrow like you see with the traditional SELECT control to allow the user to just select from this list without typing anything. This would allow for a good hybrid where the user can go either route.
Nice idea. I'm thinking about using a down arrow key handler for this.
gbahns wrote: Lastly, for use in my projects I plan to turn this into a resuable .NET control. I envision using your code as is so that it would be easy to update my control with your latest whenever you come out with updates. If you don't object I may eventually post my .NET control in a separate article with a reference back to yours
Actually, I have the ASP.NET control half-done, and I'm going to release it early in November
gbahns wrote: Thanks again for the great work and congratulations on the awards.
You're welcome Can you vote for the article please?
Thanks a lot,
- Dmitry.
-------------------------
Listen up! "Teamwork" means staying out of my way! (Seifer, Final Fantasy 8).
|
|
|
|
|
Dmitry Khudorozhkov wrote:
gbahns wrote:
Another problem I noticed is that although one of the stated goals of zichun's original control was to solve the problem where the user wants to type "apple" when "apple cart" is in the list. When the user hits ENTER or TAB, it auto-compltes to "apple cart". Not even hitting DELETE, as alluded to in zichun's article, avoids this result. Oddly, I don't think I've seen any posts about this problem. Am I missing something?
I don't understand it. Can you explain more in detail please?
Just that if "apple" is in the list and you want to enter just "ap", when you hit TAB it completes your entry to "apple". After writing my original message I discovered that you have addressed with the ESC key, which perhaps is the best that can be done. Perhaps it should leave the text alone if the user hits TAB, but take the first item if the user hits ENTER or DOWN, then TAB. That design decision might even be application-dependent.
Greg
|
|
|
|
|
If you scroll to the top of this article, you'll see a golden medal with words "Prize winner: August, 2007" to the left of it. It means, that this article won the CodeProject's Monthly Article Competition I would like to say "thank you a lot!" to everyone who voted for this article (both for the article itself, and in the survey).
Next, let me announce the next article/code update. It is due to October 8th (Monday; but the actual update will probably be delayed for a day or two because CP editors' load), and will include some fixes/features found and proposed by the users of this control.
Thank you very much again,
- Dmitry.
-------------------------
Listen up! "Teamwork" means staying out of my way! (Seifer, Final Fantasy 8).
|
|
|
|
|
If you set actb_firstText=false, then put in this array...
var customarray = ['audi','bentley','buick','chevrolet','chrysler','dodge','ford','gm','honda','hyundai','isuzu','jeep','kia','lamborghini','mazda','nissan','opel','pontiac','renault','saab','toyota','vw'].sort();
...then type the letter 'a', the display order of the results is incorrect. This does not happen on the original version.
I have not compared the code itself--just the output. Any ideas?
|
|
|
|
|
I get the same printing order with the latest version of this script and the original zichun's code.
Can you post what order you've got?
-------------------------
Listen up! "Teamwork" means staying out of my way! (Seifer, Final Fantasy 8).
|
|
|
|
|
Instead of 'a', let's go with 'c'--it's easier to see what's going on.
Zichun's code: buick, chevrolet, chrysler, pontiac
Updated code: chevrolet, chrysler, buick, pontiac
Zichun's is correct. Both are using the exact same input array, with a .sort() on it.
I have actb_firstText and actb_noDefault both false. It's possible that my "Zichun" code is improved over the original. (A lot of people worked on it over the last year and I didn't compare it back to his last post.) I already sent you that version, so you can use that for reference. Either way, that's the one that is right.
|
|
|
|
|
Aaaahhh... Now I see.
The problem is that I thought that the user should first get the variants that match the 1st letter, and then all the other variants - so I changed the Zichun's procedure that constructs the suggestion list.
Should I revert it back? Or should we have a switch (variable) for this behavior?
I'll post a patch here a bit later today.
- Dmitry.
-------------------------
Listen up! "Teamwork" means staying out of my way! (Seifer, Final Fantasy 8).
|
|
|
|
|
We should definitely have a switch. There are advantages both ways. By the way, the code looks great and congratulations on the award!
You might also look at incorporating the css like in the example I sent. Your version can easily be modified (I've been experimenting!) and the flexibility would be incredible. In fact, the code even gets a little smaller.
|
|
|
|
|
LTSpeed wrote: congratulations on the award!
Thanks a lot!
LTSpeed wrote: We should definitely have a switch.
Will be on the next update.
LTSpeed wrote: You might also look at incorporating the css like in the example I sent. Your version can easily be modified (I've been experimenting!) and the flexibility would be incredible. In fact, the code even gets a little smaller.
My current mania is focused on creating a self-contained components, but I will definitely make a CSS-enabled version a bit later.
- Dmitry.
-------------------------
Listen up! "Teamwork" means staying out of my way! (Seifer, Final Fantasy 8).
|
|
|
|
|
done function should be replaced by this code:
done: function(ot, t)
{
if(ot.length < this.actb_startcheck) return;
var re = new RegExp(this.actb_firstText ? ("^" + t) : t, "i");
this.actb_total = 0;
this.actb_tomake = false;
var al = this.actb_keywords.length;
for(var i = 0; i < al; i++)
{
this.actb_bool[i] = false;
if(re.test(this.actb_keywords[i]))
{
this.actb_total++;
this.actb_bool[i] = true;
if(this.actb_pre == i) this.actb_tomake = true;
}
}
if(this.actb_timeOut > 0)
this.actb_toid = setTimeout(function(){ this.actb_mouse_on_list = 0; this.actb_removedisp(); }, this.actb_timeOut);
this.actb_generate();
}
-------------------------
Listen up! "Teamwork" means staying out of my way! (Seifer, Final Fantasy 8).
|
|
|
|
|
Is it possible to apply the auto-suggest javascript in a Firefox toolbar extension so that the auto-suggest list pops up above all other window content similar to how the Google toolbar works?
I have so far only gotten your javascript to work by placing an iframe into my toolbar the same size as the auto-suggest pop-up, but this always shows and causes other issues with Firefox. When I try to apply the code directly to an input box it doesn't suggest anything (or maybe it does and I just can't see the list).
Google's toolbar uses a menulist as the textbox and I have yet to reverse engineer their gtb.js to see how they populate the auto-suggest list.
I'm hoping someone has already looked at gtb.js and might be able to offer a suggestion on how I could modify Dmitry's code to populate the menulist the same way that Google does.
There also may just be some simple xul code to do this that I don't know.
Thanks for any replys!
|
|
|
|
|