요소가 표시 될 때 이벤트 리스너?


113

페이지에 포함될 도구 모음을 만들고 있습니다. 포함될 div는 기본적으로 display : none 입니다. 도구 모음에 이벤트 리스너를 배치하여 표시 될 때 수신하여 초기화 할 수있는 방법이 있습니까? 아니면 포함하는 페이지에서 변수를 전달해야합니까?

감사


이 답변이 도움이 되었습니까? stackoverflow.com/questions/1397251/…
kangax

@kangax, 감사합니다. 그러나 널리 구현되지 않았기 때문에 전체 이벤트 리스너 아이디어를 스크래치하고 다른 경로로 갈 것이라고 생각합니다.
JD Isaacks

JavaScript에서 "onVisible"이벤트를 구현하려면이 답변을 참조하십시오. stackoverflow.com/a/3807340/975097
Anderson Green


제발 볼 수 있습니다. stackoverflow.com/questions/45429746/…
Martin

답변:


8

Javascript 이벤트는 사용자 상호 작용을 처리 합니다. 코드가 충분히 구성되어 있으면 가시성이 변경되는 동일한 위치에서 초기화 함수를 호출 할 수 있어야합니다 (즉 myElement.style.display, 여러 위치에서 변경해서는 안되며 대신 다음과 같은 기능 / 메소드를 호출합니다. 이것과 당신이 원하는 다른 것).


8
그러나 가시성의 변화를 어떻게 감지 할 수 있습니까 (예 : 요소가 표시되는 즉시 함수 호출)?
Anderson Green

나는 당신이 그렇게 할 수 없다고 생각합니다. 변화를 감지하는 대신 당신이 할 일은 그것이 어디에서 유발되었는지 정확히 알고 거기에 전화를 거는 것입니다. 가시성의 변화가 당신 자신의 코드가 직접적으로 책임을지는 것이 아니고 (예를 들어 lib) 그 논리가 매우 인위적인 것이라면 운이 좋지 않습니까? :)
maltalef 2013

6
나는이 질문에 대한 모든 의미에도 불구하고 실제 문제와 관련이 없기 때문에이 질문에 반대했습니다. (프레임에 아무것도 표시하지 않으면 모든 하위 요소가 표시되지 않습니다.)
Sebas

2
@Sebas, 나는 왜 아이들의 가시성이 여기서 중요한지 이해하지 못합니다. 어쨌든 대답이 특정 경우에 유용하지 않았지만 대부분의 프로그래머에게 해결책 (또는 해결책이없는 이유에 대한 설명)을 가리키는 경우, 제 겸손한 의견으로는 여전히 유효한 대답입니다. 다른 답변 중 더 좋은 답변 (특히 기술이 개선되고 새로운 옵션이 제공 될 때 나중에 만들어진 답변)이 마음에 드신다면, 반대 투표보다 정답 변경 요청이 더 적절할 것이라고 생각합니다. 어떤 경우, 헤드 업 : 감사
maltalef

2
@figha, 어린이는 아니지만보고있는 요소가 표시되는 프레임에있는 경우 = none, 그 어떤 흔적도 없습니다.
Sebas

66

앞으로는 새로운 HTML Intersection Observer API가 여러분이 찾고있는 것입니다. 대상이라고하는 하나의 요소가 장치 뷰포트 또는 지정된 요소와 교차 할 때마다 호출되는 콜백을 구성 할 수 있습니다. 최신 버전의 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/


2
> Intersection Observer API를 사용하면 대상이라고하는 하나의 요소가 장치 뷰포트 또는 지정된 요소와 교차 할 때마다 호출되는 콜백을 구성 할 수 있습니다.
stil

1
InteractionObserver는 현재 Safari에서 작동하지 않습니다. caniuse.com/#feat=intersectionobserver 패치가 진행중인 것 같습니다. bugs.webkit.org/show_bug.cgi?id=159475
Pic Mickael

8
이와 같은 멋진 것에 대한 IE의 지원 부족이 언제 우리의 삶을 망치지 않을까요?
Peter Moore

5
지원을 중단하자마자 @PeterMoore. 그냥 하지마.
johny why

4
LOL. 때로는 우리의 결정이 아닙니다.
Peter Moore

45
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
조상이 표시되지 않고 표시되기 때문에 targetNode가 표시되지 않으면 작동하지 않습니다.
Marco Eckstein

찬성! 나는 또 다른 유래 응답이 사용 : stackoverflow.com/questions/48792245/...
닉 티 메르을

안타깝게도 이는 요소에 인라인 스타일을 사용할 때만 작동합니다. CSS 클래스의 변경으로 인해 변경된 경우가 아닙니다 (이전 상황에서는 이미 완전한 프로그램 제어 권한을 가지고있을 가능성이 높은 시나리오입니다). 문제를 보여주는 바이올린 : jsfiddle.net/elmarj/uye62Lxc/4 . 스타일 변화를 관찰하는 방법에 대한 자세한 설명은 여기를 참조하십시오 : dev.to/oleggromov/observing-style-changes---d4f
엘마 얀센에게

사실 올바른 관찰자가 될 것이다 여기에 사용 IntersectionObserver- stackoverflow.com/a/52627221/2803743
카노

이 솔루션은 요소를 켜고 끄고 싶고 해당 요소를 직접 제어하지 않고 디스플레이 값 변경에 반응하려는 경우에 유용합니다
Eran Goldin

15

적어도 한 가지 방법이 있지만 그다지 좋은 방법은 아닙니다. 다음과 같이 변경 사항에 대해 요소를 폴링 할 수 있습니다.

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

이 코드는 내 머릿속에서 벗어 났으므로 작동하는지 확실하지 않습니다.

가장 쉬운 해결책은 당신의 목표를 표시하는 기능에 콜백을 가지고하는 것입니다.


1
흥미 롭군요, 감사합니다. 몇 년 후 DOMAttrModified의 상태가 변경되었습니다. "사용되지 않음.이 기능은 웹 표준에서 제거되었습니다. 일부 브라우저에서 여전히 지원할 수 있지만 삭제 중입니다." (모질라)
BurninLeo

MutationObserver 는 새로운 것입니다.
mindplay.dk

14

나는 이와 같은 문제가 있었고 우리 사이트에서 그것을 해결하기 위해 jQuery 플러그인을 만들었습니다.

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

귀하의 예에 따라 사용하는 방법은 다음과 같습니다.

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

4
이 솔루션은 사용 .is(':visible')과 함께 setTimeout.
Hp93

7

@figha가 말했듯 이 이것이 자신의 웹 페이지 라면 요소를 표시 한 후에 실행해야하는 모든 것을 실행해야합니다.

그러나 질문에 답하기 위해 (그리고 이것이 일반적인 사용 사례 인 Chrome 또는 Firefox 확장 프로그램을 만드는 모든 사람 ) Mutation SummaryMutation Observer 가 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.


아마도 그는 그것이 실제로 화면에 언제 있는지 알고 싶어하기 때문일 것입니다. 그렇습니다. 저는 반대 투표자가 같은 이유를 가지고 있다고 가정 할 수 있습니다.
Dave Hillier

질문에 대답하지 않으며 링크 만 게시하는 것은 권장되지 않습니다.
Alex Holsgrove 2011

@AlexHolsgrove 링크에서 예제를 추가했습니다. 포스터는 페이지에 툴바를 추가하는 것에 대해 이야기하기 때문에 타사 페이지에 툴바를 추가하고 요소가 DOM에 추가되기를 기다리는 것처럼 보입니다.이 경우 Mutations가 최고의 API입니다.
mikemaccana 2017

이 부분은 돌연변이 관찰 과정에서 "가시성"이 들어오는 부분을 설명하지 않습니다.
Mike 'Pomax'Kamermans


3

DOMAttrModified 이벤트 리스너 브라우저 지원에 대해 언급하기 만하면됩니다.

브라우저 간 지원

이러한 이벤트는 다른 브라우저에서 일관되게 구현되지 않습니다. 예를 들면 다음과 같습니다.

  • 버전 9 이전의 IE는 변형 이벤트를 전혀 지원하지 않았으며 버전 9에서 일부를 올바르게 구현하지 않았습니다 (예 : DOMNodeInserted).

  • WebKit은 DOMAttrModified를 지원하지 않습니다 (웹킷 버그 8191 및 해결 방법 참조).

  • "변이 이름 이벤트", 즉 DOMElementNameChanged 및 DOMAttributeNameChanged는 Firefox (버전 11 기준) 및 다른 브라우저에서도 지원되지 않습니다.

출처 : https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Mutation_events


-2

내 솔루션 :

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

5
모든 사람에게 원래 jQuery의 코드를 사용했다고 말해야합니다. 그러면 더 많은 자신감을 얻을 수 있습니다.)
aemonge

1
"내 솔루션". 이 남자의 신경.
앙드레 실바

@ AndréSilva 아마도 그는 jQuery를 썼을 것입니다. : O
앤드류
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.