Comments (32)
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.
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.
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.
@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.
Hello, how can I achieve this with Barba v2?
from barba.
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.
Thanks that worked!
from barba.
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.
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.
Yes! Use this:
var body = document.querySelector('body');
body.classname = "The new class";
from barba.
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.
Hi @mikespainhower!
Have a look to this issue: #49
from barba.
Ah, thank you!
from barba.
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.
@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.
@luruke That sounds great, thanks for sharing your work on barba.js, it's awesome!
from barba.
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.
@nicooprat events works well, thanks.
from barba.
@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.
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.
@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.
@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;
}
from barba.
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.
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:
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.
@nicooprat I created CodePen, the behavior is the same ...
from barba.
@nicooprat I also thought about this option, but Linter does not miss it ...
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.
I actually defined the variable at the beginning of the file in order to be globally scoped ;)
from barba.
@nicooprat yes, indeed, I did not notice :)
from barba.
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.
@dangelion work well in my case and the code look clean to me, thanks :-)
from barba.
thanks @dangelion works great for me too.
from barba.
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)
- `RangeError` on manual hash change
- How to check for barbacontainer HOT 1
- Safari flash the leaving container HOT 6
- Add support for multiple `namespace` in `Views`
- Improve `next.container` availability
- About `View` transitions API HOT 3
- POST Form transition HOT 1
- Source map failed to load HOT 3
- Compiling error HOT 1
- Disable `prefetch` on specific links HOT 1
- Maintain element on transition HOT 1
- Typescript issue with documentation example HOT 1
- Page content is duplicated when opened HOT 1
- CSP violation from parseFromString HOT 1
- Back button not working as intended after clicking anywhere on the page HOT 7
- Improve Google Analytics guide in the documentation
- Change the wrapper/container on the fly? HOT 3
- Typescript can't find declaration folder because the name is wrong HOT 5
- Remove polyfill.io from documentation HOT 1
- When linking to pages with hashes, hash does not appear in final URL HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from barba.