3

I'm trying to implement barba.js on a HubSpot site.

Consider the following two pages:

  1. Resources
  2. Customers

With my current barba.js implementation, this is the current flow I'm experiencing:

  1. I access the resources page (not by transitioning to it, by directly accessing it via /resources).
  2. At this point, all my js is working (slick-sliders, scroll functions etc)
  3. I then use the navigation to access the customers page. The page loads, but all of the js 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).

Freddy
  • 683
  • 4
  • 35
  • 114
  • Is the script with `src` are working? – User863 Jan 02 '22 at 11:24
  • 1
    @User863 - Yes, seems so. I have `js` that makes the `header` on scroll `fixed` and this `js` is executing when transitioning to another page. Just need a way to execute `js` on the page that has no `src` – Freddy Jan 02 '22 at 17:10

2 Answers2

0

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);
            });
    }
});
first last
  • 396
  • 2
  • 5
0

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) {
        // ...
    })
}
User863
  • 19,346
  • 2
  • 17
  • 41
  • Hi @User863 - slightly confused on the two "fixed code" approaches defined above, are you saying the the `AJAX` calls need to exist in both approaches? I've updated my question to showcase my current approach based on what I've interpreted from the above – Freddy Jan 01 '22 at 17:31
  • @Freddy Ofcourse `AJAX` calls are needed in both approaches. Also, any one approach is enough. – User863 Jan 02 '22 at 11:18