jQuery脚本在悬停和动画回调时设置活动元素的问题

Problem with a jQuery script that sets an active element on hover and animation callbacks

本文关键字:活动 设置 元素 问题 回调 脚本 悬停 动画 jQuery      更新时间:2023-09-26

我正在一个网站上工作,其中有一系列元素,并且只有其中一个必须在任何时候都是活跃的。当该元素处于活动状态时,会显示一个"Details"div。

当你将鼠标悬停在这些元素上时,这些元素就会被激活,但正如我所说的,它们中只有一个可以同时被激活。我正在用一个活动类设置活动元素。

在我当前的代码中,这是当用户悬停在任意元素上时发生的情况:

  • 上一个活动元素的类'active'被移除,并被淡出
  • 在fadeOut回调中,悬停的元素变为活动的(获得'active'类),并且是fadeIn
  • 如果当前没有活动元素,则悬停的元素变为活动元素(类'active')并淡出。

这可以正常工作,但是当您在元素之间快速悬停时,会有一小段时间没有元素处于活动状态,因此不止一个元素获得活动类并显示

你如何处理这个问题?

下面是我的代码:
function setActive(selected) {

    //stores the active element in a variable
    active = selected;
    //checks if there are currently elements with the 'active' class in the DOM
    if ( $('#info article.active').length > 0) {
        //if there is any currently active element, and its element_id attribute is not the one stored in the active variable
        //it gets the 'active' class removed, its hidden, and in the callback of the animation
        //the newly selected element gets the class 'active' and is shown with fadeIn
        $('#info article.active[element_id!="' + selected + '"]').removeClass('active').fadeOut('fast', function(){
            $('#info article[element_id="' + selected +'"]').addClass('active').fadeIn('normal');
            }); 
    } else {
        //if there is no current active element, the newly selected one is applied the class active, and shown with fadeIn
        $('#info article[element_id="' + selected +'"]').addClass('active').fadeIn('normal');
    }
}

对鼠标过路和/或挑剔的目标误射是一个常见的问题。标准的解决方案是在悬停"停留"之前有一个小的延迟。

重要:问题没有显示setActive()是如何被调用的!

但是如果你像这样构建HTML:

<div id="flyOverControls">
    <ul>
        <li rel="Article_1">Show 111</li>
        <li rel="Article_2">Show 222</li>
        <li rel="Article_3">Show 333</li>
        <li rel="Article_4">Show 444</li>
    </ul>
</div>
<div id="info">
    <article id="Article_1">First article.</article>
    <article id="Article_2">Second article.</article>
    <article id="Article_3">Third article.</article>
    <article id="Article_4">Fourth article.</article>
</div>


然后像这样激活控件:

$("#flyOverControls li").hover (function (zEvent) {setActiveArticle (zEvent); } );


那么这段代码就可以解决问题了。根据口味调整速度。就我个人而言,我会取消淡出。

function setActiveArticle (zEvent)
{
    var dDelay;
    var ActionFunction  = null;
    var targetID        = $(zEvent.currentTarget).attr ('rel');
    if (zEvent.type == 'mouseenter')
    {
        //--- Hovering over a new article control... Pause for an ergo delay.
        dDelay          = 300;
        ActionFunction  = function (targetID, context) {
            //--- If we are setting the same article, then nothing needs be done here.
            if ( ! (context.lastArticle  &&  context.lastArticle == targetID) ) {
                //checks if there are currently elements with the 'active' class in the DOM
                if ( $('#info article.active').length > 0) {
                    /*  If there is any currently active element, and its element_id attribute is not the one stored in the
                        active variable it gets the 'active' class removed, it's hidden, and in the callback of the animation
                        the newly selected element gets the class 'active' and is shown with fadeIn.
                    */
                    $('#info article.active').removeClass ('active').fadeOut ('fast', function () {
                        $('#info article#' + targetID).addClass ('active').fadeIn ('normal');
                    } );
                } else {
                    //if there is no current active element, the newly selected one is applied the class active, and shown with fadeIn
                    $('#info article#' + targetID).addClass ('active').fadeIn ('normal');
                }
                context.lastArticle = targetID;
            }
        };
    }
    else //-- zEvent.type == 'mouseleave'
    {
        //--- Done hovering, no action is needed, other than to wait, in case of user jitter.
        dDelay          = 200;
        ActionFunction  = function (targetID, context) {
            var noOp    = 0;
        };
    }
    if (typeof this.delayTimer == "number")
    {
        clearTimeout (this.delayTimer);
    }
    context             = this;
    this.delayTimer     = setTimeout (function() { ActionFunction (targetID, context); }, dDelay);
}


如果可以的话,用HTML在jsfiddle中设置一个链接,这样我就可以更详细地查看了。

但是我认为你的问题是由淡出和/或淡出的动画引起的。尝试在动画时停止悬停,$('selector').is(':animated') == false,例如

function setActive(selected) {
    //*******if animate is happening, hide elements and removes class
    if ($('#info article').is(':animated')) {
        $('#info article.active').removeClass('active').hide();
    }
    //*******Check if everything is not animated and do hover
    if (!$('#info article').is(':animated')) {
        //stores the active element in a variable
        active = selected;
        //checks if there are currently elements with the 'active' class in the DOM
        if ($('#info article.active').length > 0) {
            //if there is any currently active element, and its element_id attribute is not the one stored in the active variable
            //it gets the 'active' class removed, its hidden, and in the callback of the animation
            //the newly selected element gets the class 'active' and is shown with fadeIn
            $('#info article.active[element_id!="' + selected + '"]').removeClass('active').fadeOut('fast', function() {
                $('#info article[element_id="' + selected + '"]').addClass('active').fadeIn('normal');
            });
        } else {
            //if there is no current active element, the newly selected one is applied the class active, and shown with fadeIn
            $('#info article[element_id="' + selected + '"]').addClass('active').fadeIn('normal');
        }
    }
}