Disable links till all animations stop and enable them again - javascript

I have an image slider like animation, the differences is that in one slide are several elements, in my case 4 pictures which come from the left or right side in the scene.
The question is how to make the links that trigger the animation function to be disabled until the animation is finished 100%, and then enable again.
Here is my code...
$(document).ready(function() {
//
$('.package_box_menu li').children().click(function(){
$(this).showProducts($(this).attr("id"))
});
jQuery.fn.showProducts = function (clickedSeason) {
var nextToShowSide = $('.'+[clickedSeason]+'_img1').attr("rel");
var active = $('img[ rel |= active]').attr('season');
if (nextToShowSide == 'right') {var whereTo = '-1000px'; var currentToHideSide ="left" };
if (nextToShowSide == 'left') {var whereTo = '3000px'; var currentToHideSide ="right" };
show();
hide(active, whereTo, currentToHideSide);
function show(){
var allToShow = ($('img[ season |= '+[clickedSeason]+']').get()).length;
for (var i = 1; i<= allToShow ; i++){
var delay = $('.'+[clickedSeason]+'_img'+[i]).attr('delay');
var position = $('.'+[clickedSeason]+'_img'+[i]).attr('left');
$('.'+[clickedSeason]+'_img'+[i]).stop().delay(delay).animate({'margin-left': position }, 1000, 'easeOutExpo').attr('rel','active');
}
};
function hide(active, whereTo, currentToHideSide){
var all = ($('img[ rel |= active]').get()).length;
for (var i = 1; i<= all ; i++){
if ($('.'+[active]+'_img'+[i]).attr('rel') == 'active') {
$('.'+[active]+'_img'+[i]).stop().delay([i]+'00').animate({'margin-left': whereTo }, 1000, 'easeInExpo').attr('rel', currentToHideSide );
}
}
};
};
jQuery().showProducts('spring');
});

if you are just trying to make sure a link isn't clicked while being animated add this to your click.
$('.package_box_menu li').children().click(function(){
if($('img[class$=img1]').is(':animated')) {
event.preventDefault();
return false;
}
$(this).showProducts($(this).attr("id"));
});
This will simply refuse the click while it animated and then work when it stops. $(this) could be replaced with something that is being animated for example your slide :)
NOTE
As there is no HTML shown I had to make some assumptions on the selector i used 'img[class$=img1]' which is a img where the class ends in 'img1' taken from the '_img1').attr("rel");
Copied your site to Fiddle and got it working with the change i mentions here

Related

Javascript slider shows white screens

Hi i'm building a javascript slider for my portfolio with Javascript. The slides work properly but when i add a fading transition i keep getting a white flash between the 2 slides. Anyone knows how to create a smooth fade between them?
I added a JSfiddle down below.
Here's my javascript:
$(function () {
var theInterval; // Slide speed
var images = new Array();
var counter = 1;
var defaultSettings = {
"sliderContainer": "#slider" // SliderContainer
, "pauseWithMouse": true // Turn on/off pause with mouse
, "sliderSpeed": 3000 // Slide speed
, "transitionSpeed": 200 // transition speed
};
// intialize slider
// if myImages exists then
images = myImages;
if (images.length > 0) {
$(defaultSettings.sliderContainer).append('<img id="sliderImg" width="900" src="' + images[0] + '" />');
startSlide(images);
}
function cycleImages(images) {
if (counter >= images.length) {
counter = 0;
}
console.log(counter);
document.getElementById("sliderImg").src = images[counter];
counter++;
var images = $('#sliderImg')
var now = images.filter(':visible')
var next = now.next().length ? now.next() : images.first()
var speed = defaultSettings.transitionSpeed; //Transition speed
now.fadeOut(speed);
next.fadeIn(speed);
}
function startSlide() {
console.log('start');
theInterval = setInterval(function () {
cycleImages(images);
}, defaultSettings.sliderSpeed);
// Set interval time
};
var stopSlide = function () { // Stop slides on hover
console.log('stop');
if (defaultSettings.pauseWithMouse) {
clearInterval(theInterval);
}
};
$('#sliderImg').on('mouseover', function () { // Stop slides on mouseover
stopSlide();
});
$('#sliderImg').on('mouseout', function () { // Continue with slides on mouseout
startSlide();
});
});
The JS Fiddle Link
This is happening because there is no background while the fade in occurs. The easiest way to fix this is to add a z-index property to the image or the slide.
For example give the first image an z-index of 1 and the second one a z-index of 2
Here is the code that you should implement:
var subs = $(this).find('#sliderImg');
var index = subs.eq(0).css('z-index');
subs.gt(0).each(function() {
$(this).css('z-index', ++index);
});
The idea is to access each element of the array via the tag you provided #sliderImg and using the jQuery method each to increase the z-index css property with 1.
Here is a working fiddle: Working Fiddle

jQuery scroll to div on hover and return to first element

I basically have a div with set dimensions and overflow: hidden. That div contains 7 child divs (but only shows one at a time) that I would like to be smoothly scrolled through vertically when their respective links are hovered.
However, the first section (div) doesn't have a link and is the default section when no link is hovered.
Take a look at this jsFiddle to see a basic structure of what I'm talking about: http://jsfiddle.net/YWnzc/
I've attempted to accomplish this with jQuery scrollTo but haven't been able to get it to work.
Any help would be greatly appreciated. Thanks.
Something like this?
http://jsfiddle.net/YWnzc/5/
code:
jQuery("#nav").delegate("a", "mouseenter mouseleave", function (e) {
var i, self = this,
pos;
if (e.type == "mouseleave") {
i = 0;
}
else {
//Find out the index of the a that was hovered
jQuery("#nav a").each(function (index) {
if (self === this) {
i = index + 1; //the scrollTop is just calculated from this by a multiplier, so increment
return false;
}
});
}
//Find out if the index is a valid number, could be left undefined
if (i >= 0) {
//stop the previous animation, otherwise it will be queued
jQuery("#wrapper").stop().animate({
scrollTop: i * 200
}, 500);
//I would retrieve .offsetTop, but it was reporting false values :/
}
e.preventDefault();
});
FYI : That JSFIDDLE you sent me to went to MooTools framework, not jQuery... fyi. (might be why its not working?
Copy and paste this code exactly and it will work in jQuery for animated scrolling.
Try this for smooth scrolling within the DIV, I tested it - it works great. You
$(function() {
function filterPath(string) {
return string
.replace(/^\//,'')
.replace(/(index|default).[a-zA-Z]{3,4}$/,'')
.replace(/\/$/,'');
}
var locationPath = filterPath(location.pathname);
var scrollElem = scrollableElement('#wrapper');
// Any links with hash tags in them (can't do ^= because of fully qualified URL potential)
$('a[href*=#]').each(function() {
// Ensure it's a same-page link
var thisPath = filterPath(this.pathname) || locationPath;
if ( locationPath == thisPath
&& (location.hostname == this.hostname || !this.hostname)
&& this.hash.replace(/#/,'') ) {
// Ensure target exists
var $target = $(this.hash), target = this.hash;
if (target) {
// Find location of target
var targetOffset = $target.offset().top;
$(this).click(function(event) {
// Prevent jump-down
event.preventDefault();
// Animate to target
$(scrollElem).animate({scrollTop: targetOffset}, 400, function() {
// Set hash in URL after animation successful
location.hash = target;
});
});
}
}
});
// Use the first element that is "scrollable" (cross-browser fix?)
function scrollableElement(els) {
for (var i = 0, argLength = arguments.length; i <argLength; i++) {
var el = arguments[i],
$scrollElement = $(el);
if ($scrollElement.scrollTop()> 0) {
return el;
} else {
$scrollElement.scrollTop(1);
var isScrollable = $scrollElement.scrollTop()> 0;
$scrollElement.scrollTop(0);
if (isScrollable) {
return el;
}
}
}
return [];
}
});
FYI : Credit for this code does not go to me as an individual developer, although I did slightly tweak the code. The owner and creator of this code is Chris Coyier and you can find more about this scrolling code here:
http://css-tricks.com/snippets/jquery/smooth-scrolling/
Here's a working example: http://jsfiddle.net/YWnzc/7/
And the code (pretty similar to rizzle's, with a couple changes that I'll explain):
$('a').hover(function(){
var selector = $(this).data('section');
var scrollAmount = $(selector).offset().top + $('#wrapper')[0].scrollTop - 129;
$('#wrapper').animate({scrollTop: scrollAmount}, 250);
},function(){
$('#wrapper').animate({scrollTop: 0}, 250);
});
First, var selector = $(this).data('section'); because in jsFiddle, the href attribute was returning the full path of the page + the hash. So I changed it to an html5 data attribute (data-section).
The next line is similar to rizzle's, except that we grab the offset of the section and add it to the current scrollTop value of the #wrapper. As he pointed out, there are some weird offset issues going on still, and I found that subtracting 129 did the trick. While this 129 number might seem like something that is likely to break, I did test out changing the sizes of the sections, making them not equal, etc, and it continued to work. I'm using Chrome, and perhaps a non-webkit browser would need a different constant to subtract. But it does seem like that 129 number is at least some kind of constant.
The rest should be pretty self-explanatory.
One thing to note: as you move your cursor over the <a> tags, the content of the #wrapper div will seem to jump around, but that's just because the mouseleave part of the hover event briefly gets triggered as the cursor moves. I'm sure you can solve that one though :)
$("#nav a").hover(function () {
var sectionName = $(this).attr("href");
var sectionPos = $(sectionName).offset().top;
var wrapperPos = $("#wrapper").offset().top;
var wrapperScroll = $("#wrapper").scrollTop();
var scrollPos = sectionPos - wrapperPos + wrapperScroll;
$("#wrapper").stop().animate({scrollTop:scrollPos}, 600);
}, function () { $("#wrapper").stop().animate({scrollTop:0}, 600); });

Fading content using setInterval doesn't work properly when user switches tabs

I have a slideshow component that I wrote in javascript using jQuery. The slideshow consists of three slides, each containing HTML content. Each slide is a div with class .slide. Every 7 seconds, I fade out the slides that should be hidden and fade in the one I want to show. I also have some buttons (indicators) that let the user manually switch slides by clicking the buttons.
It all works great, unless the user switches tabs. If enough time elapses, when the user returns, there will be two slides visible. When the switch slide event fires, everything goes back to normal.
Example:
http://jsfiddle.net/vwdJ5/
Here is my code:
var slides = $(".slide");
var indicators = $(".indicator li");
var currentSlide = 1;
var incrementSlide = function () {
currentSlide = currentSlide === 2 ? 0 : currentSlide + 1;
};
var switchSlide = function () {
if (currentSlide === 0) {
var onDeck = 1;
var inTheHole = 2;
} else if (currentSlide === 1) {
var onDeck = 2;
var inTheHole = 0;
} else {
var onDeck = 0;
var inTheHole = 1;
}
indicators.removeClass("active");
$(indicators[currentSlide]).addClass("active");
$(slides[onDeck]).hide();
$(slides[inTheHole]).fadeOut(200, function () {
$(slides[currentSlide]).fadeIn(200);
incrementSlide();
});
};
var interval = setInterval(switchSlide, 7000);
indicators.click(function () {
clearInterval(interval);
if ($(this).hasClass("first")) {
currentSlide = 0;
} else if ($(this).hasClass("second")) {
currentSlide = 1;
} else if ($(this).hasClass("third")) {
currentSlide = 2;
}
switchSlide();
interval = setInterval(switchSlide, 7000);
});
Modern browsers (Chrome and FF6 for sure) are now using a "queue" system on inactive tabs. You switch tabs, and setTimeout and setInterval still run, but at a much slower speed. Then when you go back to the tab, it tries to catch up, normally resulting in weird issues (sorry, probably not the most technical description).
It's recommended to use requestAnimationFrame instead if possible.
For your example where you need something to happen at specific times, you can just add stop() prior to the animations, which will prevent multiple animations from occurring at once

JQuery ready function problems

I am using the dropShadow plugin, and I have a problem with the JQuery ready function.
When I have my code like this:
$(document).ready(function() {
$('div#shadow').dropShadow();
$('#navigation li.mainmenu').bind('mouseover', navigation_open);
$('#navigation li').bind('mouseout', navigation_timer);
});
It will only make the shadow once the drop menu has come out, which is the second function. Any ideas why?
The full code for the JS is:
$(document).ready(
function()
{
$('#navigation li.mainmenu').bind('mouseover', navigation_open);
$('#navigation li').bind('mouseout', navigation_timer);
});
var timeout = 500;
var closetimer = 0;
var ddmenuitem = 0;
var highlightmenu = 0;
var returncolor = 0;
var textreturncolor = 0;
var height = 0;
var originaltop = 0;
var resettop = 0;
var top = 0;
var shadowExists = 0;
var dropshadow = 0;
function drawShadow(){
//draw the shadow only on mouse enter
dropshadow = $(this).find('ul').dropShadow({top: 4, opacity: 1});
$('.dropShadow').css('visibility','visible');
}
function navigation_open()
{ navigation_canceltimer();
navigation_close();
height = $(this).height();
ddmenuitem = $(this).find('ul');
//Double Liners are above 40 pixels
menu = ddmenuitem.find('li');
/*===Need to get the top pos. of the item and adjust it since it is absolute; relative does not work*/
top = ddmenuitem.position().top;
resettop = top;
if (height > 40){
top = top - 53;
}
else{
top = top - 35;
}
ddmenuitem.css('top', top.toString() + "px");
//---ADD A DROP SHADOW...USING JQUERY PLUGIN
ddmenuitem.dropShadow({top: 4, opacity: 1});
$('.dropShadow').css('visibility','visible');
ddmenuitem.css('visibility', 'visible');
returncolor = $(this).find('a#highlight').css('background-color');
textreturncolor = $(this).find('a#highlight').css('color');
highlightmenu = $(this).find('a#highlight').css('background-color','#6487ad');
highlightmenu.css('color','#ffffff');
highlightmenu.css('font-weight','bold');}
function navigation_close()
{ if(ddmenuitem){
ddmenuitem.css('visibility', 'hidden');
ddmenuitem.css('top',resettop);
ddmenuitem.removeShadow();
}
if(highlightmenu){ highlightmenu.css('background-color',returncolor);
highlightmenu.css('color',textreturncolor);
}
}
function navigation_timer()
{
closetimer = window.setTimeout(navigation_close, timeout);}
function navigation_canceltimer()
{ if(closetimer)
{
window.clearTimeout(closetimer);
closetimer = null;}}
document.onclick = navigation_close;
The HTML would be like this for static:
<div id="shadow">
//images here
</div>
I don't know if you need to see anymore, however the drop menu is just a list, but I want to be able to apply this to the static images and it won't until the drop menus come out.
The dropshadow plugin appears to be designed for stationary page elements. From the dropshadow js file:
"This jQuery plug-in adds soft drop shadows behind page elements. It is only intended for adding a few drop shadows to mostly stationary objects, like a page heading, a photo, or content containers"
EDIT: Perhaps you could achieve the effect you're looking for with css? http://robertnyman.com/2010/03/16/drop-shadow-with-css-for-all-web-browsers/
The problem lies within the CSS, when calling dropShadow() for the first time the css for class dropShadow is set to hiddent (this was placed there to make the dynamic pieces work in IE (all other browsers fine without it). In the javascript you can see this by the $('.dropShadow').css('visibility','visible'); being called.

Help with modifying my custom JQuery slider to allow continous scrolling

You can view my custom slider here: http://www.awaismuzaffar.com/examples/index.html
And below is the JQuery code for it:
$(document).ready(function() {
// Slider Function
var slideWidth = $('div.slide').width();
// Set the left position of each div element
$('div.slide').each(function(index){
$(this).css('left', index * slideWidth ); // Multiply each div element by the index(0, 1 etc) so each div is placed inline
});
// Next step is to animate the div elements
var clickCount = 1;
var slideCount = $('div.slide').length;
// Set the previous button to hide when loading with the first slide
if(clickCount == 1){
$('a#previous-button').css('background-color', '#cccccc');
}
$('a#next-button').click(function() {
if(clickCount < slideCount) {
$('div.slide').animate({"left":"-=" + slideWidth}, 'slow');
$('a#previous-button').css('background-color', '#ffffff');
clickCount++;
}
if(clickCount == slideCount) {
$('a#next-button').css('background-color', '#cccccc'); // Hide or grey out button
}
});
$('a#previous-button').click(function() {
if(clickCount > 1){
$('div.slide').animate({"left":"+=" + slideWidth}, 'slow');
$('a#next-button').css('background-color', '#ffffff');
clickCount--;
}
if(clickCount == 1){
$('a#previous-button').css('background-color', '#cccccc'); // Hide or grey out button
}
});
});
I am trying to modify this slider to allow continous scrolling.
I am not sure exactly how to achieve this, I am assuming I need to use append, but I am not sure how to make use of it.
Thanks.
You're doing things a little manually, I'm thinking someone else might've solved the problem. But in any case, in your click next button, you'd need to load in additional content when you hit the end. So if I were you, I'd do something like this:
$('a#next-button').click(function() {
...
if(clickCount == slideCount) {
$('a#next-button').css('background-color', '#cccccc');
$.get(moreContentUrl, objectRepresentingCurrentScrollPosition, loadContent);
spinner.show(); // show some kind of spinner here (you can also hook up a default spinner on all ajax events with a global ajax handler
}
});
function loadContent(response) {
// append your content (your controller should return just the <div class="slide" /> elements, and give them a class="slide newSlide" so you can distinguish them below
// you can also do client side templating here. would be more efficient, then just return the items as objects instead of html
$('#slide-container').append(response.itemsHtml);
// slide all new divs right
$('div.newSlide').animate({"left":"+=" + slideWidth}, 'fast');
$('div.newSlide').removeClass('newSlide');
// update variables and un-grey the next button
$('a#previous-button').css('background-color', '#ffffff');
slideCount += response.itemCount;
// hide the spinner shown when starting the load
spinner.hide();
}
Give it a shot, hope it works. Now, to clean up that code a little bit, I'd suggest using css classes instead of inline background colors, etc.
Here's a solution (somewhat like Shaz's), just less code :):
$(document).ready(function(){
$('#previous-button').click(function(){slidePanel(-1)});
$('#next-button').click(function(){slidePanel(1)});
var n = 0;
var animating = false;
$('#slide-'+n).css('display', 'block');
function slidePanel(delta)
{
if(!animating)
{
animating = true;
var d = (delta > 0 ? $('#slide-'+n).width()*-1 : $('#slide-'+n).width());
$('#slide-'+n).animate({
left: "+="+d
}, 'slow', function() { $(this).css('display', 'none'); animating = false; });
n = (n + delta) % $('div.slide').length;
n = n < 0 ? $('div.slide').length + n : n;
$('#slide-'+n).css('left', $('#slide-container').offset().left +(d*-1));
$('#slide-'+n).css('display', 'block');
$('#slide-'+n).animate({
left: 0
}, 'slow');
}
}
});
Check out the sample here.
(I know there's a way to figure out the "current slide" with a one liner equation, but I think I'm brain dead atm :P)
(Edited to account for repeatedly clicking)
Try something like this: http://fiddle.jshell.net/Shaz/dsBkf/

Categories

Resources