Событие jQuery для запуска действия, когда div становится видимым - PullRequest
292 голосов
/ 04 августа 2009

Я использую jQuery на своем сайте, и я хотел бы вызвать определенные действия, когда определенный div становится видимым.

Можно ли присоединить какой-то "видимый" обработчик событий к произвольным элементам div и запускать определенный код, когда элемент div становится видимым?

Я бы хотел что-то вроде следующего псевдокода:

$(function() {
  $('#contentDiv').isvisible(function() {
    alert("do something");
  });
});

Код предупреждения («сделать что-то») не должен запускаться до тех пор, пока contentDiv фактически не станет видимым.

Спасибо.

Ответы [ 21 ]

182 голосов
/ 04 августа 2009

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

Расширение Jquery:

jQuery(function($) {

  var _oldShow = $.fn.show;

  $.fn.show = function(speed, oldCallback) {
    return $(this).each(function() {
      var obj         = $(this),
          newCallback = function() {
            if ($.isFunction(oldCallback)) {
              oldCallback.apply(obj);
            }
            obj.trigger('afterShow');
          };

      // you can trigger a before show if you want
      obj.trigger('beforeShow');

      // now use the old function to show the element passing the new callback
      _oldShow.apply(obj, [speed, newCallback]);
    });
  }
});

Пример использования:

jQuery(function($) {
  $('#test')
    .bind('beforeShow', function() {
      alert('beforeShow');
    }) 
    .bind('afterShow', function() {
      alert('afterShow');
    })
    .show(1000, function() {
      alert('in show callback');
    })
    .show();
});

Это фактически позволяет вам делать что-то доShow и AfterShow, в то же время выполняя нормальное поведение исходного метода .show ().

Вы также можете создать другой метод, чтобы вам не приходилось переопределять исходный метод .show ().

73 голосов
/ 09 мая 2013

Проблема решается Наблюдателями мутации DOM . Они позволяют привязывать наблюдателя (функцию) к событиям изменения содержимого, текста или атрибутов элементов dom.

С выходом IE11 все основные браузеры поддерживают эту функцию, отметьте http://caniuse.com/mutationobserver

Пример кода следующий:

$(function() {
  $('#show').click(function() {
    $('#testdiv').show();
  });

  var observer = new MutationObserver(function(mutations) {
    alert('Attributes changed!');
  });
  var target = document.querySelector('#testdiv');
  observer.observe(target, {
    attributes: true
  });

});
<div id="testdiv" style="display:none;">hidden</div>
<button id="show">Show hidden div</button>

<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
71 голосов
/ 04 августа 2009

Нет встроенного события, к которому вы можете подключиться, однако вы можете вызвать событие из своего скрипта после того, как сделали div видимым, используя. trigger function

* 1005 например *

//declare event to run when div is visible
function isVisible(){
   //do something

}

//hookup the event
$('#someDivId').bind('isVisible', isVisible);

//show div and trigger custom event in callback when div is visible
$('#someDivId').show('slow', function(){
    $(this).trigger('isVisible');
});
24 голосов
/ 16 мая 2012

Вы можете использовать плагин Live Query от jQuery . И напишите код следующим образом:

$('#contentDiv:visible').livequery(function() {
    alert("do something");
});

Тогда каждый раз, когда contentDiv виден, «делать что-то» будет предупреждено!

20 голосов
/ 04 августа 2009

Решение RedSquare - правильный ответ.

Но в качестве решения IN-THEORY вы можете написать функцию, которая выбирает элементы, классифицируемые как .visibilityCheck ( не все видимые элементы ), и проверяет их свойство visibility значение; если true, то сделай что-нибудь.

После этого функция должна периодически выполняться с использованием функции setInterval(). Вы можете остановить таймер, используя clearInterval() после успешного вызова.

Вот пример:

function foo() {
    $('.visibilityCheck').each(function() {
        if ($(this).is(':visible')){
            // do something
        }
    });
}

window.setInterval(foo, 100);

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

10 голосов
/ 22 октября 2013

Следующий код (взятый из http://maximeparmentier.com/2012/11/06/bind-show-hide-events-with-jquery/) позволит вам использовать $('#someDiv').on('show', someFunc);.

(function ($) {
  $.each(['show', 'hide'], function (i, ev) {
    var el = $.fn[ev];
    $.fn[ev] = function () {
      this.trigger(ev);
      return el.apply(this, arguments);
    };
  });
})(jQuery);
9 голосов
/ 30 сентября 2011

Если вы хотите вызвать событие на всех элементах (и дочерних элементах), которые фактически становятся видимыми, $ .show, toggle, toggleClass, addClass или removeClass:

$.each(["show", "toggle", "toggleClass", "addClass", "removeClass"], function(){
    var _oldFn = $.fn[this];
    $.fn[this] = function(){
        var hidden = this.find(":hidden").add(this.filter(":hidden"));
        var result = _oldFn.apply(this, arguments);
        hidden.filter(":visible").each(function(){
            $(this).triggerHandler("show"); //No bubbling
        });
        return result;
    }
});

А теперь ваша стихия:

$("#myLazyUl").bind("show", function(){
    alert(this);
});

Вы можете добавить переопределения к дополнительным функциям jQuery, добавив их в массив сверху (например, "attr")

9 голосов
/ 17 января 2012

триггер события скрытия / показа, основанный на Glenns ideea: убрал переключатель, потому что он запускает шоу / скрытие, и мы не хотим 2 огня для одного события

$(function(){
    $.each(["show","hide", "toggleClass", "addClass", "removeClass"], function(){
        var _oldFn = $.fn[this];
        $.fn[this] = function(){
            var hidden = this.find(":hidden").add(this.filter(":hidden"));
            var visible = this.find(":visible").add(this.filter(":visible"));
            var result = _oldFn.apply(this, arguments);
            hidden.filter(":visible").each(function(){
                $(this).triggerHandler("show");
            });
            visible.filter(":hidden").each(function(){
                $(this).triggerHandler("hide");
            });
            return result;
        }
    });
});
5 голосов
/ 28 апреля 2015

У меня была такая же проблема, и я создал плагин jQuery, чтобы решить ее для нашего сайта.

https://github.com/shaunbowe/jquery.visibilityChanged

Вот как вы могли бы использовать его на основе вашего примера:

$('#contentDiv').visibilityChanged(function(element, visible) {
    alert("do something");
});
4 голосов
/ 27 августа 2013

Используйте jQuery Waypoints:

$('#contentDiv').waypoint(function() {
   alert('do something');
});

Другие примеры на сайте jQuery Waypoints .

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