JQuery - 悬停事件未在Hover out上触发

时间:2012-09-04 15:23:26

标签: jquery

我正在实现我自己的'工具提示',每当你将鼠标悬停在它上面时它会创建一个新的div元素,并在悬停时删除它。下面的代码从我使用的内容中删除,但它显示了问题:当用户慢慢地将鼠标放在$('#'+ fieldName)对象上时,当你将鼠标移到上面时,这段代码就完美了。对象然后快速将其从工具提示中拉出来不会被删除。有没有办法改善我的代码?

我尝试实现一个系统,我在其中创建所有工具提示框并隐藏它们,然后在悬停时显示它们,但它带来了同样的问题,鼠标快速移出物体并且悬停不开火。

$('#' + fieldName).hover(
    function () { /* Create new DOM element */
        /* My ajax stuff here */
        var data = 'test';
        var tooltipBox = $('<div id="' + fieldName + '_tooltip">' + data + '</div>');
        $("body").prepend(tooltipBox);
    },
    function () { /* Remove Tooltip from DOM */
        $('#' + fieldName + '_tooltip').remove();
    }
);

答案:

在Robert Koritnik和sajawikio的帮助下:

如果您需要在悬停时使用悬停的AJAX调用进行工具提示,则可以执行小操作以使其正常工作。

var callingAjax = false;
var removeTooltip = false;
$('#tooltip').hover(
     function() {
          callingAjax = true;
          $.post(.. {
              callingAjax = false;
              /* do stuff */
              if(removeTooltip)
                   /* code to remove tooltip */
              removeTooltip = false;
          });
     },
     function() {
          if(callingAjax) 
              removeTooltip = true;
          else
              /* code to remove tooltip */
     }
);

2 个答案:

答案 0 :(得分:6)

您的代码可以使用

我已将您的代码放在JSFiddle中并且它有效,因此您必须遇到其他问题。我可以尽可能快地在链接上移动鼠标,但每次都会删除工具提示。

我正在使用Chrome。你的药物是什么?

  

注意:我在JSFiddle和你的代码之间的唯一区别是我使用了append而你使用了prepend。我已经改变了,原因很明显。尝试更改它,你会明白为什么。但它在两个方面都有效。

     

注意2 :实际上,如果您将append更改为prepend,它实际上会模拟快速鼠标移动,因为当对象被预先设置时,鼠标会悬停在链接。因此,不要尽可能快地移动鼠标,移动元素以模拟相同的行为。

实际问题

问题是您在创建工具提示之前在悬停中执行其他操作。这是否是一个Ajax调用并不重要。它可能是任何异步的,因此Javascript线程可以执行下一个函数。如果执行的时间超过你留在元素上的时间,那么你的鼠标想要删除尚未创建的东西(稍后会被删除)。

两种可能的解决方案:

  1. 添加工具提示优先,然后执行其他操作。
  2. 在悬停事件执行后推迟Ajax调用。
  3. 警告

    我强烈建议在悬停事件中不执行 ajax代码,因为您可能会触发大量请求。实际上,超过浏览器可以处理。如果你必须在悬停时执行ajax请求,那么就这样做:hover fires并准备一个函数调用,在它之后立即执行,但是如果一个函数不在进行中,那么该函数只会发出一个Ajax调用:

    // variable outside of hover closures
    var ajaxExecuting = false;
    
    // code to put within your hover handler
    setTimeout(function() {
        if (!ajaxExecuting)
        {
            ajaxExecuting = true;
            // do your AJAX stuff
        }
    }, 0);
    

答案 1 :(得分:1)

是的,有问题。让速度不是一个因素 - 不要把它留给机会并确保当你盘旋时,你的悬停激活 - 当你盘旋时,你的悬停激活!万无一失!这样,你就不会像你所说的那样陷入“扩张”状态!换句话说,一次执行一个事件“来回切换样式”而不是使用持久处理程序。

(请参阅示例代码的实际操作 - 如果您使用的元素当然更大,则效果很好) - http://jsfiddle.net/4jArC/

var fieldName = "whatever";

function b(evt) { /* Remove Tooltip from DOM */
    $('#' + fieldName + '_tooltip').remove();
    $(evt.currentTarget).one('mouseover',a);
}

function a (evt) { /* Create new DOM element */
    /* My ajax stuff here */
    var data = 'test';
    var tooltipBox = $('<div id="' + fieldName + '_tooltip">' + data + '</div>');
    $("body").prepend(tooltipBox);
    $(evt.currentTarget).one('mouseout',b);
}

$('#' + fieldName).one('mouseover', a);
​