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).
CodePudding user response:
Might be solved by using eval
as mentioned here: https://github.com/barbajs/barba/issues/32
Mentioned in the comments on the issue:
barba.hooks.after((data) => {
let js = data.next.container.querySelectorAll('main script');
if(js != null){
js.forEach((item) => {
console.log(js)
eval(item.innerHTML);
});
}
});
CodePudding user response:
According to docs
The arguments of beforeEnter
transition will be object of
Property | Description |
---|---|
data.current | Current page related |
data.next | Next page related |
data.trigger | Link that triggered the transition |
https://barba.js.org/docs/advanced/hooks/#data-properties
Therefore the container
property available inside both data.current
and data.next
properties. In this case, we have to use script from data.next
which related to a new page.
Fixed code #1
async beforeEnter(data) {
$(data.next.container).find('script').each(function (i, script) {
// ...
})
}
Fixed code #2
async beforeEnter({ next }) {
$(next.container).find('script').each(function (i, script) {
// ...
})
}