I am trying to slide out a panel and then hide it using extjs. The slideout is working fine but as soon as I add the hide function it stops working. How do I fix this.
My function is as below.
toggleSidebar : function () {
var sidebar = this.getSidebar();
if(sidebar.hidden){
sidebar['show']();
}else{
sidebar.el.slideOut('l', {
easing: 'easeOut',
duration: 200,
scope: this,
callback: this.onSidebarAnim()
});
sidebar['hide'](); // Slide works if I remove this line.
}
},
Animation is an asynchronous process, and slideOut does not block until animation has finished; in fact your code starts to animate the panel and then hides it immediately. That is why it's not working the way you expect it to.
The solution is to hide the panel after the animation has finished. That is what callback is for, except that in your original code instead of passing the function in callback property, you're calling it and assigning the result of its execution to the callback property. That is not going to work, and in fact it's going to blow up with "foo not a function" exception.
toggleSidebar: function () {
var sidebar = this.getSidebar();
if (sidebar.hidden) {
sidebar.show();
}
else {
sidebar.el.slideOut('l', {
easing: 'easeOut',
duration: 200,
scope: this,
// Pass the function itself, note no parentheses:
callback: this.onSidebarAnim
});
}
},
onSidebarAnim: function() {
this.getSidebar().hide();
...
}
Related
The problem is that when i use the toggle function without any options i.e default options the 'is(':visible')' on the item returns me the correct state.
However when i use toggle("slow"), it reveals incorrect state and always shows the item operated upon by the toggle as visible false. Of course i am checking that inside the callback function so as to be sure that the animation is complete.
please look at the below code
jQuery(document).ready(function () {
var h3 = jQuery("#myAccordion").find('h3');
jQuery("#myAccordion").find('h3').find('span').addClass("ui-state-active ui-icon");
jQuery.each(h3, function () {
jQuery(this).bind('click', function () {
jQuery(this).next('div').toggle("slow", "swing", callback);
});
});
});
function callback () {
if (jQuery(this).next('div').is(':visible')) {
alert('visible--' + jQuery(this).next('div').is(':visible'));
jQuery(this).find('span').removeClass("ui-state-default ui-icon").addClass("ui-state-active ui-icon");
}
else {
alert('visible--' + jQuery(this).next('div').is(':visible')); // always goes into this 'else' even though the item is visible.
jQuery(this).find('span').removeClass("ui-state-active ui-icon").addClass("ui-state-default ui-icon");
}
}
However the same works perfectly fine when not using the "slow" option with toggle.
Update 2:
Check this out here http://jsfiddle.net/tariquasar/7xt7D/2/
Any pointers...
Update 1: This is the fiddle http://jsfiddle.net/tariquasar/7xt7D/
The context this is not extended to the callback function too. You could try doing this. I have updated the jsfiddle (click here). Ill paste the same here.
jQuery(document).ready(function () {
var h3 = jQuery("#myAccordion").find('h3');
jQuery("#myAccordion").find('h3').find('span').addClass("ui-state-active ui-icon"); // first the item is visible
jQuery.each(h3, function () {
jQuery(this).bind('click', function () {
console.log(this);
jQuery(this).next('div').toggle("slow","swing",callback(this));
});
});
});
function callback (that) {
setTimeout( function () {
console.log(jQuery(that).next('div').is(':visible'));
if (jQuery(that).next('div').is(':visible')) {
alert('visible--' + jQuery(that).next('div').is(':visible'));
jQuery(that).find('span').removeClass("ui-state-default ui-icon").addClass("ui-state-active ui-icon");
}
else {
alert('visible--' + jQuery(that).next('div').is(':visible'));
jQuery(that).find('span').removeClass("ui-state-active ui-icon").addClass("ui-state-default ui-icon");
}
}, 1000);
}
I have added a SetTimeout to get the result you wanted. The callback function is called after the animation completes. Yes. But not after the CSS changes to display:none. CSS change happens a few millisecs later.
However the same works perfectly fine when not using the "slow" option with toggle.
I'm not really sure about how you got it working with options other than slow
I've got some Jquery that simply zooms in and out non-stop for a banner image. When I run this, I get a stack limit error in the browser. It still runs, but is there a way to make it only load into the stack "just in time"? When looking at the stack it loads zoomIn() and zoomOut() over and over again on the initial load until it hits the limit, page loads are really slow because of it.
$(document).ready(function(){
$bannerImg = $('.post-picture img')
function zoomIn(){
$bannerImg.animate({
width: 1500,
}, 50000,'linear');
$bannerImg.promise().done(zoomOut());
}
function zoomOut(){
$bannerImg.animate({
width: 1500,
}, 50000,'linear');
$bannerImg.promise().done(zoomIn());
}
zoomIn();
});
Update: Thanks for the answers. Using done(ZoomOut/ZoomIn) worked.
.done() expects a function reference - the function pass will be executed as soon as the promise object is resolved. Instead, you're just calling the functions (which return nothing, undefined, anyways). If you do this, the functions will continually call each other, acting as an infinite loop. Use this:
$bannerImg.promise().done(zoomOut);
// and later:
$bannerImg.promise().done(zoomIn);
DEMO: http://jsfiddle.net/G6uWs/
(I had to change the numbers to make it usable)
Reference:
http://api.jquery.com/deferred.done/
You're calling the function in .done() instead of passing it as a parameter.
$bannerImg.promise().done(zoomOut());
should be
$bannerImg.promise().done(zoomOut);
and
$bannerImg.promise().done(zoomIn());
should be
$bannerImg.promise().done(zoomIn);
Looks like you are causing an infinite loop. Luckily, the jQuery has a complete callback that you can leverage to prevent the infinite loop.
Non-stop zoom in and out banner
$(document).ready(function () {
$bannerImg = $('.post-picture img');
function zoomIn() {
$bannerImg.animate({
width: 1500
}, {
duration: 10000,
complete: function () {
zoomOut();
}
});
}
function zoomOut() {
$bannerImg.animate({
width: 100
}, {
duration: 10000,
complete: function () {
zoomIn();
}
});
}
zoomIn();
});
*Source: * jsfiddle
I have written your basic jQuery infinite scroll function. Expected behavior is consistent with the infinite scroll design pattern.
Upon completion of the ajax server call, I am rebinding the scroll event.
Everything works as expected for the first ajax call, however the scroll event is not being rebound for some reason. Adding in console data to debug the function shows that the code is executed through the end of setScrollingAction(), yet the scroll event does not take.
What am I missing?
// Function to make the ajax call, append the results and rebind the scroll event
function loadContent(opts) {
$(opts.scrollTarget).unbind('scroll');
$(opts.loaderObject).show();
$.get($(opts.gridObject).attr('data-link'), function(data) {
var $data = $(data);
$(opts.gridObject).append($data.find(opts.appendObject));
$(opts.loaderObject).hide();
$(opts.gridObject).attr('data-link', $data.find(opts.gridObject).attr('data-link'));
setScrollingAction(opts);
});
};
// Function to set the loading action to the scroll event
function setScrollingAction(opts) {
$(opts.scrollTarget).bind("scroll", function(event) {
if (inLoadingRange(opts)) { loadContent(opts); }
});
};
// Function to determine height from bottom of page
function inLoadingRange(opts) {
var target = opts.scrollTarget;
return ($(target).scrollTop()+opts.heightOffset >= $(document).height() - $(target).height());
};
// Fire it up
$(document).ready(function(){
opts = {
'scrollTarget': $(window),
'loaderObject': "#loading",
'gridObject' : '#tileGrid',
'appendObject': '.newItem',
'heightOffset': 10
};
setScrollingAction(opts);
});
Turns out it was a conflict with the prettyLoader plugin.
If you look through prettyLoader.js you will find the following function:
$.prettyLoader.hide = function() {
$(document).unbind('click', $.prettyLoader.positionLoader);
$(document).unbind('mousemove', $.prettyLoader.positionLoader);
$(window).unbind('scroll');
$('.prettyLoader').fadeOut(settings.animation_speed, function() { $(this).remove(); });
};
All scroll event assignments are being unbound on the third line of the function. Commenting out this line solved the problem, and did not have a noticeable effect of the loading image.
$.prettyLoader.hide = function() {
$(document).unbind('click', $.prettyLoader.positionLoader);
$(document).unbind('mousemove', $.prettyLoader.positionLoader);
//$(window).unbind('scroll');
$('.prettyLoader').fadeOut(settings.animation_speed, function() { $(this).remove(); });
};
I have created a quick jsfiddle here showing it not working.
The problem I have is with the slide up. I want it to work so that it only sets the width to 0 after the slideup has finished. The obvious callback function does not seem to be getting called after the slideup has finished.
I would like it to work like this:
Shows the red box by sliding down and increasing the width together.
Click again and the box slides up then sets the width the 0. So that if the user clicks the button again the first animation would appear the same.
var $foo = $("#elm");
$("#btn").toggle(function() {
showDropDown();
}, function() {
hideDropDown();
});
function showDropDown(){
$foo.slideDown({duration:500, queue:false}).animate({"width": 400}, 250);
}
function hideDropDown(){
$foo.slideUp({duration:800, queue:false},function(){
$foo.css({"width": 0});
});
}
UPDATE:
The strange thing is that if I add a alert() into the callback function for slidedown it never gets called.
Edit: Sorry for the first answer, didn't pay attention.
The problem is that the callback is not executed, because you don't give the parameters according to the API, and the callback is not "wired" in.
Instead, you can use the promise().done(...) combination to achieve the objective you wanted.
So, you should modify your hideDropDown method as follows:
function hideDropDown(){
$foo.slideUp({duration:800, queue:false}).promise().done(function(){
$foo.css("width", "0px");
});
}
From the jQuery docs:
"The .promise() method returns a dynamically generated Promise that is resolved once all actions of a certain type bound to the collection, queued or not, have ended."
Maybe you just need to use animate to reset width to 0 like this:
var $foo = $("#elm");
$("#btn").toggle(function() {
showDropDown();
}, function() {
hideDropDown();
});
function showDropDown(){
$foo.slideDown({duration:500, queue:false}).animate({"width": 400}, 250);
}
function hideDropDown(){
$foo.slideUp({duration:800, queue:false}).animate({"width": 0}, 1);
}
or set width to 0 like this:
function hideDropDown(){
$foo.slideUp({duration:800, queue:false}).width(0);
}
Why not chain .animate() after .slideUp()?
$foo.slideUp({duration: 800, queue: false}).animate({"width": 0}, 800);
I have a a div in a page that slides up on hover, and then back down on hover out. If you were then to hover in and out on the item, then all the actions will be queued and thus triggered, causing the object to keep sliding up and down even though you are no longer interacting with it.
You can see this in action on the site I am developing here. Simply hover over the large image in the center to see the information div to appear.
Ideally what should happen is that while an animation is taking place no further actions should be queued.
Here is my current code:
$(document).ready(function(){
$(".view-front-page-hero").hover(
function() {
$hero_hover = true;
$('.view-front-page-hero .views-field-title').slideDown('slow', function() {
// Animation complete.
});
},
function() {
$hero_hover = false;
$('.view-front-page-hero .views-field-title').slideUp('slow', function() {
// Animation complete.
});
}
);
});
Create a global variable. When the animation starts. Clear it when it completes. Set a condition to exit the function if this variable is set before calling the animation.
This is probably not the best solution, but if you run stop(true, true) before the animation, it should work.
Live demo: http://jsfiddle.net/TetVm/
$(document).ready(function(){
var continue=true;
$(".view-front-page-hero").hover(
function() {
if(continue){
$('.view-front-page-hero .views-field-title').slideDown('slow', function() {
continue=false;
});
}
},
function() {
if(continue!){
$('.view-front-page-hero .views-field-title').slideUp('slow', function() {
continue=true;
});
}
}
);
});
//this will make your code work correctly...