11

私はお互いの上に絶対に配置されたたくさんのdivを持っています。クリックイベントをそれらすべてにバインドすると、最上位のdivのみが応答します。カーソルの下にあるすべてのdivにイベントを送信するにはどうすればよいですか?

4

4 に答える 4

5

FelixKling の提案document.elementFromPoint()と Amberlamps のフィドルを使用し、DOM インタラクションに jQuery を採用すると、次のようになりました。

$divs = $("div").on('click.passThrough', function (e, ee) {
  var $el = $(this).hide();
  try {
    console.log($el.text());//or console.log(...) or whatever
    ee = ee || {
      pageX: e.pageX,
      pageY: e.pageY
    };
    var next = document.elementFromPoint(ee.pageX, ee.pageY);
    next = (next.nodeType == 3) ? next.parentNode : next //Opera
    $(next).trigger('click.passThrough', ee);
  } catch (err) {
      console.log("click.passThrough failed: " + err.message);
  } finally {
    $el.show();
  }
});

デモ

try/catch/finallyエラーが発生した場合でも、要素が再び表示されるようにするために使用されます。

2 つのメカニズムにより、クリック イベントを渡すかどうかを指定できます。

  • ハンドラーを選択した要素のみにアタッチします (標準の jQuery)。
  • click.passThroughに類似した、クリック イベントの名前空間event.stopPropagation()

個別にまたは組み合わせて、これらのメカニズムは、「パススルー」動作の接続と伝播を制御する際にある程度の柔軟性を提供します。たとえば、デモではp、「b」要素からクラスを削除してみて、伝播動作がどのように変化したかを確認してください。

現状では、異なるアプリケーション レベルの動作を取得するには、コードを編集する必要があります。より一般化されたソリューションは次のようになります。

  • アプリ固有の動作をプログラムでアタッチできるようにする
  • と同様に、「passThrough」伝播をプログラムで禁止できevent.stopPropagation()ます。

これらの野心はどちらもclickPassthrough、jQuery でイベントを確立し、"passThrough" 動作を基礎として実現することで実現できますが、それを実現するにはさらに多くの作業が必要になります。誰かが試してみたいと思うかもしれません。

于 2013-01-19T16:54:03.613 に答える
1

これはあなたが思うほど簡単ではありません。これは私が思いついた解決策です。Chrome でのみテストし、フレームワークは使用しませんでした。

次のスニペットはdiv、トリガーされたときにクラス名を出力する、ドキュメント内のすべてにクリック イベントを追加するためのものです。

var divs = document.getElementsByTagName("div");
for(var i = 0; i < divs.length; i++) {
    divs[i].onclick = function() {
        console.log("class clicked: " + this.className);
    };
}

クリック イベントを body 要素にアタッチして、すべてのクリック イベントがスクリプトによって認識されるようにします。

if(document.addEventListener) {
    document.body.addEventListener("click", countDivs);
} else if(document.attachEvent) {
    document.attachEvent("onclick", countDivs);
}

チェックするすべての div を繰り返します (ここで、好みの div 範囲に調整することをお勧めします)。計算されたスタイルを生成し、マウス座標が div の位置に幅と高さを加えた範囲内にあるかどうかを確認します。div がソース要素の場合はクリック イベントをトリガーしないでください。これは、クリック イベントがそれまでに発生しているためです。

function countDivs(e) {
    e = e || window.event;
    for(var i = 0; i < divs.length; i++) {
        var cStyle = window.getComputedStyle(divs[i]);
        if(divs[i] !== e.target && e.pageX >= parseInt(cStyle.left) && e.pageX <= (parseInt(cStyle.left) + parseInt(cStyle.width)) && e.pageY >= parseInt(cStyle.top) && e.pageY <= (parseInt(cStyle.top) + parseInt(cStyle.height))) {
            divs[i].click();
        }
    }
}

CSS:

.a, .b, .c {
  position: absolute;
  height: 100px;
  width: 100px;
  border: 1px #000 solid
}
.a {
  top: 100px;
  left: 100px;
}
.b {
  top: 120px;
  left: 120px;
}
.c {
  top: 140px;
  left: 140px;
}

HTML:

<div class="a"></div>
<div class="b"></div>
<div class="c"></div>

jsFiddleも追加しました

于 2013-01-19T12:52:37.890 に答える
0

要素を完全にスタックする場合は、配置されたコンテナーにすべてをスタックし、この親からのイベントを処理する方が簡単な場合があります。その後、何も測定せずにその子を操作できます。

于 2013-01-19T14:05:06.673 に答える
0

簡単な方法は、elementFromPoint() を使用することです。

http://jsfiddle.net/SpUeN/1/

var clicks = 0,cursorPosition={};

$('div').click(function (e) {
    if(typeof cursorPosition.X === 'undefined') {
         cursorPosition.X = e.pageX;
        cursorPosition.Y = e.pageY;
    }
    clicks++;
    e.stopPropagation();
    $(this).addClass('hided');
    var underELEM = document.elementFromPoint(cursorPosition.X, cursorPosition.Y);
    if (underELEM.nodeName.toUpperCase() === "DIV") $(underELEM).click();
    else {
        $('#clicks').html("Clicks: " + clicks);
        $('.hided').removeClass('hided');
        clicks=0;
        cursorPosition = {};
    }
});
于 2013-01-19T13:02:05.300 に答える