2009-07-18 14 views
17

Mam elementy, które są pod elementem z nieprzezroczystością: 0.5, które chcę móc kliknąć. Jak mogę kliknąć "do" najwyższego elementu?rejestrowanie kliknięć elementu znajdującego się pod innym elementem

Oto przykład, który pokazuje mój problem. Kliknij pola, aby je włączać i wyłączać. Możesz go edytować on jsbin, aby wypróbować swoje rozwiązanie.

Punkty premiowe, jeśli możesz przełączać pola przy najechaniu kursorem.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> 
<head> 
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js"></script> 
<title>Sandbox</title> 
<meta http-equiv="Content-type" content="text/html; charset=utf-8" /> 
<style type="text/css" media="screen"> 
body { background-color: #000; } 
.box {width: 50px; height: 50px; border: 1px solid white} 
.highlight {background-color: yellow;} 
</style> 
<script type="text/javascript"> 
var dthen = new Date(); 
$('<div id="past">').css({'height': (dthen.getMinutes()*60)+dthen.getSeconds() +'px' 
      ,'position': 'absolute' 
      ,'width': '200px' 
      ,'top': '0px' 
      ,'background-color': 'grey' 
      ,'opacity': '0.5' 
      }) 
     .appendTo("#container"); 

setInterval(function(){ 
    dNow = new Date(); 
    $('#past').css('height', ((dNow.getSeconds()+(dNow.getMilliseconds()/1000))*50)%300 +'px'); 
},10) 

$(".box").click(function(){ 
     $(this).toggleClass("highlight"); 
    }); 
</script> 
</head> 
<body> 
    <div id="container"> 
    <div class="box" style="position:absolute; top: 25px; left: 25px;"></div> 
    <div class="box" style="position:absolute; top: 50px; left: 125px;"></div> 
    <div class="box" style="position:absolute; top: 100px; left: 25px;"></div> 
    <div class="box" style="position:absolute; top: 125px; left: 125px;"></div> 
    <div class="box" style="position:absolute; top: 225px; left: 25px;"></div> 
    <div class="box" style="position:absolute; top: 185px; left: 125px;"></div> 
    </div> 
</body> 
</html> 
+1

Nie sądzę, że jesteśmy tutaj, aby napisać dla ciebie kompletne rozwiązanie. Korzystając z sugestii podanych poniżej, powinieneś sam wdrożyć to rozwiązanie. SO nie jest darmowym sklepem konsultacyjnym. –

+3

Nie mogę uwierzyć, że jestem jedyną osobą, która kiedykolwiek będzie chciała to zrobić. Myślę więc, że każdy kod demonstrujący, jak to zrobić, znajdzie zastosowanie poza tym, co zaplanowałem. Nie widzę problemu z pytaniem o kod, aby to zrobić. –

+1

sam, użyj również addClass zamiast wszystkich tych ustawień, używając .css – redsquare

Odpowiedz

16

OK, więc są 2 rzeczy, myślę, że należy: (1) odpowiedź CSS3, że nie jest jeszcze powszechnie przyjęte i (2) plan tworzenia kopii zapasowych JavaScript dla reszty. (nie wiem, co zrobić z użytkownikami bez JS w starszych przeglądarkach, które nie obsługują części CSS). Czytaj dalej ...

pierwsze: Użyj tego kodu CSS3 aby górny element „niewidzialne” dla myszki interakcji:

pointer-events: none; 

To nie jest jeszcze kompatybilne z różnymi przeglądarkami. Działa tylko na SVG & HTML Elements w Gecko & Przeglądarki Webkit, ale tylko na elementach SVG w Operze, a nie w ogóle w IE.

Per do MDN:

własności CSS-events wskaźnik pozwala autorom kontrolować, czy gdy element może być celem myszy imprezy. Ta właściwość jest używana do określenia, pod jaką okolicznością (jeśli dowolne) zdarzenie myszy powinno przejść "przez" element i cel, który jest "pod" tym elementem.

Oto że dokumentacja: https://developer.mozilla.org/en/css/pointer-events

drugie: korzystanie z niektórych javascript Detection Feature dla tych przeglądarek, które nie obsługują tej CSS. Musisz przetasować własny, podobny do Modernizr, ponieważ nie testuje on jeszcze tego (według mojej wiedzy). Chodzi o to, że utworzysz element, zastosujesz do CSS wskaźnik zdarzenia, sprawdzisz go i jeśli przeglądarka obsługuje tę funkcję, otrzymasz oczekiwany wynik, w przeciwieństwie do czegoś pustego lub niezdefiniowanego; następnie zniszcz element. W każdym razie, po wykryciu funkcji można użyć jQuery lub podobnego, aby dołączyć detektor do najwyższego elementu i przypisać z niego kliknięcie, aby przejść do czegoś innego. Sprawdź jQuery i skorzystaj z funkcji click(), aby uzyskać więcej informacji (za mało reputacji, aby opublikować link, sry).

Jeśli dostanę czas później, być może uda mi się opracować na nim szybki jsFiddle. Mam nadzieję, że to pomoże.

+0

To działa! Porównaj rozwiązanie [point-events] (http://jsbin.com/limesat/edit?html,css,js,output) za pomocą [original solution] (http://jsbin.com/pefop/edit?html, css, js, wyjście). Oczywiście zdarzenia wskaźnikowe nie istniały, gdy po raz pierwszy zadałem to pytanie w 2009 roku. [IE11 ​​była pierwszą wersją obsługującą zdarzenia pointerowe] (http://caniuse.com/#search=pointer-events) i która pojawiła się w 2013. –

+0

Jeśli potrzebujesz obsługi IE10 lub niższej, Modernizr wydaje się teraz mieć test na CSS Pointer Events –

+0

Rozwiązuje to również problem z hover. Możesz po prostu dołączyć style do '.box: hover' i nadal będzie to działało, jeśli pod elementem #past. –

20

Jeśli najwyższy element jest zawarty w elemencie poniżej, można pozwolić „bańki przez” zdarzenie. Jeśli tak nie jest, musisz wywołać kliknięcie ręcznie. Nie ma sposobu, aby wystrzelić obsługę zdarzenia po prostu klikając.

Aby ręcznie ognia zdarzenie, można to zrobić:

$("#topelement").click(function() { 
    $("#elementbelow").click(); 
    return false; 
}); 

EDIT (odpowiedź na komentarze):

wyliczyć wszystkie pola, można to (czy z góry na moje . głowica bez testowania, nie może być nawet składnia-bezbłędne)

$("#topelement").click(function(e) { 
    $(".box").each(function() { 
     // check if clicked point (taken from event) is inside element 
     var mouseX = e.pageX; 
     var mouseY = e.pageY; 
     var offset = $(this).offset; 
     var width = $(this).width(); 
     var height = $(this).height(); 

     if (mouseX > offset.left && mouseX < offset.left+width 
      && mouseY > offset.top && mouseY < offset.top+height) 
     $(this).click(); // force click event 
    }); 
}); 
+0

Musisz wyliczyć wszystkie elementy DOM, aby zobaczyć, czy kliknięty punkt znajduje się wewnątrz jednego lub więcej elementów. Nie ma możliwości, aby przeglądarka mogła to zrobić dla ciebie. –

+0

Dzięki, że zadziałało: http://jsbin.com/pefop/edit –

2

Mam zmodyfikowany kod od góry do funkcji jquery, ktoś może się przydać:

Znajdź alternatywa kliknięciu na elementach:

$('.child').click(function(e) { 
    $(this).siblingsUnderMouse(e).each(fn); 
}); 

Jeśli chcesz zignorować przezroczyste piksele w obrazach:

$('.child').click(function(e) { 
    $(this).siblingsUnderMouse(e).each(function() { 
     var clickOnVisiblePixel = $(this).isOnVisiblePixel(e); 
    }); 
}); 

Kod:

$.fn.reverse = [].reverse; 
$.fn.siblingsUnderMouse = function(e, filter) 
{ 
    filter = filter || '*'; 

    var arr = $(); 
    this.parent().children().filter(filter).reverse().each(function() 
    { 
     var t = $(this); 
     // check if clicked point (taken from event) is inside element 
     var x = (e.pageX - t.offset().left).toFixed(); 
     var y = (e.pageY - t.offset().top).toFixed(); 
     var w = t.width(); 
     var h = t.height(); 

     if (x < 0 || x >= w || y < 0 || y >= h) 
      return; 

     arr.push(t); 
    }); 
    return arr; 
} 

$.fn.isOnVisiblePixel = function(e) 
{ 
    if (e.type == 'mouseleave') return false; 

    var t = this[0]; 
    if (!t || t.tagName != 'IMG') 
     t = this.find('img')[0]; 
    if (!t) return; 

    var w = $(t).width(); 
    var h = $(t).height(); 
    var o = $(t).offset(); 
    var x = (e.pageX - o.left).toFixed(); 
    var y = (e.pageY - o.top).toFixed(); 
    if (x < 0 || y < 0 || x >= w || y >= h) 
     return false; 

    var c = $('<canvas>')[0]; 
    c.width = w; 
    c.height = h; 

    var ctx = c.getContext('2d'); 
    ctx.drawImage(t, 0, 0, w, h); 

    var a = ctx.getImageData(x, y, 1, 1).data[3]; 
    return (a > 128); 
} 
1

Myślę, że Lelando dostał właściwy cios. W moim przypadku rozwiązano tylko za pomocą css i można wstawić pointer-events: none do swojego elementu #past.

Powiązane problemy