sindresorhus / electron-context-menu Goto Github PK
View Code? Open in Web Editor NEWContext menu for your Electron app
License: MIT License
Context menu for your Electron app
License: MIT License
Workaround:
I am counting the number of events that come through, and only taking the odd-numbered ones (I return false on even-numbered counts in the shouldShowMenu function).
Looking for a bit of help here as I am not doing anything particularly odd with the library I don't think. Just adding a context menu to my webview element after it has been mounted via react.
How to hide the default context menu for a blank area
The append
and prepend
options solve most use-cases, but there are still some people that want 100% control. Would be nice to expose a way to build the menu with ready made components, like lego. I'm thinking:
require('electron-context-menu')({
menu: x => [
x.COPY,
{
title: 'foo'
},
x.INSPECT
]
});
Where x.COPY
is a Symbol
that includes the built-in cut/copy/paste menus. That way it would be easy to add many more built-in menu types users could pick from.
Hi! I try to use the code follow to enable webview context menu but it not work!
const BrowserWindow = electron.BrowserWindow;
const WebView = electron.WebView;
require('electron-context-menu')({
window: WebView,
prepend: (params, browserWindow) => [{
labels: {
cut: 'Configured Cut',
copy: 'Configured Copy',
paste: 'Configured Paste',
save: 'Configured Save Image',
copyLink: 'Configured Copy Link',
inspect: 'Configured Inspect'
},
// Only show it when right-clicking images
visible: params.mediaType === 'image'
}]
});
I guess the key is the this statment const WebView = electron.WebView;
, I don't know how where to get the WebView Type.
The result is still just work for BrowserWindow!
so, how can I fix the code to enable that? Thanks !
Right click to copy the picture how to do
Using the library in a global context with the following options causes an unhandled exception with every right click:
contextMenu({showInspectElement: false});
// causes this error
TypeError: Invalid template for MenuItem: must have at least one of label, role or type
at Function.Menu.buildFromTemplate (D:\Users\<user>\Dev\excalibur\node_modules\electron\dist\resources\electron.asar\browser\api\menu.js:164:11)
at WebContents.webContents.on (D:\Users\<user>\Dev\<project>\node_modules\electron-context-menu\index.js:182:74)
at WebContents.emit (events.js:182:13)
This causes the context menu to not show up at all.
Windows 10 x64
using yarn
[email protected]
Is it possible to modify the elements on the menu depending on the element clicked, for example, depending on the class or id?
In my case, I have certain boxes that should display a different context menu that other elements, I tried tinkering with the prepend callback but it doesn't provide any information about the clicked element.
Returns dispose function for removeListener('context-menu', *), in my case of using HMR(Hot Module Replacement). Avoid registering multi-times.
If the app has electron-debug
then there should be an item to "Inspect Element" like in Chrome that opens the inspector and highlights the appropriate element in the DOM.
I'm disinclined to use libraries with tests. We should add them!
There is a $40.00 open bounty on this issue. Add more on Issuehunt.
- Checkout the Issuehunt explorer to discover more funded issues.
- Need some help from other developers? Add your repositories on Issuehunt to raise funds.
Docs: https://github.com/sindresorhus/electron-dl#saveas
Now I have to fork the whole library to give the tweak :/
download(win, props.srcURL, { saveAs });
Hi.
I intend to use a react hook for creating context menus "on the fly" in the renderer process, for particular DOM elements.
The current implementation is here and the usage is something like this:
const SomeListItem = (props) => {
const ref = React.useRef(null);
useContextMenu(ref, [{
label: 'Delete',
click: () => props.onDelete(props.id)
}]);
return (
<li ref={ref}>...</li>
);
}
The hook effectively calls contextMenu()
whenever the component is mounted to the DOM. Many components may do this many times.
What I wonder is... Shouldn't I be destryoing something when the components gets unmounted again?
I skimmed the code a bit, but it's still not clear to me whether one can or should destroy menus for cleanup reasons.
(I'm aware of the potential performance issues as explained by @fabiospampinato in 78 but I don't care about that that for now.)
Hi,
How would it be possible to override SaveImage label?
Kind regards.
I'm not sure if I'm doing wrong, but when I add:
contextMenu(
{
window: new_webview,
showCopyImageAddress: true,
showSaveImageAs: true,
showInspectElement: true
})
When creating a webview. The findInPage function doesn't work at all.
I created a testing repo for this https://github.com/madprops/webview-test-for-debugging
I am not seeing the context menu rendered even though I am using simple settings. Am I missing something here? I am mainly interested in getting the inspect element menu item.
My code is below:
function createWindow() {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 1200,
height: 1200,
webPreferences: {
// nodeIntegration: false
// https://github.com/electron/electron/issues/959
partition: 'persist:xxxx'
}
});
require('electron-context-menu')({
window: mainWindow,
showInspectElement: true
});
// and load the index.html of the app.
mainWindow.loadURL(url.format({
// pathname: path.join(settings.project.root, './static/html/google.html'),
pathname: path.join(settings.project.root, 'static/html/site.html'),
protocol: 'file:',
slashes: true
}));
// Open the DevTools.
mainWindow.webContents.openDevTools({mode: 'undocked'});
require('devtron').install();
// 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;
});
}
The default example doesn't work as expected. I can click wherever and the menu would show. It seems it should trigger only if an img
tag was clicked, correct?
Seems to work great otherwise and much easier to integrate compare to other offerings.
Using the latest version.
I am able to see the context menu in BrowserWindow however I dynamically render when needed using a react app and don't see the context menu.
I don't pass anything in the window option so according to the documentation it should be visible in the webview by default but isn't.
If I need to pass webview reference I'd like an example if possible, I don't understand how you expect to pass a reference to the webview which is in the renderer while the context menu is in the main process.
I have an ID for the element but can't access and get results from the DOM from the main process or pass the element itself using IPC since it doesn't work.
Thanks
Remove existing separators before/after built-in menus allowing users to design the menu as needed/wanted.
For some reason, the Context Menu is appearing twice after the click:
Electron: v1.6.2
Usage:
const { download } = require('electron-dl');
require('electron-context-menu')({
prepend: (params, browserWindow) => [
{
label: 'Copy Audio Address',
visible: params.mediaType === 'audio',
click(item, win) {
download(win, params.srcURL);
}
}
]
});
In preload.js (renderer process).
Any ideas?
when I open right menu,the text selection will lost。
When I use Copy Link in [email protected], it throw error said writeBookmark() is not a function.
electron.clipboard.writeBookmark(props.linkText, props.linkURL);
readme.md states that showInspectElement is a boolean which should...
"Force enable or disable the Inspect Element menu item."
The following code does NOT disable the Inspect Element menu item:
require('electron-context-menu')({
prepend: (params, browserWindow) => [{
label: "Capital Flux™",
showInspectElement: false
}]
});
Environment is Electron on Windows 7.
I installed this in my app, created a basic context menu with contextMenu({window: MainWindow})
, right clicked in my app, but no context menu appeared. I tried in both the main and renderer process. I even tried cloning electron-quick-start and trying it there, but still nothing.
OS: Windows 10 x64 1903 (build 18362.239)
Electron: 6.0.0
node_modules/.bin/electron --
: 4.2.12node_modules/.bin/electron --version
on last known working Electron version (if applicable): 4.2.12Expected Behavior
When active the insect button, and the mouse hover the webview inside html element it should highlight the elemrnt.
Actual behavior
Noting happen.
To Reproduce
Add a webview tag with context-menu and open it's devTools.
Additional Information
I would like the context menu to be different in different parts of my application. For example, I have a top portion with textboxes and a right click should give me the ability to cut/copy/etc.
However, in a grid area, I would like completely different options, such as runCommandA
and runCommandB
I understand this module can be declared in the render.js
or the main.js
side, however I am noticing that I can't simply re-declare the context menu in each separate component*.
I am thinking the way to go is to initially declare the context menu in main.js
but then append custom items to individual components. Assuming this is right, how do I do this?
(If my assumption is incorrect, then simply... how do you create separate context menus in the app?)
*FYI: I am using React.JS
Update: I think I found a way to make the context menu more dynamic. I basically use ipcMain
and ipcRenderer
to send messages about the context of where I am:
ipcMain.on('removeListener', (x, y) => {
ipcMain.removeAllListeners('context-menu-row');
});
ipcMain.on('context-menu-row', (ev, args) => {
require('electron-context-menu')({});
require('electron-context-menu')({
prepend: (params, browserWindow) => [{
label: `Library Compare ${args.msn}`,
click: () => {
ev.sender.send('emit', {
event: 'onLibraryCompare',
payload: args.msn
});
}
}],
append: (params, browserWindow) => [{
label: '---',
}]
});
});
But now I am noticing the context menu to be very jittery and sometimes the args.msn
variable does not reflect properly. I am also noticing many new listeners being created. I have tried many variations, using ipcMain.once(..)
and various ideas on removing listeners, but I think I am doing something fundamentally wrong.
Any advice here would be great!
I'm defining a custom "Copy" action, which does something a bit different than the default "Copy" action, to some buttons, but on right click the content of the button gets selected (and I can't make them unselectable) and so the menu displays 2 "Copy" actions, the one I defined and the one this library defines:
I think I could generate the whole menu manually via the menu
option but that would mean detecting all the cases where the default actions should be showed.
Could we instead add an option, canOverrideDefaultActions
or something, where before inserting each default action the library check if another action with the same label has been provided already?
Either of the electron.shell.showItemInFolder
and electron.shell.openExternal
API once successfully run, lead to a future crash when trying to click the context menu without first focusing on the electron window. Maybe, the behavior could be graceful, which first focuses the window, or refuses to context menu until user explicitly focuses.
Pertinent electron docs
Stacktrace from current crash:
Uncaught exception: Cannot read property 'webContents' of null TypeError: Cannot read property 'webContents' of null
at click (/Users/charandas/serve/myproject/app/node_modules/electron-context-menu/index.js:93:9)
at MenuItem.click (/Users/charandas/serve/myproject/node_modules/electron/dist/Electron.app/Contents/Resources/electron.asar/browser/api/menu-item.js:52:9)
at Function.executeCommand (/Users/charandas/serve/myproject/node_modules/electron/dist/Electron.app/Contents/Resources/electron.asar/browser/api/menu.js:121:15)
at Menu.popup (/Users/charandas/serve/myproject/node_modules/electron/dist/Electron.app/Contents/Resources/electron.asar/browser/api/menu.js:162:8)
at WebContents.on (/Users/charandas/serve/myproject/app/node_modules/electron-context-menu/index.js:127:9)
at emitTwo (events.js:106:13)
at WebContents.emit (events.js:191:7)
Native context menus on macOS have a “Services” submenu to which other apps on the system can add actions.
I think this should be fairly trivial to implement using the services
role from Electron's menu API.
I'll give it a go later and submit a PR.
Example from Safari:
Repro:
Actual:
Error popup
Uncaught Exception:
TypeError: Cannot read property 'webContents' of null
Desired:
Element clicked on should be inspected
It seems that the window argument passed to the context menu click callback is the focused window (which is null since devtools is focused), not the clicked window. This ought to be fixed upstream in electron. However, until that happens, you should null-check win
here:
electron-context-menu/index.js
Line 93 in 6705425
Logged a bug upstream here electron/electron#8209
I've been profiling an app of mine and I've found that this library keeps the app busy considerably more than it should, the cause of that is that by using the remote
module many times many synchronous IPC calls are sent to the main process and back, and while that's occurring everything stops in the renderer process basically.
My use case is basically creating a few context menus from the renderer process.
Issue: first of all if we don't pass the window
option then that's retrieved from the main process, basically for each new context menu that's created a new IPC call is made.
Issue: there's a check here that checks if the webContents
object actually exists. According to Electron's (v5) own typescript types that object always exists.
create
function, which retrieves the webContents
object again, that shouldn't happen I think.Issue: the webContents
object of the window is retrieved multiple times, but I don't think that object ever changes, I haven't found anything about that in the docs.
webContents
object should be cached, by window id, if it exists (which maybe it's always the case anyway?).Issue: when a context menu is displayed it takes about 60ms on my system to do that, again mostly because of synchronous IPC calls. I think ideally that number should be closer to 16ms at maximum on an average computer, in order to make the app feel snappier.
When implementing fixes for the first 3 issues I mentioned the time needed for the creation of a single context menu when down from ~12ms to ~2.5ms on my system. IMHO that's significant enough to deserve addressing, especially considering that those wasted ~10ms need to be multiplied by the number of context menus, in my case that added up to about 100ms, which is significant especially considering that those context menus are created at startup.
Should I submit a PR for addressing these issues?
In Safari, it looks like the following:
And with too much text:
##Should be possible to turn it off in the options.
Or should it be off by default?
IssueHunt has been backed by the following sponsors. Become a sponsor
Right now I don’t have a need for the label. However if I set the label
property in prepend
to null
or undefined
, it just generates a blank label. Is there a way to disable it so the context menu just says Cut, Copy, Paste, and Inspect Element?
is there a callback function or something that will fire up when user clicks on certain label ?
Hi,
This issue is related to #14, but I think it is appropriate to discuss it separately.
The specific use case for altering the behaviour of the default roles is found in Caprine.
Currently it is impleted that clicking on links removes the tracking bits from the URL.
This is not the case when using the context-menu (e.g. "Copy Link").
Therefore it would be useful to be able to modify the content of that link without the need to rewrite some of the boilerplate.
Thoughts?
Is it possible to change the selected text when opening and clicking the context menu?
This is my code
const {webFrame} = require('electron')
const SpellChecker = require('spellchecker')
const context_menu = require('electron-context-menu')({
prepend: (params, browserWindow) => {
var suggestions = [];
SpellChecker.getCorrectionsForMisspelling(params.selectionText).forEach(function(element) {
suggestions.push({
label: element,
visible: true,
click: function(selected){
// what code here?
}
})
});
return suggestions;
}
});
SpellChecker.setDictionary('nl_BE', '')
webFrame.setSpellCheckProvider('nl-NL', true, {
spellCheck (text) {
return !SpellChecker.isMisspelled(text);
}
})
I've tried it a number of times with a electron 2.0.x webview and no context menu appears.
Works fine with electron 1.8.x.
Totally default, no customization.
Would make this a more attractive replacement for https://github.com/mixmaxhq/electron-editor-context-menu and should be simple enough to add.
IssueHunt has been backed by the following sponsors. Become a sponsor
Use case: there might be nothing to prepend, in which case returning undefined
(ie. not returning anything) makes sense.
As an alternative, update docs to say "must return an array" instead of "should return an array":
https://github.com/sindresorhus/electron-context-menu#append
Wdyt? Happy to send a pr..
What would be the recommended way of translating/overwriting the default labels? Maybe it would be interesting to take that into account when implementing an implementation for issue #14?
It would be nice to have an option to hide certain menu options that are built-in by default.
Hi!
I'm looking to use electron-context-menu, but I would like to add additional menu options to the created template, of menuTpl
and set up a callback for this myself.
Would it be possible to expose a function to create the template to do this, as illustrated in the example below below
// expose template creator in electron-context-menu
import {createContextMenuTemplate} from 'electron-context-menu';
win.webContents.on('context-menu', (e, props) => {
// new exposed function to create the menu template
const menuTpl = createContextMenuTemplate(props);
// add more options
// menuTpl.push(SOME_MORE_OPTIONS)
const menu = (electron.Menu || electron.remote.Menu).buildFromTemplate(menuTpl);
menu.popup(win);
});
I'll create a pull request for this if you're open to it!
Hi there,
when I copy a link on WIndows a bookmark is being written to the clipboard:
electron.clipboard.writeBookmark(props.linkText, props.linkURL);
I'm not able to paste this bookmark in most applications including the electron app I copied it from. The only app I found which allows pasting these bookmarks is actually Chrome.
I could create a PR to make this configurable, but wasn't sure what the actual advantage of the bookmark API is and if there might be another way to fix this.
I have tried using this at the start of my main.js:
require('electron-context-menu')({
prepend: (params, browserWindow) => [{}]
});
I can only get the inspect Element menu and cannot figure out what extra things I need to do to add more options like Reload page to the context menu. Please help.
Our applications calls into electron-context-menu
in order to show 1 Inspect Element
menu. Simplified it is doing this (coffeescript):
contextMenu = require("electron-context-menu")
contextMenu({
showInspectElement: true
window: win
})
The complete code in our project is here: https://github.com/cypress-io/cypress/blob/renovate/electron-context-menu-0.x/packages/server/lib/gui/windows.coffee#L150
This menu is working in version 0.11.0 of electron-context-menu
, but showing up as disabled in version 0.12.0.
We waited until now to update because of the breaking change for Electron - we recently updated to use Electron 5.0.10.
Forgive me if I missed something in the changelog that we were meant to update.
After running npm install --save electron-context-menu
and adding
require('electron-context-menu')({
prepend: [{}],
showInspectElement: true,
});
I've tried a variety of configurations, nothing seems to add Inspect Element to my rightclick menu, which I don't have. I tried looking into the source and have come up empty so I'd love advice on how to get this working.
Thanks!
hello,i use save picture function,but i want to choice folder,can u provide an option to config this part , this download function's third parameter, thank you
if (props.mediaType === 'image') {
menuTpl = [
{
type: 'separator'
},
{
id: 'save',
label: 'Save Image',
click(item, win) {
download(win, props.srcURL)
}
},
{
type: 'separator'
}
]
}
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.