I've made an extension for pandora.com and when the user clicks the extension icon it opens a new tab with pandora.
When pandora is already open in a new tab and the user clicks the extension, the extension will not open a new tab but I would like it to instead change the active tab to the tab with pandora already open.
This is what I have so far in my background page:
chrome.browserAction.onClicked.addListener(function(tab) {
var found = false;
chrome.tabs.query({}, function (tabs) {
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].url.search("pandora.com") > -1){
found= true;
}
}
if (found==false){
chrome.tabs.executeScript(null,{file: "buy.js"});
} else {
// Changes active tab to the tab with pandora open
}
});
});
UPDATE- chrome.tabs.update(tabId, {selected: true}); achieves what I needed. Here's the final code:
chrome.browserAction.onClicked.addListener(function(tab) {
var found = false;
var tabId;
chrome.tabs.query({}, function (tabs) {
for (var i = 0; i < tabs.length; i++) {
if (tabs[i].url.search("www.pandora.com/") > -1){
found = true;
tabId = tabs[i].id;
}
}
if (found == false){
chrome.tabs.executeScript(null,{file: "buy.js"});
} else {
chrome.tabs.update(tabId, {selected: true});
}
});
});
Seems like the selected property of the second argument of chrome.tabs.update has now been deprecated.
Using the active property is the new way to do it:
chrome.tabs.update(tabId, {active: true})
If the tab to be activated is in another window, you also need to change the active window to that window using chrome.windows.update:
chrome.windows.update(windowId, {focused: true}, (window) => {
chrome.tabs.update(tabId, {active: true})
})
Related
I'm creating a Firefox Extension. It opens a new tab and then closes it a moment later. When the new tab closes, I want to go back to the original tab I was on, NOT the rightmost tab. This is what I have so far and it always goes to the rightmost.
function openNewTab(tabs) {
let tab = tabs[0];
browser.tabs.create({"url": tab.url});
}
function closeTab(tabs) {
let tab = tabs[0];
browser.tabs.remove(tab.id);
}
function onError(err){
console.error(err);
}
function openAndClose() {
var mytab = browser.tabs.query({currentWindow: true, active: true}).then(openNewTab, onError);
setTimeout(function () {
var closeIt = browser.tabs.query({currentWindow: true, active: true}).then(closeTab, onError);
}, 1000);
}
browser.browserAction.onClicked.addListener(openAndClose);
Given a tab id, or tab index, how do I activate, or go to that specific tab?
You want the window & tab update functions. You can disregard focusing the window as long as you keep focus of the window when you create your new tab. (As currently shown in your code sample)
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/windows/update
https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/tabs/update
browser.tabs.query({}, function(tabs) {
for (var i=tabs.length-1; i>=0; i--) {
if (tabs[i].id == myTabID) {
browser.windows.update(tabs[i].windowId, {focused: true}); //focus window
browser.tabs.update(tabs[i].id, {active: true}); //focus tab
break;
}
}
});
I'm trying to build a chrome extension using the Chrome tabs API that will cycle through all of the open tabs in a window and refresh each one every n seconds. I'm having trouble iterating my for loop once every 5 seconds. I've tried a few different ways of setting timeouts and such but I'm either ending up with the loop not running at all, or I get an infinite loop. I'm new to javascript. Any help would be appreciated!
background.js
chrome.browserAction.onClicked.addListener(function(tab) {
// Send a message to the active tab
chrome.tabs.query({currentWindow: true}, function(tabs) {
var foundSelected = false;
(function switch() {
for(i = 0; i <= tabs.length; i++){
if(i == tabs.length){
i = 0;
}
if (tabs[i].active){
foundSelected = true;
}
// Finding the next tab
else if (foundSelected){
// Selecting the next tab.
chrome.tabs.update(tabs[i].id, {active: true});
chrome.tabs.reload(tabs[i].id);
setTimeout(switch, 5000);
}
}
})();
// var activeTab = tabs[0];
chrome.tabs.sendMessage(activeTab.id, {"message": "clicked_browser_action"});
});
});
content.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if( request.message === "clicked_browser_action" ) {
chrome.tabs.update(tabId, {selected: true});
}
}
);
I realize that there are already extensions out there that do this. I'm creating my own as a learning experience and for more control over functionality.
Create background.js like given below. I thnik it will work properly.
background.js
/* Below code start background.js when you start your browser
* and sw function work after every 5 second and reload every tab.
*/
function sw()
{
chrome.tabs.query({currentWindow: true},function(tabs){
var i=0;
console.log(tabs.length);
for(i=0;i<=tabs.length;i++)
{
chrome.tabs.reload(tabs[i].id);
}
})
};
setInterval(sw,5000);
This is the working solution.
chrome.browserAction.onClicked.addListener(function(tab) {
setInterval(function () {
chrome.tabs.query({currentWindow: true}, function(tabs) {
var foundSelected = false;
for(var i = 0; i <= tabs.length; i++){
if(i == tabs.length){
i = 0;
}
if (tabs[i].active){
foundSelected = true;
}
// Finding the next tab.
else if (foundSelected){
// Selecting the next tab.
chrome.tabs.update(tabs[i].id, {active: true});
chrome.tabs.reload(tabs[i].id);
return;
}
}
});
}, 5000);
});
I have the following code in popup.js which responds to a button press to get all the tabs, create a new tab (template.html), and send the tabs as an array to the new tab. Later I will delete the current tabs and display the links on one page to save space (That's the idea of the extension).
function saveAll() {
var openTabs = [];
chrome.tabs.query({}, function(tabs) {
for (var i = 0; i < tabs.length; i++) {
openTabs[i] = tabs[i];
}
createSavedPage(openTabs);
});
}
function createSavedPage(tabsToSave) {
chrome.tabs.create({
"url": chrome.extension.getURL("template.html"),
"active": false
},
function(tab) {
sendListToPage(tab, tabsToSave);
}
);
}
function sendListToPage(tab, tabsArray) {
chrome.tabs.sendMessage(tab.id, {
"action": "fill-list",
"data": tabsArray
});
}
var saveAllButton = document.getElementById("select-all-tabs");
saveAllButton.addEventListener("click", saveAll);
The tab that is created includes a template.js file:
function fillList(array) {
var list = document.getElementById("link-list");
for (var item in array) {
//Something
}
}
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.action == "fill-list") {
var data = request.data;
fillList(data);
}
}
);
When I create the new tab, the message is sent from the extension but never received. What is causing this issue?
I also thought that the message was being sent before the created tab was fully loaded. So I've changed popup.js by adding a chrome.tabs.onUpdated listener:
function createSavedPage(tabsToSave) {
chrome.tabs.create({
"url": chrome.extension.getURL("template.html"),
"active": false
},
function(tab) {
chrome.tabs.onUpdated.addListener(function(tabId, info) {
if (tabId == tab.id && info.status == "complete")
sendListToPage(tab, tabsToSave);
});
}
);
}
And it seems to solve the issue. Is there still a better way?
The code in buttonClicked() function and onTabCreate() function worked when the button is the BrowserAction icon.
But when I added a popup.html and created few buttons in it. When "Trello" button is clicked. I want the code in buttonClicked() to be executed, I put this code in eventPage.js.
The control is reaching the function, but I'm unable to capture the visible Tab now.
Why is it so? How can I fix this?
As evident from the code, imageData is holding the image of the tab (3rd line in buttonClicked())
The last 4th line in buttonClicked(), calls onTabCreate(). InonTabCreate(), I'm passing the imageData, but I'm not receiving the image.
I'll furnish more info if needed.
Thanks
buttonClicked()-
function buttonClicked() {
chrome.tabs.captureVisibleTab(null, {}, function (image) {
imageData = image;
createdTabUrl = chrome.extension.getURL('cardCreate.html');
chrome.tabs.query({ active: true }, function (tabs) {
var i, tab;
// Only select the current active tab, not any background tab or dev tools
for (i = 0; i < tabs.length; i += 1) {
// TODO: more robust way to check if current tab is a page from this extension (either when I get a static extension id or with a flag)
if (tabs[i].url.match(/^http/) || tabs[i].url.match(/^chrome-extension.*\/cardCreate\.html$/)) {
tab = tabs[i];
}
}
chrome.tabs.create({ url: createdTabUrl, index: (tab.index || 0) + 1 }, onTabCreated);
});
});
}
onTabCreate()-
// TODO: more robust way to send image data to page ?
function onTabCreated(tab) {
setTimeout(function (){
chrome.runtime.sendMessage({ imageData: imageData }, function(response) {
// Callback does nothing
});
}, 1000);
var views = chrome.extension.getViews();
for (var i = 0; i < views.length; i++) {
var view = views[i];
// If this view has the right URL and hasn't been used yet...
if (view.location.href == createdTabUrl) {
console.log("----------------------");
// console.log(view);
// console.log(view.location.href);
}
}
}
chrome.browserAction.onClicked.addListener(buttonClicked);
EDIT :
window.onload = function() {
document.getElementById('loginText').addEventListener('click', login);
document.getElementById('Trello').addEventListener('click', buttonClicked);
//listener for ButtonClick
// In popup.html , I included eventPage.js as well.
};
I have a web application that opens multiple windows. The problem that I have is that when the parent window is closed/refreshed, the child windows remain opened.
I've tried using onunload and onbeforeunload but none of them catches the window close event (in Chrome and Firefox).
I have an array of windows but after refresh the reference to them is lost.
Is there any other way to catch this event?
This is my code related to closing windows (running closeAll() outside unload and onbeforeunload closes all my opened window, but not when the page is refreshed):
window.unload = function() {
closeAll();
}
window.onbeforeunload = function() {
closeAll();
}
var closePopup = function(popup) {
removePopup(popup);
popup.close();
};
var closeAll = function() {
for (var popup in _this.popups) {
closePopup(_this.popups[popup]);
}
}
This works only in Chrome but not in Firefox and IE (latest versions).
use this
var popup = window.open("popup.html", "popup", "width=200,height=200");
window.onunload = function() {
if (popup && !popup.closed) {
popup.close();
}
};
If you open all child windows with window.open, include this javascript in all pages, then CloseAll(false); from any included page will close all child, grandchildren, great-grand... etc., and redirect the first (root) page to login.aspx, and will not interfere with any event triggers because it pases the intial handler through.
function CloseAll(bTopFound)
{
if (!bTopFound && nParent != null && !nParent.closed) {
//parent window was not closed
nParent.CloseAll(false);
return;
} else {
if (nParent == null || nParent.closed)
{
top.location = '/login.aspx';
}
}
for (var i = 0; i < Windows.length; i++)
{
if (!Windows[i].closed) {
Windows[i].CloseAll(true);
}
}
nParent = null;
setTimeout(window.close, 150);
}
var Windows = [];
//override window.open to inject store child window objects
window.open = function (open) {
return function (url, name, features) {
// set name if missing here
name = name || "default_window_name";
var newWindow = open.call(window, url, name, features);
Windows.push(newWindow);
return newWindow;
};
}(window.open);
var nParent = null;
window.onload = function (load) {
return function (e) {
nParent = window.opener;
if (load != null) {
load.call(e);
}
}
}(window.onload);
window.onunload = function (unload) {
return function (e) {
//promote first branch page to parent
if (nParent != null && !nParent.closed && Windows.length > 0) {
nParent.Windows.push(Windows[0]);
Windows[0].nParent = nParent;
}
//make first child window new root
for (var i = 1; i < Windows.length; i++) {
Windows[i].nParent = Windows[0];
Windows[0].Windows.push(Windows[i]);
}
if (unload != null) {
unload.call(e);
}
}
}(window.onunload);
Found a proper solution (jQuery) that works in the lastest versions of Chrome, Firefox and IE.
Initially wanted to use jQuery $().unload() function (http://api.jquery.com/unload/) but it's deprecated since 1.8 (http://bugs.jquery.com/ticket/11733). Since $().unload() is the shortcut for $().bind('unload', fn), I tried to use the basic one and it worked.
$(window).on('unload', function() {
closeAll();
});
If the goal is to close the child window when the parent is closed or refreshed, rather than actually detecting the event, you can use a setInterval to detect when the window.opener is no longer there.
function CloseOnParentClose() {
if (typeof window.opener != 'undefined' && window.opener != null) {
if (window.opener.closed) {
window.close();
}
}
else {
window.close();
}
}
$(window).ready(function () {
setInterval(CloseOnParentClose, 1000);
});