I am using JQuery for making a widget effect i.e. minimizing and maximizing a widget..
But the problem is that when i click on the minimize button speedily the widget crashes..
I think that the problem is that it takes mid animation height as its new height at the time of toggle...
Please help...
$(document).ready(function () {
$('.widget-minimize').click(function () {
toggleMinimize($(this).parents('.widget').attr('id'));
});
$('.widget-close').click(function () {
closeWidget($(this).parents('.widget').attr('id'));
});
});
function toggleMinimize(widgetId) {
var $content = $('#' + widgetId + ' .widget-content');
if ($content.height()) {
$content.data('oldheight', $content.height());
$content.animate({height: 0});
$('#' + widgetId).find('.widget-minimize').attr('src', 'http://dl.dropbox.com/u/638285/SO/images/icon-maximize.png').attr('alt', 'maximize');
}
else {
$content.animate({height: $content.data('oldheight')});
$('#' + widgetId).find('.widget-minimize').attr('src', 'http://dl.dropbox.com/u/638285/SO/images/icon-minimize.png').attr('alt', 'minimize');
}
}
function closeWidget(widgetId) {
$('#' + widgetId).animate({ "opacity": 0, "height": 0 }, 200, "swing");
}
Click here to see jsFiddle
Just return from your toggleMinimize function if your content is currently being animated, like this:
function toggleMinimize(widgetId) {
var $content = $('#' + widgetId + ' .widget-content');
if ($content.is(':animated')) {
return;
}
See working fiddle
In my case, the fiddle is working correctly, but I would recommend you to use max-height in case of height, so use max-height: 0 and max-height: 80 (assuming 80 is a bit more of the max height). Also you can pass the element and not just the ID.
$(document).ready(function () {
$('.widget-minimize').click(function () {
toggleMinimize($(this).parents('.widget'));
});
$('.widget-close').click(function () {
closeWidget($(this).parents('.widget'));
});
});
function toggleMinimize(selector) {
var $content = $('.widget-content', selector);
if ($content.height()) {
$content.data('oldheight', $content.height());
$content.animate({maxHeight: 0});
$('.widget-minimize', selector).attr('src', 'http://dl.dropbox.com/u/638285/SO/images/icon-maximize.png').attr('alt', 'maximize');
}
else {
$content.animate({maxHeight: $content.data('oldheight')});
$('.widget-minimize', selector).attr('src', 'http://dl.dropbox.com/u/638285/SO/images/icon-minimize.png').attr('alt', 'minimize');
}
}
function closeWidget(widgetId) {
$('#' + widgetId).animate({ "opacity": 0, "max-height": 0 }, 200, "swing");
}
Take a look at jQuery's .stop() method and its :animated selector. I often use them in situations like this to help me handle animations that are already running.
For example:
$("#element").on("click", function() {
if ($(this).not(":animated")) {
...animation code...
}
});
and
$("#element").on("click", function() {
$(this).stop();
...animation code...
});
Related
I'm having an issue with this jQuery that is blowing my mind. I've tried three different JS and jQuery functions people suggested online for accomplishing this and can't seem to get anything to work.
I'm trying to hide the class .arrow-up when .first is actually visible on the screen and hide the class .arrow-down when .last is visible on the screen.
Sounds simple enough, right?
Well the parent element has overflow: hidden on it (like most carousels–they really are from hell). Anyone know how to do this? I'd really appreciate any help, JS really isn't my strongest by any means...
Here's my current jQuery–
jQuery(document).ready(function ($) {
$(".arrow-down").bind("click", function (event) {
event.preventDefault();
$(".vid-list-container").stop().animate({
scrollTop: "+=300"
}, 300);
});
$(".arrow-up").bind("click", function (event) {
event.preventDefault();
$(".vid-list-container").stop().animate({
scrollTop: "-=300"
}, 300);
});
});
In this, .vid-list-container is the parent with overflow: hidden on it and .first and .last are both inside the container. The arrow classes are both outside of the container.
Built this pen for anyone who wants to play around with it.
http://codepen.io/seancrater/pen/waPNEW
Thanks!
This should work. Notice however that I used opacity:0, so the arrow can still be clicked. You need to change that!
function checkDownArrow() {
setTimeout(function() {
if($(".vid-list-container").scrollTop() != 0){
$('.arrow-up').css('opacity',1);
}
if(($(".vid-list-container").scrollTop() + $(".vid-item").height()+5) >= $(".vid-item").length * $(".vid-item").height()) {
$('.arrow-down').css('opacity',0);
}
},350);
}
function checkUpArrow() {
setTimeout(function() {
if($(".vid-list-container").scrollTop() == 0){
$('.arrow-up').css('opacity',0);
}
if(($(".vid-list-container").scrollTop() + $(".vid-item").height()+5) < $(".vid-item").length * $(".vid-item").height()) {
$('.arrow-down').css('opacity',1);
}
},350);
}
checkDownArrow();
checkUpArrow();
jQuery(document).ready(function ($) {
$(".arrow-down").bind("click", function (event) {
event.preventDefault();
$(".vid-list-container").stop().animate({
scrollTop: "+=173"
}, 300);
checkDownArrow();
});
$(".arrow-up").bind("click", function (event) {
event.preventDefault();
$(".vid-list-container").stop().animate({
scrollTop: "-=173"
}, 300);
checkUpArrow();
});
});
EDIT
Okay, I see you have a different problem... may I suggest using a different approach? Something like this.
HTML:
<div class="outer-wrapper">
<div class="inner-wrapper">
<div class="vid-item">
...
</div>
<div class="vid-item">
...
</div>
</div>
</div>
CSS:
.outer-wrapper {width:200px; height:150px; overflow:hidden;}
.inner-wrapper {height:auto; margin-top:0;}
.vid-item {width:200px; height:150px;}
JS:
var itemHeight = $('.vid-item').first().height();
var wrapperHeight = $('.inner-container').height();
$(".arrow-down").bind("click", function (event) {
event.preventDefault();
var margin = parseInt($('.inner-container').css('margin-top'));
if(itemHeight - margin > wrapperHeight) {
$('.inner-container').css('margin-top', (itemHeight-wrapperHeight) + 'px');
$('.arrow-down').addClass('hidden');
}
else {
$('.inner-container').css('margin-top', (margin-itemHeight) + 'px');
}
$('.arrow-up').removeClass('hidden');
});
$(".arrow-up").bind("click", function (event) {
event.preventDefault();
var margin = parseInt($('.inner-container').css('margin-top'));
if(margin + itemHeight >= 0) {
$('.inner-container').css('margin-top', '0');
$('.arrow-up').addClass('hidden');
}
else {
$('.inner-container').css('margin-top', (margin+itemHeight) + 'px');
}
$('.arrow-down').removeClass('hidden');
});
I am having an issue with my slideToggle function. Once pressed it opens up the way I need it to. But when I scale the browser to test the responsive flow to the site the slideToggle still stays active instead of sliding down. I tried a few functions but nothing seems to work. Below is the scrip I am using without the code to slide down when it hits a specific screen resoultion. How would I go about fixing this issue?
$('#more').click(function () {
var open = $('header').is('.open');
$('#footerPanel')['slide' + (open ? 'Up' : 'Down')](400);
$('header').animate({
bottom: (open ? '-' : '+') + '=120' }, 400, function () {
$('header').toggleClass('open');
});
});
$('#menu').click(function () {
if ($('header').is('.open')) {
$('header')
.removeClass('open')
.animate({
'bottom': "-=120"
}, function () {
var $footer = $('.activetoggle');
if ($footer.length)
$footer
.toggleClass('activetoggle footerButton')
.text('Footer');
});
$('#footerPanel').slideUp(400);
}
});
$('.footerButton').click(function () {
var $this = $(this);
$this.toggleClass('footerButton');
if ($this.hasClass('footerButton')) {
$this.text('Footer');
} else {
$this.text('Close');
}
$(this).toggleClass('activetoggle');
});
My Code
http://jsfiddle.net/wyze/XqUp4/4/
Try if this works for you. I have added to check whether the width is 780(you can change it), when the panel to slide down. Try adding this in you fiddle and check if this works
$(window).resize(function(){ //check when window resize
if($(window).width() < 780){ // check when the window width is less than 780
if ($('header').is('.open')) {
$('header')
.removeClass('open')
.animate({
'bottom': "-=120"
});
$footer = $('.activetoggle');
if ($footer.length) {
$footer.toggleClass('activetoggle footerButton').text('Footer');
}
$('#footerPanel').slideToggle(400);
}
}
});
I'm using Jquery Collision to detect two objects overlapping each other. Here is a JSFiddle of the problem.
(apologies for including jquery collision script in HTML, couldn't find other way)
Click anywhere in the gray container to move the green div over the white div.
HTML Structure:
<div class="container">
<div class="test"></div>
<div class="menu"></div>
</div>
JS:
$(document).ready(function () {
var hit_list;
$(".container").click(function () {
$(".menu").stop().animate({
left: "+=100px"
}, 300, function () {
$(".menu").animate({
left: "0"
}, 800);
});
//Test for collision
hit_list = $(".menu").collision(".test");
if (hit_list.length != 0) {
alert("welcome Earthling!");
}
});
});
The problem with my method is that, it doesn't detect collision every time. Even though it passes over the white division fine, the alert isn't displayed everytime.
Am I going wrong anywhere in checking for collision? Is there a better/more efficient method to detect collisions during animation ?
jQuery animate has a step callback (https://api.jquery.com/animate/), it gets executed after each step of the animation.
Use it like this:
$(document).ready(function () {
var hit_list;
$(".container").click(function () {
$(".menu").stop().animate({
left: "+=100px"
}, {
duration: 300,
complete: function () {
$(".menu").animate({
left: "0"
}, 800);
},
step: function(){
//Test for collision
hit_list = $(".menu").collision(".test");
if (hit_list.length != 0) {
alert("welcome Earthling!");
}
}
});
});
});
Try this http://jsfiddle.net/aamir/y7PEp/6/
$(document).ready(function () {
var hit_list;
var hits=0;
$(".container").click(function () {
var $this = $(this);
function checkCollision() {
//Test for collision
hit_list = $(".menu").collision(".test");
if (hit_list.length != 0) {
hits++;
$(".menu").html(hits+ ' hits');
}
}
$(".menu").stop().animate({
left: "100px"
}, 300, function () {
checkCollision();
$(".menu").animate({
left: "0"
}, 800);
});
});
});
I developed a simple jQuery animation first and later I create a jQuery function for reusability which will do the same thing. Here is a demo: http://jsfiddle.net/SpMns/
My code is working but not reliably so: when I click on the button to run the code, nothing happens; clicking it two or three times will start the animation. Why wouldn't it work the first time?
Please have a look at my routine and tell me which area I need to rectify:
jQuery.fn.busyToggle = function(ImgLoadSrc, marginBottom, opacity, speed,
easing, callback) {
var oDiv = $("<div id='BusyBox'><img src='" + ImgLoadSrc
+ "' alt='Loading...'/><div><em>Loading Wait...</em></div></div>");
if ($("#BusyBox").exists() == false) {
//alert('div not exist');
oDiv.css("background", "-moz-linear-gradient(center top , #F1F2F2 0%, #F1F2F2 100%) repeat scroll 0 0 transparent");
oDiv.css("border-top-left-radius", "5px");
oDiv.css("border-top-right-radius", "5px");
oDiv.css("bottom", "0px");
oDiv.css("font-size", "0.8em");
oDiv.css("font-style", "normal");
oDiv.css("font-weight", "normal");
oDiv.css("left", "50%");
oDiv.css("margin-left", "-45px");
oDiv.css("padding-top", "20px");
oDiv.css("position", "fixed");
oDiv.css("text-align", "center");
oDiv.css("width", "90px");
oDiv.css("height", "50px");
oDiv.css("margin-bottom", "-70px");
oDiv.css("background-repeat", "no-repeat");
oDiv.css("background-position", "center center");
oDiv.data('IsUp', 1)
oDiv.appendTo('body');
}
// i work with jquery data function for achieving toggle behaviour
if (oDiv.data('IsUp') == 1) {
oDiv.data('IsUp', 0);
return this.stop(true).animate({
marginBottom: marginBottom,
opacity: opacity
}, {
queue: false,
duration: speed,
complete: callback
});
}
else {
oDiv.data('IsUp', 1);
return this.stop(true).animate({
marginBottom: marginBottom,
opacity: opacity
}, {
queue: false,
duration: speed,
complete: callback
});
}
};
$(document).ready(function() {
$("#Process").click(function() {
if (flag == 1) {
$('#BusyBox').busyToggle('images/loader.gif', 0, 1, 500, 0, function() {
alert('div visible')
});
flag = 0;
}
else {
$('#BusyBox').busyToggle('images/loader.gif', -70, 0, 500, 0, function(){
alert('div hide')
});
flag = 1;
}
return false;
});
});
What could be causing this to fail the first time it's run?
The problem are is the this usage in the #busyToggle
On the first call $('#BusyBox') becomes an empty Array, which means that this (in #busyToggle) is also empty Array.
A better solution to your probelm would be to call busyToggle this way:
$('#Process').busyToggle('images/loader.gif', 0, 1, 500, 0, function() {
alert('div visible')
});
and use $('#BusyBox') instead of this in your function.
You can find all the code over there: http://jsfiddle.net/ubmCt/8/
P.S: I've also added following line to the ready function, otherwise it won't run in most browsers
var flag = 1;
I'm trying to implement the scrollTo script jquery script from http://flesler.blogspot.com/2007/10/jqueryscrollto.html but I cant figure it out because of the way my script is setup:
$(".viewproject").click(function() {
$(...).scrollTo( '#lightwrap', 2500, {easing:'elasout'} );
var id = $(this).attr("id").replace(/^.(\s+)?/, "");
var contentTobeLoaded = $("#workitem" + id).html();
$('#projectajax').animate({
opacity: '0'
}, 600, function() {
$('#projectpanel').show();
if ($('#projectajax').is(':visible')) {
$('#projectajax').html(contentTobeLoaded).delay(500).animate({
opacity: '1'
}, 500, function() {
$('#thumbnails, h3').css('border-top', '1px solid #fff');
});
}
else {
$('#projectajax').html(contentTobeLoaded).hide().slideDown(1000).delay(500).animate({
opacity: '1'
}, 500, function() {});
}
});
});
$(document).on('click', '#projectclose', function(e) {
e.preventDefault();
$("#projectpanel").slideUp('1000');
});
or http://jsfiddle.net/Rvgk9/
what im trying to do is when the image or link is clicked, i want it to scroll to the top of the website before if #projectajax is visible and also if #projectajax isnt visible.. from what I've tried it just didnt have the scrolling effect at all just snapped to the top of the page.