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.
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'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');
});
Here I have a widget and I want to call a function once #slider.slider();. what is the code?
$( "#slider" ).slider({
//initial function here.
alert("A");
value: 50,
slide: function(event, ui) {
displaySlideValue();
}
});
Why not just do
$('#slider').slider({ ... }).each(function() { /* your code here */ });
Alternatively you could wrap the .slider() call in your own mini-extension:
$.fn.sliderWithInit = function(params, init) {
return this.slider(params).each(init);
});
then you could say
$('#slider').sliderWithInit({ /* params */ }, function() { /* init code */ });
Obviously "slider" could be made generic:
$.wrapWithInit = function(widgetName) {
$.fn[widgetName + 'WithInit'] = function(params, init) {
return this[widgetName](params).each(init);
});
});
Then you can do it for "dialog" for example:
$.wrapWithInit('dialog');
$('#dialog').dialogWithInit({ /* dialog params */ }, function() { /* init code */ });
As #mikerobi points out, it's not 100% clear when you want your initialization function to be called. Most widgets have an "onFoo" type callback that's called when the widget is activated (whatever that means for the given widget). If you just want to initialize on the first call, you could just make the callback be a closure that keeps track of whether it's ever done the initialization work. If it detects it's already done it, it would just return.