I have a NWJS app that should run in system tray and only show main window if user requests it. So far I have this code to make it happen:
package.json:
{
"name": "helloworld",
"bg-script": "bg.js",
"main": "index.html"
}
in my index.html:
var win = nw.Window.get();
win.hide();
bg.js:
var tray = new nw.Tray({ icon: 'icon.png' });
var gui = require('nw.gui');
var menu = new nw.Menu();
menu.append(new nw.MenuItem({
label: 'Quit',
click() {
gui.App.closeAllWindows();
}
}));
tray.menu = menu;
The only issue is that a window flashes momentarily before disappearing. Is it possible to ensure it starts in hidden state instead of hiding it manually as I am doing?
Found the answer. Had to add to my package.json:
"window": {
"show": false
}
Related
I'm making a basic Firefox extension, which takes the selected text on a page, puts it into an URL and opens it in a new tab. I'm struggling with taking the selected text.
I'm aware of the Firefox bug in textarea and input, however, I'm testing it on regular page text.
manifest.json:
{
"manifest_version": 2,
"name": "Send2search test",
"version": "1.0",
"permissions": ["menus"],
"background": {
"scripts": ["bg.js"]
},
}
bg.js:
browser.menus.create(
{
id: "gglSearch",
title: "Search in new tab.",
contexts: ["selection"],
},
);
browser.menus.onClicked.addListener(async function (info, tab) {
var selectedTxt = window.getSelection().toString();
if (info.menuItemId == "gglSearch") {
var searchUrl = `https://www.google.com/search?q=${selectedTxt}`;
let openNewTab = browser.tabs.create(
{
active: false,
url: searchUrl,
index: tab.index+1
}
);
};
});
Every time it just opens blank google search, so nothing is saved in the selectedTxt variable. What am I doing wrong?
I also tried content.getSelection().toString() instead (https://stackoverflow.com/a/670258/20367262), but that caused the new tab to not get created at all.
PS: I know Firefox has "Search Google for" on right click by default, I'm just trying to work out extension developing basics on this.
I have a menu in my application that when you click on document properties another window pops up, but the application menu is also being inherited by this window, so you can open the document properties window from the document properties window. I just want to disable the menu for the document properties window,the only way I've been able to achieve this was by making the window frameless, but I still want the title bar to show, so that's not the solution I'm looking for.
I've tried using docProps.removeMenu(), docProps.setMenu(null), and even docProps.setApplicationMenu(null). I've moved it around, tried making docProps a global variable, nothing has worked.
This is my code:
//Create references for modules that require electron
const { app, BrowserWindow, Menu } = require('electron')
//Create a global reference for the main window
let mainWindow
function createWindow () {
//Create the browser window
mainWindow = new BrowserWindow({
minWidth: 300,
minHeight: 300,
backgroundColor: '#888888'
})
//Load the index.html file
mainWindow.loadFile('index.html')
//Reload the main window on resize
mainWindow.on('resize', function () {
mainWindow.reload()
})
}
function createAppMenu () {
//Create application menu template
const template = [
{
label: 'File',
submenu: [
{
label: 'Document Properties...',
click: function () {
docProps = new BrowserWindow({
width: 250,
height: 300,
resizable: false,
title: 'Document Properties'
})
//This isn't working and I'm not sure why
docProps.removeMenu()
}
}
]
},
{
label: 'Edit'
},
{
label: 'View'
},
{
label: 'Window'
},
{
label: 'Help'
}
]
//Build app menu from template
const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
}
//Call the createWindow function once electron has finished initializing
app.on('ready', function () {
createWindow()
mainWindow.maximize()
createAppMenu()
})
You can see the entire project at https://github.com/Leglaine/ElectroText
The only error message I get is when I try to call docProps.setApplicationMenu(null), it says that setApplicationMenu cannot be called on docProps, but I didn't really expect that to work anyway. Thanks in advance for your help!
win.removeMenu() and win.setMenu(null) seem to be currently broken in Electron when you have already set an application menu via Menu.setApplicationMenu()
Try setting an empty menu like this
docProps.setMenu(Menu.buildFromTemplate([]))
Like in any standard native application, also my electron's application needs to change the status (enabled/dsabled) of several menu item, based on live usage results.
I am setting up my menu in main.js:
function createWindow () {
...
...
require('./menu/mainmenu');
}
The MenuItem I need to change is defined in mainmenu:
{ label: "Show Colors",
accelerator: 'CmdOrCtrl+1',
enabled: getStatus(),
click() {getWebviewWebContents().send('switchToColors');}
},
where getStatus() is function returning false or true.
All this is not working in Electron, as the menu is created at application start and it can't be modified at all. I believe this is a serious lack, as dynamic menu items are very common (i.e.: menu checkboxes, enabled/disabled, etc).
Is there any workaround for this?
I have fixed this by setting an Id to the menu item,
{ label: "Show Colors",
id: 'color-scale',
accelerator: 'CmdOrCtrl+1',
enabled: getStatus(),
click() {getWebviewWebContents().send('switchToColors');}
},
and getting the menu item with:
myItem = menu.getMenuItemById('color-scale')
Then, when I need to enable/disable it programmatically, I am using:
myItem.enabled = true
or
myItem.enabled = false
The only workaround so far I aware and using is reconstruct whole menu each time menuitem changes. This is not very ergonomics friendly, but works suffeciently enough and doesn't cause lot of overhead.
Here is my solution:
main.js (main process)
const menuTemplate = [{
label: 'Options',
submenu: [
{
label: 'Config',
enabled: false,
click() { //do stuff }
}
]
}];
// Enable menu items when user login. Fetching value from renderer process
ipcMain.on('logged-in', (event, args) => {
if (args !== true) {
return;
}
// Modify menu item status
menuTemplate[0].submenu[0].enabled = true;
// Rebuild menu
const menu = Menu.buildFromTemplate(menuTemplate);
Menu.setApplicationMenu(menu);
});
How to implement background service using electron.
i'm having a trouble can anyone tell me how to start a background
service using electron which runs even after closing the app. i have
tried many solutions but all of them stop the service after closing
the app.
You can use tray. here is an example (source):
"use strict";
// [run the app]
// $ npm install electron
// $ ./node_modules/.bin/electron .
const {app, nativeImage, Tray, Menu, BrowserWindow} = require("electron");
let top = {}; // prevent gc to keep windows
app.once("ready", ev => {
top.win = new BrowserWindow({
width: 800, height: 600, center: true, minimizable: false, show: false,
webPreferences: {
nodeIntegration: false,
webSecurity: true,
sandbox: true,
},
});
top.win.loadURL("https://google.com/");
top.win.on("close", ev => {
//console.log(ev);
ev.sender.hide();
ev.preventDefault(); // prevent quit process
});
// empty image as transparent icon: it can click
// see: https://electron.atom.io/docs/api/tray/
top.tray = new Tray(nativeImage.createEmpty());
const menu = Menu.buildFromTemplate([
{label: "Actions", submenu: [
{label: "Open Google", click: (item, window, event) => {
//console.log(item, event);
top.win.show();
}},
]},
{type: "separator"},
{role: "quit"}, // "role": system prepared action menu
]);
top.tray.setToolTip("hello electrol");
//top.tray.setTitle("Tray Example"); // macOS only
top.tray.setContextMenu(menu);
// Option: some animated web site to tray icon image
// see: https://electron.atom.io/docs/tutorial/offscreen-rendering/
top.icons = new BrowserWindow({
show: false, webPreferences: {offscreen: true}});
top.icons.loadURL("https://trends.google.com/trends/hottrends/visualize");
top.icons.webContents.on("paint", (event, dirty, image) => {
if (top.tray) top.tray.setImage(image.resize({width: 16, height: 16}));
});
});
app.on("before-quit", ev => {
// BrowserWindow "close" event spawn after quit operation,
// it requires to clean up listeners for "close" event
top.win.removeAllListeners("close");
// release windows
top = null;
});
Yes, it is possible by using electron-process npm library.
ref :- https://www.npmjs.com/package/electron-process
First you will have to register the module which you want to run in background, just create simple background.html,
--background.html--
add below lines in script tag,
const background = require('electron-process').background;
background.registerModule(require('../main/snippets/SnippetsManager'));
In main process just create one browser window in which your background.html will run and keep it as hidden window,
--main.js--
app.once("ready", ev => {
service = new BrowserWindow({
width: 80, height: 60, center: true, minimizable: false, show: false,
webPreferences: {
nodeIntegration: false,
webSecurity: true,
sandbox: true,
},
});
service.loadURL("file://' + __dirname + '/background.html");
service.on("close", ev => {
ev.sender.hide();
ev.preventDefault(); // prevent quit process
});
});
Hope it helped,
Regards.
Electron is not designed to run in background. If you are closing
application then it will terminate all processes related with it.
Electron is only used to provide GUI layer. After all it is hybrid application and it doesn't interact with core OS services to live
itself like background service.
Apart from this there are two options:
If you write a service with something else, say a node or .net application, then you probably could use Electron to interact with that service (via bundled Node accessing Windows APIs).
Create feature like system tray. Minimise application to system tray.
Ref Link
I need to run Chrome extension when new tab is opened and html document is loaded.
Extension needs to check for new tab title and if it's equal to predefined string, tab should close.
For now, I have manage to write extension that works when I click on it's icon. But I want to make it to run without click on icon after the page is loaded in new tab.
Here is the current code.
function getCurrentTabData(callback) {
var queryInfo = {
active: true,
currentWindow: true
};
chrome.tabs.query(queryInfo, function(tabs) {
var tab = tabs[0];
var title = tab.title;
var id = tab.id;
callback(title, id);
});
}
document.addEventListener('DOMContentLoaded', function() {
getCurrentTabData(function(title, id) {
if(title == 'Page title') {
chrome.tabs.remove(id, function() { });
}
});
});
And here is my manifest.json
{
"manifest_version": 2,
"name": "Auto close tab",
"description": "Auto closes tab if title is matched",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png"
},
"permissions": [
"activeTab"
]
}
How to make it run without click on it's icon?
To accomplish this first of all you will need to have a Background Page that will manage your extension state. You can read about it here: https://developer.chrome.com/extensions/background_pages
Then in the background page script you will need to listen when the tab is created with this piece of code:
chrome.tabs.onCreated.addListener(function callback)
Here is documentation for this: https://developer.chrome.com/extensions/tabs#event-onCreated
Hope this will help to solve your issue.