How can I access the DOM of a <webview>?


#1

I’m just getting started with Electron, with prior experience with node-webkit (nw.js).

In nw.js, I was able to create iframes and then access the DOM of said iframe in order to grab things like the title, favicon, &c. When I picked up Electron a few days ago to port my nw.js app to it, I saw advice to use webviews instead of iframes, simply because they were better. Now, the functionality I mentioned above was relatively easy to do in nw.js, but I don’t know how to do it in Electron (and examples are slim to none). Can anyone help?

Also, I have back/forward buttons for my webview (and I intend on having more than one). I saw in the documentation that I could call functions for doing so on a webview, but nothing I have tried worked either (and, I haven’t found examples of them being used in the wild).


EDIT 1:

Alright, found something.

I was trying to attach Electron handlers to my webview like var webview = $("webview.active"); , but for some reason, that doesn’t work. What does work is var webview = document.getElementById("tab1");, but this is highly inflexible. I intend to have more than one webview, which is why I was trying to target it view a class.

Is it at all possible to make the handlers work with classes?


EDIT 2:

Thanks to this answer on SO, I understand that

document.getElementById("contents"); // returns a HTML DOM Object
var contents = $("#contents");       // returns a jQuery Object

// which led to 

var contents = $("#contents")[0];    // returns a HTML DOM Object

I then tried var webview = document.getElementsByClassName("tabs-pane active")[0]; and it worked! I would still like to access the DOM, but at least I got history working. I would also prefer to use jQuery everywhere instead of mixing JavaScript with jQuery but eh, what can you do.


#3

Regarding accessing the elements within the webview itself, I have been trying to solve this myself here: https://github.com/atom/electron/issues/3315


#4

Here’s what my code looks like. In my preloaded file:

document.addEventListener("DOMContentLoaded", function () {
  var data = {
    "title": document.title,
    "url": window.location.href,
    "favicon": "https://www.google.com/s2/favicons?domain=" + window.location.href
  };

  ipc.sendToHost("window-data", data);
});

In my render index.html page, I have a JavaScript file that contains this:

  var webview = document.getElementsByClassName("tabs-pane active")[0];

  webview.addEventListener("ipc-message", function (e) {
    if (e.channel === "window-data") {
      // console.log(e.args[0]);

      $(".tab.active .tab-favicon").attr("src", e.args[0].favicon);
      $(".tab.active .tab-title").html(e.args[0].title);
      $("#url-bar").val(e.args[0].url);

      /*
      if ($(".tab.active").data("page") === "pages/start.html") {
        $(".tab.active .tab-title").html(e.args[0].title);
      } else {
      }
      */
    }
  });

Now, I have not found a way to inject jQuery into my <webview>, even with:

window.$ = window.jQuery = require(__dirname + "/resources/scripts/vendor/jquery.min.js");

So that could be a problem with your jQuery keyboard. It sucks that no one seems able to help with our questions, but I’m glad I’m making headway into my own project.

I’m making a web browser. Previously, I was using nw.js, but Electron has been easier to use (less hacks needed to do certain things, like history!), but there are still some things that aren’t working…for now, anyway.


#5

I am also making a web browser :smile:

The keyboard lives in the renderer so I don’t need to inject jquery into the webview (this would be dangerous anyway as the page that is being rendered in the webview may already have it). So jquery isn’t the cause of the issue I am having.

I have managed to get the IPC to send the commands back up. Although I send mine using the IPC module into the main process then back down via webContents rather than via sendToHost. I tried doing it the same way as you, but I have the same issue as before, the command works fine but the event object is empty.


#6

Ah okay, cool! I’ll have to check out webContents, never heard of it. Do you think it’s better than sendToHose?


#7

I don’t know really as with mine I had to have the IPC listen in the main process and send back down to the page renderer even though that’s where the webview process is created. So the method you have used seems leaner. But I guess for this example it doesn’t matter which option you go with.