регистрация кликов на элементе, который находится под другим элементом - PullRequest
18 голосов
/ 18 июля 2009

У меня есть элементы, которые находятся под элементом с непрозрачностью: 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>

Ответы [ 4 ]

20 голосов
/ 18 июля 2009

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

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

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

РЕДАКТИРОВАТЬ (ответ на комментарии):

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

$("#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
    });
});
17 голосов
/ 29 апреля 2011

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

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

pointer-events: none;

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

За MDN:

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

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

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

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

2 голосов
/ 17 ноября 2012

Я изменил код сверху в функцию 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);
}
0 голосов
/ 30 августа 2017

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...