событие mouseenter вызывается дважды, даже после stopPropagation - PullRequest
2 голосов
/ 31 июля 2011

Я новичок в jquery и сейчас сталкиваюсь со странной проблемой.Мне удалось сузить его до того факта, что событие mouseenter вызывается дважды: один раз для содержащего div (это было моим намерением) и снова для элементов внутри этого div (не хорошо).Я пытался использовать «return false» и «stopPropagation», но, похоже, это не работает.вот код:

<!-- JS files (order matters!) -->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.js"></script>


<script type="text/javascript">
$(function (){
    $(".testDiv").hover(
    function(e) /* IN */ {
        $(this).data("htmlBackup", $(this).html());
        $(this).html("TEST 123");
        e.stopPropagation();
        return false;
    }, function(e) /* OUT */ {
        $(this).html($(this).data("htmlBackup"));
        e.stopPropagation();
        return false;
    });
});         
</script>

<!-- this one works -->
<div class="testDiv" style="border: solid">ORIG HTML</div>

<br /> <br /> <br />

<!-- this doesn't work -->
<div class="testDiv" style="border: solid"> <p style="border: solid">ORIG HTML</p></div>

Вы также можете увидеть его здесь: http://jsfiddle.net/rFqyP/3/

Любая помощь будет очень ценится!

Ответы [ 4 ]

3 голосов
/ 31 июля 2011

Происходит следующее: событие mouseenter запускается дважды подряд (это можно легко проверить с помощью некоторых вызовов console.log). Это проблематично, поскольку он изменит html элемента (и сделает его просто «тестовой» строкой), а затем при втором последовательном запуске возьмет html и сохранит его в данных элемента. Но поскольку событие mouseleave не было инициировано, как уже упоминалось, html является «тестовой» строкой, поэтому теперь он сохраняет , что , в данные элемента.

После этого события mouseenter и mouseleave продолжают срабатывать очень хорошо, но html элемента и его данные имеют одинаковую строку "test", поэтому он не изменяется.

Причина, по которой mouseenter срабатывает два раза подряд, заключается в границах. Размеры div меняются, и происходит следующая серия событий:

  1. mouseenter (div становится тоньше)
  2. mouseleave (div становится толще, что приводит к почти автоматическому mouseenter)
  3. mouseenter, как упомянуто в 2, потому что даже если мышь вышла из div, div расширился, и мышь вошла. Но с момента запуска mouseenter div перешел к «тестовой» строке и стал тоньше, поэтому теперь мышь находится за границами div, но без стрельбы mouseleave.
  4. В следующий раз при наведении мыши на div, mouseenter снова сработает <== это два раза подряд </li>

Вы можете увидеть, что это происходит, если, например, вы медленно вводите мышью, некоторые из перечисленных выше событий не происходят, и они действительно будут работать, как и ожидалось.

Кроме того, я не думаю, что это лучшая идея - поменять местами содержимое HTML. Если вы хотите переключаться, я предлагаю hide() и show(). Во-первых, это сохраняет обработчики событий, и это имеет более интуитивный смысл. Вы заинтересованы в сокрытии вещей, а не в сериализации и сохранении.

1 голос
/ 31 июля 2011

Вы можете предотвратить застревание кода, используя флаг, чтобы вы могли определять, когда вы получаете двойные mouseenter события:

$(function(){

  var inside = false;

  $(".testDiv").hover(
    function(e) /* IN */ {
      if (!inside) {
        inside = true;
        $(this).data("htmlBackup", $(this).html());
        $(this).html("TEST 123");
      }
    }, function(e) /* OUT */ {
      inside = false;
      $(this).html($(this).data("htmlBackup"));
    }
  );

});

http://jsfiddle.net/rFqyP/16/

Это будетОднако не решить проблему с разницей в размерах.Когда вы покидаете элемент, перемещаясь за нижнюю границу, он увеличивается и вызывает событие mouseenter, которое снова меняет размер так, что мышь находится снаружи, но не вызывает событие mouseleave, в результате чего элемент выглядит как мышьвсе еще зависает.

Удаление границы из элементов p решает проблему полностью, без необходимости в флаге, поскольку именно граница вызывает разницу в размере.

0 голосов
/ 31 июля 2011

Я вижу проблему (после отладки).У вас есть div и p внутри него, так что ...

Когда вы наводите курсор мыши на div с p, сначала вызывается событие div "mouseover", которое хранит весь html, включая тег p.

Но перед записью этого html-кода обратно в div запускается наведение мыши "p", которое заменяет ваши данные текстом, а не html.

И затем ваш текст наконец-то записывается в div.

0 голосов
/ 31 июля 2011

Я думаю, что второй не работает, потому что HTML отличается. Если вы используете тот же HTML, вам не нужно stopPropagation или return false вообще. Посмотрите на скрипку: http://jsfiddle.net/aC3TG/1/

$(function (){
    $(".testDiv").hover(
    function(e) /* IN */ {
        $(this).data("htmlBackup", $(this).html());
        $(this).html("TEST 123");
    }, function(e) /* OUT */ {
        $(this).html($(this).data("htmlBackup"));

    });
});         
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...