barbajs / barba

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

reload scripts after page transition #432

Closed DemBrabus closed 5 years ago

DemBrabus commented 5 years ago

Alright Gang,

Im having fun with Barba/Core and look forward to Barba/head but am having a hard time reloading my scripts after a page transition.

I understand the nature of Barba and understand that i need to run a function within a hook (beforeEnter) OR use views: to specify what should happen at a given transition.

Im using parcel so all of my script files are imported into one file (index.js) and then injected to the DOM / *.html through one script tag. so really id like to be able to just reinitialize that one file(index.js) and hopefully have access to all my scripts through that one injection on all my .html pages. please correct me if my thinking is wrong**.

Im using GSAP for my page transitions and smoothing scrolling on all of my pages along with some other JS functionalities that i would like to have access to on all my pages. I have provided what i believe is all the relevant code below. im obviously doing something wrong and cant seem to figure this out, any help would be greatly appreciated and you shall surely be blessed 🙏🏼 lol


//---- index.html script tag

<script src="index.js" defer></script>
 </ body>
 </html>

//---- index.js

import $ from 'jquery';
import BarbaCore from './scripts/Transition/Barba-Core';
import MobileNav from './scripts/MobileNav/MobileNav';
import Scroll from './scripts/Scroll/Scroll';

//---- Transition.js - Barba code

import $ from 'jquery';
import barba from '@barba/core';
import TimelineMax from 'gsap/TimelineMax';
import TweenMax from 'gsap/TweenMaxBase';
import ScrollScript from '../Scroll/Scroll';

barba.init({

  views: [{
    namespace: 'gallery',
    beforeEnter({ next }) {
      let script = document.createElement('script');
      script.src="/index.js";        <--- my src might be an issue, ive tried different ones.**
      next.container.appendChild(script);
    }
  }],

  transitions: [{
    name: 'Core-Transition',
    leave: function(data) {
      const done = this.async();
      const TransitionTl = new TimelineMax();
            TransitionTl
                .set(Slide1, {display: 'flex', bottom: '-100%'}, 'wave1')
                .add('wave2')
                .fromTo(Slide1, .8, {bottom: '-100%', ease: Expo.easeInOut}, {bottom: 0, ease: Expo.easeInOut}, 'wave2')
                .to(data.current.container, 1, {
                    opacity: 0,
                    onComplete: done
                })
                .to(Slide1, 1, {bottom: '100%', ease: Expo.easeInOut}, '+=.4')
                .set(Slide1, {display: 'none', bottom: '-100%'})
            ;
    },

    beforeEnter({ next }) {
      let script = document.createElement('script');
      script.src="/src.e31bb0bc.js";   <--- my src might be an issue, ive tried different ones.**
      next.container.appendChild(script);
    },

    enter: function(data) {
      const done = this.async();
      TweenMax.from(data.next.container, 1, {
        opacity: 0,
        onComplete: done
      });
    }
  }]
});

** i have tried to use just views and just the beforeEnter Hook.

Maybe im just not understanding how to properly use the hooks or view, or maybe my function to inject a script tag is wrong.

please help my fellow devs. 😩 im dying here!

JayBox325 commented 5 years ago

This is something I'm currently looking into. For Barba 1, it used to be:

Barba.Dispatcher.on('newPageReady', function(currentStatus, oldStatus, container) {
  // Re initialising scripts when the next page has loaded but not shown
});

And this worked a treat. I'm keen to learn how this has been updated with Barba 2. Watching this ticket.

thierrymichel commented 5 years ago

Hi all (@DemBrabus, @JayBox325 ),

With v2, you can use global hooks. For example:

barba.hooks.beforeEnter((data) => {
  // this hook will be called during every transitions
  // before new page content enter…
});
DemBrabus commented 5 years ago

@thierrymichel Gotcha okay thank you, and what method of re-initializing a script tag would you recommend?

thierrymichel commented 5 years ago

@DemBrabus As you mentioned, there is a @barba/head plugin planned to manage those kind of situations (you can follow it here).

In the meantime, you can use an "evil eval" >_< or manually append your script tag… But, if possible, I will prefer no script tags and using code + hooks or views…

prilcool commented 4 years ago

Hi can you give an example on how to reinitialize a script .

for example how do i reinitialize this :

please help me ..

barba.hooks.beforeEnter((data) => { // this hook will be called during every transitions // before new page content enter… });

Manu10744 commented 4 years ago

@prilcool I would also appreciate an example. This is literally driving me crazy. I have tried to fetch all script src strings from container of the next page, then make an AJAX Request for those src's, create a script for each and insert it into the DOM, but still no custom JS works after page has been changed.

seojake commented 1 year ago

Late response, but I was quizzed on this too - and thought I'd comment a solution anyway as other people may be in the same boat.

The best thing to do here is to use a class, and ensure you're initialising Barba.js outside of the class. Then you can simply call your class on the beforeEnter hook.

yCodeTech commented 1 year ago

For future Googler's, I've implemented some code to allow a WordPress site (with Bedrock, Sage and Blade) to update it's scripts according to the next page.

In the file app.blade.php (the same file as you'd add the data-barba stuff), all enqueued scripts are outputted by wp_footerfunction, so you can just wrap this in a div with an ID.

<!doctype html>
<html {!! get_language_attributes() !!}>
@include('partials.head')

<body @php body_class() @endphp data-barba="wrapper">
    @php do_action('get_header') @endphp
    @include('partials.header')

    <main class="main" data-barba="container" data-barba-namespace="{{ $post->post_name }}">
        @yield('content')
    </main>
    @if (App\display_sidebar())
        <aside class="sidebar">
            @include('partials.sidebar')
        </aside>
    @endif

    @php do_action('get_footer') @endphp
    @include('partials.footer')

    // The scripts
    <div id="scripts">
        @php wp_footer() @endphp
    </div>

</body>
</html>

Then in the main.js file, you hook into barba's global beforeEnter as mentioned in other comments, and get the contents of the next page #scripts and replace the current ones.

barba.hooks.beforeEnter(({ current, next }) => {
    let nextHtml = next.html;
    // Get next page scripts.
    const nextScripts = $(nextHtml).filter("#scripts");
    // Replace the current scripts with the new ones.
    $("#scripts").html(nextScripts.html());
});

Works like a dream!

Christophershivers commented 1 year ago

if you either don't care how long your code is or if it's short you can directly write the code in one of the hooks in order for your script to work. I copied my code from the script into the global enter hook, and every time I go on the page it works like it suppose to. I did it the other way of deleting the javascript file and then reinitializing it. But when I switched to asp.net it wouldn't work. So I just copied the code directly into a hook and it works.