How to Find Text on Page in ElectronJS ?

ElectronJS is an Open Source Framework used for building Cross-Platform native desktop applications using web technologies such as HTML, CSS, and JavaScript which are capable of running on Windows, macOS, and Linux operating systems. It combines the Chromium engine and NodeJS into a Single Runtime.

In certain desktop applications, developers would like to provide a feature wherein the user can find a custom text selection in the contents of the web page. Just like search functionality triggered by Ctrl+F in Chromium browsers. Electron provides a way by which we can successfully find a custom text in the contents of the page using the Instance methods and events of the built-in BrowserWindow object and the webContents property. This tutorial will demonstrate how to find text in the contents of the page in Electron.

We assume that you are familiar with the prerequisites as covered in the above-mentioned link. For Electron to work, node and npm need to be pre-installed in the system.

  • Project Structure:
    Project Structure

Example: We will start by building the basic Electron Application by following the given steps.

  • Step 1: Navigate to an Empty Directory to setup the project, and run the following command,
    npm init

    To generate the package.json file. Install Electron using npm if it is not installed.



    npm install electron --save

    This command will also create the package-lock.json file and install the required node_modules dependencies. Once Electron has been successfully installed, Open the package.json file and perform the necessary changes under the scripts key.
    package.json:

    {
      "name": "electron-find",
      "version": "1.0.0",
      "description": "Find Text in Electron",
      "main": "main.js",
      "scripts": {
        "start": "electron ."
      },
      "keywords": [
        "electron"
      ],
      "author": "Radhesh Khanna",
      "license": "ISC",
      "dependencies": {
        "electron": "^8.3.0"
      }
    }
    
  • Step 2: Create a main.js file according to the project structure. This file is the Main Process and acts as an entry point into the application. Copy the Boilerplate code for the main.js file as given in the following link. We have modified the code to suit our project needs.

    main.js:

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    const { app, BrowserWindow } = require('electron')
      
    function createWindow () {
      // Create the browser window.
      const win = new BrowserWindow({
        width: 800,
        height: 600,
        webPreferences: {
          nodeIntegration: true
        }
      })
      
      // Load the index.html of the app.
      win.loadFile('src/index.html')
      
      // Open the DevTools.
      win.webContents.openDevTools()
    }
      
    // This method will be called when Electron has 
    // finished initialization and is ready to create
    // browser windows. Some APIs can only be used 
    // after this event occurs. This method is 
    // equivalent to 'app.on('ready', function())'
    app.whenReady().then(createWindow)
      
    // Quit when all windows are closed.
    app.on('window-all-closed', () => {
      
      // On macOS it is common for applications and 
      // their menu bar to stay active until the user 
      // quits explicitly with Cmd + Q
      if (process.platform !== 'darwin') {
        app.quit()
      }
    })
      
    app.on('activate', () => {
        // On macOS it's common to re-create a window in the 
        // app when the dock icon is clicked and there are no 
        // other windows open.
      if (BrowserWindow.getAllWindows().length === 0) {
        createWindow()
      }
    })
      
    // In this file, you can include the rest of your 
    // app's specific main process code. You can also 
    // put them in separate files and require them here.

    chevron_right

    
    

  • Step 3: Create the index.html file and index.js file within the src directory. We will also copy the boilerplate code for the index.html file from the above-mentioned link. We have modified the code to suit our project needs.

    index.html:

    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    <!DOCTYPE html>
    <html>
      <head>
        <meta charset="UTF-8">
        <title>Hello World!</title>
                               /security#csp-meta-tag -->
        <meta http-equiv="Content-Security-Policy" 
              content="script-src 'self' 'unsafe-inline';" />
      </head>
      <body>
        <h1>Hello World!</h1>
        We are using node 
        <script>
            document.write(process.versions.node)
        </script>, Chrome 
        <script>
            document.write(process.versions.chrome)
        </script>, and Electron 
        <script>
            document.write(process.versions.electron)
        </script>.
      
        <!-- Adding Individual Renderer Process JS File -->
        <script src="index.js"></script>
      </body>
    </html>

    chevron_right

    
    

  • Output: At this point, our basic Electron Application is set up. To launch the Electron Application, run the Command:
    npm start

    GUI Output

Find Text on Page in Electron: The BrowserWindow Instance and webContents Property are part of the Main Process. To import and use BrowserWindow in the Renderer Process, we will be using Electron remote module.

The webContents.findInPage(text, options) method starts a request to find all the positive matches for the text in the contents of the BrowserWindow page. This method returns an Integer which represents the requestID used for the request. The results for the request can be obtained by subscribing to the found-in-page Instance Event which is explained in detail below. This method automatically highlights the text in the content for every positive match. If there are multiple matches, multiple segments of the content will be highlighted with the matching text. In our code, this is triggered by the Find in Text button. It takes in the following parameters.

  • text: String This value cannot be empty. This value represents the content to be searched in the BrowserWindow instance.
  • options: Object (Optional) It takes in the following parameters,
    • forward: Boolean (Optional) This value represents whether to perform search operation forwards from the start of the page content or backwards from the end of the page content. Default value is true. This property impacts the result Object obtained from the found-in-page Instance Event.
    • findNext: Boolean (Optional) This value represents whether the search operation is a first-request operation or a follow-up operation. Default value is false. In case, this value is set to true, the search operation will work as expected but we will not be able to fetch and display the result object obtained from the found-in-page Instance Event.
    • matchCase: Boolean (Optional) This value represents whether the search operation should be case-sensitive or not. Default value is false.
    • wordStart: Boolean (Optional) This value represents whether the search operation should look only at the start of the words. Default value is false. This property is used in combination with the medialCapitalAsWordStart property.
    • medialCapitalAsWordStart: Boolean (Optional) When combined with the wordStart property, it lets the search operation accept a match in the middle of the word if the match begins with an Uppercase letter followed by the lowercase letter or a non-letter. It accepts several other intra-word match combinations including alphanumeric characters. Default value is false.

The webContents.stopFindInPage(action) Instance method stops any webContents.findInPage() active request for find text in page contents with the provided action parameter. In our code, this is triggered by the Clear Selection button. It takes in the following values,

  • action: String This parameter specifies the action to be taken when ending an active request started by webContents.findInPage() method. It can assume any of the following values.
    • clearSelection: Clears the selection/search results obtained from the found-in-page Instance Event. It removes all the highlighted search results from the contents of the page.
    • keepSelection: Translates the highlighted selection/search results obtained from the found-in-page Instance Event into a normal selection.
    • activateSelection: It enables focus and click for the selection node. It selects the first positive match and highlights it.

To get the current BrowserWindow Instance in the Renderer Process, we can use some of the Static Methods provided by the BrowserWindow object.

  • BrowserWindow.getAllWindows(): This method returns an Array of active/opened BrowserWindow Instances. In this application, we have only one active BrowserWindow Instance and it can be directly refered from the Array as shown in the code.
  • BrowserWindow.getFocusedWindow(): This method returns the BrowserWindow Instance which is focused in the Application. If no current BrowserWindow Instance is found, it returns null. In this application, we only have one active BrowserWindow Instance and it can be directly referred using this method as shown in the code.

The found-in-page Instance Event belongs to the webContents Property. It is emitted when the webContents.findInPage() method has completed its operations and the results are available. It returns the following parameters.

  • event: The Global Event object.
  • result: Object It returns the following parameters,
    • requestId: Integer The Integer ID returned by the webContents.findInPage() method which is used to represent the active request.
    • activeMatchOrdinal: Integer According to official Electron documentation, it represents the index of the first Active Match. This value depends on the forward property set in the options Object. In case of single positive match, there is no impact however in case of multiple matches, this value changes depending on forward search or backward search.
    • matches: Integer The number of positive matches for the text in the page content.
    • selectionArea: Rectangle Coordinates of the first match region. This value depends on the forward property set in the options Object. It returns an Object containing the following parameters,
      • x: Integer The x-coordinate. It is the matched text’s left offset from the page boundary.
      • y: Integer The y-coordinate. It is the matched text’s top offset from the page boundary.
      • width: Integer The width of the matched Region.
      • height: Integer The height of the matched Region.
    • finalUpdate: Boolean It returns true when the found-in-page Instance Event has been successfully emitted and the last positive match in the content has been found. We can successfully trigger webContents.stopFindInPage() instance method when this value is returned as true.
  • index.html: Add the following snippet in that file.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    <h3>Find Text in Page</h3>
        <div>Lorem ipsum dolor sit amet consectetur 
             adipisicing elit. GeeksForGeeks. Dolores
             numquam quae ipsum, voluptas nisi dicta
             dolorem eaque omnis nulla fuga.Provident
             dolorem amet quas perferendis culpa, 
             vitae eius dolores facere? GeeksForGeeks.
        </div>
        <br><br>
        <input id="enter" type="text">
        <button id="find">Find in Text</button>
        <button id="clear">Clear Selection</button>

    chevron_right

    
    

  • index.js: Add the following snippet in that file.
    filter_none

    edit
    close

    play_arrow

    link
    brightness_4
    code

    const electron = require('electron')
    // Importing BrowserWindow from Main Process
    const BrowserWindow = electron.remote.BrowserWindow;
      
    var find = document.getElementById('find');
    var clear = document.getElementById('clear');
    let win = BrowserWindow.getFocusedWindow();
    // let win = BrowserWindow.getAllWindows()[0];
      
    var options = {
        forward: true,
        findNext: false,
        matchCase: false,
        wordStart: false,
        medialCapitalAsWordStart: false
    }
      
    find.addEventListener('click', () => {
        var text = document.getElementById('enter').value;
        console.log(text);
        if (text) {
            const requestId = win.webContents.findInPage(text, options);
            console.log(requestId);
        } else {
            console.log('Enter Text to find');
        }
      
        win.webContents.on('found-in-page', (event, result) => {
            console.log(result.requestId);
            console.log(result.activeMatchOrdinal);
            console.log(result.matches);
            console.log(result.selectionArea);
        });
    });
      
    clear.addEventListener('click', () => {
        win.webContents.stopFindInPage('clearSelection');
    });

    chevron_right

    
    

  • Output:

    full-stack-img




    My Personal Notes arrow_drop_up

    Check out this Author's contributed articles.

    If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

    Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.