Is it possible to detect a shift-click or command-click on a browser action button in the chrome bar?
For example, the following code does not work:
chrome.browserAction.onClicked.addListener(function(e) {
console.log(e.shiftKey) // is undefined
});
I've found a way to accomplish this. In my case, I needed to detect a ctrl-click and a ctrl-alt-click event on the toolbar icon.
Apparently the background script cannot capture keyboard events, but the content script can. So I set an event listener in the content script to listen for ctrl and alt keypresses and send a message to the background script. As it happens, the keydown event has boolean properties for ctrlKey and altKey built in so I did't have to implicitly check the value of the keypress. In your case, can use the shiftKey property.
content.js
window.addEventListener('keydown',function(event){
if(event.ctrlKey){
chrome.runtime.sendMessage({type: 'ctrlPressed'}, function(){});
}
if(event.altKey){
chrome.runtime.sendMessage({type: 'altPressed'}, function(){});
}
});
window.addEventListener('keyup',function(event){
chrome.runtime.sendMessage({type: 'keyup'}, function(){});
});
background.js
var ctrlPressed = false;
var altPressed = false;
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
switch(request.type){
case 'ctrlPressed':
ctrlPressed = true;
break;
case 'altPressed':
altPressed = true;
break;
case 'keyup':
ctrlPressed = false;
altPressed = false;
break;
}
});
Now my chrome.browserAction.onClicked.addListener can detect a click, double-click, ctrl-click, and ctrl-alt-click. (With just a little more code I could also detect ctrl-double-click and ctrl-alt-double-click.) The only caveat is that the active tab must have focus to capture keypresses. The window.focus() line at the end of the routine should handle that.
background.js
// Listen for toolbar icon clicks
var clickCnt = 0;
chrome.browserAction.onClicked.addListener(function(tab){
clickCnt++;
if(clickCnt > 1){
console.log('Double click detected');
clickCnt = 0;
clearTimeout(timer);
}else{
if(ctrlPressed){
if(altPressed){
console.log('ctrl-alt-click detected');
}else{
console.log('ctrl-click detected');
}
}
timer = setTimeout(function(){
console.log('Single click detected');
clickCnt = 0;
}, 250);
}
window.focus()
});
No, it's not provided by the API. You can't detect modifiers, or different mouse buttons.
Chrome API events are not DOM events, looking for e parameter won't help. Each event has its own list of parameters passed to the callback; look it up in the documentation.
In case of the browserAction.onClicked:
The callback parameter should be a function that looks like this:
function(tabs.Tab tab) {...};
tabs.Tab tab
So the only information you get is the current tab at the time the button was clicked.
Related
When I log in to my application, I am being shown a number of broadcast messages which may or may not be shown and whose number is not under my control. I need to click on a checkbox and next button to dismiss one message and move to the next. So, I need to write a loop on basis of a common element present on the messages with webdriver.io and node.js
I am new to selenium with node.js and webdriver.io and trying to write webdriver.io fucntion inside while and if loop, correct me if that is not possible
The code which I have used is below :
//Code to loop the click on elements depending upon presence of an Element
//Gherkin- I should see if Elementxyz exist then I click on Elementabc and Elementdef
//Author : Rohit
this.Then(/^I should see if "([^"]*)" exist then I click on "([^"]*)" and "([^"]*)"$/, function (selectorelement, selectorcheckbox, selectornext) {
// Element whose presence is checked
selectorelement = this.getSelector(selectorelement);
//Checkbox which needs to be ticked
selectorcheckbox = this.getSelector(selectorcheckbox);
//next button which needs to be clicked
selectornext = this.getSelector(selectornext);
return this.client
.waitForElemReady(selectornext, this.TIMEOUT_CONST)
.then(function(){
if(this.client.isExisting(selectorelement))
{
while(this.client.isExisting(selectorelement))
{
this.client
.click(selectorcheckbox)
.click(selectornext)
.pause(12000)
}
}
else{
console.log("you got lucky there are no messages this time :)")
}
}.bind(this)); });
Please help me as i am new to node.js and wedriver.io world
Hi t33n ,
i have tried the below code and loop is working fine now only thing is that my script is not waiting as .pause() is not working. Could you please help in that.
When I log in to my application, I am being shown a number of broadcast messages which may or may not be shown and whose number is not under my control. I need to click on a checkbox and next button to dismiss one message and move to the next. So, I need to write a loop on basis of a element present on the messages with webdriver.io and node.js I am new to selenium with node.js and webdriver.io and trying to write webdriver.io function for loop.
The code which i am trying to use is working and looping, only thing is giving me problem is pause which is not working as i need to pause a bit till the next message appears.
this.Then(/^I should see if "([^"])" exist then I click on "([^"])" and "([^"]*)"$/, function (selectorelement, selectorcheckbox, selectornext) {
selectorelement = this.getSelector(selectorelement);
// Checking presence of selectorcheckbox
selectorcheckbox = this.getSelector(selectorcheckbox);
selectornext = this.getSelector(selectornext);
var flag1 = false;
// function used for loop
function runNext(flag1,selectorcheckbox, selectornext,browser) {
setTimeout(function (){
browser
.isExisting(selectorcheckbox)
.then(function (isExisting) {
flag1 = isExisting;
if (flag1) {
flag1 = false;
browser.click(selectorcheckbox)
.pause(1000)
.click(selectornext)
.pause(5000); // Pause statements not working
runNext(flag1, selectorcheckbox, selectornext, browser);
}
else {
console.log("no messages left or no messages this time");
}
}, 50000)
}
.bind(this));
}
var loop= runNext(flag1,selectorcheckbox, selectornext,this.client);
});
.pause statements are only working when i am doing return this.client.pause but this stops the execution wherever i write this line.
Please help me with some solution.
maybe this working for you. If not you should see how loops can work and you can create your own loop with this.
function loop() {
client
.isVisible(selectornext).then(function(isVisible) {
if (isVisible) {
client
.isVisible(selectorelement).then(function(isVisible2) {
if (isVisible2) {
client
.click(selectorcheckbox)
.pause(1000)
.click(selectornext)
.pause(12000)
loop()
} // if (isVisible2) {
}) // .isVisible(selectorelement).then(function(isVisible2) {
} // if (isVisible) {
else{
// cancel loop here?
}
}) // .isVisible(selectornext).then(function(isVisible) {
} // function loop() {
How to identify a tab is reloading, I mean actual page reload?
I see chrome.tabs.onUpdated event, but for this event status is 'loading' even in case of AJAX calls from a webpage.
How can I detect a page is getting reloaded ?
You are right, looks like not possible to recognize AJAX and page reload calls. As workaround you could listen for onunload event for tab webpage. You probably need to check if tabid and url were not changed after that.
But do you really need to know if page reloaded?
It's an old question, but here is my solution that could be in help (without AIAX).
Since the method 'chrome.tabs.get()' return a promise, you can use the 'callback function' to check the current 'tab.status'.
Setting a boolean variable 'waitingForComplete = true', you will run your code, only when the tab will return at status = 'complete'.
background.js
var waitingForComplete = false;
chrome.tabs.onUpdated.addListener((tabId. changeInfo,tab) => {
if(changeInfo.status == 'complete'){
if(waitingForComplete){
waitingForComplete = false;
// runYourCode...
}
}
};
function checkTabStatusComplete(tabId){
chrome.tabs.get(tabId. function(tab){
if(tab.status == 'complete'){
// runYourCode...
} else {
waitingForComplete = true;
}
}
};
I have a Chrome extension (specifically, a "content script") where I'd like to detect whether the page I am monitoring/changing is in fullscreen state. I have tried several APIs, as well as the "screenfull" library, but no luck so far. Any ideas?
Thanks for your help!
If you want to detect whether the page has used the Fullscreen API to enter fullscreen mode, just check document.webkitIsFullscreen.
If you want a general method to reliably detect full screen mode, the chrome.windows API is your only option. Since this API is unavailable to content scripts, you need to use the message passing API to interact with a background or event page.
Example: content script
function isFullScreen(callback) {
chrome.runtime.sendMessage('getScreenState', function(result) {
callback(result === 'fullscreen');
});
}
// Example: Whenever you want to know the state:
isFullScreen(function(isFullScreen) {
alert('Window is ' + (isFullScreen ? '' : 'not ') + 'in full screen mode.');
});
Example: background / event page
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (message === 'getScreenState') {
chrome.windows.get(sender.tab.windowId, function(chromeWindow) {
// "normal", "minimized", "maximized" or "fullscreen"
sendResponse(chromeWindow.state);
});
return true; // Signifies that we want to use sendResponse asynchronously
}
});
You can try something like this:
var isFullScreen = (screen.width == window.outerWidth) && (screen.height == window.outerHeight);
if(isFullScreen) {
// ...
}
The simplest way is to listen for webkitfullscreenchange event, e.g
$(document).on('webkitfullscreenchange',function(){
if (document.webkitIsFullScreen === true) {
console.log('Full screen mode is on");
} else {
console.log('Full screen mode is off");
}
});
I'm not good at JS and I'm having some -I hope- stupid problem I'm not seeing on my code... if you guys could help me out, I'd really appreciate it.
My extension does some stuff with the current tab's URL. It worked ok using the onUpdate event on my background page, setting the tab's URL on a variable and then I used it on a pop-up.
The thing is that if the user starts, selecting different tabs, without updating the URLs my event won't be triggered again... so I'm now also listening to the onSelectionChanged event.
The thing is that there's no "tab" object within the onSelectionChanged event's parameters, so I cannot ask for the tab.url property.
I tried to use the chrome.tabs.getCurrent() method, but obviously I'm doing something wrong... and I reached the limit of my -very little- knowledge.
Here's the code, if you guys could take a look and point me in the right direction, I'll really appreciate it.
<script>
var tabURL = '';
var defaultURLRecognition = [ "test" ];
// Called when the url of a tab changes.
function checkForValidUrl(tabId, changeInfo, tab) {
//THIS IS WHAT'S NOT WORKING, I SUPPOSE
if (tab==undefined) {
chrome.tabs.getCurrent(function(tabAux) {
test = tabAux;
});
}
//
// If there's no URLRecognition value, I set the default one
if (localStorage["URLRecognition"]==undefined) {
localStorage["URLRecognition"] = defaultURLRecognition;
};
// Look for URLRecognition value within the tab's URL
if (tab.url.indexOf(localStorage["URLRecognition"]) > -1) {
// ... show the page action.
chrome.pageAction.show(tabId);
tabURL = tab.url;
}
};
// Listen for any changes to the URL of any tab.
chrome.tabs.onUpdated.addListener(checkForValidUrl);
// Listen for tab selection changes
chrome.tabs.onSelectionChanged.addListener(checkForValidUrl);
</script>
I would do something like this:
function checkForValidUrl(tab) {
//...
}
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
if(changeInfo.status == "loading") {
checkForValidUrl(tab);
}
});
chrome.tabs.onSelectionChanged.addListener(function(tabId, selectInfo){
chrome.tabs.getSelected(null, function(tab){
checkForValidUrl(tab);
});
});
This is the code which i used for window.onbeforeunload
<head>
<script>
window.onbeforeunload = func;
function func()
{
var request = new XMLHttpRequest();
request.open("POST", "exit.php", true);
request.onreadystatechange = stateChanged;
request.send(null);
}
function stateChanged()
{
if (request.readyState == 4 || request.readyState == "complete")
alert("Succes!");
}
</script>
</head>
this works with IE and Mozilla but does not work with Chrome..... please help......
thanks in advance.....
It seems that the only thing you can do with onbeforeunload in recent version of Chrome is to set the warning message.
window.onbeforeunload = function () {
return "Are you sure";
};
Will work. Other code in the function seems to be ignored by Chrome
UPDATE: As of Chrome V51, the returned string will be ignored and a default message shown instead.
Know I'm late to this, but was scratching my head why my custom beforeunload message wasn't working in Chrome and was reading this. So in case anyone else does the same, Chrome from Version 51 onwards no longer supports custom messages on beforeunload. Apparently it's because the feature has been misused by various scams. Instead you get a predefined Chrome message which may or may not suit your purposes. More details at:
https://developers.google.com/web/updates/2016/04/chrome-51-deprecations?hl=en#remove-custom-messages-in-onbeforeload-dialogs
Personally do not think the message they've chosen is a great one as it mentions leaving the site and one of the most common legitimate uses for onbeforeunload is for dirty flag processing/checking on a web form so it's not a great wording as a lot of the time the user will still be on your site, just have clicked the cancel or reload button by mistake.
You should try this:
window.onbeforeunload = function(e) {
e.returnValue = 'onbeforeunload';
return 'onbeforeunload';
};
This works on latest Chrome. We had the same issue the e.returnValue with value of onbeforeunload solved my problem.
Your code should be like this:
<head>
<script>
window.onbeforeunload = function(e) {
e.returnValue = 'onbeforeunload';
func();
return ''onbeforeunload'';
};
function func()
{
var request = new XMLHttpRequest();
request.open("POST", "exit.php", true);
request.onreadystatechange = stateChanged;
request.send(null);
}
function stateChanged()
{
if (request.readyState == 4 || request.readyState == "complete")
alert("Succes!");
}
</script>
</head>
Confirmed this behavior on chrome 21.0.1180.79
this seems to work with the same restritions as XSS, if you are refreshing the page or open a page on same domain+port the the script is executed, otherwise it will only be executed if you are returning a string (or similar) and a dialog will be shown asking the user if he wants to leans or stay in the page.
this is an incredible stupid thing to do, because onunload/onbeforeunload are not only used to ask/prevent page changes.
In my case i was using it too save some changes done during page edition and i dont want to prevent the user from changing the page (at least chrome should respect a returning true or change the page without the asking if the return is not a string), script running time restrictions would be enought.
This is specially annoying in chrome because onblur event is not sent to editing elements when unloading a page, chrome simply igores the curent page and jumps to another. So the only change of saving the changes was the unload process and it now can't be done without the STUPID question if the user wants to change it... of course he wants and I didnt want to prevent that...
hope chrome resolves this in a more elegant way soon.
Try this, it worked for me:
window.onbeforeunload = function(event) {
event.returnValue = "Write something clever here..";
};
Try this. I've tried it and it works. Interesting but the Succes message doesn`t need confirmation like the other message.
window.onbeforeunload = function()
{
if ( window.XMLHttpRequest )
{
console.log("before"); //alert("before");
var request = new XMLHttpRequest();
request.open("POST", "exit.php", true);
request.onreadystatechange = function () {
if ( request.readyState == 4 && request.status == 200 )
{
console.log("Succes!"); //alert("Succes!");
}
};
request.send();
}
}
None of the above worked for me. I was sending a message from the content script -> background script in the before unload event function. What did work was when I set persistent to true (in fact you can just remove the line altogether) in the manifest:
"background": {
"scripts": [
"background.js"
],
"persistent": true
},
The logic is explained at this SO question here.
Current versions of Chrome require setting the event's returnValue property. Simply returning a string from the event handler won't trigger the alert.
addEventListener('beforeunload', function(event) {
event.returnValue = 'You have unsaved changes.';
});
I'm running Chrome on MacOS High Sierra and have an Angular 6 project whithin I handle the window.beforeunload an window.onbeforeunload events. You can do that, it's worked for me :
handleUnload(event) {
// Chrome
event.returnValue = true;
}
It show me an error when I try to put a string in event.returnValue, it want a boolean.
Don't know if it allows custom messages to display on the browser.
<script type="text/javascript">
window.addEventListener("beforeunload", function(e) {
e.preventDefault(); // firefox
e.returnValue = ''; // Chrome
});
</script>