24

I'm trying to write a wrapper for Twitter using Electron (formerly Atom Shell).

My main.js file (it looks almost identical to the "Hello World" example, I just changed it in one place):

var app = require('app');  // Module to control application life.
var BrowserWindow = require('browser-window');  // Module to create native browser window.

// Report crashes to our server.
require('crash-reporter').start();

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the javascript object is GCed.
var mainWindow = null;

// Quit when all windows are closed.
app.on('window-all-closed', function() {
  if (process.platform != 'darwin')
    app.quit();
});

// This method will be called when atom-shell has done everything
// initialization and ready for creating browser windows.
app.on('ready', function() {

  // Create the browser window.
  mainWindow = new BrowserWindow ({'width':1000,'height':600});
  // and load the index.html of the app.
  mainWindow.loadUrl('https://twitter.com');

  // Emitted when the window is closed.
  mainWindow.on('closed', function() {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null;
  });
});

I try to call alert() function right after mainWindow.loadUrl() but it does not execute.

I understand that main.js file is like the server side of my app, but the question is... How can I call a JavaScript function on page? Where should I write the code?

For example, I want to perform this:

$(document).ready(function() {
    alert("Hurray!");
});

3 Answers 3

36

I have solved the problem. Here's the example code:

...

app.on('ready', function() {

  ...

  mainWindow.webContents.on('did-finish-load', function() {
    mainWindow.webContents.executeJavaScript("alert('Hello There!');");
  });

  ...

});
1
  • 4
    Although the code you proposed shows the alert, you should clearly understand why would the main process want to ask mainWindow(renderer process) to display the alert. I think that the separation of concerns between main process and the renderer is quite an important question here. For that reason controlling of the UI behavior of the renderer process from the main process is most probably the thing one should avoid. In case your main goal with alert() was the tracing of main.js, you can read my answer for this question. Some other debugging techniques are noted there. Commented Apr 25, 2015 at 17:42
16

First of all, you should clearly see the differentiation of processes within Electron (formerly Atom Shell). Electron makes use of the main process as a sort of a back-end (you might call it "server side" as you do) and an entry point of your application. As you probably understand the main process can spawn multiple instances of BrowserWindow, which are actually separate operating system windows each hosting a Chromium rendered web page run in a separate process called renderer process. You can think of renderer process as a simple browser window with potentially extended capabilities, like accessing Node.js modules (I write "potentially", because you can turn off Node.js integration for renderer process).

It should be mentioned that while you have a window with GUI for renderer process, you have none for the main process. In fact, it doesn't make a lot of sense to have one for the back-end logic of your app. So, it is not possible to call alert() directly in the main process and see the alert window. The solution that you proposed shows the alert indeed. But it's important to understand that the pop up is created by the renderer process and not the main process itself! The main process just asks the renderer to show the alert (that's what webContents.executeJavaScript function actually does).

Secondly, as I understand what you're really trying to achieve here with calling alert() function in the main process is the tracing of program execution. You can call console.log() to output the desired message to console. In this case the application itself must be started from the console:

/path/to/electron-framework/electron /your/app/folder

Now, what's even better is that you can debug the main process. In order to do that the application must be started with the --debug (or --debug-brk) key and the value of the listening port assigned to it. Just like that:

/path/to/electron-framework/electron --debug=1234 /your/app/folder

You can use any kind of V8 debugger to attach to the assigned port and start the debugging. That means that theoretically any Node.js debugger must work. Take a look at node-inspector or WebStorm debugger. There's a popular question here at StackOverflow about debugging Node.js apps: How do I debug Node.js applications?.

0
4

The proper way is to use contents.send('some_js_Method','parameters') to invoke a javascript method in a web page from main.js

// In the main.js
const {app, BrowserWindow} = require('electron')
let win = null

app.on('ready', () => {
  win = new BrowserWindow({width: 800, height: 600})
  win.loadURL(`file://${__dirname}/index.html`)
  win.webContents.send(some_js_Method', 'window created!') //calling js method (async call)
})


//in index.html
<html>
<body>
  <script>
    require('electron').ipcRenderer.on('some_js_Method', (event, message) => {
      console.log(message)  // Prints 'window created!'
    })
  </script>
</body>
</html>

Not the answer you're looking for? Browse other questions tagged or ask your own question.