Подтвердить что ты не робот

Регистрация кликов на элементе, который находится под другим элементом

У меня есть элементы, которые находятся под элементом с непрозрачностью: 0.5, который я хочу, чтобы иметь возможность щелкнуть. Как я могу нажать "через" самый верхний элемент?

Вот пример, демонстрирующий мою проблему. Нажмите на квадратики для включения и выключения. Вы можете отредактировать его на jsbin, чтобы попробовать свое решение.

Бонусные баллы, если вы можете переключать флажки при наведении курсора.

<!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>
4b9b3361

Ответ 1

ОК, поэтому есть две вещи, которые, я думаю, я бы сделал: (1) ответ CSS3, который еще не получил широкого распространения, и (2) резервный план Javascript для остальных. (не уверен, что делать с пользователями без JS в старых браузерах, которые не поддерживают часть CSS). Читайте дальше...

Сначала: используйте этот CSS3-код, чтобы сделать верхний элемент невидимым для взаимодействия с мышью:

pointer-events: none;

Это еще не совместимо с кросс-браузером. Он работает только на SVG и HTML Elements в браузерах Gecko и Webkit, но только на SVG-элементах в Opera и совсем не в IE.

В MDN:

Указатели-указатели свойств CSS позволяют авторов для контроля того, элемент может быть объектом мыши мероприятие. Это свойство используется для указать, при каких обстоятельствах (если любое) событие мыши должно проходить "через", элемент и цель, что угодно "под" этот элемент.

Вот эта документация: https://developer.mozilla.org/en/css/pointer-events

Второе: используйте некоторые функции определения JavaScript для тех браузеров, которые еще не поддерживают этот CSS. Вам придется катиться самостоятельно, подобно Modernizr, так как он пока не проверяет это (насколько мне известно). Идея заключается в том, что вы создаете элемент, применяете к нему CSS-указатели-события, проверяете его, и если браузер поддерживает эту функцию, вы получите ожидаемый результат, а не что-то null или undefined; затем уничтожьте элемент. Во всяком случае, как только вы обнаружите функцию, вы можете использовать jQuery или подобное, чтобы прикрепить прослушиватель к самому верхнему элементу и назначить клик от него, чтобы перейти к другому. Проверьте jQuery и используйте функцию click() для получения дополнительной информации (недостаточно репутации, чтобы опубликовать ссылку, sry).

Если я получу время позже, я смогу обработать быстрый jsFiddle. Надеюсь, это поможет.

Ответ 2

Если верхний элемент содержится внутри элемента ниже, вы можете позволить событию "пробиваться сквозь пузырь". Если это не так, вам нужно вызвать клик вручную. Невозможно запустить обработчик событий, просто нажав.

Чтобы запустить событие вручную, вы можете сделать это:

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

EDIT (ответ на комментарии):

Чтобы перечислить все поля, вы можете сделать это (с верхней части головы, без тестирования, не может быть даже синтаксически-без ошибок)

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

Ответ 3

Я изменил код сверху в функцию jquery, кто-то может найти его полезным:

Найдите альтернативные элементы с щелчком:

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

Если вы хотите игнорировать прозрачные пиксели в изображениях:

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

код:

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

Ответ 4

Я думаю, что Леландо получит правильный удар. В моем случае я решил использовать только css, и вы можете вставить указатель-события: none в свой #past элемент.