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.
Related
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'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');
});
I inherited this modal/overlay/content close/empty method that works, but abruptly:
method.close = function () {
$modal.hide();
$overlay.hide();
$content.empty();
$(window).unbind('resize.modal');
};
To fade out gradually, I modified the method like below, but elements are left behind and subsequent clicks don't open new modals loaded with content, only the overlay:
method.close = function () {
$modal.fadeOut('slow', function() {
$(this).hide();
});
$overlay.fadeOut('slow', function() {
$(this).hide();
});
$content.fadeOut('slow', function() {
$(this).empty();
});
$(window).unbind('resize.modal');
};
What am I missing?
UPDATE: The solution is a single nested callback, based on garryp's answer, like this:
method.close = function() {
$overlay.fadeOut('slow', function() {
$overlay.hide();
$content.empty();
});
$modal.hide();
$(window).unbind('resize.modal');
};
Hide is asynchronous; the calls you have in your original code do not block while the transition occurs, execution moves immediately to the next. You need to use callbacks, like this:
var me = $(this); //Added to ensure correct this context
$modal.fadeOut('slow', function () {
me.hide(function () {
$overlay.fadeOut('slow', function () {
me.hide(function () {
$content.fadeOut('slow', function () {
me.empty();
});
});
});
});
});
Assuming the rest of your code is correct this should ensure the transitions fire one after the next.
Firstly, you do not need $(this).hide(). JQuery fadeOut automatically set display: none at the end of fading animation (read more: http://api.jquery.com/fadeout/).
That mean, in your case $content element will also have display: none after fadeOut animation. I expect you forgot to add $content.show() in modal open method.
I have code
$(function() {
// run the currently selected effect
function runEffect() {
// get effect type from
var selectedEffect = $( "#effectTypes" ).val();
// most effect types need no options passed by default
var options = {};
// some effects have required parameters
if ( selectedEffect === "scale" ) {
options = { percent: 100 };
} else if ( selectedEffect === "size" ) {
options = { to: { width: 280, height: 185 } };
}
// run the effect
$( "#effect" ).show( selectedEffect, options, 500, callback );
};
//callback function to bring a hidden box back
function callback() {
setTimeout(function() {
$( "#effect:visible" ).removeAttr( "style" ).fadeOut();
}, 1000 );
};
// set effect from select menu value
$( "#button" ).click(function() {
runEffect();
});
like dis i want to change dis on click function into on load function am a beginner so please help me
If I am understanding you correctly you want to run the runEffect function on page load?
You can do this by calling the function from within the jQuery ready event.
// This is shorthand for $(document).ready(function() { ... })
$(function() {
// Declare the runEffect function here
runEffect();
});
Is this possible? I've got one jquery file that is loaded in every page that uses the .load() event, but then a few select pages also require some specific jquery stuff where I'd like to use .load() again. Thanks for reading.
Yep, that's no worries.
The events will run in the order they were defined:
$(function() {
$('body').append('<span>A</span>');
});
$(function() {
$('body').append('<span>B</span>');
});
$(function() {
$('body').append('<span>C</span>');
});
The above would append "ABC" to the page.
Interestingly, if you use the long-hand method, it completes in a different order:
$(function() {
$('body').append('<span>A</span>');
});
$(document).ready(function() {
$('body').append('<span>B</span>');
});
$(function() {
$('body').append('<span>C</span>');
});
This outputs "ACB"
Even more confusingly, if you only use the longhand, then it appears as though the first handler runs last and the rest in order:
$(document).ready(function() { /* A */ });
$(document).ready(function() { /* B */ });
$(document).ready(function() { /* C */ });
$(document).ready(function() { /* D */ });
$(document).ready(function() { /* E */ });
// BCDEA