Keywords: javascript | firefox-addon | browser-history | pushstate
Abstract: This article presents a method for detecting changes in browser history when using HTML5 history.pushState in combination with Ajax, addressing the limitation of onhashchange. By employing monkey-patching to modify history.pushState, developers can add custom pushstate events for reliable monitoring. The paper details the implementation, code examples, and practical applications in contexts like Firefox add-ons, while discussing the constraints of popstate events and updates to window.location.
Introduction
HTML5 introduced the history.pushState method, enabling websites to modify browser history without reloading pages, often combined with Ajax for enhanced user experiences. However, this approach poses a significant challenge: the traditional onhashchange event no longer detects these changes, which is problematic for applications, such as Firefox add-ons, that need to respond to history updates.
Problem Statement
The onhashchange event is typically used to detect URL fragment changes, but when applications use history.pushState to update history, this event is not triggered because the specification does not define any associated events. This necessitates a reliable method for detecting these changes to enable appropriate actions in web applications.
Solution
To solve this issue, we can use JavaScript monkey-patching to replace the window.history.pushState function with a custom one that adds a custom onpushstate event. This technique involves wrapping the original function to trigger the custom event before executing the standard operation. Firefox host objects are generally accommodating to such modifications, making this approach relatively straightforward.
Code Implementation
Based on the best answer, here is an implementation example that modifies history.pushState to check for and trigger onpushstate:
(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);In practice, you can set history.onpushstate to a function to handle history updates. Similarly, window.history.replaceState can be patched in the same way to support broader scenarios.
Discussion and Enhancements
This method is advantageous due to its practicality and broad compatibility, especially for Firefox add-on developers. Note that the popstate event is not triggered by pushState calls, as per its specification. Additionally, when using pushState, the window.location value does not update automatically; developers must handle this manually to ensure correct URL representation.
Conclusion
By monkey-patching history.pushState, developers can reliably detect history changes in HTML5 environments, supporting advanced Ajax applications. This approach is widely applicable in contexts like Firefox add-ons and single-page applications, providing a flexible solution for modern web development.