How can I open multiple times new tab in chrome using window.open with for loop?
example:
const openFollowedProfiles = () => {
for (const profile of store.followed){
console.log(profile)
window.open(profile, '_blank');
}
};
Due to security reasons, you can't open multiple windows at once.
Each time you want to create a new window you must get user's interaction with a site ("click" event for example).
Related
On my chrome extension, I have a popup page and a background script.
As default, when I click on the extension's icon in two different windows, a popup will open in both windows.
I want to limit the amount of popups opened by the extension to be at most one at a time.
Here's how the full scenario that I'm trying to create:
At first no pop up is activated.
Window A opened a popup.
Window B opened a popup, in which case, Window A's popup will close.
Window C is created, go to 2, but this time Window A<-Window B and Window B<-Window C
If in any time The only popup that is open was closed, return to 1.
I know that a popup windows was created because I have a simple port connection that is invoked on the popup startup. Thus, the background is in theory aware of all popup windows that are created, namely, that is the code that I run in the popup to connect:
const port = chrome.runtime.connect({ name: 'popup-communications' });
I attempted to solve the problem in 3 ways, all of them failed.
Attempt 1
Hold the last popup that was connected. If a new one appears, close the old one before you save the new one. Use chrome.extension.getViews to get the new port. I imagined this would work, but rapid clicks on the extension icon (to invoke browserAction) makes this popUp state confused.
let popUp;
chrome.runtime.onConnect.addListener(function connect(port) {
if (port.name === 'popup-communications') {
// attempt 1
if (popUp) {
popUp?.close?.();
popUp = null;
console.log('removed old pop up');
}
[popUp] = chrome.extension.getViews({
type: 'popup',
});
});
Attempt 2
Close all popups that received from chrome.extension.getView, but the last one. The problem with this approach is that the chrome.extension.getView does not guarantee any order.
let popUp;
chrome.runtime.onConnect.addListener(function connect(port) {
if (port.name === 'popup-communications') {
// attempt 2
const popUps = chrome.extension.getViews({
type: 'popup',
});
console.log(popUps);
for (let i = 0; i < popUps.length - 1; i++) {
popUps[i].close();
}
});
I also experimented with chrome.browserAction.disable and chrome.browserAction.enable. This solution maintains indeed maintains 1 popup at all time, but I want it the popup to be available whenever I click on the extension icon, and this will not happen with this approach (instead I will need to find the relevant window with this popup)
Is there a way to achieve what I'm trying to do here?
I was able to achieve this behavior in the following way.
background.js
The background listens to connecting popups.
When a popup connects, it will broadcast a message to all open popups to close. Note this message is not sent over the port since the port connection does not broadcast.
There should exist a way to optimize, since at most one other popup can be open, but I will leave that for another time and prefer not to create global variables.
chrome.runtime.onConnect.addListener(function connect(port) {
if (port.name === 'popup-communications') {
port.onMessage.addListener(function (msg) {
if (msg.here) {
const activeTabId = msg.here;
// broadcast close request
chrome.runtime.sendMessage({closeUnmatched: activeTabId});
}
});
}
});
popup.js
Perform a lookup of its tab id.
Add a message listener to know when to close. If the message to close does not match current tab id, popup will close. window.close() is sufficient to close a popup.
"announce" to background that popup is ready by sending the tab Id over the port.
async function getCurrentTab() {
let queryOptions = {active: true, currentWindow: true};
let [tab] = await chrome.tabs.query(queryOptions);
return tab;
}
function addListener(myTabId) {
chrome.runtime.onMessage.addListener(function (msg) {
if (msg.closeUnmatched && msg.closeUnmatched !== myTabId) {
window.close();
}
});
}
(async function constructor() {
const port = chrome.runtime.connect({name: 'popup-communications'});
// whoami lookup
const {id: myTabId} = await getCurrentTab();
// add handler to self-close
addListener(myTabId);
// tell background I'm here
port.postMessage({here: myTabId});
// do whatever with port..
}());
I assume steps 1-3 can be done faster than user switching tabs/windows to activate another popup. The port connection was complicating things, but I left it in the answer, since you may have a use case for it.
I want to enforce a Single Instance for my electron app. When a user clicks the app shortcut icon on Windows, I want to enforce the single instance, but still open up a new window on the main instance when this happens.
All other current solutions seem to just quit the new instance and refocus the current instance.
const singleInstanceLock = app.requestSingleInstanceLock();
if (!singleInstanceLock) {
app.exit();
} else {
app.focus();
}
app.on('second-instance', (_event: Electron.Event, argv: string[]) => {
app.focus();
// code to open up second window lives here. As far as I can tell, it doesnt get called
});
app.exit(); Is a more severe way of quitting an app which quits all the instances of Electron instead of just the current one.
Try using app.quit() instead.
Also, separately, I'd re-arrange your code so it's like this:
const singleInstanceLock = app.requestSingleInstanceLock();
if (!singleInstanceLock) {
app.quit();
} else {
app.on('second-instance', (_event: Electron.Event, argv: string[]) => {
app.focus();
// Code to open up second window goes here.
});
}
Replacing your first app.focus() with the app.on('second-instance'.
This is because you're running app.requestSingleInstanceLock() when the app first starts (as it should), but doing app.focus() wouldn't do anything since the app was only just opened, and there wouldn't be any windows to focus.
So lately I have been learning JS and trying to interact with webpages, scraping at first but now also doing interactions on a specific webpage.
For instance, I have a webpage that contains a button, I want to press this button roughly every 30 seconds and then it refreshes (and the countdown starts again). I wrote to following script to do this:
var klikCount = 0;
function getPlayElement() {
var playElement = document.querySelector('.button_red');
return playElement;
}
function doKlik() {
var playElement = getPlayElement();
klikCount++;
console.log('Watched ' + klikCount);
playElement.click();
setTimeout(doKlik, 30000);
}
doKlik()
But now I need to step up my game, and every time I click the button a new window pops up and I need to perform an action in there too, then close it and go back to the 'main' script.
Is this possible through JS? Please keep in mind I am a total javascript noob and not aware of a lot of basic functionality.
Thank you,
Alex
DOM events have an isTrusted property that is true only when the event has been generated by the user, instead of synthetically, as it is for the el.click() case.
The popup is one of the numerous Web mechanism that works only if the click, or similar action, has been performed by the user, not the code itself.
Giving a page the ability to open infinite amount of popups has never been a great idea so that very long time ago they killed the feature in many ways.
You could, in your own tab/window, create iframes and perform actions within these frames through postMessage, but I'm not sure that's good enough for you.
Regardless, the code that would work if the click was generated from the user, is something like the following:
document.body.addEventListener(
'click',
event => {
const outer = open(
'about:blank',
'blanka',
'menubar=no,location=yes,resizable=no,scrollbars=no,status=yes'
);
outer.document.open();
outer.document.write('This is a pretty big popup!');
// post a message to the opener (aka current window)
outer.document.write(
'<script>opener.postMessage("O hi Mark!", "*");</script>'
);
// set a timer to close the popup
outer.document.write(
'<script>setTimeout(close, 1000)</script>'
);
outer.document.close();
// you could also outer.close()
// instead of waiting the timeout
}
);
// will receive the message and log
// "O hi Mark!"
addEventListener('message', event => {
console.log(event.data);
});
Every popup has an opener, and every different window can communicate via postMessage.
You can read more about window.open in MDN.
I use a few state variables to determine which sites should be opened in new tabs (or maybe a new window if tabs aren't possible) with a single button click. However, window.open() only opens the first link.
In this code I tried pushing the target sites to an array and running .forEach and .map on the array items.
open_selected_websites() {
const sites_to_open = [];
// check each property for true and array.push if so
this.final_social_media_site_selections.facebook && sites_to_open.push('http://facebook.com');
this.final_social_media_site_selections.twitter && sites_to_open.push('http://twitter.com');
this.final_social_media_site_selections.linkedin && sites_to_open.push('http://linkedin.com');
this.final_social_media_site_selections.instagram && sites_to_open.push('http://instagram.com');
this.final_social_media_site_selections.pinterest && sites_to_open.push('http://pinterest.com');
console.log(sites_to_open); // all observables are true and all sites appear in the array.
sites_to_open.forEach((social_media_site) => {
// setTimeout(() => {
window.open(social_media_site);
// }, 500)
})
In both cases, facebook loaded in a new tab. It is the first array item.
Then I tried adding a setTimeout to see if some time space might affect things. No, still only Facebook.
Then I tried testing only one site in each function:
<Button
size='huge'
color='orange'
onClick={ () => {
// final_edits_store.open_selected_websites();
final_edits_store.test_to_open_twitter();
final_edits_store.test_to_open_facebook();
} }
>
Copy Text and Open Social Media Sites in New Tabs
</Button>
In this case Twitter opened. The twitter function was listed first.
Does anyone know what is causing window.open() not to fire multiple times? And how to overcome this limit?
You can't.
Browsers only allow a single window to be triggered from a given user interaction.
This is a security feature to prevent websites bombing the user with vast numbers of new windows.
jsFiddle here - https://jsfiddle.net/523bLxf4/12/
Try the name parameter that window.open takes. I was able to open multiple windows.
Instead of window.open(social_media_site); try window.open(social_media_site, social_media_site);
In the name parameter use some tag that uniquely identifies the window.
Do we have to create new popup if google crome updated or we can continue with the older one.
No one is sure what you're asking, but I'm going to take a stab at it. I believe you're asking if you have to use a new popup every time an advertisement is changed? If that is the case, the answer is no, you don't always have to have a new popup. HOWEVER, if the window was closed by the user, a new popup will have to be created. The following code will bring a named window to the front:
function GetAdWindow() {
// Change the window.open parameters to your liking
var AdWindow = window.open("", "AdWindow", "toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=no,width=500,height=500");
return AdWindow;
}
After that, you have to determine if the page is blank, or already has an advertisement on it.
function UpdateAd(){
var AdWindow = GetAdWindow();
// If the AdWindow wasn't populated (meaning it was closed)
if (AdWindow.location.href === "about:blank") {
AdWindow.location = /*ADVERTISEMENT URL*/
} else {
// DO WHATEVER YOU WANT IF THE WINDOW HAD CONTENT
}
}
If you asking if your popup will go away if Chrome has an update, the answer is yes. Chrome as a whole will shot down and close all of the windows, then start back up clean.