Giter Site home page Giter Site logo

Update body class? about barba HOT 32 CLOSED

barbajs avatar barbajs commented on May 17, 2024
Update body class?

from barba.

Comments (32)

dangelion avatar dangelion commented on May 17, 2024 19

I'm doing this with Barba v2

barba.hooks.afterLeave((data) => {
  // Set <body> classes for "next" page
  var nextHtml = data.next.html;
  var response = nextHtml.replace(/(<\/?)body( .+?)?>/gi, '$1notbody$2>', nextHtml)
  var bodyClasses = $(response).filter('notbody').attr('class')
  $("body").attr("class", bodyClasses);
});

Don't know if it's the best way but it seems work.

from barba.

nicooprat avatar nicooprat commented on May 17, 2024 16

Got it working with events too:

Barba.Dispatcher.on('newPageReady', function(currentStatus, oldStatus, container, newPageRawHTML) {
  var response = newPageRawHTML.replace(/(<\/?)body( .+?)?>/gi, '$1notbody$2>', newPageRawHTML)
  var bodyClasses = $(response).filter('notbody').attr('class')
  $('body').attr('class', bodyClasses)
})

from barba.

toonvandenbos avatar toonvandenbos commented on May 17, 2024 4

I rewrote @nicooprat 's solution so it could work without jQuery:

Barba.Dispatcher.on('newPageReady', (currentStatus, oldStatus, container, newPageRawHTML) => {
    let regexp = /\<body.*\sclass=["'](.+?)["'].*\>/gi,
        match = regexp.exec(newPageRawHTML);
    if(!match || !match[1]) return;
    document.body.setAttribute('class', match[1]);
});

from barba.

mtwalsh avatar mtwalsh commented on May 17, 2024 2

@hartey11 Yes, you should be able to assign the body classes to a global variable, which you then apply later on. For example:

    // Create a global variable to store the bodyClasses
    var bodyClasses;
    // Update body classes by replacing the barba.js internal function
    // See: https://github.com/luruke/barba.js/issues/49#issuecomment-237966009
    var originalFn = Barba.Pjax.Dom.parseResponse;
    Barba.Pjax.Dom.parseResponse = function(response) {
        // Because jQuery will strip <body> when parsing a HTML DOM, change
        // <body> to <notbody>, then we can grab the classes assigned to it
        // See: http://stackoverflow.com/a/14423412/4081305
        response = response.replace(/(<\/?)body( .+?)?>/gi, '$1notbody$2>', response);
        // Get the classes on the <notbody> element
        bodyClasses = $(response).filter('notbody').attr('class');
        // Call the original barba.js function
        return originalFn.apply(Barba.Pjax.Dom, arguments);
    };

And then later on...

// Apply the classes to the current body
$('body').attr('class', bodyClasses);

from barba.

OksanaRomaniv avatar OksanaRomaniv commented on May 17, 2024 2

Hello, how can I achieve this with Barba v2?

from barba.

djave-co avatar djave-co commented on May 17, 2024 2

To combine some of the above, a jQuery-less, Barba v2 version:

  // Get body class from incoming page
  let regexp = /\<body.*\sclass=["'](.+?)["'].*\>/gi,
    match = regexp.exec(data.next.html);
  if (!match || !match[1]) {
    // If no body class, remove it
    document.body.setAttribute("class", "");
  } else {
    // Set the new body class
    document.body.setAttribute("class", match[1]);
  }
});

from barba.

jonny-harte avatar jonny-harte commented on May 17, 2024 1

Thanks that worked!

from barba.

nicooprat avatar nicooprat commented on May 17, 2024 1

Ok first thing you could rewrite you first block like this:

$('body').click('a[href^="' + getHomeUrl + '"]', (event) => {
  event.preventDefault()
})

This way, the listener is alway live on body and check if element matches when the event happens. So it would automatically works on newly added elements without anything more. And you can remove all semi-colon too :)

Back to your issue, as per the docs it should work... Maybe @luruke will have a better idea of what's going on here?

from barba.

nicooprat avatar nicooprat commented on May 17, 2024 1

I'm really confused, indeed the event seems to be fired as soon as the content has been loaded, even if the Out transition hasn't finished. But it doesn't work like this on my project. I really think Barba API should be cleaned up...

Anyway, got this working: https://codepen.io/nicooprat/project/editor/ZMYGVe (have a look at newBodyClasses). It's really dirty but can't think of anything better at the moment.

Btw, you shouldn't have to preventDefault on links as Barba does it already.

from barba.

mtreik avatar mtreik commented on May 17, 2024

Yes! Use this:

var body = document.querySelector('body');
body.classname = "The new class";

from barba.

mikespainhower avatar mikespainhower commented on May 17, 2024

Thanks @mtreik.

To clarify, I'd like to pull the body classes from the new URL into the existing DOM (outside of the Barba container).

from barba.

luruke avatar luruke commented on May 17, 2024

Hi @mikespainhower!
Have a look to this issue: #49

from barba.

mikespainhower avatar mikespainhower commented on May 17, 2024

Ah, thank you!

from barba.

mtwalsh avatar mtwalsh commented on May 17, 2024

I'm still getting to grips with barba.js but this code seems to be working in terms of swapping the <body> classes over on page transition (using jQuery):

    // Update body classes by replacing the barba.js internal function
    // See: https://github.com/luruke/barba.js/issues/49#issuecomment-237966009
    var originalFn = Barba.Pjax.Dom.parseResponse;
    Barba.Pjax.Dom.parseResponse = function(response) {
        // Because jQuery will strip <body> when parsing a HTML DOM, change
        // <body> to <notbody>, then we can grab the classes assigned to it
        // See: http://stackoverflow.com/a/14423412/4081305
        response = response.replace(/(<\/?)body( .+?)?>/gi, '$1notbody$2>', response);
        // Get the classes on the <notbody> element
        var bodyClasses = $(response).filter('notbody').attr('class');
        // Apply the classes to the current body
        $('body').attr('class', bodyClasses);
        // Call the original barba.js function
        return originalFn.apply(Barba.Pjax.Dom, arguments);
    };

from barba.

luruke avatar luruke commented on May 17, 2024

@mtwalsh 👍

In the next version of barba, i'm planning to add a new argument to the newPageReady that returns the raw HTML, so you will not need to replace .parseResponse.

Stay updated :)

from barba.

mtwalsh avatar mtwalsh commented on May 17, 2024

@luruke That sounds great, thanks for sharing your work on barba.js, it's awesome!

from barba.

jonny-harte avatar jonny-harte commented on May 17, 2024

Hi, Thanks for the fix. Is there anyway to make sure it only changes the body classes once the new page has loaded? I'm working on a new site and if you click a link that's already cached the body classes change before the page transition is complete and you can see the styling removed from the page?

from barba.

spidoche avatar spidoche commented on May 17, 2024

@nicooprat events works well, thanks.

from barba.

9585999 avatar 9585999 commented on May 17, 2024

@nicooprat I use barba.js with Wordpress, and this code really works, but the problem is that the classes change before the animation starts, which creates certain difficulties when working, if in css there are dependencies on body classes ...

Examples

// Page-1
<body class="content-full">
  ...
</body>

// Page-2
<body class="content-right">
  ...
</body>

when going from page-2 to page-1, on page-2, you can see how the class changes even before it disappears ...

from barba.

nicooprat avatar nicooprat commented on May 17, 2024

This event should be fired right between the two transitions. So the class should change when no content is visible. I think there is an issue in your transition declaration, are you using Promises to ensure the In transtion starts when the Out has finished (and the content is loade)? Can you try with the basic fadeInOut transition in the docs?

from barba.

9585999 avatar 9585999 commented on May 17, 2024

@nicooprat Hi, thanks for the feedback.

I use the base transitions from the documentation, here is an example of the code that I have at the moment

const getUrl = window.location;
const getHomeUrl = getUrl.protocol + "//" + getUrl.host;

// •••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
// Barba.js
// •••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••••
Barba.Pjax.Dom.wrapperId = 'wrap-main';
Barba.Pjax.Dom.containerClass = 'wrap-main-container';

$('a[href^="' + getHomeUrl + '"]').each(function() {
  this.addEventListener("click", (event) => {
    event.preventDefault();
  });
});

Barba.Pjax.start();
Barba.Prefetch.init();

let FadeTransition = Barba.BaseTransition.extend({
  start: function() {
    Promise
      .all([this.newContainerLoading, this.fadeOut()])
      .then(this.fadeIn.bind(this));
  },

  fadeOut: function() {
    return $(this.oldContainer).animate({
      opacity: 0,
    }).promise();
  },

  fadeIn: function() {
    let _this = this;
    let $el = $(this.newContainer);

    $(this.oldContainer).hide();

    $el.css({
      visibility: 'visible',
      opacity: 0,
    });

    $el.animate({
      opacity: 1,
    }, 500, 'linear', function() {
      _this.done();
    });
  },
});

Barba.Pjax.getTransition = function() {
  return FadeTransition;
};

Barba.Dispatcher.on('newPageReady', function(currentStatus, oldStatus, container, newPageRawHTML) {
  $('a[href="' + currentStatus.url + '"]').each(function() {
    this.addEventListener("click", (event) => {
      event.preventDefault();
    });
  });

  let response = newPageRawHTML.replace(/(<\/?)body( .+?)?>/gi, '$1notbody$2>', newPageRawHTML);
  let bodyClasses = $(response).filter('notbody').attr('class');
  $('body').attr('class', bodyClasses);
});

from barba.

9585999 avatar 9585999 commented on May 17, 2024

@nicooprat Yes, thanks, your version of the code I like more.

Regarding the problem, I added styles for clarity and increased the animation time to 1s, below you can see how it works.

.archive #wrap-main {
  background: red;
}

kapture 2017-10-08 at 14 47 19

from barba.

9585999 avatar 9585999 commented on May 17, 2024

The event is triggered as soon as a new container is ready, and judging by the name 'newPageReady' it should be ...

I tried to delay the event via setTimeout(), but this solution does not work so long as the delay sometimes slips ...

Can anyone have any ideas on how to stick this event between the old container and the new container will start to appear?

from barba.

nicooprat avatar nicooprat commented on May 17, 2024

It's pretty weird, my code is almost the same as yours and works as expected. I agree that the name newPageReady is a bit confusing!

Could you try to set some debugger in your code to see what's going on? For example, add a breakpoint at the start of the event, and check in the Elements tab in the inspector to see what the HTML looks like at this moment. In my case, I see this:

capture d ecran 2017-10-09 a 14 06 47

It's at this precise moment that the body classes should be swapped.

Or you could create a Codepen with a small test to reproduce the issue?

from barba.

9585999 avatar 9585999 commented on May 17, 2024

@nicooprat I created CodePen, the behavior is the same ...

from barba.

9585999 avatar 9585999 commented on May 17, 2024

@nicooprat I also thought about this option, but Linter does not miss it ...

img 2017-10-09 16 35 33

and about the links thank you, I did not know that Barba already forbids himself.

In general while as a temporary solution hung the body_class on .wrap-main-conteiner ...

from barba.

nicooprat avatar nicooprat commented on May 17, 2024

I actually defined the variable at the beginning of the file in order to be globally scoped ;)

from barba.

9585999 avatar 9585999 commented on May 17, 2024

@nicooprat yes, indeed, I did not notice :)

from barba.

cfxd avatar cfxd commented on May 17, 2024

Hello, I was wondering if anyone was able to get this working so that the new body classes are added after the fade out transition without using a setTimeout()?

from barba.

julianfox avatar julianfox commented on May 17, 2024

@dangelion work well in my case and the code look clean to me, thanks :-)

from barba.

timotheus0106 avatar timotheus0106 commented on May 17, 2024

thanks @dangelion works great for me too.

from barba.

MarcGaumont avatar MarcGaumont commented on May 17, 2024

Got it working with events too:

Barba.Dispatcher.on('newPageReady', function(currentStatus, oldStatus, container, newPageRawHTML) {
  var response = newPageRawHTML.replace(/(<\/?)body( .+?)?>/gi, '$1notbody$2>', newPageRawHTML)
  var bodyClasses = $(response).filter('notbody').attr('class')
  $('body').attr('class', bodyClasses)
})

Thanks this works perfect.

from barba.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.