scrollIntoView съедает следующий клик

207
18 июня 2018, 06:40

Есть кастомный дропдаун (вообще на реакте, но это не важно).

Когда input получает фокус, отображается выпадающий блок и делается подписка на capturing-стадию клика по документу. В этом обработчике проверяется, клик произошёл внутри области, или вне. Если вне, то дропдаун закрывается, а обработчик снимается.

Так всё работает. Проблема возникает при добавлении в код inp.scrollIntoView() или ручном изменении scrollTop контейнера: если следующий клик происходит по аналогичному интупу, то обработчик клика вообще не вызывается.

Функции вызываются как-то так:

focus #1 #1
focus #2 #2
click #1
close #1
click #2
close #2

https://jsfiddle.net/2qb5L7og/1/

for (let inp of document.querySelectorAll("input")) { 
  inp.addEventListener('focus', e => { 
    console.log("focus", e.target.value, inp.value) 
     
    var dd = inp.nextElementSibling 
 
    dd.style.display = 'block' 
    inp.scrollIntoView() 
 
    document.addEventListener('click', function close(e) { 
      console.log("click", inp.value) 
       
      if (e.target.closest("section") !== inp.parentElement) { 
        console.log("close", inp.value) 
       
        dd.style.display = '' 
        document.removeEventListener('click', close, true) 
      } 
    }, true) 
  }) 
}
* { 
  box-sizing: border-box; 
} 
 
main { 
  border: 1px solid red; 
  height: 11.4em; 
  overflow: auto; 
} 
 
section { 
  position: relative; 
  margin: 1em 1em 7em 1em; 
  border: 1px solid blue; 
  background: #8FF; 
} 
 
input { 
  cursor: pointer; 
  display: block; 
  width: 100%; 
} 
 
div { 
  position: absolute; 
  top: 100%; 
  left: -1px; 
  right: -1px; 
  display: none; 
  border: 1px solid green; 
  border-top: 0; 
}
<main> 
  <section> 
    <input value="#1" readonly> 
    <div>In #1<br>In #1<br>In #1<br>In #1</div> 
  </section> 
  <section> 
    <input value="#2" readonly> 
    <div>In #2<br>In #2<br>In #2<br>In #2</div> 
  </section> 
  <section> 
    <input value="#3" readonly> 
    <div>In #3<br>In #3<br>In #3<br>In #3</div> 
  </section> 
  <section> 
    <input value="#4" readonly> 
    <div>In #4<br>In #4<br>In #4<br>In #4</div> 
  </section> 
  <section> 
    <input value="#5" readonly> 
    <div>In #5<br>In #5<br>In #5<br>In #5</div> 
  </section> 
</main>

Answer 1

Похоже из-за того, что в момент клика двигается контент, отпуск клавиши мышки происходит в другом месте, что браузером не интерпретируется, как событие click.

Я вижу два решения:

  • Поставить задержку прокрутки.
  • Использовать событие mousedown.

Пример с событием mousedown.

for (let inp of document.querySelectorAll("input")) { 
  inp.addEventListener('focus', e => { 
    console.log("focus", e.target.value, inp.value) 
 
    var dd = inp.nextElementSibling 
 
    dd.style.display = 'block' 
    inp.scrollIntoView() 
 
    document.addEventListener('mousedown', function close(e) { 
      console.log("click", inp.value) 
 
      if (e.target.closest("section") !== inp.parentElement) { 
        console.log("close", inp.value) 
 
        dd.style.display = '' 
        document.removeEventListener('mousedown', close, true) 
      } 
    }, true) 
  }) 
}
* { 
  box-sizing: border-box; 
} 
 
main { 
  border: 1px solid red; 
  height: 11.4em; 
  overflow: auto; 
} 
 
section { 
  position: relative; 
  margin: 1em 1em 7em 1em; 
  border: 1px solid blue; 
  background: #8FF; 
} 
 
input { 
  cursor: pointer; 
  display: block; 
  width: 100%; 
} 
 
div { 
  position: absolute; 
  top: 100%; 
  left: -1px; 
  right: -1px; 
  display: none; 
  border: 1px solid green; 
  border-top: 0; 
}
<main> 
  <section> 
    <input value="#1" readonly> 
    <div>In #1<br>In #1<br>In #1<br>In #1</div> 
  </section> 
  <section> 
    <input value="#2" readonly> 
    <div>In #2<br>In #2<br>In #2<br>In #2</div> 
  </section> 
  <section> 
    <input value="#3" readonly> 
    <div>In #3<br>In #3<br>In #3<br>In #3</div> 
  </section> 
  <section> 
    <input value="#4" readonly> 
    <div>In #4<br>In #4<br>In #4<br>In #4</div> 
  </section> 
  <section> 
    <input value="#5" readonly> 
    <div>In #5<br>In #5<br>In #5<br>In #5</div> 
  </section> 
</main>

READ ALSO
изменение ссылки href при помощи jQuery в таблице

изменение ссылки href при помощи jQuery в таблице

Всем привет! Делаю таблицу с товаром, в которой будет меняться количество товара и сумма заказаНа кнопку "купить" меняется ссылка подобным...

229
Запрет на ввод знака &ldquo;минус&rdquo; в input страницы (JSF)

Запрет на ввод знака “минус” в input страницы (JSF)

Нужно сделать запрет на ввод знака "минус" в поле inputСтраница написана с использованием JSF и Primefaces

198
Spring: @Configuration vs non-@Configuration classes

Spring: @Configuration vs non-@Configuration classes

В документации приведен такой пример:

205
Как отправить пост запрос и вернуть GET

Как отправить пост запрос и вернуть GET

отправляю POST запрос в строку поиска, и нужно получить страницу ответную например В поисковую строку StackOverFlow вбиваю TEST И получаю https://rustackoverflow

209