I'm trying to use Masonry and smoothState together using SmoothState animations between pages.
The code below makes smoothState animations work both forwards and in reverse:
$(function(){
'use strict';
var $page = $('#main'),
options = {
debug: true,
prefetch: true,
cacheLength: 2,
onStart: {
duration: 500, // Duration of our animation
render: function ($container) {
// Add your CSS animation reversing class
$container.addClass('is-exiting');
// Restart your animation
smoothState.restartCSSAnimations();
}
},
onReady: {
duration: 0,
render: function ($container, $newContent) {
// Remove your CSS animation reversing class
$container.removeClass('is-exiting');
// Inject the new content
$container.html($newContent);
}
}
},
smoothState = $page.smoothState(options).data('smoothState');
});
I can make Masonry work by invoking
$(document).ready(function() {
var $container = $('#portfolio');
$container.imagesLoaded( function() {
$container.masonry({
itemSelector : '.p-item',
});
});
});
But they don't play nicely together. Masonry works, but smoothState doesn't (the forward animations are still fine, because they're pure CSS, but the JS doesn't seem to work). If I get rid of the Masonry code, smoothState works fine, which seems odd because they ought to be unrelated.
Is there a way to have both?
According to the FAQ, the $(document).ready functions must be re-initialised in the onAfter. After looking at lots of articles in the issues section and here, the developer has created a gist here that re-runs any $(document).ready functions.
I still can't get it working though (I'm not using masonry but using imagesLoaded from desandro and some other plugins), seems $.readyFn.execute(); is supposed to run on option.callback but the FAQs say to run onAfter callback. I have tried both and it's not worked for me, I've also tried removing all other plugins and just doing some menial task on ready but that didn't work, seems onAfter just doesn't fire for me.
So even though this doesn't work for me, according to other posts this should fix it for you.
Paste in the following right after including jQuery
;(function($){
var $doc = $(document);
/** create mod exec controller */
$.readyFn = {
list: [],
register: function(fn) {
$.readyFn.list.push(fn);
},
execute: function() {
for (var i = 0; i < $.readyFn.list.length; i++) {
try {
$.readyFn.list[i].apply(document, [$]);
}
catch (e) {
throw e;
}
};
}
};
/** run all functions */
$doc.ready(function(){
$.readyFn.execute();
});
/** register function */
$.fn.ready = function(fn) {
$.readyFn.register(fn);
};
})(jQuery);
Then add the following, make sure the original masonry call is inside a $(document).ready function
$(function(){
'use strict';
var $page = $('#main'),
options = {
debug: true,
prefetch: true,
cacheLength: 2,
onStart: {
duration: 500, // Duration of our animation
render: function ($container) {
// Add your CSS animation reversing class
$container.addClass('is-exiting');
// Restart your animation
smoothState.restartCSSAnimations();
}
},
onReady: {
duration: 0,
render: function ($container, $newContent) {
// Remove your CSS animation reversing class
$container.removeClass('is-exiting');
// Inject the new content
$container.html($newContent);
}
},
// over a year ago, this was simply callback: function(){}
onAfter: function($container, $newContent){
$.readyFn.execute();
}
},
smoothState = $page.smoothState(options).data('smoothState');
});
Related
I have site using smoothstate.js on every page. on a couple of pages, I have a modal box pop up with a form. Those forms work just fine.
On another page, I have a basic form included in the html. When I click the submit button on the form, the form actually submits but smoothstate starts which fades out the content and starts my loading screen.
I would like for that not to happen. Here is my smoothstate function:
$(function(){
'use strict';
var $page = $('#main'),
options = {
debug: true,
prefetch: true,
cacheLength: 2,
allowFormCaching: false,
forms: 'form',
blacklist: 'input[type="submit"], .animsition-loading, .hs-button',
onStart: {
duration: 1050, // Duration of our animation
render: function ($container) {
$('.animsition-loading').show();
$container.addClass( 'slide-out' );
smoothState.restartCSSAnimations();
}
},
onReady: {
duration: 0,
render: function ($container, $newContent) {
$container.html($newContent);
sitejs();
$(document).ready();
$(window).trigger('load');
}
},
onAfter: function( $container ) {
$('.animsition-loading').hide();
$container.removeClass( 'slide-out' );
}
},
smoothState = $page.smoothState(options).data('smoothState');
});
I had the same problem for me with a newsletter form. Here is the solution to your problem. You have to add the blacklisted class that you have in your JS (for example "no-smoothsate") to the FORM tag. It works perfectly.
<form class="no-smoothState">
...
</form>
I found the solution here
I believe smoothstate is designed to work on forms as well as links by default, so as cf7 already works with AJAX you just need to blacklist as mentioned.
For cf7 this is the code:
;(function($) {
'use strict';
var $body = $('html, body'),
content = $('#main').smoothState({
blacklist: '.wpcf7-form',
// Runs when a link has been activated
onStart: {
duration: 500, // Duration of our animation
render: function ($container) {
// Add your CSS animation reversing class
$container.addClass('is-exiting');
// Restart your animation
smoothState.restartCSSAnimations();
}
},
onReady: {
duration: 0,
render: function ($container, $newContent) {
// Scroll user to the top, this is very important, transition may not work without this
$body.scrollTop(0);
// Remove your CSS animation reversing class
$container.removeClass('is-exiting');
// Inject the new content
$container.html($newContent);
// Trigger load functions
$(document).ready();
$(window).trigger('load');
}
},
onAfter: function($container) {
initContactForm();
}
}).data('smoothState');
})(jQuery);
I'm using smoothState on a WordPress site, however I need to add a section of javascript to create a pop-up modal.
The javascript I currently have only works when the page is refreshed, I tried a few different methods I've seen posted on here and on stackoverflow. Anything I try either doesn't work or breaks the site.
This is my working smoothstate code:
jQuery(document).ready(function( $ ) {
'use strict';
var $page = $('#smoothstate'),
options = {
debug: true,
prefetch: true,
cacheLength: 4,
onStart: {
duration: 150, // Duration of our animation
render: function ($container) {
// Add your CSS animation reversing class
$container.addClass('is-exiting');
// Restart your animation
smoothState.restartCSSAnimations();
}
},
onReady: {
duration: 0,
render: function ($container, $newContent) {
// Remove your CSS animation reversing class
$container.removeClass('is-exiting');
// Inject the new content
$container.html($newContent);
$container.addClass('fade--in');
}
}
}
});
This is my javascript I need to load:
(function($) {
$(".orange-btn").click(function(e){
$(".hidden").fadeIn( 500 );
$(".hidden").addClass( "click" );
e.preventDefault();
$(".closebox").addClass( "close" );
});
}(jQuery));
I'd be really grateful if anyone could help! Thanks!
I have managed to implement the smoothState.js plugin on my website and it works nicely, but my other very simple jQuery plugin will not work, wich starts with:
$(document).ready()
I need to refresh the page in order for it to work again.
I've read the smoothState documentation and it says I should wrap your plugin initializations in a function that we call on both $.fn.ready() and onAfter — but I'm farely new to programming, so I'm asking for your help.
How can I make my jQuery plugins work with smoothState?
You need to wrap scripts that are initiated with $(document).ready() in a function, and then call that function when you need it.
For example, let’s say this is your current script:
$(document).ready(function() {
$('.btn--homepage').click(function(e) {
e.preventDefault();
var goTo = $(this).attr('href');
$('#page').addClass('is-exiting');
$(this).addClass('exit-btn');
setTimeout(function() {
window.location = goTo;
}, 260);
});
});
It’ll work fine when the page loads as it’s wrapped in $(document).ready(function()), but as the page won’t be reloading when using Smoothstate, we need a way to call the snippet both when the page originally loads and when smoothstate loads content. To do this we’ll turn the above snippet in to a function like this:
(function($) {
$.fn.onPageLoad = function() {
$('.btn--homepage').click(function(e) {
e.preventDefault();
var goTo = $(this).attr('href');
$('#page').addClass('is-exiting');
$(this).addClass('exit-btn');
setTimeout(function() {
window.location = goTo;
}, 260);
});
};
}(jQuery));
As you can see, we’ve swapped $(document).ready(function()) with the function wrapper, everything else stays the same.
So now we’ve got a function all we need to do is call it when the page loads and in Smoothstate.
To call it when a page loads all we need to do is this:
$(document).ready(function() {
$('body').onPageLoad();
});
And to trigger it in Smoothstate we need to call it in the InAfter callback like this:
onAfter: function($container) {
$container.onPageLoad();
}
And here's an example Smoothstate script showing where to put the onAfter callback:
$(function() {
var $page = $('#main');
var options = {
prefetch : true,
pageCacheSize: 4,
forms: 'form',
scroll: false,
onStart: {
duration: 1200,
render: function($container) {
$container.addClass('is-exiting');
smoothState.restartCSSAnimations();
}
},
onReady: {
duration: 0,
render: function($container, $newContent) {
$container.removeClass('is-exiting');
$container.html($newContent);
$('html, body').scrollTop(0);
}
},
onAfter: function($container) {
$container.onPageLoad();
}
};
var smoothState = $('#main').smoothState(options).data('smoothState');
});
Happy to provide further assistance if needed.
I have a site that has elements like a slider on most pages. I am trying to implement the SmoothState JS but I am running into the issue of the second page breaking. I know through the documentation I probably need to add the onAfter callback but I was wondering where and how this would be applied. Apparently it can be tricky if unfamiliar with Ajax.
Here is the documentation on the issue.
And this is the code that I have that fires the script:
$(function(){
'use strict';
var $page = $('#uber'),
options = {
debug: true,
prefetch: true,
cacheLength: 2,
onStart: {
duration: 250, // Duration of our animation
render: function ($container) {
// Add your CSS animation reversing class
$container.addClass('is-exiting');
// Restart your animation
smoothState.restartCSSAnimations();
}
},
onReady: {
duration: 0,
render: function ($container, $newContent) {
// Remove your CSS animation reversing class
$container.removeClass('is-exiting');
// Inject the new content
$container.html($newContent);
}
}
},
smoothState = $page.smoothState(options).data('smoothState');
});
Does anyone have any ideas on how I would add the onAfter callback?
I've just started trying out smoothState, but here is what first worked for me.
$(document).ready(function(){
prep();
});
$('#main').smoothState({
onAfter: function() {
prep();
}
});
function prep(){
$('#loadBtn').click(function () {
$( '#remote1' ).load( 'external.html #myExternalDiv', function( response, status, xhr ) {
if ( status == 'error' ) {
var msg = 'Sorry but there was an error: ';
$( '#error' ).html( msg + xhr.status + ' ' + xhr.statusText );
}
$('#remote1').slideToggle();
});
});
} // prep
So I put stuff that would normally go into my $(document).ready section into a prep() function. Then I call that for both doc init and onAfter.
I've been trying to figure out how to trigger animations on scroll, and I can't quite get it. Basically, I want to have a class that I can add to my titles that will trigger an animation any time the element with the class is scrolled into view.
I tried using the jQuery Inview plugin, but I couldn't get it to do what I wanted. Then I switched to Waypoints.js and I kind of have it working, but it's not perfect. Right now, the elements animate when I scroll to them for the first time but they do nothing when I scroll up and back down the page. The animations only fire once.
Below is my current code. If anyone can help me figure out a way to get the animations triggering every time the user scrolls past them—and also a way to condense the code so that it fires based on class and not ID—that would be really excellent. (Right now, I have separate function for each element.)
PS: I'm using animate.css, wow.js, textillate.js for the animations.
HTML
<h1 class="lettering wow fadeInDown" id="l1" data-in-effect="flipInY">Yo. Check it out.</h1>
jQuery
$(function () {
var l1 = $("#l1");
var waypoint = new Waypoint({
element: document.getElementById('l1'),
handler: function() {
l1.textillate({ in: { effect: 'flipInY' } });
},
offset: 'bottom-in-view',
});
});
Thanks for your help!
EDIT: I have found a partial solution that triggers the animations every time you scroll past them. However, I can only seem to get it to work with ids. I'd rather be able to target a class than have to write a separate function for each new title. Any ideas on how to modify the following code so that it works for a class of .lettering?
// Animate #l1
$(function () {
var animatel1 = $('#l1').textillate({
autoStart: false,
in: { effect: 'flipInY' },
out: { effect: 'fadeOut', sync: true, }
});
var l1 = $("#l1");
var inview = new Waypoint.Inview({
element: $('#l1'),
enter: function(direction) {
},
entered: function(direction) {
animatel1.textillate('in')
},
exit: function(direction) {
animatel1.textillate('out')
},
exited: function(direction) {
}
})
});
Having it work with a class is a matter of looping through your array of elements. I see you're using jQuery, so it can help you with a bit of the boilerplate:
$(function () {
$('.your-class').textillate({
autoStart: false,
in: { effect: 'flipInY' },
out: { effect: 'fadeOut', sync: true, }
});
$('.your-class').each(function() {
new Waypoint.Inview({
element: this,
entered: function(direction) {
$(this.element).textillate('in')
},
exit: function(direction) {
$(this.element).textillate('out')
}
});
});
});
This is what worked for me. Needed to wrap everything in an .each() function. Replace lettering with your class name and you should be good to go.
$('.lettering').each(function() {
var animatelettering = $('.lettering').each(function(){
$(this).textillate({
autoStart: false,
in: { effect: 'flipInY' },
out: { effect: 'fadeOut', sync: true, }
});
});
new Waypoint.Inview({
element: this,
enter: function(direction) {
},
entered: function(direction) {
animatelettering.textillate('in')
},
exit: function(direction) {
animatelettering.textillate('out')
},
exited: function(direction) {
}
});
});