0 Like
How to build Find-in-Page in Electron

How to build Find-in-Page in Electron

5 PV0 LikeElectronFind-in-Page
In Chrome browser, we naturally use Cmd + F to call the Find-in-Page Popover. But unlike the built-in feature in Chrome, implementing this functionality in an Electron app requires manually invoking APIs.

The composition of Find-in-Page

As a useful feature in web browsers, Find-in-Page allows users to search for specific text within the current page. In this image shown below, we can see the ① is search input field, ② is the position of active match and the total match count, ③ is the previous match button, ④ is the next match button, ⑤ is the close button, ⑥ is the active match that can be switched from previous and next match buttons. Other yellow background highlights are the all search results.

image.png
image.png

Relevant APIs

In Electron's documentation, the following APIs are relevant for Find-in-Page functionality:

  • `webContents.findInPage(text, options)`: Starts a Find-in-Page operation.
  • `webContents.stopFindInPage(action)`: Stops the Find-in-Page operation.

image.png
image.png

To retrieve the the position of active match and the total match count, we can listen to the `found-in-page` event. The `activeMatchOrdinal` property indicates the position of the active match, and the `matches` property indicates the total number of matches found.

image.png
image.png

The layer of Find-in-Page Component

An original Electron APP includes main process, preload process and renderer process. When the main process is launched, you can use `BrowserWindow` to create a window to load `index.html` or a remote URL, this is the UI to display to users.

function createWindow(): void {   // Create the browser window.   mainWindow = new BrowserWindow({     width: 1280,     height: 960,     show: false,     autoHideMenuBar: true,     ...(process.platform === 'linux' ? { icon } : {}),     webPreferences: {       preload: join(__dirname, '../preload/index.js'),       sandbox: false,       contextIsolation: true,       nodeIntegration: true     }   })   mainWindow.on('ready-to-show', () => {     mainWindow?.show()   })   mainWindow.webContents.setWindowOpenHandler((details) => {     shell.openExternal(details.url)     return { action: 'deny' }   })   // HMR for renderer base on electron-vite cli.   // Load the remote URL for development or the local html file for production.   if (is.dev && process.env['ELECTRON_RENDERER_URL']) {     mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])     mainWindow.webContents.openDevTools({ mode: 'undocked' })   } else {     mainWindow.loadFile(join(__dirname, '../renderer/index.html'))   } }

But, if you create your Find-in-Page component in this `BrowserWindow` instance, you will get wrong results. Because the `webContents.findInPage(text, options)` search the entire page, including the Find-in-Page component itself. That means if your search query is `hello`, the highlighted blocks not only include the text `hello` in the main content of the page, but also include the text `hello` in your search input element. To avoid this issue, you can create a separate View instance for the Find-in-Page component. This way, the search will only target the main content of the page, excluding the Find-in-Page UI itself.

How to manually install Electron in your APP

PREVIOUS POST

How to manually install Electron in your APP

    Search by