JS: слушатель события, когда элемент становится видимым? - PullRequest
87 голосов
/ 22 сентября 2009

Я создаю панель инструментов, которая будет включена в страницу. div, в который он будет включен, по умолчанию будет display: none . Есть ли способ, которым я могу разместить прослушиватель событий на панели инструментов, чтобы прослушивать, когда он становится видимым, чтобы он мог инициализироваться? или мне придется передать ему переменную со страницы, содержащей ее?

Спасибо

Ответы [ 9 ]

38 голосов
/ 21 июня 2017

В будущем вам понадобится новый API-интерфейс HTML Intersection Observer. Он позволяет настроить обратный вызов, который вызывается всякий раз, когда один элемент, называемый целью, пересекает либо область просмотра устройства, либо указанный элемент. Он доступен в последних версиях Chrome, Firefox и Edge. См. https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API для получения дополнительной информации.

Простой пример кода для наблюдения за дисплеем: нет переключения:

// Start observing visbility of element. On change, the
//   the callback is called with Boolean visibility as
//   argument:

respondToVisibility(element, callback) {
  var options = {
    root: document.documentElement
  }

  var observer = new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
      callback(entry.intersectionRatio > 0);
    });
  }, options);

  observer.observe(element);
}

В действии: https://jsfiddle.net/elmarj/u35tez5n/5/

30 голосов
/ 17 января 2018
var targetNode = document.getElementById('elementId');
var observer = new MutationObserver(function(){
    if(targetNode.style.display != 'none'){
        // doSomething
    }
});
observer.observe(targetNode, { attributes: true, childList: true });

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

15 голосов
/ 28 апреля 2015

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

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

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

$('#contentDiv').visibilityChanged(function(element, visible) {
    alert("do something");
});
14 голосов
/ 23 сентября 2009

Javascript события имеют дело с Взаимодействие с пользователем , если ваш код организован достаточно, вы сможете вызывать функцию инициализации в том же месте, где меняется видимость (т.е. вы не должны ' * во многих местах изменить myElement.style.display, вместо этого вызывать функцию / метод, который делает это, и все, что вы захотите).

14 голосов
/ 23 сентября 2009

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

var previous_style,
    poll = window.setInterval(function()
{
    var current_style = document.getElementById('target').style.display;
    if (previous_style != current_style) {
        alert('style changed');
        window.clearInterval(poll);
    } else {
        previous_style = current_style;
    }
}, 100);

Стандарт DOM также определяет события мутации , но у меня никогда не было возможности их использовать, и я не уверен, насколько хорошо они поддерживаются. Вы бы использовали их так:

target.addEventListener('DOMAttrModified', function()
{
    if (e.attrName == 'style') {
        alert('style changed');
    }
}, false);

Этот код не в моей голове, поэтому я не уверен, сработает ли он.

best и самым простым решением было бы иметь обратный вызов в функции, отображающей вашу цель.

6 голосов
/ 03 июля 2014

Как говорит @figha, если это ваша собственная веб-страница , вам нужно просто запустить все, что вам нужно, после того, как вы сделаете элемент видимым.

Однако, для целей ответа на вопрос (и кто-либо делает расширения Chrome или Firefox , где это распространенный случай использования), Краткое описание мутаций и Наблюдатель мутаций позволит изменениям DOM вызывать события.

Например, запуск события для элементов с атрибутом data-widget, добавляемых в DOM. Заимствование этого превосходного примера из блога Дэвида Уолша :

var observer = new MutationObserver(function(mutations) {
    // For the sake of...observation...let's output the mutation to console to see how this all works
    mutations.forEach(function(mutation) {
        console.log(mutation.type);
    });    
});

// Notify me of everything!
var observerConfig = {
    attributes: true, 
    childList: true, 
    characterData: true 
};

// Node, config
// In this case we'll listen to all changes to body and child nodes
var targetNode = document.body;
observer.observe(targetNode, observerConfig);

Ответы включают added, removed, valueChanged и другие . valueChanged включает в себя все атрибуты, включая display и т. Д.

4 голосов
/ 08 сентября 2014

Вы также можете попробовать этот плагин jQuery: https://github.com/morr/jquery.appear

3 голосов
/ 26 ноября 2014

Просто прокомментируйте поддержку браузера прослушивателя событий DOMAttrModified:

Кросс-браузерная поддержка

Эти события не реализованы согласованно в разных браузерах, например:

  • IE до версии 9 вообще не поддерживал события мутации и некоторые из них не реализованы правильно в версии 9 (например, DOMNodeInserted)

  • WebKit не поддерживает DOMAttrModified (см. Ошибку webkit 8191 и обходной путь)

  • "события имени мутации", т.е. DOMElementNameChanged и DOMAttributeNameChanged не поддерживается в Firefox (начиная с версии 11) и, вероятно, в других браузерах.

Источник: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events

0 голосов
/ 24 апреля 2014

мое решение:

; (function ($) {
$.each([ "toggle", "show", "hide" ], function( i, name ) {
    var cssFn = $.fn[ name ];
    $.fn[ name ] = function( speed, easing, callback ) {
        if(speed == null || typeof speed === "boolean"){
            var ret=cssFn.apply( this, arguments )
            $.fn.triggerVisibleEvent.apply(this,arguments)
            return ret
        }else{
            var that=this
            var new_callback=function(){
                callback.call(this)
                $.fn.triggerVisibleEvent.apply(that,arguments)
            }
            var ret=this.animate( genFx( name, true ), speed, easing, new_callback )
            return ret
        }
    };
});

$.fn.triggerVisibleEvent=function(){
    this.each(function(){
        if($(this).is(':visible')){
            $(this).trigger('visible')
            $(this).find('[data-trigger-visible-event]').triggerVisibleEvent()
        }
    })
}
})(jQuery);

например:

if(!$info_center.is(':visible')){
    $info_center.attr('data-trigger-visible-event','true').one('visible',processMoreLessButton)
}else{
    processMoreLessButton()
}

function processMoreLessButton(){
//some logic
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...