Why window.onhashchange
Doesn't Work in Tampermonkey
Tampermonkey, a popular browser extension for user scripts, can sometimes present unexpected behavior when dealing with JavaScript's window.onhashchange
event. This event is typically used to trigger actions when the URL's hash portion (the part after the # symbol) changes, but it doesn't function as expected within Tampermonkey scripts.
The Problem:
Imagine you have a Tampermonkey script that aims to listen for hash changes on a website and perform actions based on the new hash value. You might use the window.onhashchange
event to accomplish this. However, you'll find that the script fails to detect hash changes.
The Scenario:
Let's say you have the following Tampermonkey script:
// ==UserScript==
// @name Hash Change Listener
// @namespace http://tampermonkey.net/
// @version 1.0
// @description Tries to listen for hash changes
// @match *://*/*
// @grant none
// ==/UserScript==
window.onhashchange = function() {
console.log("Hash changed!");
console.log("New hash:", window.location.hash);
}
You expect this script to log "Hash changed!" and the new hash value whenever the URL's hash changes. However, the script remains silent, even when the hash is modified.
Why This Happens:
The reason lies in how Tampermonkey executes scripts. Tampermonkey runs user scripts in a separate isolated environment to maintain security and prevent conflicts with the website's JavaScript. This isolation prevents direct access to certain browser events, including window.onhashchange
.
The Solution:
To address this, you need to find an alternative approach to detect hash changes within Tampermonkey:
-
Use a Polling Mechanism: Create a function that periodically checks the current hash value and compares it to the previous value. If they differ, it indicates a hash change.
// ... let previousHash = window.location.hash; function checkHashChange() { const currentHash = window.location.hash; if (currentHash !== previousHash) { console.log("Hash changed!"); console.log("New hash:", currentHash); previousHash = currentHash; } } setInterval(checkHashChange, 100); // Check every 100 milliseconds
-
Utilize MutationObserver: Observe the changes to the
window.location
object, specifically thehash
property.// ... const observer = new MutationObserver(mutations => { mutations.forEach(mutation => { if (mutation.attributeName === 'hash') { console.log("Hash changed!"); console.log("New hash:", window.location.hash); } }); }); observer.observe(window.location, { attributes: true, attributeFilter: ['hash'] });
Additional Tips:
- Optimize Polling: Adjust the interval for
setInterval
based on the expected frequency of hash changes to balance performance and responsiveness. - Handle Navigation: Consider implementing checks to ensure that the hash change event wasn't triggered due to a page navigation.
In Conclusion:
While window.onhashchange
doesn't work directly in Tampermonkey scripts, you can effectively achieve the same functionality using alternative techniques like polling or MutationObserver. By understanding these limitations and adopting suitable solutions, you can successfully work with hash changes within your Tampermonkey scripts.