I’m trying to implement barba.js on a HubSpot
site.
Consider the following two pages:
- Resources
- Customers
With my current barba.js
implementation, this is the current flow I’m experiencing:
- I access the
resources
page (not by transitioning to it, by directly accessing it via/resources
). - At this point, all my
js
is working (slick-sliders
, scroll functions etc) - I then use the navigation to access the
customers
page. The page loads, but all of thejs
specific to modules and forms for that page are not working.
In short, js
for pages that I transition
to do not work.
To resolve this, what I’m trying to do is to reload all scripts
within the container
beforeEnter()
.
See below:
$(function() {
function delay(n){
n = n || 2000;
return new Promise((done) => {
setTimeout(() => {
done();
}, n);
});
}
barba.init({
sync: true,
prefetchIgnore: true,
debug: true,
transitions: [{
async leave(data){
const done = this.async();
await delay(200);
done();
},
async beforeEnter({ next, container }) {
$(container).find('script').each(function (i, script) {
var $script = $(script);
$.ajax({
url: $script.attr('src'),
cache: true,
dataType: 'script',
success: function () {
$script.trigger('load');
}
});
});
},
async enter(data){
let scrollX = 0
let scrollY = 0
barba.hooks.leave(() => {
scrollX = barba.history.current.scroll.x;
scrollY = barba.history.current.scroll.y;
});
window.scrollTo(scrollX, scrollY);
},
async once(data){
console.log("done");
},
}]
});
});
However, my current beforeEnter()
still yields the same results. Any way around this?
Edit
To provide more details, this barba.js
implementation is for a HubSpot
site. When you create custom modules
in HubSpot
it spits out the JS for that module on the page (in script
tags). For example, here is how JS is rendered on the page:
<script>
// js from custom module is here
</script>
<script src=".../scripts-min.min.js"></script>
As such, when a barba
transition is executed, I need all JS that have src
and those that are rendered inline (like custom modules) to reload.
Latest approach based on User863‘s feedback
$(function() {
function delay(n){
n = n || 2000;
return new Promise((done) => {
setTimeout(() => {
done();
}, n);
});
}
function reload_scripts(param){
$(param).find('script').each(function (i, script) {
var $script = $(script);
$.ajax({
url: $script.attr('src'),
cache: true,
dataType: 'script',
success: function () {
$script.trigger('load');
console.log("scripts loaded");
}
});
});
}
barba.init({
sync: true,
prefetchIgnore: true,
debug: true,
transitions: [{
async leave(data){
const done = this.async();
await delay(200);
done();
},
async beforeEnter(data) {
reload_scripts(data.next.container);
},
async beforeEnter({ next }) {
reload_scripts(next.container);
},
async enter(data){
// scroll to top of page when transitioning
let scrollX = 0
let scrollY = 0
barba.hooks.leave(() => {
scrollX = barba.history.current.scroll.x;
scrollY = barba.history.current.scroll.y;
});
window.scrollTo(scrollX, scrollY);
},
async once(data){
console.log("transition complete");
},
}]
});
});
Current behaviour: Same as before (scripts for modules are broken when page changes). Modules with slick slider
‘s for example, do not work (slick
isn’t initiated).
2
Answers
Might be solved by using
eval
as mentioned here: https://github.com/barbajs/barba/issues/32Mentioned in the comments on the issue:
According to docs
The arguments of
beforeEnter
transition will be object ofhttps://barba.js.org/docs/advanced/hooks/#data-properties
Therefore the
container
property available inside bothdata.current
anddata.next
properties. In this case, we have to use script fromdata.next
which related to a new page.Fixed code #1
Fixed code #2