2013-01-19 17 views
8

Ho un gruppo di div posizionati assolutamente uno sopra l'altro. Quando lego un evento click a tutti, solo il div principale risponde. Come posso inviare l'evento a tutti i divs sotto il cursore?Come propagare un clic a tutte le div al cursore?

+0

È l'errore che non è possibile accedere per consolare il messaggio su cui si fa clic? – defau1t

+0

@ defau1t: Vuole che il clic venga visualizzato tre volte nella console quando si fa clic una volta. – Amberlamps

+0

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

risposta

3

Prendendo il suggerimento di FelixKling utilizzare document.elementFromPoint() e violino di Amberlamps, e impiegando jQuery per le interazioni DOM, ho finito con il seguente:

$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 viene utilizzato per garantire gli elementi sono mostrato di nuovo, anche se si verifica un errore.

Due meccanismi permettono l'evento click da passare attraverso o meno:

  • fissare il conduttore di solo gli elementi selezionati (standard di jQuery).
  • namespace l'evento click, click.passThrough analogo a event.stopPropagation().

Separatamente o in combinazione, questi meccanismi offrono una certa flessibilità nel controllare l'attaccamento e la propagazione del comportamento "passThrough". Ad esempio, in DEMO, provare a rimuovere la classe p dall'elemento "b" e vedere come è cambiato il comportamento di propagazione.

Così com'è, il codice deve essere modificato per ottenere un comportamento a livello di applicazione diverso. Una soluzione più generale sarebbe:

  • permettere l'attacco di programmazione del comportamento specifica per l'applicazione
  • consentono un'inibizione programmatica di propagazione "PassThrough", analogo a event.stopPropagation().

Entrambe queste aspirazioni potrebbe essere ottenuto mediante un evento clickPassthrough in jQuery, con sottostanti comportamento "PassThrough", ma più lavoro sarebbero coinvolti per conseguire tale. Forse qualcuno vorrebbe provare.

+0

Quanto è cortese da parte tua concedere crediti laddove è dovuto il credito. :) – TheOne

+0

I problemi sorgono quando l'elemento su cui si fa clic è un'ancora –

+0

Se qualcun altro ha lo stesso problema di me: 'if ($ (successivo) .prop (" tagName ") === 'A') {window.location .href = $ (successivo) .attr ('href'); } ' –

1

Questo non è così facile come si potrebbe pensare. Questa è una soluzione che mi è venuta in mente. L'ho testato solo su Chrome e non ho utilizzato alcun framework.

Il seguente snippet è solo per aggiungere un evento click a ogni div nel documento, che emette il nome della classe quando viene attivato.

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

Collegamento di un evento click per l'elemento del corpo in modo che ogni singolo evento click viene notato dal nostro script.

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

scorrere tutti i div che si desidera controllare (si potrebbe desiderare di registrare qui al tuo campo preferito di div). Genera il loro stile calcolato e controlla se le coordinate del mouse si trovano nel raggio della posizione div più la sua larghezza e altezza. Non attivare l'evento click quando il div è il nostro elemento di origine perché l'evento click è già stato attivato da allora.

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> 

Ho anche aggiunto un jsFiddle

+0

Come funziona la tua soluzione? Potresti spiegarlo invece di pubblicare semplicemente il codice? –

+1

@FelixKling: ho aggiunto alcune spiegazioni. Penso che sia sufficiente, vero? – Amberlamps

+0

Ottimo! Basta notare che 'e.srcElement' è solo IE (Chrome ha aggiunto alcune delle funzionalità di IEs). La proprietà ufficiale dell'elemento originario è 'e.target'. –

0

Un modo semplice potrebbe essere quella di utilizzare 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

Questo dà il mio 'Clic: 3' quando clicco solo sulle due div inferiori. – Amberlamps

+0

Mi spiace, vedere l'aggiornamento. –

0

Se vengono impilate elementi assolutamente potrebbe essere più semplice per impilare tutti in un contenitore posizionato, e gestire gli eventi di questo genitore. È quindi possibile manipolare i suoi bambini senza dover misurare nulla.

Problemi correlati