2010-11-08 59 views
2

我有一个html表,我试图用jQuery添加一些动画。我非常接近我想要的,但有一个突出的问题。我将尝试描述我正在做什么,尽可能减少表格和脚本的版本。如何让这个jquery动画延迟正常工作?

该表定义如下;

<table> 
    <tbody class="group"> 
    <tr>First</tr> 
    <tr class='slide'><div class='hidden'>Surprise!</div></tr> 
    </tbody> 
    <tbody class="group"> 
    <tr>Second</tr> 
    <tr class='slide'><div class='hidden'>Surprise!</div></tr> 
    </tbody> 
    <tbody class="group"> 
    <tr>Third</tr> 
    <tr class='slide'><div class='hidden'>Surprise!</div></tr> 
    </tbody> 
</table> 

我想要的效果是所有<tr class='slide'>行一旦页面被加载,然后到了slideDown到视图当鼠标指针进入上面的行被隐藏。只要鼠标指针保留在上面的行或.slide行(包含在<tbody>标签中),我就希望.slide行保持在视图中。然后,当鼠标离开<tbody>标记中的任一行时,我希望.slide行能够滑出视图。我已经设法用下面的代码成功地做到了这一点。

<script> 

$(function() { 
    hideRows(); 
    setupEventHandlers(); 
}); 

function hideRows() { 
    $("div.hidden").each(function() { 
    $(this).hide(); 
}); 
}; 
//The hideRows function is much more complicated in my actual page 
//as I have to calculate the div height prior to hiding so it animates 
//correctly. That's why I don't just set display:none; in the stylesheet. 

function setupEventHandlers() { 
    $('.group').mouseenter(function() { 
    var tr = $(this).children('tr.slide'); 
    tr.find("div.hidden").each(function() { 
     $(this).slideDown(); 
    }); 
    }); 
    $('.group').mouseleave(function() { 
    var tr = $(this).children('tr.slide'); 
    tr.find("div.hidden").each(function() { 
     $(this).slideUp(); 
    }); 
}); 
}; 
//note that I have to animate the div rather than the tr 
//as slidedown and slideup don't work on table rows 

</script> 

虽然这个工程有问题,如果你运行的鼠标多行它建立直到所有的动画完成,可以很长时间运行一个巨大的不平稳的混乱。我想要做的就是添加超时时间,以便在进入<tbody>后动画不会一秒钟左右开始播放。如果鼠标在动画被触发前离开了<tbody>,它应该被取消。当鼠标指针离开<tbody>时,slideUp效果也应该延迟相同的数量 - 我希望最后一项要求是,如果您从一个<tbody>向下移动到下一个,slideDown和slideUp效果将同时发生,所以它只是看起来他们之间的标题行正在向上移动(我希望这有些意义)。我已经尝试了几种这样做的方法,但都没有成功。我的最大努力如下:

var timer; 

function setupEventHandlers() { 
    $('.group').mouseenter(function() { 
    var tr = $(this).children('tr.slide'); 
    tr.find("div.hidden").each(function() { 
     div = $(this); 
     timer = setTimeout("div.slideDown();",1000); 
    }); 
    }); 
    $('.group').mouseleave(function() { 
    var tr = $(this).children('tr.slide'); 
    tr.find("div.hidden").each(function() { 
     clearTimeout(timer); 
     div = $(this); 
     setTimeout("div.slideUp();",1000); 
    }); 
}); 
}; 

几乎作品。如果我快速进入然后离开一排,则不会出现动画。如果我输入一行并等待1秒钟,则下一行按计划滑下。如果我然后将该行退出,那么隐藏的行按计划在1秒后向上滑动。但是,如果我输入下面的行出错了。新行按预期在1秒后滑入视图,但旧行仍然存在。我的假设是我的计时器变量被无意中销毁。我试着通过定时器数组和每个行分配一个特定的一个来更具体地了解这个过程,但这没有什么区别。你可能会说,Javascript并不是我的强项。

+0

我解决了我的问题的最大部分。使用相同的变量“div”是主要问题。用div2替换第二个div修复了大部分问题(小问题仍然存在,当快速移植时需要动态变量名 - 希望我很快就能解决这个问题)。 – brad 2010-11-08 10:42:56

回答

0

好的,我终于解决了这个问题(并且学到了很多东西)。

如果我在代码的mouseleave部分中将div替换为div2,则所提供的代码可以工作。向上和向下使用相同的变量名称导致动画不会发生。唯一的问题是,如果我快速淹没无数行,我仍然会得到意想不到的结果,因为这一个变量名被滥用和滥用。

我的解决方案是为每个.slide行提供一个唯一的id,像这样;

<tr class='slide'><div class='hidden'>Surprise!</div></tr> 

我然后使用此ID来生成使用eval和参考这在setTimeout的字符串动态变量名。我的最终代码看起来像这样。

var timer; 

function setupEventHandlers() { 
    $('.group').mouseenter(function() { 
    var tr = $(this).children('tr.slide'); 
    tr.find("div.hidden").each(function() { 
     id = this.id; 
     eval("divdown_" + id + " = $(this);"); 
     downstring = "divdown_" + id + ".slideDown();"; 
     timer = setTimeout(downstring,1000); 
    }); 
    }); 
    $('.group').mouseleave(function() { 
    var tr = $(this).children('tr.slide'); 
    tr.find("div.hidden").each(function() { 
     clearTimeout(timer); 
     id = this.id; 
     eval("divup_" + id + " = $(this);"); 
     upstring = "divup_" + id + ".slideUp();"; 
     setTimeout(upstring,1000); 
    }); 
}); 
}; 

并且很漂亮地工作(至少在Firefox中,我太害怕尝试IE了 - 我要去健身房代替)。

1

尝试使用hoverIntent插件,而不是试图模拟“延迟悬停”与mouseentermouseleave。我几乎总是使用hoverIntent而不是简单的悬停。

+0

谢谢。我看了一下hoverintent,并没有完全达到我想要的。 – brad 2010-11-08 10:43:24