programing

요소가 표시되는 시점에 대한 이벤트 수신기?

megabox 2023. 7. 28. 21:54
반응형

요소가 표시되는 시점에 대한 이벤트 수신기?

저는 페이지에 포함될 도구 모음을 만들고 있습니다.포함될 div는 기본적으로 다음과 같이 표시됩니다.이벤트 수신기를 초기화할 수 있도록 이벤트가 표시될 때 들을 수 있는 방법이 있습니까?아니면 포함된 페이지에서 변수를 전달해야 합니까?

감사해요.

앞으로 새로운 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:

function 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/

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

제가 조금 늦을 수도 있지만, Mutation Observer를 사용하여 원하는 요소의 변화를 관찰할 수 있습니다.변경 사항이 발생하면 요소가 표시되는지 확인하기만 하면 됩니다.

요소가 뷰포트에 표시될 때 일부 코드만 실행하려는 경우:

function onVisible(element, callback) {
  new IntersectionObserver((entries, observer) => {
    entries.forEach(entry => {
      if(entry.intersectionRatio > 0) {
        callback(element);
        observer.disconnect();
      }
    });
  }).observe(element);
}

눈에 이벤트가 하면) 교차 는 " 가이되면화교시발약다호생니관출합요차가찰자소로간가가트벤이▁when다"라고 부릅니다.callback그리고 나서 스스로를 파괴합니다..disconnect().

다음과 같이 사용합니다.

onVisible(document.querySelector("#myElement"), () => console.log("it's visible"));

요소가 완전히 표시될 때 콜백이 트리거되도록 하려면 변경해야 합니다.entry.intersectionRatio > 0entry.intersectionRatio === 1.

적어도 한 가지 방법이 있지만, 그다지 좋은 방법은 아닙니다.요소를 폴링하여 다음과 같은 변경 사항을 확인할 수 있습니다.

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

이 코드는 제 머리에서 빗나가서 잘 될지 모르겠어요.

가장 좋고 쉬운 해결책은 대상을 표시하는 함수에 콜백을 설정하는 것입니다.

저도 같은 문제가 있었고 우리 사이트를 위해 그것을 해결하기 위해 jQuery 플러그인을 만들었습니다.

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

다음은 예제를 기반으로 사용하는 방법입니다.

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

@figa가 말했듯이, 만약 이것이 당신 자신의 웹 페이지라면, 당신은 당신이 요소를 볼 수 있게 만든 후에 당신이 실행할 필요가 있는 모든 것을 실행해야 합니다.

그러나 질문에 대답하기 위해(및 Chrome 또는 Firefox Extensions를 만드는 모든 사용자(일반적인 사용 사례), Mutation Summary 및 Mutation Observer를 통해 DOM 변경사항이 이벤트를 트리거할 수 있습니다.

를 들어, 예들어사, 다여하요로 구성된 data-widgetDOM에 추가할 속성입니다.David Walsh의 블로그에서 다음과 같은 훌륭한 예를 인용합니다.

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

응답에는 , 이 포함됩니다.valueChanged를 포함한 특성이 됩니다.display

중첩된 요소에 대해서도 작동하는 간단한 해결책은 관찰자 크기 조정을 사용하는 것입니다.

모든 최신 브라우저(https://developer.mozilla.org/en-US/docs/Web/API/Resize_Observer_API) 에서 작동해야 합니다.

규칙이 때 CSS 규칙은 다음과 .display:none(직접 또는 조상 요소를 통해) 적용되면 모든 차원이 0이 됩니다.따라서 가시화를 감지하기 위해서는 가시화 시 0이 아닌 차원을 가진 원소가 필요합니다.

const block=document.querySelector("#the-block")
const resizewatcher=new ResizeObserver(entries => {
  for (const entry of entries){
    console.log("Element",entry.target, 
      (entry.contentRect.width == 0) ? 
      "is now hidden" : 
      "is now visible"
    )
  }
})
resizewatcher.observe(block)

DOMAtrModified 이벤트 수신기 브라우저 지원에 대해 설명하려면 다음과 같이 하십시오.

크로스 브라우저 지원

이러한 이벤트는 다음과 같은 여러 브라우저에서 일관되게 구현되지 않습니다.

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

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

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

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

Elmar의 이전 답변을 확장하여 Bootstrap navbar 하위 메뉴의 입력 상자에 초점을 맞추기 위해 사용했습니다.

메뉴가 확장되었을 때 검색 상자에 포커스가 가기를 원했습니다. .onfocus()가 작동하지 않았습니다. 이벤트가 트리거될 때(마우스업 이벤트에서도) 요소가 보이지 않기 때문인 것 같습니다.하지만 이것은 완벽하게 작동했습니다.

<ul class="navbar-nav ms-auto me-0 ps-3 ps-md-0">
    <li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" title="Search" id="navbardrop" data-bs-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
            <i class="fas fa-search"></i>
        </a>
        <div class="dropdown-menu dropdown-menu-end search-menu">
            <form action="{% url 'search' %}" method="get">
                <div class="form-group row g-1 my-1 pb-1">
                    <div class="col">
                        <input type="text" name="query" id="searchbox" class="form-control py-1 ps-2" value="{% if search_query %}{{ search_query }}{% endif %}">
                    </div>
                    <div class="col-auto">
                        <input type="submit" value="Search" class="btn-primary form-control py-1">
                    </div>
                </div>
            </form>
        </div>
    </li>
</ul>

그러면 js에서:

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

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

  observer.observe(element);
};

respondToVisibility(document.getElementById("searchbox"), (visible) => {
  if (visible) {
    document.getElementById("searchbox").focus();
  }
});

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

내 해결책:

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

언급URL : https://stackoverflow.com/questions/1462138/event-listener-for-when-element-becomes-visible

반응형