要素が表示されるときのイベントリスナー?


113

ページに含めるツールバーを作成しています。含まれるdivは、デフォルトでdisplay:noneになります。初期化できるように、表示されたときにリッスンするようにツールバーにイベントリスナーを配置する方法はありますか?またはそれを含むページから変数を渡す必要がありますか?

ありがとう


この回答は役に立ちますか?stackoverflow.com/questions/1397251/...
kangax

@kangax、ありがとうございます。しかし、広く実装されていないので、イベントリスナーのアイデア全体をスクラッチして、別のルートに進むと思います。
JD Isaacks

JavaScriptでの "onVisible"イベントの実装については、この回答を参照してください:stackoverflow.com/a/3807340/975097
Anderson Green


回答:


8

JavaScriptイベントはユーザーインタラクションを処理します。コードが十分に構成されている場合、可視化が変更されるのと同じ場所で初期化関数を呼び出すことができるはずです(つまりmyElement.style.display、多くの場所で変更してはならず、代わりに関数/メソッドを呼び出します)これとあなたが望むかもしれない他のもの)


8
しかし、どのようにして可視性の変化を検出できますか(つまり、要素が可視化されたらすぐに関数を呼び出します)?
アンダーソングリーン

あなたにはそれができないと思います。変更を検出しようとするのではなく、変更が引き起こされる場所を正確に把握し、そこに電話をかけます。可視性の変化があなた自身のコードが直接責任を負うものではなく(たとえば、いくつかのlib)、それが発生するロジックが非常に不自然なものである場合、私はあなたが運が悪いと思いますか?:)
maltalef 2013

6
私がこの質問に反対票を投じたのは、それが作るすべての意味にもかかわらず、実際の問題とは無関係だからです。(フレームに何も表示しないと、すべての子要素が非表示になります)
Sebas

2
@セバス、私は子供たちの可視性がなぜここで重要であるのか本当にわかりません。とにかく、答えが特定のケース(それが何であれ)に役に立たないが、ほとんどのプログラマにとって解決策(または解決策がない理由の説明)を指し示している場合、それは私の謙虚な意見では依然として有効な答えです。他のより良い回答(特に、テクノロジーが改善されて新しいオプションが利用可能になったときに後で作成された回答)が気に入った場合、正解を変更するリクエストは反対票よりも適切だと思います。いずれにせよ、ヘッズアップに感謝します:)
maltalef 2016年

2
@figha、子ではありませんが、表示している要素が、displayed = noneのフレームにある場合は、その兆候はありません。
セバス

66

今後、新しいHTML Intersection Observer APIがあなたの求めるものです。これにより、ターゲットと呼ばれる1つの要素がデバイスのビューポートまたは指定された要素と交差するたびに呼び出されるコールバックを構成できます。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を使用すると、ターゲットと呼ばれる1つの要素がデバイスのビューポートまたは指定された要素と交差するたびに呼び出されるコールバックを構成できます。
2017年

1
現時点では、InteractionObserverはSafariでは機能しないことに注意してください。caniuse.com/#feat=intersectionobserverパッチが進行中のようです。bugs.webkit.org/show_bug.cgi?id=159475
Pic Mickael

8
このようなクールなものに対するIEのサポートの欠如が私たちの生活を台無しにするのを止めるのはいつですか?
Peter Moore

5
あなたがそれをサポートしようとするのをやめるとすぐに@PeterMoore。しないでください。
ジョニーなぜ

4
笑。時にはそれは私たちの決定ではありません。
Peter Moore

44
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の答えでこれを使用stackoverflow.com/questions/48792245/...
ニックTimmer

残念ながら、これは要素でインラインスタイルを使用している場合にのみ機能し、変更がCSSクラスの変更の結果である場合は機能しません(前者の状況ではおそらく完全にプログラムによる制御が可能であることを考えると、これはより可能性の高いシナリオです)。問題を示すフィドル:jsfiddle.net/elmarj/uye62Lxc/4。スタイルの変更を確認する方法の詳細については、こちらをご覧ください:dev.to/oleggromov/observing-style-changes---d4f
Elmar Jansen

実際には、ここで使用する正しいオブザーバーは次のようになりますIntersectionObserver- stackoverflow.com/a/52627221/2803743
狩野

このソリューションを使用すると、オンとオフを切り替える要素、およびその要素の直接制御がないようにしたいときに便利であり、表示値の変化に反応するようにしたい
エラン・ゴールディン

15

少なくとも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);

このコードは頭から離れているので、うまくいくかどうかはわかりません。

最善かつ最も簡単な解決策は、あなたのターゲットを表示する機能でコールバックを持っているだろう。


1
興味深い、ありがとう。数年後、DOMAttrModifiedのステータスが変更されました。「非推奨。この機能はWeb標準から削除されました。一部のブラウザはまだサポートしているかもしれませんが、削除中です。」(Mozilla)
BurninLeo 2017年

MutationObserverは新しいものです。
mindplay.dk

14

私はこれと同じ問題を抱えており、私たちのサイトのためにそれを解決するためのjQueryプラグインを作成しました。

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

以下は、例に基づいて使用する方法です。

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

4
このソリューションは.is(':visible')とともに使用しsetTimeoutます。
Hp93 2018

7

@fighaが言うように、これが独自のWebページである場合は、要素を表示した後で実行する必要があるものを実行するだけです。

ただし、質問(および一般的なユースケースであるChromeまたはFirefoxの拡張機能を作成しているユーザー)に答えるために、Mutation SummaryおよびMutation Observerでは DOMの変更によってイベントをトリガーできます。

たとえばdata-widget、DOMに追加される属性を持つ要素のイベントをトリガーします。この優れた例を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);

応答が含まれaddedremovedvalueChangedそしてより多くのvalueChanged含め、すべての属性を含んでいるdisplayなど


おそらく、それが実際に画面に表示されるタイミングを知りたいからでしょう。私はそうだ、私はダウンボーターが同じ理由を持っているとしか仮定できない。
デイブヒリアー2017年

質問に答えず、リンクのみを投稿することはお勧めしません。
Alex Holsgrove 2017

@AlexHolsgroveリンクから例を追加しました。ポスターはツールバーをページに追加することについて話しているため、サードパーティのページにツールバーを追加し、要素がDOMに追加されるのを待っているようです。この場合、Mutationsが最良のAPIです。
mikemaccana 2017年

なお、これはまだ突然変異観測プロセス「可視性」での出番を説明し、その部分をカバーしていません。
マイクのPomax時"Kamermans


3

DOMAttrModifiedイベントリスナーのブラウザーサポートについてコメントするだけです。

クロスブラウザのサポート

これらのイベントは、さまざまなブラウザ間で一貫して実装されていません。次に例を示します。

  • バージョン9より前のIEは変異イベントをまったくサポートしていなかったため、バージョン9でそれらの一部を正しく実装していません(たとえば、DOMNodeInserted)。

  • WebKitはDOMAttrModifiedをサポートしていません(webkitバグ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
Andrew
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.