[Proto-Scripty] Re: Very performant list filter
Thanks again for the advice, and let me tell you it made a huge difference when testing with 2,000 rows vs. 200. Kangax's code made for a very quick sort, but trying to do so at each keyup was a killer. Here's where I ended up in the end: var list = $$("#delegates li"); var lastValue = $F("filter"); var timeout = false; for (var i = list.length - 1; i >= 0; i--){ list[i]['d'] = list[i].innerHTML.stripTags().toLowerCase(); }; $('filter').observe('keyup', function(e) { var value = this.value; clearTimeout(timeout); if (value !== lastValue) { value = value.toLowerCase(); var stripe = 'even'; timeout = setTimeout(function(){ list.each(function(el) { if (el.d.include(value)) { Element.show(el); el.className = alternate(); }else{ Element.hide(el); } }) }, 200); lastValue = value; } }); This worked just fine on Firefox without the pre-calculation step, but Safari was a real dog, beachballing all over the place while it ran through the sort. Once I added the step to calculate the match string once for all elements, it all worked perfectly in both browsers. Walter On Dec 2, 2008, at 1:09 PM, Matt Foster wrote: > By using the keyup event you can avoid the conditions to check for > change, if the user has pressed and released a key on the input then > the value has changed. Also it is very wise to add the timeout, your > users will thank you. --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype & script.aculo.us" group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to prototype-scriptaculous+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Very performant list filter
By using the keyup event you can avoid the conditions to check for change, if the user has pressed and released a key on the input then the value has changed. Also it is very wise to add the timeout, your users will thank you. document.observe("dom:loaded", function() { var list = $$("#listAll li"); var lastValue = $F("filter"); var timeout = false; $('filter').observe('keyup', function(e) { var value = this.value; clearTimeout(timeout); timeout = setTimeout(function(){ list.each(function(ele){ filterElement(ele, value) }); }, 500); }) }) On Dec 2, 9:11 am, Walter Lee Davis <[EMAIL PROTECTED]> wrote: > On Dec 1, 2008, at 11:01 PM, kangax wrote: > > > > >> This behaves the way you would want it to -- so fast that the change > >> doesn't register until the list starts getting very short. > > > I think something along these lines could be faster: > > > document.observe("dom:loaded", function() { > > > var list = $$("#listAll li"); > > var lastValue = $F("filter"); > > > $('filter').observe('keyup', function(e) { > > var value = this.value; > > if (value !== lastValue) { > > value = value.toLowerCase(); > > list.each(function(el) { > > if (el.innerHTML.toLowerCase().include(value)) { > > Element.show(el); > > } > > else { > > Element.hide(el); > > } > > }) > > lastValue = value; > > } > > }) > > }) > > Thanks very much, I'll give this a try. I can see where your shortcuts > are, and they make a lot of sense. > > Walter --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype & script.aculo.us" group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Very performant list filter
On Dec 1, 2008, at 11:01 PM, kangax wrote: >> This behaves the way you would want it to -- so fast that the change >> doesn't register until the list starts getting very short. > > I think something along these lines could be faster: > > document.observe("dom:loaded", function() { > > var list = $$("#listAll li"); > var lastValue = $F("filter"); > > $('filter').observe('keyup', function(e) { >var value = this.value; >if (value !== lastValue) { > value = value.toLowerCase(); > list.each(function(el) { >if (el.innerHTML.toLowerCase().include(value)) { > Element.show(el); >} >else { > Element.hide(el); >} > }) > lastValue = value; >} > }) > }) Thanks very much, I'll give this a try. I can see where your shortcuts are, and they make a lot of sense. Walter --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype & script.aculo.us" group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Very performant list filter
On Dec 1, 1:43 pm, Walter Lee Davis <[EMAIL PROTECTED]> wrote: > I've been working on a problem today and wanted to share the results > here. I have a very tall list of authors on a page, and wanted to make > a simple filter field where you could type in a few characters of the > name and have the list shrink down to only include matches. After > struggling for an hour or more with various different methods, I > finally stopped trying to swim upstream and did less. > > I was using a Form.Element.Observer, but inside that function I was > using an optimized (backwards) for loop to iterate over my found array > of list items, and toggling visibility on each one in turn. This was > taking forever, causing a beachball on an 8-core Mac Pro in Firefox (I > shudder to think what would happen in a lesser Mac). > > I was looking through the various enumerable options and saw reject, > and then select, and the lightbulb went on: > > document.observe("dom:loaded",function(){ > var t = $$("#listAll li"); > var f = $F("filter"); > new Form.Element.Observer( > "filter", > 0.2, > function(el, value){ > if(value != f){ > t.invoke('hide'); > t.select(function(elm){ > return > elm.down('a').innerHTML.toLowerCase().include(value.toLowerCase()); > }).invoke('show'); > f = value; > } > } > ) > }); > > This behaves the way you would want it to -- so fast that the change > doesn't register until the list starts getting very short. I think something along these lines could be faster: document.observe("dom:loaded", function() { var list = $$("#listAll li"); var lastValue = $F("filter"); $('filter').observe('keyup', function(e) { var value = this.value; if (value !== lastValue) { value = value.toLowerCase(); list.each(function(el) { if (el.innerHTML.toLowerCase().include(value)) { Element.show(el); } else { Element.hide(el); } }) lastValue = value; } }) }) > > Walter -- kangax --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype & script.aculo.us" group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Very performant list filter
Thanks, both good ideas. Here's what I was thinking: On Dec 1, 2008, at 2:27 PM, Matt Foster wrote: > > I'd say your DOM traversals might add quite a bit of weight to your > filter. Why select the LI element if you're really looking at its > child A element's innerHTML property ? > Select those nodes and skip the execution of down, should speed things > up quite a bit. It's a chicken-or-egg problem, if I do what you suggest, then I have to do up('li') in order to hide and show the parent list item later. Since that's two up()s to one down(), I thought this was a good trade. > > > Also if you're using a text input control then why not use keydown or > keyup events to trigger the filter instead of a timer? Timers > (Intervals) add weight to the app, also it could execute as the user > is typing which could slow down data entry before the user has > finished what they were hoping to filter by. If you do go for a key > event put a timeout on it such that it won't execute until the user > has *finished* typing, if you filter on each keystroke and the user > types fast it could really gum things up. That's an interesting idea. I had tried executing on the change event, but that wasn't firing until the field blurred. I didn't think of trying to capture the keystrokes. Do you have any examples of this I could look at for reference? Thanks, Walter --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype & script.aculo.us" group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Very performant list filter
I'd say your DOM traversals might add quite a bit of weight to your filter. Why select the LI element if you're really looking at its child A element's innerHTML property ? Select those nodes and skip the execution of down, should speed things up quite a bit. Also if you're using a text input control then why not use keydown or keyup events to trigger the filter instead of a timer? Timers (Intervals) add weight to the app, also it could execute as the user is typing which could slow down data entry before the user has finished what they were hoping to filter by. If you do go for a key event put a timeout on it such that it won't execute until the user has *finished* typing, if you filter on each keystroke and the user types fast it could really gum things up. On Dec 1, 1:52 pm, Walter Lee Davis <[EMAIL PROTECTED]> wrote: > Wow, thanks! Had no idea. > > Walter > > On Dec 1, 2008, at 1:46 PM, Diodeus wrote: > > > > > "Performant" isn't a word. > > >http://weblogs.asp.net/jgalloway/archive/2007/05/10/performant-isn-t-... --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype & script.aculo.us" group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Very performant list filter
Wow, thanks! Had no idea. Walter On Dec 1, 2008, at 1:46 PM, Diodeus wrote: > > "Performant" isn't a word. > > http://weblogs.asp.net/jgalloway/archive/2007/05/10/performant-isn-t-a-word.aspx --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype & script.aculo.us" group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---
[Proto-Scripty] Re: Very performant list filter
"Performant" isn't a word. http://weblogs.asp.net/jgalloway/archive/2007/05/10/performant-isn-t-a-word.aspx On Dec 1, 1:43 pm, Walter Lee Davis <[EMAIL PROTECTED]> wrote: > I've been working on a problem today and wanted to share the results > here. I have a very tall list of authors on a page, and wanted to make > a simple filter field where you could type in a few characters of the > name and have the list shrink down to only include matches. After > struggling for an hour or more with various different methods, I > finally stopped trying to swim upstream and did less. > > I was using a Form.Element.Observer, but inside that function I was > using an optimized (backwards) for loop to iterate over my found array > of list items, and toggling visibility on each one in turn. This was > taking forever, causing a beachball on an 8-core Mac Pro in Firefox (I > shudder to think what would happen in a lesser Mac). > > I was looking through the various enumerable options and saw reject, > and then select, and the lightbulb went on: > > document.observe("dom:loaded",function(){ > var t = $$("#listAll li"); > var f = $F("filter"); > new Form.Element.Observer( > "filter", > 0.2, > function(el, value){ > if(value != f){ > t.invoke('hide'); > t.select(function(elm){ > return > elm.down('a').innerHTML.toLowerCase().include(value.toLowerCase()); > }).invoke('show'); > f = value; > } > } > ) > }); > > This behaves the way you would want it to -- so fast that the change > doesn't register until the list starts getting very short. > > Walter --~--~-~--~~~---~--~~ You received this message because you are subscribed to the Google Groups "Prototype & script.aculo.us" group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to [EMAIL PROTECTED] For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~--~~~~--~~--~--~---