2 клика по элементу
Не могу сделать 2 клика по элементу. У меня есть коллекция div блоков, на них повешен скрипт выделения активного блока. В чем суть: чтобы произошло какое то действие у активного блока, надо щелкнуть на него один раз, на не активный - 2 раза(1 раз - для того чтобы его выделить и сделать его активным, 2 раз - для того чтобы выполнить какое либо действие). Проблема в том что когда нажимаешь один элемент на другой и потом щелкаешь элемент на который вы уже нажали он выделяется и одновременно выполняет определенное действие(грубо говоря клик сохраняется, а этого мне не нужно)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style_1.css">
<title>Document</title>
</head>
<body>
<div class="content">
<div class="block">
1
</div>
<div class="block">
2
</div>
<div class="block">
3
</div>
<div class="block">
4
</div>
<div class="block">
5
</div>
<div class="block">
6
</div>
<div class="block">
7
</div>
</div>
</body>
<script src="js.js"></script>
</html>
body
{
margin: 0;
display: grid;
justify-content: center;
}
.content
{
width: 30vw;
height: 30vw;
overflow-x: hidden;
overflow-y: auto;
border: 1px solid black;
}
.block
{
display: flex;
text-align: center;
height: 5vw;
background-color: brown;
margin: 0 0 1vw;
}
.content .active{
background-image: linear-gradient(0deg, #5dcc41 0%, #31d86f 100%);
color: #ffffff;
}
/**
* @param {number} value
* @param {number} min
* @param {number} max
*/
function minMax(value, min, max) {
return Math.min(Math.max(value, min), max)
}
/**
* @param {HTMLElement} container
* @param {string} queryItem
*/
function listItems(container, queryItem) {
const items = [...container.querySelectorAll(queryItem)]
const { length } = items
const activeClass = 'active'
const state = { selected: 0 }
function update() {
for (let i = 0; i < length; i++) {
let g = 0;
if (i == state.selected)
{
items[i].classList.add(activeClass);
items[i].addEventListener("click", elemEventHandler);
}
else
items[i].classList.remove(activeClass)
}
}
var elemEventHandler = function()
{
for (let i = 0; i < length; i++)
{
if(items[i].classList.contains("active"))
{
alert("ggп")
}
else
{
items[i].removeEventListener("click", elemEventHandler);
}
}
}
const fix = () => {
if (state.selected >= length) state.selected = length - 1
if (state.selected < 0) state.selected = 0
}
const incState = () => {
state.selected++
fix()
update()
}
const decState = () => {
state.selected--
fix()
update()
}
/**
* @param {KeyboardEvent} param0
*/
const keyDown = ({ key }) => {
if (key === 'ArrowUp') decState()
if (key === 'ArrowDown') incState()
}
addEventListener('keydown', keyDown)
/**
* @param {number} index
*/
function select(index) {
state.selected = minMax(index, 0, length - 1)
update()
}
for (let i = 0; i < length; i++) {
items[i].onclick = select.bind(null, i)
}
update()
return () => {
removeEventListener('keydown', keyDown)
for (let i = 0; i < length; i++) {
items[i].onclick = null
delete items[i].onclick
}
}
}
listItems(document.querySelector('.content'), '.block')
Ответы (2 шт):
Вы назначаете слушатель "второго" нажатия на каждый когда-либо нажатый элемент в функции update, хотя уже есть слушатель нажатий: items[i].onclick = select.bind(null, i).
Решение: не добавлять новых обработчиков нажатий, изменить прежнюю функцию. Теперь она выглядит следующим образом:
items[i].onclick = function() {
if (i == state.selected) alert("ggп");
else select(i);
}
/**
* @param {number} value
* @param {number} min
* @param {number} max
*/
function minMax(value, min, max) {
return Math.min(Math.max(value, min), max)
}
/**
* @param {HTMLElement} container
* @param {string} queryItem
*/
function listItems(container, queryItem) {
const items = [...container.querySelectorAll(queryItem)]
const content = document.getElementsByClassName("content")[0];
const {
length
} = items
const activeClass = 'active'
const state = {
selected: 0,
lastSelected: 0
}
function update() {
items[state.lastSelected].classList.remove(activeClass);
items[state.selected].classList.add(activeClass);
}
const fix = () => {
if (state.selected >= length) state.selected = length - 1;
if (state.selected < 0) state.selected = 0;
}
const incState = () => {
state.lastSelected = state.selected++;
fix();
update();
}
const decState = () => {
state.lastSelected = state.selected--;
fix();
update();
}
/**
* @param {KeyboardEvent} param0
*/
const keyDown = (event) => {
event.preventDefault();
let key = event.key;
if (key === 'ArrowUp') decState();
if (key === 'ArrowDown') incState();
let contentParams = content.getBoundingClientRect();
let itemParams = items[state.selected].getBoundingClientRect();
if (contentParams.top > itemParams.top) content.scrollBy({left:0, top:itemParams.top-contentParams.top, behavior: "smooth"});
if (contentParams.bottom < itemParams.bottom) content.scrollBy({left:0, top:itemParams.bottom-contentParams.bottom, behavior: "smooth"});
}
addEventListener('keydown', keyDown);
/**
* @param {number} index
*/
function select(index) {
state.lastSelected = state.selected;
state.selected = index;
update();
}
for (let i = 0; i < length; i++) {
items[i].onclick = function() {
if (i == state.selected) alert("ggп");
else select(i);
}
}
update();
return () => {
removeEventListener('keydown', keyDown);
for (let i = 0; i < length; i++) {
items[i].onclick = null;
delete items[i].onclick;
}
}
}
listItems(document.querySelector('.content'), '.block')
body {
margin: 0;
display: grid;
justify-content: center;
}
.content {
width: 30vw;
height: 30vw;
overflow-x: hidden;
overflow-y: auto;
border: 1px solid black;
}
.block {
display: flex;
text-align: center;
height: 5vw;
background-color: brown;
margin: 0 0 1vw;
}
.content .active {
background-image: linear-gradient(0deg, #5dcc41 0%, #31d86f 100%);
color: #ffffff;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style_1.css">
<title>Document</title>
</head>
<body>
<div class="content">
<div class="block">
1
</div>
<div class="block">
2
</div>
<div class="block">
3
</div>
<div class="block">
4
</div>
<div class="block">
5
</div>
<div class="block">
6
</div>
<div class="block">
7
</div>
</div>
</body>
<script src="js.js"></script>
</html>
Просто проверяйте при нажатии - есть ли класс 'active'. Если есть, производите действие.
let items = document.querySelectorAll('.block');
let content = document.querySelector('.content');
content.addEventListener('click',(e)=>{
if (e.target.classList.contains('active')) {
alert('Second click');
return;
}
if (e.target.classList.contains('block')) {
items.forEach(item => item.classList.remove('active'));
e.target.classList.add('active');
}
})
body {
margin: 0;
display: grid;
justify-content: center;
}
.content {
width: 30vw;
height: 30vw;
overflow-x: hidden;
overflow-y: auto;
border: 1px solid black;
}
.block {
display: flex;
text-align: center;
height: 5vw;
background-color: brown;
margin: 0 0 1vw;
}
.content .active {
background-image: linear-gradient(0deg, #5dcc41 0%, #31d86f 100%);
color: #ffffff;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="style_1.css">
<title>Document</title>
</head>
<body>
<div class="content">
<div class="block active">
1
</div>
<div class="block">
2
</div>
<div class="block">
3
</div>
<div class="block">
4
</div>
<div class="block">
5
</div>
<div class="block">
6
</div>
<div class="block">
7
</div>
</div>
</body>
<script src="js.js"></script>
</html>