I'd like to understand how can I make changes to the HTML of popup.html in a Chrome extension that reloads a given URL every x seconds and looks for a certain text in the webpage.
More precisely: the extension's UI has two buttons "Run" and "Stop", respectively running and stopping the reload-and-search function above.
I also wanted to include in the UI a "loading" gif to display when the user clicks on the "Run" button and the extension is searching for the text. The loading gif should disappear either when the user clicks on the "Stop" button (and the extension stops searching) or when the the text is found on the target website.
The loading gif is inside an invisible with id="searching" in popup.html:
<div id="searching" style="display: none;" align="center"><img src="loading.gif" style="width: auto; height: 30%"/></div>
and I tried to reach the desired outcome by adding in app.js two functions that change its attributes, as well as chrome.runtime.onMessage.addListener (in addition to backround.js):
function showSrc() {
document.getElementById('searching').style.display ='block';
}
function hideSrc() {
document.getElementById('searching').style.display ='none';
}
document.querySelector('.button-run').addEventListener('click', () => {chrome.runtime.sendMessage('start'); showSrc();});
document.querySelector('.button-stop').addEventListener('click', () => {chrome.runtime.sendMessage('stop'); hideSrc();});
chrome.runtime.onMessage.addListener(function(message, callback){
if(message === 'stop') {
hideSrc();
} else if(message === 'run') {
showSrc();
}
});
As you can see from app.js, when the user clicks on "Run" or "Stop", the script not only sends the respective messages to background.js for the extension to perform/stop its reload-and-search function, but also changes the attribute of the with id="searching" so that the loading gif is visible/invisible in the UI accordingly by calling showSrc() or hideSrc(), respectively.
However, this works fine only when I stay with the UI open in the tab where I launch the script. If I switch the tab while the extension is running, then the UI (popup.html) closes and when I reopen it by clicking on the extension's icon, loading.gif is gone although the extension is still running.
How can I fix this?
Related
I am trying to build this chrome extension that only displays the popup when I am on a youtube video page. However, I am having a lot of difficulties doing this and used many approaches.
My latest approach is to use chrome.action.onClicked and check if the URL contains https://youtube.com/watch. Then I would use chrome.action.setPopup to my HTML file. This works on all pages until when I click on the extension while on a youtube video page, then it would just show on every single page.
Here is my background.js:
chrome.action.onClicked.addListener((tab) => {
console.log(tab.tabId);
if (tab.url.includes("https://www.youtube.com/watch") == true) {
chrome.action.setPopup({ tabId: tab.tabId, popup: "/Pages/index.html" });
} else if (tab.url.includes("https://www.youtube.com/watch") == false) {
chrome.action.setPopup({ tabId: tab.tabId, popup: "" });
}
});
I think that it is not working because after setting the popup, that means it does not check the onClicked event anymore (specified here).
Any help would be much appreciated!
It's not tab.tabId but tab.id. You can check for it. And setPopup when onClicked, you have to click the extension twice will the popup show up.
I am working to create a Web Extension for both google chrome and Firefox.
Ultimately my goal is to open a file dialogue when I click on the context menu item added by my extension. However, there are two major problems when trying to do this.
The file dialogue must be opened by user action that activates an input element with type=file.
Context menu events are added and called from the background script of the extension.
Is there a silver bullet solution I am missing?
Failed Solutions
Background input element: Input elements will not function when used in the background script.
Message Passing (works on Chrome but not Firefox): Sending a message from the background to the content script keeps its user triggered status on chrome, but loses it in Firefox.
For those interested: this is the code that works in Chrome but not Firefox.
Background.js:
chrome.contextMenus.create({
title: "Clickme",
contexts:["image"], // ContextType
onclick: function(){sendMsg("openDialog")} // Called when clicked in menu
});
Content.js:
var fInput= document.createElement("input"); //hidden input to open filedialog
fInput.setAttribute("type", "file"); //opens files
fInput.setAttribute("id", "fileopeninput"); ////only useful for inspector debugging
///TAKE MESSAGE FROM Background
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if(request.msg === "openDialog"){
fInput.click(); //triggers open file dialogue
}
});
I'm building a chrome extension and every time the user click on the icon the popup.html page is loaded(reloaded). Is there a way to load the popup page only the first time, or to load it in the background?
Here is the code from my background script
var x=false;
chrome.browserAction.onClicked.addListener(function(tab) {
if(x==false){
alert("test");
chrome.browserAction.setPopup({popup: "popup.html"});
}
});
So the alert("text") is triggered only one time, but the popup.html is changed every time I click the icon. In popup.html I simply generate a different random number.
document.addEventListener('DOMContentLoaded', function () {
document.getElementById("test").innerHTML=Math.random();
});
Thanks
Everytime a users clicks the browserAction button chrome will open or close the attached popup. There is no way to stop it.
I have a notification functionality in my chrome extension which is managed by a background page (background.html)
This page calls the setNotificationDelay() function which is basically a deletion of the previous timer followed by a setTimeOut.
function setNotificationDelay() {
clearNotificationTimer();
newDelay = getNotificationDelay()
notificationTimer = setTimeout(showNotification, newDelay);
}
}
I have also an options.html page which allows the configuration of the notification hour. I want to modify the background timeout when the configuration is modified, but when I call the setNotificationDelay() from the Option page it doesn't work, and I presume it's because the scope of the timers are attached to the parent page.
If I let the Option page opens the timeout is triggered, if I close it the notification never happened.
How can I attach this timer to the background page ?
Is there a better way to achieve it ?
Thanks.
EDIT: The chrome.extension have the getBackground page method which returns the window object for the background page:
function setNotificationDelay() {
clearNotificationTimer();
newDelay = getNotificationDelay()
notificationTimer = chrome.extension.getBackgroundPage().setTimeout(showNotification, newDelay);
}
}
options.js is only active while the options.html page is open, and I presume you don't want to leave the page open while you're waiting for the notification. What you want (I think) is to have background.js set the notification (both background.js and options.js access the same string variable localStorage.yourNotificationDelay).
One thing to watch out for is that if you are using event pages instead of background pages, a notification of more than a few seconds won't happen because Chrome will unload the background page. In that case, you'll need to use alarms instead.
Edit: Your edit makes me think I'm not understanding you. Perhaps you're expecting the user to change the interval while the timer is running? Then I'd recommend sending a message to background.js with newDelay, and use that to call setNotificationDelay().
I got this problem during development of my own addon, but I get the same with the reddit example, so I'll use that for simplicity.
Using the exact code from the example found here, this is what happens.
Reddit Example
This example add-on creates a panel containing the mobile version of Reddit. When the user clicks on the title of a story in the panel, the add-on opens the linked story in a new tab in the main browser window.
To accomplish this the add-on needs to run a content script in the context of the Reddit page which intercepts mouse clicks on each title link and fetches the link's target URL. The content script then needs to send the URL to the add-on script.
main.js:
var data = require("self").data;
var reddit_panel = require("panel").Panel({
width: 240,
height: 320,
contentURL: "http://www.reddit.com/.mobile?keep_extension=True",
contentScriptFile: [data.url("jquery-1.4.4.min.js"),
data.url("panel.js")]
});
reddit_panel.port.on("click", function(url) {
require("tabs").open(url);
});
require("widget").Widget({
id: "open-reddit-btn",
label: "Reddit",
contentURL: "http://www.reddit.com/static/favicon.ico",
panel: reddit_panel
});
panel.js:
$(window).click(function (event) {
var t = event.target;
// Don't intercept the click if it isn't on a link.
if (t.nodeName != "A")
return;
// Don't intercept the click if it was on one of the links in the header
// or next/previous footer, since those links should load in the panel itself.
if ($(t).parents('#header').length || $(t).parents('.nextprev').length)
return;
// Intercept the click, passing it to the addon, which will load it in a tab.
event.stopPropagation();
event.preventDefault();
self.port.emit('click', t.toString());
});
The icon is displayed in the bar, and clicking it launches the panel. Clicking a link within the panel opens it in a new tab - just as described and expected.
Clicking the "next page" link within the tab successfully fetches the next page, within the panel - as expected.
Clicking a link on the 2nd page does NOT open it in a tab, it opens it WITHIN the panel.
Here's my guess: When the page reloads within the panel, it does not reload the script specified in the contentScriptFile. Does anyone else experience this? And is there a workaround?
I'm using SDK 1.0 and FF 5.0
Question cross-posted on the Addon forum here
Recieved this answer at the Mozilla forum, and will post here as well for future reference.
Perhaps you are seeing Bug 667664 - Panel content scripts don't work after reloading or changing location. I think the workaround is to load the content in an iframe.
Which I believe might be the case, I'll try this during the day and report back.
EDIT: iframe seems to do the trick