Отправка события мыши на элемент, который визуально находится «позади» принимающего элемента - PullRequest
5 голосов
/ 28 марта 2012

На моей веб-странице есть два div, A и B:

enter image description here

DOM выглядит следующим образом (упрощенно).Здесь главное отметить, что div находятся на одном уровне в иерархии DOM, и они ничем не упорядочены.Кроме того, внешний div не только содержит A и B, но также содержит больше div C, D, E и т. Д. B не обязательно должен перекрываться A. Это также может быть C, лежащий позади A.

<div>
    <div style="...">B</div>
    <div style="...">A</div>
</div>

Обработчик щелчков прикреплен к внешнему элементу, фиксируя события щелчков мышью на A или B в фазе всплытия.Щелчок в пересечении A и B вызовет событие щелчка на A, которое всплывает до моего обработчика щелчков, который теперь срабатывает.

Теперь проблема: при определенных условиях обработчик решает, что событие не должно обрабатываться A, а должно принадлежать B. Если событие должно обрабатываться B, будет запущен тот же обработчик щелчков, но* объектами события currentTarget будет B вместо A

Как мне этого добиться?

Я уже рассмотрел обработчик указателей css3 и некоторые методы диспетчеризации событий в JS, ноне могли бы на самом деле найти решение здесь.

Возможное решение 1 (не совместимо с браузерами)? :

Я думаю, что я мог бы использовать1022 * свойство указателя-событий css3 .Если обработчик решает, что событие должно быть обработано B, он устанавливает значение указателя-события в none.Затем он повторно запускает щелчок мышью. Вопрос здесь: можно ли перезапустить щелчок мышью только с координатами, не указывая конкретный элемент?

В любом случае, поддержка событий указателя ограничена: http://caniuse.com/pointer-events

1 Ответ

3 голосов
/ 28 марта 2012

Вы можете попытаться передать событие на B (используя jQuery):

( псевдокод )

var $A = $('#A'), $B = $('#B');

$B.on('click', function () {
  console.log('B clicked');   
});

$('#outer').on('click', function (evt) {
    if (Math.random() < 0.1) { // << pseudo condition
        $B.trigger(evt);
    }
});​

http://jsfiddle.net/hzErh/


Обновление

используя такую ​​функцию:

// this function should (did not enough testing) return all elements at a given
// point in the order of top to bottom.
var elementsFromPoint = function (x, y, root) {
  var buffer = [], result = [], el, i = 0, lim;

  while ((el = document.elementFromPoint(x, y)) && [root, document.body, document.body.parentNode].indexOf(el) < 0) {
    result.push(el);
    buffer.push({el: el, visibility: el.style.visibility});
    el.style.visibility = 'hidden';
  }

  for (lim = buffer.length; i < lim; i += 1) {
    buffer[i].el.style.visibility = buffer[i].visibility;
  }

  return result;
};

вы можете получить элементы для заданной координаты x / y. Это немного глупо и требует дополнительного тестирования.

$('#outer').on('click', function (evt) {
  var elements = elementsFromPoint(
    evt.pageX + $(this).offset().left,
    evt.pageY + $(this).offset().top,
    this
  );

  console.log(elements);
});

демо: http://jsfiddle.net/hzErh/1/


Обновление 2 : эта версия должна обеспечивать лучшую производительность для многих элементов:

// this function should (did not enough testing) return all elements at a given
// point, though the order is not representative for the visible order.
var elementsFromPoint = function (root, x, y) {
  var result = [], i = 0, lim = root.childNodes.length, bb;

  for (; i < lim; i += 1) {
    bb = root.childNodes[i].getBoundingClientRect();
    if (bb.left <= x && x <= bb.right && bb.top <= y && y <= bb.bottom) {
      result.push(root.childNodes[i]);
    }
  }

  return result;
};

демо: http://jsfiddle.net/CTdZp/2/

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