If you are integrating this code within a <script>
at the conclusion of the <body>
, there might not be a necessity to monitor for the turbolinks:load
event. Why? Upon initial loading, the browser will have the ability to retrieve any elements positioned prior to the script element. As Turbolinks loads scripts in the <body>
, they will possess access to all the rendered elements on the page.
It's important to note that by executing
document.addEventListener("turbolinks:load", …)
in a
<script>
element within the body, the listener will be activated on
every subsequent page load, not solely on the page where the script is displayed. In case the
#nav-tab
elements are absent during a subsequent page load, an error related to
querySelector
will be encountered. Moreover, if the script is incorporated on multiple pages, the listener will continuously duplicate, which may not align with your intentions!
To address this issue, the initial step involves removing the event listener. We shall encapsulate your code within an immediately invoked function to prevent contamination of the global scope:
;(function() {
let url = location.href.replace(/\/$/, "");
if (location.hash) {
const hash = url.split("#");
document.querySelector('#nav-tab a[href="#'+hash[1]+'"]').Tab.show();
url = location.href.replace(/\/#/, "#");
history.replaceState(null, null, url);
setTimeout(() => {
window.scrollTo(0,0);
}, 400);
}
})();
Another key aspect to consider is that Turbolinks maintains its own cache of visited pages, ensuring that when a user selects "Back," a page is retrieved from this cache. To accomplish this, it operates a mechanism for augmenting the browser's history
stack. If you circumvent the Turbolinks system and trigger history.replaceState
(or history.pushState
) manually, you risk disrupting the "Back" navigations. While Turbolinks lacks a documented method for manually enhancing its history stack, you can experiment with the following approach:
;(function() {
let url = location.href.replace(/\/$/, "");
if (location.hash) {
const hash = url.split("#");
document.querySelector('#nav-tab a[href="#'+hash[1]+'"]').Tab.show();
url = location.href.replace(/\/#/, "#");
Turbolinks
.controller
.replaceHistoryWithLocationAndRestorationIdentifier(url, Turbolinks.uuid())
setTimeout(() => {
window.scrollTo(0,0);
}, 400);
}
})();
Note that this technique is not officially documented, hence it may not remain accessible in forthcoming versions.
Lastly, it could prove beneficial to incorporate this snippet within your primary application JavaScript bundle and include it in the <head>
section instead of within the body. Under such circumstances, you might require utilizing a `turbolinks:load` handler. The implementation could resemble the following:
document.addEventListener('turbolinks:load', function () {
let url = location.href.replace(/\/$/, "");
const hash = url.split("#");
const navLink = document.querySelector('#nav-tab a[href="#'+hash[1]+'"]')
if (location.hash && navLink) {
navLink.Tab.show();
url = location.href.replace(/\/#/, "#");
Turbolinks
.controller
.replaceHistoryWithLocationAndRestorationIdentifier(url, Turbolinks.uuid())
setTimeout(() => {
window.scrollTo(0,0);
}, 400);
}
});