I'm a bit new with javascript/jquery. I've taken over a page design with images and links that animate on rollovers. I've almost got things working, but there's one last glitch. The mouseover effects of an image growing/shrinking work fine when the page is first loaded. But if the user clicks on a link, a secondary animation fires, and an embedded page is loaded. If they click to return to the "main page" the original growing/shrinking rollover animation no longer fires. I'm positive it's because the page has already passed the onload, but I don't know how to fix this. Here's a stripped down version of my jquer:

$(document).ready(function(){

/* now the image animations */


var $width_one = $("#sq1").width();
var $height_two = $("#sq2").height();
var $height_three = $("#sq3").height();
var $width_three = $("#sq3").width()
var $width_four = $("#sq4").width();
var $height_four = $("#sq4").height();

/* this following is the portion that will no longer work after they've clicked on things */

 $(".square.one,#link_nest").mouseenter(function(){

    if ($(".the-nest")[0]){
        $("#link_nest").css({color:"#153d53",fontWeight:"400"},100);
        }
    else{

        $(".square.one").filter(':not(:animated)').animate({width:"150px"},200);
        $("#link_nest").css({color:"#153d53",fontWeight:"400"},100);
        $("#square_caption1").css('visibility','visible');
    } 
 });


 $(".square.one,#link_nest").mouseleave(function(){
    if ($(".the-nest")[0]){
        $("#link_nest").css({color:"black",fontFamily: "Source Sans Pro",fontWeight:"300"},100);
    }
    else{
        $(".square.one").filter(':not(:animated)').animate({width:$width_one},200);

        $("#link_nest").css({color:"black",fontFamily: "Source Sans Pro",fontWeight:"300"},100);
        $("#square_caption1").css('visibility','hidden');
    }

 });

  /* several other, like this. This ends the section that won't run. */

/* now starts the onclick animation. After this runs, and they click on the link that repositions the page back to the "home page" the above animation no longer fires */

$('.square-container').on('click', '.square', function(event) {


    if ( $(this).hasClass('active') ) {

            $('.details h1').animate({ opacity: 0 }, 600, function() { $('.details h1').html(' '); });
            $('.details .article').animate({ opacity: 0 }, 600, function() { $('.details .article').unload(); });
            $('.one').stop().animate({ width: '135', height: '207', left: '648', top: '190', opacity: 1}, 600, function() { /*animation completed*/ });         
            $('.two').stop().animate({ width: '154', height: '208', left: '485', top: '125', opacity: 1}, 600, function() { /*animation completed*/ });
            $('.three').stop().animate({ width: '245', height: '145', left: '231', top: '170', opacity: 1}, 600, function() { /*animation completed*/ });   
            $('.four').stop().animate({ width: '190', height: '139', left: '413', top: '340', opacity: 1}, 600, function() { /*animation completed*/ });
            $('.square').removeClass('active');


        } else if ( $(this).hasClass('one') ) {


            /*hide the currently visible stuff*/
            $('.details h1').animate({ opacity: 0 }, 600, function() { /*animation completed*/ });
            $('.details .article').animate({ opacity: 0 }, 600, function() { /*animation completed*/ });
            $('#sub-nav').animate({ opacity: 0 }, 1, function() { /*animation completed*/ });


            /*Animate squares positions*/
            $('.one').stop().animate({ width: '227', height: '320', left: '260', top: '26', opacity: 1}, 600, function() {

                /*load content*/;

                $('.details h1').html(' ');
                $('.details .article').load('inc/page1.php');           
                $('.details h1').animate({ opacity: 1 }, 600, function() { /*animation completed*/ });
                $('.details .article').animate({ opacity: 1 }, 600, function() { /*animation completed*/ });
                $('.details .article').animate({ width: '400',left: '260', opacity: 1 }, 600, function() { /*animation completed*/ });
                $('.home-register').animate({ opacity: 0 }, 1, function() { /*animation completed*/ });
                $('#sub-nav').animate({ opacity: 0 }, 1, function() { /*animation completed*/ });
                $('.gallery-subs').css({display:"none",overflow:"visible",position:"relative"},800);
                $('.gallery-subs').animate({ opacity: 0 }, 1, function() { /*animation completed*/ });


             });

             /*Position unselected squares*/    
            $('.two').stop().animate({ width: '90', height: '126', left: '160', top: '180', opacity: 1}, 600, function() { /*animation completed*/ });
            $('.three').stop().animate({ width: '70', height: '70', left: '50', top: '320', opacity: 1}, 600, function() { /*animation completed*/ });  
            $('.four').stop().animate({ width: '80', height: '80', left: '129', top: '350', opacity: 1}, 600, function() { /*animation completed*/ });


            /*Select active square*/
            $('.square').removeClass('active');
            $(this).addClass('active');

        }   /*again, several other rollovers,then … */

            else {          
            alert('nothing');
        }       

    });
});

Dani AI

Generated

Short summary and diagnosis: the hover handlers were bound only once on page ready (and, in ’s follow-up, only when #testit had class main_page). When the UI is driven to a “sub page” the element state changes (and parts of the DOM may be replaced), so the original binding either never runs again or the logic that gated it prevents it from firing. ’s jQuery check fixed the fiddle environment, and was right to suggest delegation — the correct .on signature is different from the example posted.

Two practical, reliable fixes (pick one):

  1. Delegated handlers that check current mode at event time (simplest)
  • Bind the events once to a stable ancestor (document or a container). Inside the handler test whether the page is in “main” mode (for example by checking #testit’s class). This works if elements are replaced by .load() because delegation uses event bubbling.

Example pattern:

// capture original sizes once
var origW = $('#sq1').width();

// bind once, always check the current mode
$(document).on('mouseenter mouseleave', '.square.one, #link_nest', function(e){
  if (!$('#testit').hasClass('main_page')) return;   // ignore on sub-pages
  if (e.type === 'mouseenter') {
    $('.square.one').stop(true).animate({ width: 160 }, 200);
    $('#square_caption1').css('visibility','visible');
  } else {
    $('.square.one').stop(true).animate({ width: origW }, 200);
    $('#square_caption1').css('visibility','hidden');
  }
});
  1. Namespaced bind/unbind (explicit enable/disable)
  • Attach the hover handlers with an event namespace, and call .off('.namespace') to remove them when entering sub-pages; call the enable function when returning to main page.

Example pattern:

function enableRollover(){ $(document).on('mouseenter.roll mouseleave.roll', '.square.one, #link_nest', handler); }
function disableRollover(){ $(document).off('.roll'); }

Other tips and cautions:

  • Verify that addClass/removeClass calls actually run (console.log or inspect the element); missing class changes are a common oversight.
  • If content is being replaced with .load(), prefer delegated handlers or rebind after the replacement.
  • Use .stop(true) (or .stop(true,true) after testing) to avoid queued animations.
  • Avoid using .unload() to clear loaded HTML; use .empty(), .html('') or .remove() and .off() to unbind events from removed nodes.

Tie-back: ’s delegation idea was the right direction; the corrected .on call above and either the runtime-check or namespaced binding pattern will make the rollovers reliably enable/disable as the UI switches between main and sub pages.

Recommended Answers

All 7 Replies

Do you have link that we could test this? Maybe an http://jsfiddle.net/ ?

Just by looking at your code I coudln't find the problem.

I just tried jsfiddle.net for the first time. The animation doesn't seem to be running in there at all:

http://jsfiddle.net/Z4hZh/

tuperntyne, you forgot to add the jQuery reference is the left panel. That's why it didn't work.

I updated it for you, check: http://jsfiddle.net/Z4hZh/2/

I tested the animations and it all seemns to work, verify if theres any problem there please.

strange... The animations are working in jsfiddle. Yet not so on my own location. that's a bummer. :(

Did you tried other browsers in your local env?

Try replacing

$(".square.one,#link_nest").mouseenter(function(){

with

$(document).on(".square.one,#link_nest", 'mouseenter', function(){

actually, I ended up reworking the entire animation and... hah! Now I have the exact opposite problem. hahah! I don't want the mouseovers to work while the user is in the 'sub pages'. ack!

I'm trying to do it with a simple div class , but for some reason it's not switching the class name:

$(document).ready(function(){

/* here I wanted to use a div class to dictate whether this animation runs. By default, page loads with it at 'main_page' */
if ($("#testit").hasClass('main_page')) {


/* now the image animations */


var $width_one = $("#sq1").width();
var $height_one = $("#sq1").height();


$(".square.one,#link_nest").hover(function(){
    if (!$(".square.one").hasClass('animated')) {
        $(".square.one").dequeue().stop().animate({ width:"155px",height:"219px" },240);
        $("#link_nest").css({color:"#153d53",fontWeight:"400"},100);
        $("#square_caption1").css('visibility','visible');
            }
}, function() {
    $(".square.one").addClass('animated').animate({ width:$width_one, height:$height_one }, "normal", "linear", function() {
        $("#square_caption1").css('visibility','hidden');
        $("#link_nest").css({color:"black",fontFamily: "Source Sans Pro",fontWeight:"300"},100);
        $(this).removeClass('animated').dequeue();
    });
});

} else if ( $(this).hasClass('sub_page') ) { /* do nothing */

};


/* end image animations */

/* start showing,hiding */


    $('.square-container').on('click', '.square', function(event) {

/* Here, I'm trying to remove the class - i know it should probably be an 'if' statement. I'm just testing the idea */

    $('#testit').removeClass('main_page');

/* now on to the rest of the actions when clicked */

    if ( $(this).hasClass('active') ) {


            $('.details h1').animate({ opacity: 0 }, 600, function() { $('.details h1').html(' '); });
            $('.details .article').animate({ opacity: 0 }, 600, function() { $('.details .article').unload(); });
            $('.one').stop().animate({ width: '135', height: '207', left: '648', top: '190', opacity: 1}, 600, function() { /*animation completed*/ });         
            $('.two').stop().animate({ width: '154', height: '208', left: '485', top: '125', opacity: 1}, 600, function() { /*animation completed*/ });
            $('.three').stop().animate({ width: '245', height: '145', left: '231', top: '170', opacity: 1}, 600, function() { /*animation completed*/ });   
            $('.four').stop().animate({ width: '190', height: '139', left: '413', top: '340', opacity: 1}, 600, function() { /*animation completed*/ });
            $('.square').removeClass('active');
            /* this animation takes them back to the beginning, so I want to switch div back again */
            $('#testit').addClass('main_page');

        } else if ( $(this).hasClass('one') ) {

    /* in here, I don't want those first animations to run */

            /*hide the currently visible stuff*/
            $('.details h1').animate({ opacity: 0 }, 600, function() { /*animation completed*/ });
            $('.details .article').animate({ opacity: 0 }, 600, function() { /*animation completed*/ });
            $('#sub-nav').animate({ opacity: 0 }, 1, function() { /*animation completed*/ });


            /*Animate squares positions*/
            $('.one').stop().animate({ width: '227', height: '320', left: '260', top: '26', opacity: 1}, 600, function() {

                /*load content*/;

                $('.details h1').html(' ');
                $('.details .article').load('inc/the-nest.php');            
                $('.details h1').animate({ opacity: 1 }, 600, function() { /*animation completed*/ });
                $('.details .article').animate({ opacity: 1 }, 600, function() { /*animation completed*/ });
                $('.details .article').animate({ width: '400',left: '260', opacity: 1 }, 600, function() { /*animation completed*/ });
                $('.home-register').animate({ opacity: 0 }, 1, function() { /*animation completed*/ });
                $('#sub-nav').animate({ opacity: 0 }, 1, function() { /*animation completed*/ });
                $('.gallery-subs').css({display:"none",overflow:"visible",position:"relative"},800);
                $('.gallery-subs').animate({ opacity: 0 }, 1, function() { /*animation completed*/ });
                $("#link_nest").css({color:"#153d53",fontWeight:"400"},100);
                $("#link_hillcrest, #link_3little, #link_early, #link_contact, #link_ii_by_iv, #link_rockport, #link_raw").css({color:"black",fontFamily: "Source Sans Pro",fontWeight:"300"},100);

             });

             /*Position unselected squares*/    
            $('.two').stop().animate({ width: '90', height: '126', left: '160', top: '180', opacity: 1}, 600, function() { /*animation completed*/ });
            $('.three').stop().animate({ width: '70', height: '70', left: '50', top: '320', opacity: 1}, 600, function() { /*animation completed*/ });  
            $('.four').stop().animate({ width: '80', height: '80', left: '129', top: '350', opacity: 1}, 600, function() { /*animation completed*/ });


            /*Select active square*/
            $('.square').removeClass('active');
            $(this).addClass('active');

        }  else {       
            alert('nothing');
        }       

    });
});
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.