Can't register click events in html BrowserWindow within Electron - javascript

I have been following through a tutorial for Electron and I am using a html document in a new BrowserWindow as a pop-up. The problem is, when I use an onclick handler on a html tag, it doesn't seem to fire. If I open the developer tools, I can type my function into the console and it behaves as expected!
Not sure if I'm missing something really obvious here but would appreciate anyone who could help me solve the issue.
Here is the body tag from the html for BrowserWindow:
<body id="page-info">
<main class="info-content">
<h3 class="page-headline">Wisdom Pet</h3>
<p>Welcome to the Wisdom Pet App.<br>
<strong>Version 1.0.0</strong><br>
<small>Built with love by Ray Villalobos</small>
</p>
<p>close window</p>
</main>
<script type="text/javascript">enter code here
var electron = require('electron');
var shell = electron.shell;
var ipc = electron.ipcRenderer;
/* Also tried using event listeners without html onclick
var closeAbout= document.getElementById("closeAbout");
closeAbout.addEventListener("click", function(){
send();
});
*/
function send(){
console.log("sending...");
ipc.sendSync('closeInfoWindow')
}
</script>
And here is the main.js file:
var Electron = require("electron");
var Menu = Electron.Menu;
var BrowserWindow = Electron.BrowserWindow;
var app = Electron.app;
var ipc = Electron.ipcMain;
var myAppMenu, menuTemplate;
app.on("ready", function(){
var appWindow = new BrowserWindow({
show: false
});
appWindow.loadURL("file://" + __dirname + "/index.html");
var infoWindow = new BrowserWindow({
show: false,
width: 400,
height: 300,
frame: false,
transparent: true,
});
infoWindow.loadURL('file://' + __dirname + '/info.html');
appWindow.once("ready-to-show", function(){
appWindow.show();
});
ipc.on("openInfoWindow", function(event, arg){
event.returnValue = "";
infoWindow.show();
})
ipc.on('closeInfoWindow', function(event, arg){
event.returnValue = '';
infoWindow.hide();
}); //closeInfoWindow
});
The ipc.on("openInfoWindow") work fine from the main window, but once the infoWindow is open, I can't close it unless I send the code directly from the developer tools.

Related

Electron - close renderer from main handler

TLDR: Best way to close a renderer window from main (or the renderer itself).
I am splitting up a process between X invisible renderer windows. When a renderer finishes its work, I want it to send an event to the main process and then close. Right now I have
//invisibleRenderer.js
doStuff().then(() => {
ipcRenderer.invoke('finish');
}
What is the best way to close the window? Is it in the ipcMain.handle? I can't figure out which method to call with which id.
ipcMain.handle('finish', (event, args) => {
//do what? event.frameId, event.processId, event.sender.id...
})
You can use BrowserWindow.fromId(event.sender.id) to get a reference to the window from where the IPC call originated, as demonstrated in this question.
This works fine in the main process. The following example opens 5 windows and loads the same contents. Each renderer script invocation picks a random delay (to simulate some work) and then dispatches the finish message to the main process. There, the main process picks up the BrowserWindow reference using event.sender.id and closes the corresponding window.
app.js
const {app, BrowserWindow, ipcMain} = require("electron");
const windows = [];
app.on("ready", function() {
for (let i=0; i<5; i++) {
let win;
win = new BrowserWindow( {
width: 300,
height: 300,
x: i*100,
y: i*100,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
},
});
win.loadURL(`file://${__dirname}/index.html`);
windows.push(win);
}
});
ipcMain.handle("finish", (event, args) => {
const win = BrowserWindow.fromId(event.sender.id);
win.close();
});
index.html
<html>
<body>
Renderer
</body>
<script type="text/javascript" src="renderer.js"></script>
</html>
renderer.js
const {ipcRenderer} = require("electron");
// Simulate some work by choosing a random delay..
const delay = Math.round(Math.random()*10000);
setTimeout(() => ipcRenderer.invoke("finish"), delay);

Electron non-context-aware native module in renderer issue

I have tried many things and can not seem to get the robotjs code to execute even with rebuild, and other examples I've seen to try.
I still get the Loading non-context-aware native module in renderer error.
I have a button, and on click of the button I want the robotjs code to be executed.
Here is my current code :
bot.js
const robot = require('robotjs')
const electron = require('electron')
const ipc = electron.ipcRenderer
const Bot = () => {
const button = document.getElementById('start');
// button.addEventListener('click', () => console.log('Click'))
button.addEventListener('click', function (e) {
// Get mouse position.
var mouse = robot.getMousePos();
// Get pixel color in hex format.
var hex = robot.getPixelColor(mouse.x, mouse.y);
console.log("#" + hex + " at x:" + mouse.x + " y:" + mouse.y);
});
}
Bot();
My main file :
index.js
const { app, BrowserWindow, ipcMain } = require('electron');
const robot = require('robotjs')
const path = require('path');
// const Bot = require('./bot')
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
if (require('electron-squirrel-startup')) { // eslint-disable-line global-require
app.quit();
}
const createWindow = () => {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
}
});
// and load the index.html of the app.
mainWindow.loadFile(path.join(__dirname, 'index.html'));
// Open the DevTools.
mainWindow.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.
app.on('ready', createWindow);
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', () => {
// 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 (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 import them here.
Here is the index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title>Hello World!</title>
<link rel="stylesheet" href="index.css" />
</head>
<body>
<div class="App">
<div class="Header">
<h1>Checkout-Bot</h1>
</div>
<div class="Wrapper">
<p>Click Start</p>
<button id="start">Start</button>
</div>
</div>
<script src="bot.js">
Bot();
</script>
</body>
</html>
Have you read this issue on Github?
They removed the ability to use non-NAPI and non-context aware modules.
If you're not using Electron 11 yet, you can still use those modules, if you add the following line in the main process:
app.allowRendererProcessReuse = false
As an alternative solution, Try https://www.npmjs.com/package/#nut-tree/nut-js instead of robotjs. Electron (Last checked with 18.2.0) works well with nutjs.
Please refer to https://www.npmjs.com/package/#nut-tree/nut-js & https://nutjs.dev/docs/tutorial-first_steps/get_moving to see the documentation and working samples.

how to save a picture taken with window.getusermedia in js

Currently i am working on a open webapp camera, right now i have implemented the camera setup(live stream as viewport, take picture button, capture, display taken picture in corner... etc) but now i am running into the issue of how to save that picture for the user to their device or computer, this app is currently being designed for mobile b2g primarily. I know most people are gonna tell me security issues!!! i dont mean tell the device exactly where to put it. I mean something like
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<script type="text/javascript">
window.onload = function () {
var img = document.getElementById('embedImage');
var button = document.getElementById('saveImage');
img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUA'+
'AAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO'+
'9TXL0Y4OHwAAAABJRU5ErkJggg==';
img.onload = function () {
button.removeAttribute('disabled');
};
button.onclick = function () {
window.location.href = img.src.replace('image/png', 'image/octet-stream');
};
};
</script>
</head>
<body>
<img id="embedImage" alt="Red dot"/>
<input id="saveImage" type="button" value="save image" disabled="disabled"/>
</body>
</html>
that specific code executed on mobile triggers the file to automatically be saved on click of the button. now what i want to do is use that to take my picture from its var its in and save it as that file, for example that will be in downloads folder.
this is what my code is currently https://github.com/1Jamie/1Jamie.github.io
any help would be appreciated and this is the current running implementation if you want to take a working look http://1Jamie.github.io
This worked for me when I was playing around with getUserMedia - I did notice that you did not have the name of the method in the proper case and it is a method of the navigator.mediaDevices interface - not a method of the window directly...
References:
[Navigator for mozilla]https://developer.mozilla.org/en-US/docs/Mozilla/B2G_OS/API/Navigator
https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices
[mediaDevices for chrome and android]https://developers.google.com/web/updates/2015/10/media-devices?hl=en
var video = document.getElementById('monitor');
var canvas1 = document.getElementById('photo1');
var img1 = document.getElementById('canvasImg');
navigator.mediaDevices.getUserMedia({
video: true
}).then(function (stream) {
video.srcObject = stream;
video.onloadedmetadata = function () {
canvas1.width = video.videoWidth;
canvas1.height = video.videoHeight;
document.getElementById('splash').hidden = true;
document.getElementById('app').hidden = false;
};
}).catch(function (reason) {
document.getElementById('errorMessage').textContent = 'No camera available.';
});
function snapshot1() {
canvas1.getContext('2d').drawImage(video, 0, 0);
}
"save_snap" is the id of a button - Disclaimer I am using jQuery- but you should easily see where this corresponds to your code:
$("#save_snap").click(function (event){
// save canvas image as data url (png format by default)
var dataURL = canvas2.toDataURL();
// set canvasImg image src to dataURL
// so it can be saved as an image
$('#canvasImg').attr("src" , dataURL);
$('#downloader').attr("download" , "download.png");
$('#downloader').attr("href" , dataURL);
//* trying to force download - jQuery trigger does not apply
//Use CustomEvent Vanilla js: https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent
// In particular
var event1 = new MouseEvent('click', {
'view': window,
'bubbles': true,
'cancelable': true
});
//NOW we are effectively clicking the element with the href attribute:
//Could use jQuery selector but then we would have to unwrap it
// to expose it to the native js function...
document.getElementById('downloader').dispatchEvent(event1);
});

Electron developer tools in separate window not showing on Windows

I'm developing a quick proof of concept app using Electron (formerly known as atom-shell), while trying to debug it I popped the Dev tools to a separate window and it was working for a while until today. I can see the developer tools window in the windows task bar but when I click it nothing shows up.
I've tried restarting the computer, reinstalling atom, toggling developer tools via menu and Alt+Ctrl+I but the window is nowhere to be seen.
Here's the relevant code of my app, but I've tweaked it and it doesn't help either.
var app = require('app');
var BrowserWindow = require('browser-window');
require('crash-reporter').start();
var mainWindow = null;
app.on('window-all-closed', function() {
if(process.platform != 'darwin') {
app.quit();
}
});
app.on('ready', function() {
mainWindow = new BrowserWindow({
'width': 450,
'height': 800,
'max-width': 450,
'max-height': 800,
'min-width': 450,
'min-height': 800
});
mainWindow.loadUrl('file://' + __dirname + '/app/index.html');
mainWindow.openDevTools();
mainWindow.on('closed', function() {
mainWindow = null;
});
});
I figured out how to make it appear, and in case this happens to anyone else I fixed it by just pressing win+up.

Titanium is not defined when attempting Titanium.UI.currentWindow using titanium appcelerator

When I run the app on the device I get no error (well nothing occurs at all) as there is no debug console but when I run the app in the browser I get "Titanium is not defined"
Is there a js file I need to include?
I got the camera code from here:
http://www.mindfiresolutions.com/Capture-Image-with-device-camera-in-IPhoneAndroid-application-using-Titanium-1912.php
I call it from an html file from webview.
I created a new project from scratch and I get he same error. This is so frustrating:
in html:
<!doctype html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width;initial-scale=1.0 maximum-scale=1.0; user scalable=0;">
<title>Notes</title>
<script language="JavaScript" type="text/javascript">
function play(locid) {
Ti.App.fireEvent('play', {
locid : locid
});
}
</script>
</head>
<body>
<a id="Home" onclick ="play(125)" title = "" > hello </a>
</body>
</html>
in app.js:
Ti.App.addEventListener('play', function(e)
{
alert(e.locid);
});
Uncaught ReferenceError: Ti is not defined in the HTML file!!!
That code has a number of things preventing it from working as a standalone app.js. I want to address a couple of the concerns brought up by it, and then I'll directly address the app.js so you can get on your way.
First, "Ti.UI.currentWindow" is how you get a reference to a window in a situation like this:
In the file "app.js", you have:
var win = Ti.UI.createWindow({
url: 'win.js'
});
win.open();
And in "win.js", you have:
var win = Ti.UI.currentWindow;
win.add(Ti.UI.createLabel({
text: 'Hello, world!', textAlign: 'center',
color: '#000'
}));
But structuring your apps like that isn't the recommended approach anymore. If you're starting fresh, start right -- with Alloy. http://docs.appcelerator.com/titanium/3.0/#!/guide/Alloy_Quick_Start
If all you really care about is getting the example to work, below is the code updated to work:
//Define the current window
var myWin = Ti.UI.createWindow({
backgroundColor: 'white'
});
//Define the button to activate camera
var cameraBtn = Ti.UI.createButton({
title: 'Click to activate Camera',
top: 10 //Set the button position on the screen
});
cameraBtn.addEventListener('click', function () {
//Activate camera
Ti.Media.showCamera({
success: function (event) {
//Holds the captured image
var capturedImg = event.media;
// Condition to check the selected media
if (event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO) {
//Define an image view with captured image
var imgView = Ti.UI.createImageView({
left: 10,
width: 250,
height: 250,
image: capturedImg //Set captured image
});
//Add the image to window for displaying
myWin.add(imgView);
}
},
cancel: function () {
//While cancellation of the process
},
error: function (error) {
// If any error occurs during the process
}
});
});
myWin.add(cameraBtn);
myWin.open();
use "Titanium" instead of "Ti" in WebView HTML code.

Categories

Resources