Using webContents.findInPage() to implement typical "Find" function


#1

I am trying to implement “Find” functionality (Find, Find Next) in my app using webContents.findInPage(). When the user invokes “Find” command, I present a search box, where the user can type what to search for. The search box is implemented as an input element (of my webapp). In the “keyup” event I call webContents.findInPage().

I have run into a couple of issues with this approach:

  • The input element itself seems to included in the webContents.findInPage() search, which interferes with the subsequent “find next” function. I did not find any way to mark the input element to be excluded from findInPage() search.

  • Every time findInPage() is called, it steals focus from the input element (so that the user must click back into the input). Hacks like regaining focus in “blur” event or via setTimeout() are not reliable.

Any idea how to work around it?

Thanks


#2

Hi @martin, I’ve recently faced with the same problem and I solved it using webviews. What I did was to put search control and webapp in separate webviews and communicate them via IPC messages. As both pages are isolated, search text is not included in search results and focus is kept in search control as you type.

Here’s a working example https://github.com/edulan/electron-search-example

Hope it helps you :+1:


#3

Thanks @edulan. I have tried something similar but it worked only partially for me. I was able to exclude the input element from search by separating it in a different webview, but the main webview kept steeling focus from the input element anytime webContents.findInPage() was called. But I will look into your example to see you’re doing something different.


#4

If you need more control over the the feature, I find it better not to use findInPage() at all.
You can mark the content you want with findandreplacedomtext, adding a class to the matches, then you can use jQuery to scroll to the marked elements.


#5

I have finally gotten to test your sample code. Yes, your implementation works well and the focus from the input element is not being stolen by findInPage().

The main difference with my code was, and I missed that when I read your post initially, that you put both – the search box and the web app content into two separate webviews.

My app used the separate webview for the search box only (but the main app remained in the main “index.html” file). Once I put the web app into a separate webview also, the focus was no longer lost when performing findInPage().

I still think this might be a bug (in electron, webkit?) but thanks a lot for sharing your example!


#6

i had this same problem, a good workaround is to add a “focusout” event listener on the search input, then focus back.


#7

I tried the same with the “blur” event but that did not work in my case. Could you please check whether “blur” works in your case? That would give the definitive answer whether “focusout” fixes it or it’s something else.


#8

using “blur” on this case will not get the job done, the “focusout” happens before the input loses its focus, so firing “focus()” at it again will not even let the the “blur” event to get fired, the input el will have focus for as long as you want.

do something like this
inputEl.addEventListener("focusout", function() {
inputEl.focus();});`

Now, keep in mind that every time the findInPage gets invoked, which is every time the “keyup” fires in this case, the focus will try to leave the input because a selection will happen on what you may be trying to search.

Also, if you are using input element for the search you might want to use the “input” event instead of “keyup”…


#9

Thanks for the info! This may be very useful for anyone implementing the “Find” function in their app.


#10

Ok, I’ve found an issue with this approach. The problem is, if you want to call findInPage(text, {findNext: true}); In this case, since the focus is kept in the input element by re-focusing it in the “focusout” event, findInPage seems to start searching from the beginning of the page, no matter what findNext option is set to.


#11

I had the same issue, the problem does not seems to be with the approach on the input, since every time a match is found that match is selected you have to unselect it before doing the next search.

use this snippet:

webContents.unselect();
webContents.findInPage(text, {findNext: true});

so, every time you do a new search for the next match you unselect the previous one…

anyways, that was a solution for me.


#12

Thanks again, that seems to do the job.

Well, there is another small issue that I noticed. The findInPage() function highlights not only the text found on the page but also in the input element used for entering the search string.

If I try to move the input element from the main document into a separate webview, which helps with the highlighting issue, then the solution with “focusout” event does not work. I wonder if you were able to work around this as well.


#13

i’m still trying to figure out the highlights, no much luck yet, but there is always a catch, we just have to try…