barbajs / barba

Create badass, fluid and smooth transitions between your website’s pages
https://barba.js.org/
MIT License
11.64k stars 474 forks source link

Dealing with inline scripts #485

Closed pedrofmiguel closed 4 years ago

pedrofmiguel commented 4 years ago

I'm using barba js on a wordpress website , and I'm trying to load inline <script> on a certain page but barba js doesn't seem to load them .... particularty a google maps map... I've read that one could use this code

   Barba.Dispatcher.on('newPageReady', function(currentStatus, oldStatus, container) {
            eval(container.querySelector("script").innerHTML);
          }); 

But it doesn't seem to work in v2. Maybe it's because of the syntax ? or the es6 ?

Currently this is my code, i've been searching for a solution all over issues in github but the solutions are only for the v1 version:

window.addEventListener('DOMContentLoaded', (event) => {
console.log('Barba Js Loaded')
    barba.init({
    transitions: [{
        name: 'legacy-example',
        leave: function(data) {

          var done = this.async();
          TweenMax.to(data.current.container, 1, {
            opacity: 0,
            onComplete: done
          });
        },
        enter: function(data) {
          var done = this.async();
          TweenMax.from(data.next.container, 1, {
            opacity: 0,
            onComplete: done
          });
        }
      }]
    });
});
xavierfoucrier commented 4 years ago

Hi @pedrofmiguel,

The code you are using is for BarbaJS v1: Barba.Dispatcher.on('newPageReady.., not the v2, that's why it doesn't work :wink:

For now, there is no fluent way to load inline script with Barba: we are working on @barba/head that will be able to update the <head> tag to automatically load scripts depending on the next page content.

But... if you need to load script for a specific page on your website, you should use Barba Views in the v2, in addition you will need some code to load your map.

Here is an example of what you can do:

import barba from '@barba/core';

barba.init({
  transitions: [{
    ...
  }]
  views: [{
    namespace: 'contact',
    beforeEnter({ next }) {

      // prevent Google Map API script from being loaded multiple times
      if (typeof window.createMap === 'function') {
        window.createMap();
      } else {
        window.createMap = () => {
          // create your map here using the Map API
          // Map, LatLng, InfoWindow, etc.
        };

        // load the Google Map API script
        let script = document.createElement('script');
        script.src = 'https://maps.googleapis.com/maps/api/js?key=KEY&callback=createMap';
        next.container.appendChild(script);
      }
    }
  }]
});

Assuming that contact is the namespace of the page that contain the map

Hope this help! :sunglasses:

pedrofmiguel commented 4 years ago

Yes thanks! i knew that it was a v1 script but i didn't know the equivalent in v2! 😃

pedrofmiguel commented 4 years ago

@xavierfoucrier one more thing namespace: 'contact', this is defined here right?

<div data-barba="container" class="barba-container" data-barba-namespace="contact">
xavierfoucrier commented 4 years ago

@pedrofmiguel yes :wink:

Glad to help! I am closing the issue.

danielpost commented 2 months ago

For those of you finding this issue because you're looking for @barba/head, this code should be a good approximation. It parses the HTML of the next page as well as the current page, loops through each element in <head>, and adds/removes any tags that are different between the pages:

import barba from '@barba/core';

const elementExistsInArray = ( element, array ) =>
    array.some( ( el ) => el.isEqualNode( element ) );

barba.init( {
    transitions: [
        {
            name: 'default-transition',
            leave() {
                // create your stunning leave animation here
            },
            enter() {
                // create your amazing enter animation here
            },
            beforeEnter( { next } ) {
                const nextElement = new DOMParser().parseFromString(
                    next.html,
                    'text/html'
                );

                const newHeadElements = [ ...nextElement.head.children ];
                const currentHeadElements = [ ...document.head.children ];

                // Add new elements that are not in the current head
                newHeadElements.forEach( ( newEl ) => {
                    if ( ! elementExistsInArray( newEl, currentHeadElements ) ) {
                        document.head.appendChild( newEl.cloneNode( true ) );
                    }
                } );

                // Remove old elements that are not in the new head
                currentHeadElements.forEach( ( currentEl ) => {
                    if ( ! elementExistsInArray( currentEl, newHeadElements ) ) {
                        document.head.removeChild( currentEl );
                    }
                } );
            },
        },
    ],
} );