2013-01-19 12 views
8

我有一堆絕對互相重疊的divs。當我將一個點擊事件綁定到所有這些事件時,只有頂級div響應。我該如何將事件發送給光標下的所有div?如何傳播點擊光標下的所有div?

+0

是否無法記錄以控制點擊的消息的錯誤? – defau1t

+0

@ defau1t:當點擊一次時,他希望在控制檯中出現三次'clicked'。 – Amberlamps

+0

http://jsfiddle.net/vA5WQ/23/ – TheOne

回答

3

以FelixKling的建議,使用document.elementFromPoint()和Amberlamps的小提琴,並採用的jQuery的DOM的交互,我結束了以下內容:

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

DEMO

try/catch/finally用於確保元素再次顯示,即使發生錯誤。

兩種機制允許通過或不被傳遞點擊事件:

  • 處理程序安裝於僅選擇的元素(標準的jQuery)。
  • 命名空間點擊事件,click.passThrough類似於event.stopPropagation()

單獨或組合起來,這些機制在控制「passThrough」行爲的附着和傳播方面提供了一些靈活性。例如,在DEMO中,嘗試從「b」元素中刪除類p,並查看傳播行爲是如何改變的。

就目前而言,代碼需要進行編輯才能獲得不同的應用程序級行爲。一個更廣義的解決辦法:

  • 允許的針對特定應用的行爲
  • 允許「直通」傳播的編程抑制,類似於event.stopPropagation()方案附件。

這兩個雄心可能通過在jQuery中建立clickPassthrough事件來實現,具有潛在的「passThrough」行爲,但是要做到這一點將涉及更多的工作。也許有人想去一趟。

+0

在信用到期的情況下,你如何禮貌地給予信用。 :) – TheOne

+0

當被點擊的元素是一個錨點時出現問題 –

+0

如果其他人有和我一樣的問題:'if($(next).prop(「tagName」)==='A'){window.location .href = $(next).attr('href'); }' –

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元素,以便每個單擊事件都被我們的腳本注意到。遍歷你要檢查的所有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

+0

您的解決方案如何工作?你能否解釋它,而不是隻發佈代碼? –

+1

@FelixKling:我添加了一些解釋。我認爲這就夠了,不是嗎? – Amberlamps

+0

太棒了!請注意,'e.srcElement'只是IE瀏覽器(儘管Chrome增加了一些IE功能)。原始元素的官方屬性是「e.target」。 –

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 = {}; 
    } 
}); 
+0

當我點擊兩個底部div時,這給了我'Clicks:3'。 – Amberlamps

+0

對不起,請參閱更新。 –

0

如果您堆疊元素絕對可能更爲簡單堆疊它們放在一個定位的容器,並處理這個父的事件。然後,您可以操作其兒童而無需測量任何東西。