I'm writing a Chrome extension that provides a content script to any page on GitHub (i.e. any URL matching https://github.com/*).
I'm simply trying to log something to the console each time a page on GitHub loads, like so:
window.onload = function() {
console.log("LOAD");
};
This listener function is executed the very first time a GitHub page is loaded, but if the user navigates to other pages on GitHub from there (by clicking on links or through other means), it doesn't fire. Why? :(
Steps to reproduce:
Open any repository's page on GitHub (example). You should see the message logged to the console.
Click on any link on that page. When the new page is loaded, no message is logged. :(
How do I solve this?
It seems that GitHub uses AJAX (along with history.pushState) to load some parts of the site, so onload will fire only when the page truly loads, but not when content is loaded via AJAX.
Since GitHub uses pushState to change the URL when AJAX content is done loading, you can detect when that happens, and execute your code.
There isn't actually a native event right now that fires when pushState is used, but there's this little hack:
(function(history){
var pushState = history.pushState;
history.pushState = function(state) {
if (typeof history.onpushstate == "function") {
history.onpushstate({state: state});
}
return pushState.apply(history, arguments);
}
})(window.history);
So, run that, and then, instead of window.onload, you can do:
history.onpushstate = function () {
console.log("LOAD");
};
Not ALL of GitHub page's load this way (AJAX + pushState), so you'd have to use both, window.onload and history.onpushstate.
Also, you should use window.addEventListener('load', fn); instead of window.onload, since you don't know if GitHub's code could be overwriting window.onload.
Related
I am trying to get some information from innerHTML from Youtube source page.
However, when I do this
var myStr = document.getElementById('player').innerHTML;
alert(myStr);
this only procs the alert if I visit the same Youtube page twice. If I navigate to a different video, no alert shows up, unless I refresh the page again.
I am also doing this:
if(document.readyState === 'loading') {
document.addEventListener("load", searchSomething, false);
} else {
searchSomething();
}
at the beginning of the Javscript just to make sure that I am getting the innerHTML after the whole page loads. What is the problem here? How do I fix this so that I do not have to refresh the page to proc the alert!
UPDATE ----------------------
I started to log every event that gets fired on Youtube.
However, Youtube does not fire any events including "load", "unload", "hashchange". It only fires Javascript events if you refresh the page!!!
How can this be possible?
If you use jquery it will be like this
$(document).ready(function() {
var myStr = document.getElementById('player').innerHTML;
alert(myStr);
}
I'm looking to load a banner once AddThis loads on the page, or when it becomes viewable. Unfortunately, everything I've tried has failed. Tried the suggested code from the site, but hasn't worked, just throws a referenceerror, and am not sure what to try next.
Here's the code from the site:
// Alert a message when the AddThis API is ready
function addthisReady(evt) {
alert('AddThis API is fully loaded.');
}
// Listen for the ready event
addthis.addEventListener('addthis.ready', addthisReady);
Here's the link to the page: AddThis JavaScript Events
Tanel is right. The problem is that addthis object has not been initialized before calling. Here's a simple solution, that I used for my website:
var addThisTimer = setInterval(function() {
if (typeof addthis !== 'undefined') {
clearInterval(addThisTimer);
addthis.addEventListener('addthis.ready', function() {
console.log('AddThis API is fully loaded.');
});
}
}, 100);
Have you actually initialized the addthis object before listening to the event? If not, that's most likely your problem.
Please write a function that stop load tab. To refresh a simple reload (); complaint is on the page sdk stopping function.
Use this code to stop the most recently used tab from loading its page. (note: the page has to be loading something)
const { getMostRecentBrowserWindow } = require('sdk/window/utils');
getMostRecentBrowserWindow().gBrowser.selectedBrowser.stop();
This one here reloads: getMostRecentBrowserWindow().gBrowser.selectedBrowser.reload();
I'm using programmatic injection to inject my extension's code into a page only when the browser action is clicked.
This is what I have on my extension's event page (per the example in the documentation):
chrome.browserAction.onClicked.addListener(function callback(tab){
chrome.tabs.executeScript(null, {file: "content-script.js"});
});
However, the way this works, the script is injected every time the button is clicked.
How can I change it so that the script is not injected on subsequent button presses - so that it is inserted only the first time the button is clicked on that page?
Put a global variable in your contentscript to judge if the contentscript has been executed.
if (something) { return; }
One way I can think of right now (easy and simple) is to use html5webstorage. Since you are running this code from your background or popup page it will be ok.
if(!localStorage.getItem("isAlreadyInjected")){
localStorage['isAlreadyInjected'] = "true";
chrome.browserAction.onClicked.addListener(function callback(tab){chrome.tabs.executeScript(null, {file: "content-script.js"});});}
So, the very first time when storage value "isAlreadyInjected" does not exist, the listener will be added. Afterwards, even when the browser closes and opens again this value will remain stored and so the listener will not be added to your extension.
UPDATE
As your background page loads only once at the beginning, it can keep variable that is not re-initialized with the browser action click. So you can use that variable to do your job!
background.js
var isAlreadyInjected =false;
function isInjected(){
if(!isAlreadyInjected ){
isAlreadyInjected=true;
return false;
}
else
return true;
}
popup.js
var bgpage=chrome.extension.getBackgroundPage();
if(!bgpage.isInjected()){
chrome.browserAction.onClicked.addListener(function callback(tab) {chrome.tabs.executeScript(null, {file: "content-script.js"});});
}
or
var bgpage=chrome.extension.getBackgroundPage();
chrome.browserAction.onClicked.addListener(function callback(tab) {
if(!bgpage.isInjected()){
chrome.tabs.executeScript(null, {file: "content-script.js"});
}});
I know this is an older question but I encountered the issue now that Manifest V3 is out and persistent background pages have been replaced with service workers. I figured I'd give what I used as a solution in case anyone else needs it. Code must be executed within the global context of the content script. Anytime it tries to inject it again, the relevant code will only be executed if the global variable is not defined.
if (typeof hasBeenExecuted === 'undefined') {
// Code that needs to execute only once goes here
}
var hasBeenExecuted = true;
Hopefully this is helpful for someone else who comes across the question.
When I use the back button on Firefox to reach a previously visited page, scripts on that page won't run again.
Is there any fix/workaround to have the scripts execute again when viewing the page the second time?
Please note that I have tested the same pages on Google Chrome and Internet Explorer and they work as intended.
Here are the files and the steps I used to test the problem:
(navigate to 0.html, click to get to 1.html, back button)
0.html
<html><body>
<script>
window.onload = function() { alert('window.onload alert'); };
alert('inline alert');
</script>
Click Me!
</body></html>
1.html
<html><body>
<p>Go BACK!</p>
</body></html>
Set an empty function to be called on window.onunload:
window.onunload = function(){};
e.g.
<html><body>
<script type="text/javascript">
window.onload = function() { alert('window.onload alert'); };
window.onunload = function(){};
alert('inline alert');
</script>
Click Me!
</body></html>
Source:
http://www.firefoxanswer.com/firefox/672-firefoxanswer.html (Archived Version)
When I use the back button on Firefox to reach a previously visited page, scripts on that page won't run again.
That's correct and that's a good thing.
When you hit a link in Firefox (and Safari, and Opera), it does not immediately destroy your page to go onto the next one. It keeps the page intact, merely hiding it from view. Should you hit the back button, it will then bring the old page back into view, without having to load the document again; this is much faster, resulting in smoother back/forward page transitions for the user.
This feature is called the bfcache.
Any content you added to the page during the user's previous load and use of it will still be there. Any event handlers you attached to page elements will still be attached. Any timeouts/intervals you set will still be active. So there's rarely any reason you need to know that you have been hidden and re-shown. It would be wrong to call onload or inline script code again, because any binding and content generation you did in that function would be executing a second time over the same content, with potentially disastrous results. (eg. document.write in inline script would totally destroy the page.)
The reason writing to window.onunload has an effect is that the browsers that implement bfcache have decided that — for compatibility with pages that really do need to know when they're being discarded — any page that declares an interest in knowing when onunload occurs will cause the bfcache to be disabled. That page will be loaded fresh when you go back to it, instead of fetched from the bfcache.
So if you set window.onunload= function() {};, what you're actually doing is deliberately breaking the bfcache. This will result in your pages being slow to navigate, and should not be used except as a last resort.
If you do need to know when the user leaves or comes back to your page, without messing up the bfcache, you can trap the onpageshow and onpagehide events instead:
window.onload=window.onpageshow= function() {
alert('Hello!');
};
You can check the persisted property of the pageshow event. It is set to false on initial page load. When page is loaded from cache it is set to true.
window.onpageshow = function(event) {
if (event.persisted) {
alert("From bfcache");
}
};
For some reason jQuery does not have this property in the event. You can find it from original event though.
$(window).bind("pageshow", function(event) {
if (event.originalEvent.persisted) {
alert("From bfcache");
}
});
In my case window.onunload with an empty function didn't help (I tried to set a value for dropdown when user uses backwards button). And window.onload didn't work for other reason - it was overridden by <body onload="...">.
So I tried this using jQuery and it worked like a charm:
$(window).on('pageshow', function() { alert("I'm happy"); });
Wire in an "onunload" event that does nothing:
<html><body>
<script type="text/javascript">
window.onload = function() { alert('window.onload alert'); };
window.onunload = function(){};
alert('inline alert');
</script>
Click Me!
</body></html>
As far as i know Firefox does not fire onLoad event on back.
It should trigger onFocus instead based from this link here.
A simple way to cause a page to execute JavaScript when the user navigates back to it using browser history is the OnPopState event. We use this to pause and replay the video on our home page (https://fynydd.com).
window.onpopstate = function() {
// Do stuff here...
};
for some cases like ajax operations url change listener can be used
$(window).on('hashchange', function() {
....
});