Слушатель событий, когда элемент становится видимым?

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

Спасибо

Ответ 1

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

Ответ 2

В дальнейшем вам нужно новое 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/

Ответ 3

var targetNode = document.getElementById('elementId');
var observer = new MutationObserver(function(){
    if(targetNode.style.display != 'none'){
        // doSomething
    }
});
observer.observe(targetNode, { attributes: true, childList: true });

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

Ответ 4

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

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

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

$('#contentDiv').visibilityChanged(function(element, visible) {
    alert("do something");
});

Ответ 5

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

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);

Этот код не работает, поэтому я не уверен, что он сработает.

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

Ответ 6

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

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

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

var observer = new MutationObserver(function(mutations) {
    // For the sake of...observation...let 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 и т.д.

Ответ 8

Просто, чтобы прокомментировать поддержку браузера прослушивателя событий 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

Ответ 9

мое решение:

; (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
}