Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Клик сквозь элемент для разных кнопок мыши (https://javascript.ru/forum/misc/85583-klik-skvoz-ehlement-dlya-raznykh-knopok-myshi.html)

roland 02.11.2023 07:03

Клик сквозь элемент для разных кнопок мыши
 
Здравствуйте. Есть простая на первый взгляд задача, которая легко решается на системных языках программирования, но которая поставила меня в тупик при попытке реализации её на Web:

На странице располагается 1 элемент - div.box, к примеру.
Клик левой кнопкой мыши должен проходить сквозь этот элемент. Для клика элемента не должно существовать вообще, а срабатывать он должен на родителе (document.body).
Клик правой кнопкой мыши должен регистрироваться на элементе как обычно.

Как сделать так, чтобы элемент игнорировал сразу все события мыши с помощью CSS, я знаю - pointer-events: none. Но как игнорировать события мыши для одной кнопки и одновременно регистрировать для другой - я не знаю.

Кто-нибудь может подсказать решение или функции языка JavaScript, с помощью которых можно решить эту задачу?

voraa 02.11.2023 07:47

Цитата:

Сообщение от roland
Клик правой кнопкой мыши должен регистрироваться на элементе как обычно.

Как обычно это значит, что событие должно всплывать до document? Или document не должен обрабатывать это событие?
const box = document.querySelector('div.box');

box.addEventListener('click', function (event) {
	if(event.button !== 2) return;  // Нажата не правая кнопка
    event.stopPropagation();  // Если не надо всплывать до document
	// Обработка события правой кнопки
})

document.addEventListener('click', function (event) {
	if(event.button !== 0) return;  // Нажата не левая кнопка
	// Обработка события
})

roland 02.11.2023 09:40

Цитата:

Сообщение от voraa (Сообщение 553825)
Как обычно это значит, что событие должно всплывать до document?

Да.

Небольшое замечание по вашему коду:
В вашем примере в обработчике для box события "click" выполнение кода будет всегда завершаться первой строкой (return), так как событие "click" вызывается только для "главной кнопки" (event.button для мыши будет всегда равен "0"). Поэтому событие "click" нужно заменить на "auxclick".

В остальном ваш пример не совсем здесь подходит, так как не происходит главного: клика сквозь элемент div.box. Если под элементом div.box будет другой элемент (к примеру, div.box2) со своим собственным обработчиком:
box2.onclick = () => console.log('box_2')
Он не будет вызван, так как события мыши будут перехватываться div.box.

voraa 02.11.2023 11:03

Цитата:

Сообщение от roland
нужно заменить на "auxclick".

В Сафари не будет работать
Значит mouseup на box ловить нужно. И отменять контекстное меню на нем
<head>
<style>
.box2 {
	position: relative;
	background-color: yellow;
	width: 400px;
	height: 200px;	
}
.box {
	position: relative;
	background-color: red;
	width: 200px;
	height: 100px;	
	margin: 30px auto;
}
</style>
</head>
<body>
<div class=box2>
box2
<div class=box>
box<br>
Click
</div>
</div>
<script>
const box = document.querySelector('.box');
const box2 = document.querySelector('.box2');

document.body.addEventListener('click', (event) => {
	console.log('body left click');
})


box2.addEventListener('click', (event) => {
	console.log('box2 left click');
})
/*
box2.addEventListener('mouseup', (event) => {
	console.log('box2 mouse up');
})
*/

box.addEventListener('mouseup', (event) => {
	if (event.button === 2) {
		event.preventDefault();
		console.log('box right click');
	}
})

box.addEventListener('contextmenu', (event) => {
	event.preventDefault();
})

</script>


Надо пересматривать такие интерфейсы. Не принято в WEB кликать правой клавишей. Это для контекстного меню. И реализовать для тачскринов будет проблематично.

roland 02.11.2023 12:24

В вашем примере .box2 является родителем для .box, что является очень специфичным примером, который, к сожалению, нельзя назвать универсальным решением. Это похоже на создание условий задачи под решение, а не создание решения под условия задачи. В любом случае, спасибо вам за уделённое время и старания.

Кажется решение нашлось в виде имитации "pointer-events: none" средствами JаvaScript: Во время клика по ".box" устанавливать "display: none", делать программный клик по элементу под курсором и возвращать для ".box" начальное значение "display".

Цитата:

Сообщение от voraa (Сообщение 553829)
Надо пересматривать такие интерфейсы. Не принято в WEB кликать правой клавишей.

Если под WEB подразумевать веб-сайты со страницами с информацией, я не могу не согласиться и кажется разумным решением не ломать привычки пользователей и классические приёмы взаимодействия. Но сейчас WEB это совокупность технологий, с помощью которой требуется реализовывать самые разнообразные интерфейсы. В том числе для web-приложений, оффлайн приложений, портированных desktop-приложений, игр и других вещей.

voraa 02.11.2023 12:42

Цитата:

Сообщение от roland
Это похоже на создание условий задачи под решение, а не создание решения под условия задачи.

А разве не такое условие было?
Цитата:

Сообщение от roland
Если под элементом div.box будет другой элемент (к примеру, div.box2) со своим собственным обработчиком:

Вы четко сформулируйте. Как расположены элементы, какой элемент на что должен реагировать, и на что не должен. Просто описывая трудно понять, что имеет в виду "под" и "над"

ruslan_mart 02.11.2023 13:15

box.addEventListener('click', (event) => {
  event.stopImmediatePropagation();
});

box.addEventListener('pointerdown', (event) => {
  event.preventDefault();
});

box.addEventListener('contextmenu', (event) => {
  event.preventDefault();
  alert('Hello');
});


Оно?

voraa 02.11.2023 17:31

Цитата:

Сообщение от ruslan_mart
box.addEventListener('click', (event) => {
  event.stopImmediatePropagation();
});

Цитата:

Сообщение от roland
не совсем здесь подходит, так как не происходит главного: клика сквозь элемент div.box.

Я это понял так, что при клике на box все равно должен срабатывать клик на body


Часовой пояс GMT +3, время: 10:56.