Create window-like menu on OS X - node.js

I'd like to create a same sort of tray menu like this application. Because it is on the list of applications that use node-webkit/nw.js, I think it's possible. I have looked through all the documentation and couldn't find anything on how to achieve that. Searching Google also wasn't really fruitful.
Maybe one of you guys has done this before and could send me in the right direction?

First you need to prevent app appear in taskbar
{
"name": "My App",
"version": "1.0.0",
"main": "app.html",
"window": {
"show": false,
"show_in_taskbar": false
}
}
Then you need to create tray (top bar) menu: (example from his source)
tray = new app.node.gui.Tray({
title: '',
icon: 'assets/css/images/menu_icon.png',
alticon: 'assets/css/images/menu_alticon.png',
iconsAreTemplates: false
});
Then need create hidden window and show it on click in tray:
// create window
var params = {toolbar: app.devMode, frame: false, transparent: true, resizable: false, show: false};
window = app.node.gui.Window.open('templates/panel.html', params);
function showPopup (x, y) {
window.on('document-end', function()
window.moveTo(x - (window.window.width / 2) - 6, y);
window.show();
window.focus();
});
}
// show panel when click in tray
tray.on('click', function (evt) {
showPopup(evt.x, evt.y);
});

Related

Chrome extension for selected text which matches a specific form [duplicate]

I am trying to create entries on the Chrome context menu based on what is selected.
I found several questions about this on Stackoverflow, and for all of them the answer is: use a content script with a "mousedown" listener that looks at the current selection and creates the Context Menu.
I implemented this, but it does not always work. Sometimes all the log messages say that the context menu was modified as I wanted, but the context menu that appears is not updated.
Based on this I suspected it was a race condition: sometimes chrome starts rendering the context menu before the code ran completely.
I tried adding a eventListener to "contextmenu" and "mouseup". The later triggers when the user selects the text with the mouse, so it changes the contextmenu much before it appears (even seconds). Even with this technique, I still see the same error happening!
This happens very often in Chrome 22.0.1229.94 (Mac), occasionally in Chromium 20.0.1132.47 (linux) and it did not happen in 2 minutes trying on Windows (Chrome 22.0.1229.94).
What is happening exactly? How can I fix that? Is there any other workaround?
Here is a simplified version of my code (not so simple because I am keeping the log messages):
manifest.json:
{
"name": "Test",
"version": "0.1",
"permissions": ["contextMenus"],
"content_scripts": [{
"matches": ["http://*/*", "https://*/*"],
"js": ["content_script.js"]
}],
"background": {
"scripts": ["background.js"]
},
"manifest_version": 2
}
content_script.js
function loadContextMenu() {
var selection = window.getSelection().toString().trim();
chrome.extension.sendMessage({request: 'loadContextMenu', selection: selection}, function (response) {
console.log('sendMessage callback');
});
}
document.addEventListener('mousedown', function(event){
if (event.button == 2) {
loadContextMenu();
}
}, true);
background.js
function SelectionType(str) {
if (str.match("^[0-9]+$"))
return "number";
else if (str.match("^[a-z]+$"))
return "lowercase string";
else
return "other";
}
chrome.extension.onMessage.addListener(function(msg, sender, sendResponse) {
console.log("msg.request = " + msg.request);
if (msg.request == "loadContextMenu") {
var type = SelectionType(msg.selection);
console.log("selection = " + msg.selection + ", type = " + type);
if (type == "number" || type == "lowercase string") {
console.log("Creating context menu with title = " + type);
chrome.contextMenus.removeAll(function() {
console.log("contextMenus.removeAll callback");
chrome.contextMenus.create(
{"title": type,
"contexts": ["selection"],
"onclick": function(info, tab) {alert(1);}},
function() {
console.log("ContextMenu.create callback! Error? " + chrome.extension.lastError);});
});
} else {
console.log("Removing context menu")
chrome.contextMenus.removeAll(function() {
console.log("contextMenus.removeAll callback");
});
}
console.log("handling message 'loadContextMenu' done.");
}
sendResponse({});
});
The contextMenus API is used to define context menu entries. It does not need to be called right before a context menu is opened. So, instead of creating the entries on the contextmenu event, use the selectionchange event to continuously update the contextmenu entry.
I will show a simple example which just displays the selected text in the context menu entry, to show that the entries are synchronized well.
Use this content script:
document.addEventListener('selectionchange', function() {
var selection = window.getSelection().toString().trim();
chrome.runtime.sendMessage({
request: 'updateContextMenu',
selection: selection
});
});
At the background, we're going to create the contextmenu entry only once. After that, we update the contextmenu item (using the ID which we get from chrome.contextMenus.create).
When the selection is empty, we remove the context menu entry if needed.
// ID to manage the context menu entry
var cmid;
var cm_clickHandler = function(clickData, tab) {
alert('Selected ' + clickData.selectionText + ' in ' + tab.url);
};
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
if (msg.request === 'updateContextMenu') {
var type = msg.selection;
if (type == '') {
// Remove the context menu entry
if (cmid != null) {
chrome.contextMenus.remove(cmid);
cmid = null; // Invalidate entry now to avoid race conditions
} // else: No contextmenu ID, so nothing to remove
} else { // Add/update context menu entry
var options = {
title: type,
contexts: ['selection'],
onclick: cm_clickHandler
};
if (cmid != null) {
chrome.contextMenus.update(cmid, options);
} else {
// Create new menu, and remember the ID
cmid = chrome.contextMenus.create(options);
}
}
}
});
To keep this example simple, I assumed that there's only one context menu entry. If you want to support more entries, create an array or hash to store the IDs.
Tips
Optimization - To reduce the number of chrome.contextMenus API calls, cache the relevant values of the parameters. Then, use a simple === comparison to check whether the contextMenu item need to be created/updated.
Debugging - All chrome.contextMenus methods are asynchronous. To debug your code, pass a callback function to the .create, .remove or .update methods.
MDN doc for menus.create(), 'title' param
You can use "%s" in the string. If you do this in a menu item, and some text is selected in the page when the menu is shown, then the selected text will be interpolated into the title.
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/menus/create
Thus
browser.contextMenus.create({
id: 'menu-search',
title: "Search '%s'", // selected text as %s
contexts: ['selection'], // show only if selection exist
})

dialog.showMessageBoxSync(null, options) getting hidden

I have an Electron app. If I use dialog.showmessageBoxSync normally it has to wait for user input. The options are: close, cancel or ok.
It is working fine but if I click outside of the dialog box (anywhere inside my app) then this message box hidden. I'm unable to click on any option.
How can I make the message box stay focused until the user chooses a button to click or closes the dialog box? The user should be forced to respond to the message box before continuing to work in the rest of the app.
dialog.showMessageBoxSync({
type: "info",
buttons: ["Ok,", "Cancel"],
defaultId: 0,
title: "",
message:""
cancelId: 1,
})
I'd suggest passing in a parent window
From the docs
The browserWindow argument allows the dialog to attach itself to a
parent window, making it modal.
const iconPath = upath.toUnix(upath.join(__dirname, "app", "assets", "icon.png"));
const dialogIcon = nativeImage.createFromPath(iconPath);
var options = {
type: 'question',
buttons: ['&Yes', '&No'],
title: 'Confirm Quit',
icon: dialogIcon,
normalizeAccessKeys: true,
message: 'Do you really want to close the application?'
};
const win = BrowserWindow.getFocusedWindow();
dialog.showMessageBox(win, options)
.then((choice) => {
if (choice.response === 0) {
quitApplication();
}
}).catch(err => {
console.log('ERROR', err);
});

how can i disable default menu in gojs

i'm new to gojs,
when i press my mobile's screen (#myDiagram div) in page , some default menu shows up but i don't want it.
i try to disable it by setting "toolManager.isEnable":false, but didn't work
myDiagram =
$(go.Diagram, "myDiagramDiv",
{
initialAutoScale: go.Diagram.Uniform,
initialContentAlignment: go.Spot.Center,
allowDrop: false,
allowMove: false,
"toolManager.isEnable":false,
nodeSelectionAdornmentTemplate:
$(go.Adornment, "Auto",
{ layerName: "Grid" },
$(go.Placeholder)
),
layout: // use a custom layout, defined below
$(GenogramLayout, { direction: 90, layerSpacing: 30, columnSpacing: 10 })
});
how can i disable it?
here is what shows after press
As described in https://gojs.net/latest/intro/contextmenus.html#DefaultContextMenuForTouchEnabledDevices, you can just set a ContextMenuTool property to null. For example, during the initialization of a Diagram:
$(go.Diagram, . . .,
{
"contextMenuTool.defaultTouchContextMenu": null
})

How to limit visible rows in a JList in groovy

I'm building a small dialog.
I using Groovy from a gradle build script.
The dialog consists of a JList, a JTextField and a JButton.
The list is populated with names of files. There are many files so I only wanna show 5 files together with a scollbar to go thru the list.
I have tried to set visibleRowCount but it still shows all rows.
new SwingBuilder().edt {
dialog(modal: true, // Otherwise the build will continue running before you closed the dialog
title: 'Enter program name',// Dialog title
alwaysOnTop: true, // pretty much what the name says
resizable: true, // Don't allow the user to resize the dialog
locationRelativeTo: null, // Place dialog in center of the screen
pack: true, // We need to pack the dialog (so it will take the size of it's children
show: true // Let's show it
) {
vbox { // Put everything below each other
label(text: "Program Name:")
list(id:"programName", items: progNames, visibleRowCount: 8)
label(text: "Start Rule Name:")
input = textField(id: 'ruleName', text: startRuleName)
button(defaultButton: true, text: 'OK', actionPerformed: {
testProgram = programName.selectedValuesList
startRuleName = ruleName.text
dispose() // Close dialog
})
}
}
}
How can I limit the number of visible rows?
You just need to wrap the call to list in a scrollPane node, ie:
new groovy.swing.SwingBuilder().edt {
dialog(modal: true, // Otherwise the build will continue running before you closed the dialog
title: 'Enter program name',// Dialog title
alwaysOnTop: true, // pretty much what the name says
resizable: true, // Don't allow the user to resize the dialog
locationRelativeTo: null, // Place dialog in center of the screen
pack: true, // We need to pack the dialog (so it will take the size of it's children
show: true // Let's show it
) {
vbox { // Put everything below each other
label(text: "Program Name:")
scrollPane {
list(id:"programName", items: progNames, visibleRowCount: 8)
}
label(text: "Start Rule Name:")
input = textField(id: 'ruleName', text: startRuleName)
button(defaultButton: true, text: 'OK', actionPerformed: {
testProgram = programName.selectedValuesList
startRuleName = ruleName.text
dispose() // Close dialog
})
}
}
}

Website Message Box by Automating InternetExplorer with VBA Excel

I am in the process of automating a process to fill up a website. With an Excel Macro, once I log into the website, insert a value in the required textbox and click the button, a website Message Box comes up with an alert asking me to confirm - Are you sure to update the value?
The execution of the macro stops at that level, resulting in no further execution of the macro.
On searching for the solution, I found out that a JavaScript function, the function which is executed on confirmation of the message box, should be called from macro instead of clicking the original button on the webpage.
I would like to have help in writing the code to call JavaScript function in Excel Macro.
Following is the HTML code from the view source page of the webpage.
$('#reloadButton').click(function () {
$(this).text(
$(this).attr('name')
).attr('disabled', 'disabled');
window.location.href = window.location.href.replace(/#.*$/, '');
});
SignalConsumer = function () {};
SignalConsumer.prototype = new TraderSettingsTool();
SignalConsumer.prototype.mySummaryPage = 'https://kvinvest.com/month/?action=template&tid=my_status';
SignalConsumer.prototype.isShowWaiver = 0;
SignalConsumer.prototype.amountPrecision = 1;
SignalConsumer.prototype._elements = {
"trading": {
"popup": $('#ssc-trading-popup'),
"amount": $('#ssc-trading-amount'),
"trade": $('#ssc-trading-trade'),
"provides": $('#ssc-trading-provides')
},
"slippage": {
"popup": $('#ssc-slippage-popup')
},
"provider": {
"popup": $('#ssc-provider-popup')
},
"consumers":{
"holder": $('#ssc-consumers-holder'),
"template": $('#ssc-consumers-template'),
"form": $('#ssc-consumers-form')
},
"subscribe": {
"server": $('#ssc-subscribe-server'),
"apply": $('#ssc-subscribe-apply'),
"loader": $('#ssc-subscribe-loader'),
"info": $('#ssc-subscribe-info'),
"form": $('#ssc-subscribe-form'),
"description": $('#ssc-subscribe-description')
},
"activate": {
"form": $('#ssc-activate-form'),
"slippage": $('#ssc-activate-slippage'),
"amount": $('#ssc-activate-amount'),
"popup": $('#ssc-activate-popup'),
"apply": $('#ssc-activate-apply'),
"cancel": $('#ssc-activate-cancel'),
"agree": $('#ssc-activate-agree'),
"sll": $('#ssc-activate-sll-value'),
"loader": $('#ssc-activate-sll-loader'),
"redirect": $('#ssc-activate-redirect')
},
"waiver": {
"popup": $('#ssc-waiver-popup'),
"agree": $('#ssc-waiver-agree'),
"apply": $('#ssc-waiver-apply'),
"subscribe": $('#ssc-waiver-subscribe')
},
"history": {
"log": $('#ssc-history-log')
}
};
SignalConsumer.prototype.bindEvents = function () {
var self = this;
this._elements.subscribe.form.find('form').submit(function () {
return false;
});
// I THINK BELOW IS THE MESSAGE BOX POP UP
this._elements.subscribe.apply.click(function () {
if(!confirm('Are you sure to update?')){
return false;
}
self.subscribeToServer();
return false;
});
// On show history popup
this._elements.history.log.click(function () {
self.loadHistoryLog();
return false;
});
// --- ACTIVATION LOGIC ---
this._elements.activate.apply.click(function () {
self.applyActivateServer();
return false;
});
this._elements.activate.agree.change(function () {
var disabled = $(this).is(':checked') ? '' : 'disabled';
self._elements.activate.apply.attr('disabled', disabled);
});
this._elements.activate.cancel.click(function () {
self.hidePopUp();
return false;
});
this._elements.activate.redirect.click(function () {
self.hidePopUp();
});
Well, what I won't do in this answer is provide the code that you request.
This answer is more like a suggestion since I'm not entirely sure about where you are going with this and if the technical approach that you suggest is what you are actually looking for.
It doesn't make a lot of sense to me, to connect the VBA engine with a web client unless you're aiming at retrieval of data only - such as for example a web query.
If you want to create an interactive data flow between the VBA engine and a web application, it seems more logical to create a connection with a server side script (written in PHP or ASP) that is connected to a database system (or if you want to store values in temporary session variables for that matter).
The fact that a user inputs a value, followed by a button click suggests that you want to build in a certain calculation logic. This is typically done on the server, and not browser level.
Therefore what I suggest you do is:
Javascript/jQuery -> PHP/ASP -> VBA
If that makes any sense to you.

Resources