Haroenv / holmes

Fast and easy searching inside a page
https://haroen.me/holmes/
Apache License 2.0
1.7k stars 71 forks source link

Search started/ended events? #89

Closed ADRDev closed 7 years ago

ADRDev commented 7 years ago

Possibly a feature request, but perhaps there's a current way to support this?

I have a page with a large number of inputs that I'm using holmes to filter down. Currently when you enter a character into the search box it will freeze up for 2-3 seconds while it searches through the elements. Each subsequent character takes less time (as there's fewer elements to search through).

The experience is awkward because the character you type doesn't display until after the 2-3 second period.

I'm interested in any possible improvements (asynchronous behavior somehow?).

However, a quick fix would be to have an event that fires before the search happens and another that fires after it's finished, that way I can throw up a loading indicator/spinner while the process completes.

Haroenv commented 7 years ago

There’s an event after the search finishes already (onInput), before could be adding an event listener on “input” on your input.

ADRDev commented 7 years ago

Thanks! I was confused about when that onInput event actually fired.

That should work for my case.

Haroenv commented 7 years ago

Good luck!

I didn’t expect it to be slow though, how much is “a lot of elements” and is dynamic on?

ADRDev commented 7 years ago

Nearly 6,000 elements. I turned dynamic on and it is a bit more responsive now, still slow enough that I'd like to show an indicator (especially slow when I clear the input box to get everything back).

It may be that the jQuery selection itself is taking up most of the time. I'm going to try to simplify my DOM structure to see if I get any improvements there.

Haroenv commented 7 years ago

That shouldn't be an issue, 6000 elements is just really a lot I guess. If you could (maybe confidentially) send me that file it'd be useful for benchmarking

ADRDev commented 7 years ago

I'll see if I can throw together a jsfiddle or something and make the content generic. That might also help me determine if there's any other JS involved that might be contributing to the problem.

ADRDev commented 7 years ago

https://jsfiddle.net/b9ztuz9z/1/

Note: I left the tristate function enabled as that's my use case. But, disabling it doesn't really affect the performance.

It may be the sheer amount of DOM elements + an older FireFox version (corporate-enforced) that is the root of the issue.

Haroenv commented 7 years ago

Wow yeah that is a huge list of elements. I found that the actual hiding, not the loop or anything. The actual applying of css is the bottleneck (10ms vs 2s). So maybe the case is worse for you, if the JS went a bit slower too, but applying that much css to that much elements will always be that slow. To get really good performance you’d have to look at way more advanced things that are probably out of scope here. In this case a message to wait is appropriate I guess. I noticed that there was a tiny difference when the options were

{
  input: '#pageSearch',
  find: '.item-wrapper',
  class: {},
  hiddenAttr: true,
  mark: false,
  dynamic: true
}

is .2s average faster than:

{
  input: '#pageSearch',
  find: '.item-wrapper',
  class: {
    hidden: 'hidden'
  },
  hiddenAttr: true,
  mark: false,
  dynamic: true
}

Your file is so big that it crashed my Sublime Text a few times when trying to reindent it 😂

ADRDev commented 7 years ago

Haha, well.. I think I'm going to have to figure out a better way to go about this.

I tried $('#pageSearch').on('input') as well as $('#pageSearch').keydown() and logged to console in each handler. The console message doesn't actually show up until after the delay (same time as the holmes onInput event.

Any (very high level) ideas for those 'way more advanced' things?

Haroenv commented 7 years ago

My idea would be to in this case do the searching on an actual js array, then do some dom diffing and then insert a part of the array into the Dom. A vdom like react will probably have an implementation, diffing can be done with tools like morphdom used in choo.

ADRDev commented 7 years ago

Ah, that sounds like a good approach. I'll look into it. Thanks!