In Electron I want to trigger a javascript function in a browser window when that browser window is shown.
The code I have at the moment is as follows:
main.js (Main Process)
myWin = new BrowserWindow({ width: 1200, height: 400, show: false })
.... some time later and under certain circumstances ;-) ....
myWin.show()
usbUpload.js (Browser Window)
function validateFlights() {
...blar...
}
this.addEventListener('onshow', () => {
validateFlights()
})
ValidateFlights() is the function in the browser window that I want to execute when the browser window is shown.
Any ideas?
You can directly call javascript in the renderer process from main process using executeJavaScript. Combined with 'show' event of BrowserWindow you can do the following:
myWin.on('show', () => {
myWin.webContents.executeJavaScript('validateFlights()')
})
Example:
main.js
const { app, BrowserWindow } = require('electron')
const path = require('path')
app.once('ready', () => {
let win = new BrowserWindow({show: false})
win.once('show', () => {
win.webContents.executeJavaScript('validateFlights()')
})
win.loadURL(path.resolve(__dirname, 'index.html'))
win.show()
})
index.html
<html>
<head>
<script type="text/javascript">
function validateFlights() {
console.log('validated')
}
</script>
</head>
<body></body>
</html>
In your main process you probably want to do something with win.show() and the focus event if your window is already open in the background. Something like so:
let win = new BrowserWindow({width: 800, height: 600})
win.on('onFocus', () => {
win.show()
})
Related
I implemented a touch bar button to my program which loads a file. My question is: How can I click to a specific button on the website after that page has loaded when I press the touch bar button? Here is my main.js file:
const { app, BrowserWindow, TouchBar } = require('electron')
const { TouchBarButton } = TouchBar
const path = require('path')
let window
function createWindow() {
const win = new BrowserWindow({
width: 1366,
height: 758,
minWidth: 1300,
minHeight: 700,
icon: __dirname + 'logoSquare.icns',
webPreferences: {
//preload: path.join(__dirname, 'preload.js')
}
})
win.loadFile('login.html')
win.maximize()
return win
}
app.whenReady().then(() => {
window = createWindow()
const button = new TouchBarButton({
label: `🛫 Add Flight`,
accessibilityLabel: 'Add Flight',
backgroundColor: '#a20021',
click: () => {
window.loadFile('./flights.html')
},
});
const touchBar = new TouchBar({
items: [
button,
],
})
window.setTouchBar(touchBar);
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit()
}
})
I have just started learning electron.js and couldn't find a solution yet.
I found an alternate way to solve this issue. I sent a query and got that information with JavaScript. This is the main.js file that is responsible for sending the query:
const button = new TouchBarButton({
label: `🛫 Add Flight`,
accessibilityLabel: 'Add Flight',
backgroundColor: '#3a2e39',
click: () => {
//window.loadFile('./flights.html?addflight=1')
window.loadURL('file://'+__dirname+'/flights.html?addflight=1')
},
})
And this is the code that is responsible for receiving data in the flights.html file with JavaScript:
function addFlightRedir() {
if (location.search == '?addflight=1') {
addNewFlight(); // This is the code that I wanted to execute
}
}
addFlightRedir();
And since it is reusable with standard JS, now I can implement it to the other areas of my program as well (independent from the Touch Bar buttons).
I need to reload my site/app after network re-connect. So, I'm using win.reload after reconnect but after reloading it shows me a blank white screen
I have tried to re-create the window but it gives me the same output. Another question reported here by me.
I found window.location.href is set to "chrome-error://chromewebdata/" after reload
This sample code from is main.js
let mainWindow = null;
let offlineWindow = null;
let loadingwindow = null;
let mainWindowWidth = 1100;
let mainWindowHeight = 650;
var nativeApp = {
appUrl: "https://google.com",
connected: false
}
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: false,
preload: path.join(app.getAppPath(), 'preload.js')
},
minWidth: mainWindowWidth,
width: mainWindowWidth,
minHeight: mainWindowHeight,
height: mainWindowHeight,
show: false
});
createLoadingWindow();
mainWindow.once('ready-to-show', () => {
closeLoadingWindow();
mainWindow.show();
});
mainWindow.setMenu(null);
mainWindow.loadURL(nativeApp.appUrl);
mainWindow.webContents.openDevTools();
}
function createLoadingWindow(){
// codes to create the loading window
// .....
}
function createOfflineWindow(){
// codes to create the offline window
//....
}
function checkAndConnect() {
checkInternet(function (connected) {
if (!connected) {
if (!offlineWindow) { createOfflineWindow(); }
} else {
if (offlineWindow) {
offlineWindow.close();
mainWindow.reload();
}
}
nativeApp.connected = connected;
});
}
function checkInternet(callback) {
if(navigator.onLine){
return callback(true);
}
return callback(false);
}
I need to reload my site/app after re-connection. Is there anything wrong in my code? or is it a bug by the electron?
It's an old thread, but if someone comes across the same problem, you can fix it by adding the following in the main js file:
function createMainWindow () {
mainWindow = new BrowserWindow({
width: 1280,
height: 720,
...
})
// This code block is not related to the issue
// I included it to demostrate how my app loads the index page
if (process.env.WEBPACK_DEV_SERVER_URL) {
if (!process.env.IS_TEST) {
mainWindow.webContents.openDevTools()
}
}
else {
createProtocol('app')
mainWindow.loadURL('app://./index.html')
}
// Create listener that will handle the white screen issue
mainWindow.webContents.on('did-fail-load', () => {
if (process.env.NODE_ENV === 'production') {
// Load the index URL the same way you load it above
mainWindow.loadURL('app://./index.html')
}
})
...
I'm using electron JS to build an app. I want to reload my app after reconnect. Need to show a loader window while reloading and hide after complete. Is there any way to do it?
I don't want to put loader inside my app. I like to show it in a separate browser window.
I'm expecting like this
BrowserWindow.on('reload-complete', (e) => {
hideLoadingWindow();
})
Finally, I got another method to overcome this situation. I'm not sure is it a good solution. but it looks simple to me.
var mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: false,
preload: path.join(app.getAppPath(), 'preload.js')
},
minWidth: 1018,
width: 640,
minHeight: 1018,
height: 640,
title: 'Electron app',
show: false
});
createLoadingWindow();
mainWindow.once('ready-to-show', () => {
mainWindow.show();
});
mainWindow.webContents.on('did-start-loading', (e) => {
createLoadingWindow();
});
mainWindow.webContents.on('did-stop-loading', (e) => {
closeLoadingWindow();
});
The event below is the correct one for you:
BrowserWindow.webContents.once('did-finish-load', (e) => {
//hideLoadingWindow();
})
the 'did-finish-load' event will be triggered after the page is reloaded.
You can use show method and then use 'dom-ready' to detect your app loading ,
let loading= new BrowserWindow({show: false, frame: false})
loading.once('show', () => {
main = new BrowserWindow({show: false})
main.webContents.once('dom-ready', () => {
console.log('main loaded')
main.show()
loading.hide()
loading.close()
})
// load your app
main.loadURL(url);
})
I am trying to add thumbnail toolbar with specified buttons in a taskbar layout of an application from it's doc. But it's showing some problem.
The main.js:
// Modules to control application life and create native browser window
const {app, BrowserWindow, ipcMain, dialog} = require('electron')
const path = require('path')
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
const isSecondInstance = app.makeSingleInstance((commandLine, workingDirectory) => {
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
}
})
if (isSecondInstance) {
app.quit();
}
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
show: false,
width: 500,
height: 200,
minWidth: 500,
minHeight: 200,
transparent: true,
frame: false,
})
mainWindow.setResizable(false)
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
mainWindow.once('ready-to-show', () => {
mainWindow.show()
mainWindow.focus()
})
// 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
})
}
// 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.
app.on('ready', createWindow)
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X 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', function () {
// On OS X 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 (mainWindow === null) {
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.
ipcMain.on('open-information-dialog', (event) => {
if (mainWindow) {
const options = {
type: 'info',
title: 'I am abled',
buttons: ['Ok'],
message: 'This is the way.'
}
dialog.showMessageBox(mainWindow, options, function () {})
}
})
ipcMain.on('close', (event) => {
app.quit()
})
ipcMain.on('minimize', (event) => {
mainWindow.minimize()
})
ipcMain.on('progress', (event, per) => {
mainWindow.setProgressBar(per)
})
mainWindow.setThumbarButtons([
{
tooltip: 'button1',
icon: path.join(__dirname, 'button1.png'),
click () { console.log('button1 clicked') }
}, {
tooltip: 'button2',
icon: path.join(__dirname, 'button2.png'),
flags: ['enabled', 'dismissonclick'],
click () { console.log('button2 clicked.') }
}
])
The error:
All of my mainWindow reference working fine but when I am trying to set thumbar buttons with setThumbarButtons() it's getting the problem. I just try this one and I don't get any error but it's not showing any buttons on taskber window,
The Code:
app.on('ready', function(){
console.log(mainWindow)
mainWindow.setThumbarButtons([
{
tooltip: 'button1',
icon: path.join(__dirname, 'start.png'),
click () { console.log('button1 clicked') }
}
])
})
I can't make any sense with this problem.
The problem is that when you run mainWindow.setThumbarButtons your window hasn't been created. Therefor mainWindow is undefined. Which is the error you are running into, and what it says in the error screenshot you posted.
Currently you are creating and setting your window in the createWindow function.
If you move your setThumbarButtons code into the createWindow function it should work.
Something like the following:
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({
show: false,
width: 500,
height: 200,
minWidth: 500,
minHeight: 200,
transparent: true,
frame: false,
})
mainWindow.setResizable(false)
// and load the index.html of the app.
mainWindow.loadFile('index.html')
mainWindow.setThumbarButtons([
{
tooltip: 'button1',
icon: path.join(__dirname, 'start.png'),
click () { console.log('button1 clicked') }
}
])
// Open the DevTools.
// mainWindow.webContents.openDevTools()
mainWindow.once('ready-to-show', () => {
mainWindow.show()
mainWindow.focus()
})
// 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
})
}
That way you are creating the mainWindow first and defining it before calling that function. Otherwise mainWindow will be undefined which is what you were experiencing.
I am trying to create my own version of http://meetfranz.com/ using Electron.
The app should allow up multiple URLs such as https://messenger.com/ and https://gmail.com/ to be visible and have a tabbed interface.
I've tried both generating Webview and BrowserWindow.
WebView can't seem to load Messenger completely (does not load login)
BrowserWindow pops out of the main window…
I tried earlier on also with iFrames which was a no-go.
Any ideas on best way to accomplish a tabbed minimal browser interface that allows cookies/https?
index.html
<html>
<head>
<style>
webview {
display: inline-flex;
width: 800px;
height: 600px;
}
</style>
</head>
<body>
<form name="form">
<input name="input" placeholder="https://messenger.com/" value="https://messenger.com">
<button type="submit">submit</button>
</form>
<div class="tabs">
</div>
<div class="webviews">
</div>
<!--<webview src="https://messenger.com/" autosize="on" nodeintegration="on" disablewebsecurity="on" webpreferences="allowRunningInsecureContent"></webview>-->
<script type="text/javascript">
require('./app.js')
</script>
</body>
</html>
main.js
const {app, BrowserWindow, BrowserView} = require('electron')
app.on('ready', createWindow)
function createWindow(){
let win = new BrowserWindow({
width: 1000,
height: 600,
height: 600,
"node-integration": "iframe", // and this line
"web-preferences": {
"web-security": false,
"nodeIntegration": false,
}
})
win.on('closed', () => {
win = null
})
win.webContents.openDevTools()
// Load a remote URL
//win.loadURL('https://github.com')
// Or load a local HTML file
win.loadURL(`file://${__dirname}/index.html`)
/*win.webContents.session.webRequest.onHeadersReceived({}, (d, c) => {
if(d.responseHeaders['x-frame-options'] || d.responseHeaders['X-Frame-Options']){
delete d.responseHeaders['x-frame-options']
delete d.responseHeaders['X-Frame-Options']
}
c({cancel: false, responseHeaders: d.responseHeaders})
})*/
}
//app.commandLine.appendSwitch('disable-web-security')
app.js
const {app, BrowserWindow, BrowserView} = require('electron').remote
let tabs = document.querySelector(".tabs")
let webviews = document.querySelector(".webviews")
document.getElementsByTagName("form")[0].onsubmit = function(event){
//createWebview(form.input.value)
createBrowserWindow(form.input.value)
return false;
}
function createWebview(url){
let webview = new WebView()
webview.setAttribute("autosize","on")
webview.setAttribute("nodeintegration","on")
webview.setAttribute("disablewebsecurity","on")
webview.setAttribute("webpreferences","allowRunningInsecureContent")
webview.src = url
webviews.appendChild(webview)
let tab = document.createElement("div")
tab.textContent = url
tab.target = webview
tabs.appendChild(tab)
}
function createBrowserWindow(url){
let win = new BrowserWindow({
width: 800,
height: 600,
y: 100,
x: 100,
webPreferences: {
webSecurity: false,
nodeIntegration: false
}
})
win.setMenu(null)
win.on('closed', () => {
win = null
})
view = new BrowserView({
webPreferences: {
nodeIntegration: false
}
})
win.webContents.openDevTools()
// Load a remote URL
win.loadURL(url)
}
<webview> clearly is the way to if you want to have a single window. It's also a lot better than an <iframe>, because it's securely isolated from your app and runs in a separate process.
See the docs: https://electron.atom.io/docs/api/webview-tag/
If messenger.com doesn't load properly, this should be the problem you should be addressing (e.g. inspect console messages, network log). Follow your instincts, your first choice was the right one, now it's about making it work.