0

In a single function, I'm trying to achieve 2 things :

  1. Scroll to a section
  2. Focus on an input

This is my code :

function search() {
  document.getElementById("searchbar").style.display = "block";
  document.getElementById("flex").style.display = "none";
  document.getElementById("books").scrollIntoView({behavior: 'smooth'});
  key();
};
function key(){
  document.getElementById("searchbox").focus();
};

The scrolling is not working here. If i remove the 'key' function, it works.

There's no need for separate 'key' function, but i tried.

The input with id "searchbox" is placed inside a "position:fixed" division. Its outside the "books" section.

sakhyamedha
  • 5
  • 1
  • 4

1 Answers1

1

You can simply invert the order in which you call these methods.

function search() {
  document.getElementById("searchbox").focus(); 
  document.getElementById("books").scrollIntoView({behavior: 'smooth'});
};
document.getElementById("btn").onclick = search;
#books {
  margin-top: 300vh;
}
<button id="btn">search</button>
<input id="searchbox" value="#searchbox">
<div id="books">Some books</div>

What happens is that calling Element.focus() will automatically make your browser scroll to that element. Doing so, it will cancel the previous call to scrollIntoView. By inversing the calls order, scrollIntoView will cancel the focus' scroll, which is what you want.

Kaiido
  • 123,334
  • 13
  • 219
  • 285
  • Hey! This worked fine on desktop but not working on chrome for Android - which is my main target. – sakhyamedha Aug 05 '20 at 09:25
  • Ah I guess there is a delay then (maybe related to the appearance of the virtual keyboard?) I don't have much time right now to look at it, but maybe something like `document.addEventListener('scroll', e=>.scrollIntoView(), { once;true} )` would do, or an ugly setTimeout... I'll try to look at this when I'll get time. – Kaiido Aug 05 '20 at 11:35
  • Spent a few more minutes on this and I didn't found a good enough solution for mobiles... There is a `{ preventScroll: true }` option that we can pass to HTMLElement.focus, but the scroll that happens in mobile browsers is not *directly* caused by this `focus` call. It's part of showing the virtual-keyboard, and we don't have any way to prevent this. https://github.com/whatwg/html/issues/4608 And since such action can even cause a zoom, there is really not much we can do. But, maybe your case allows you to not stick that input but rather have it `position:fixed` -> no need for scroll. – Kaiido Aug 08 '20 at 04:00
  • Thank you for giving your time to look into this. Your answer helped to new fix the issue on desktop. – sakhyamedha Aug 09 '20 at 04:05
  • Actually, input is a searchbox and scrolling takes place to bring up a table, which can be filtered using seachbox. At a same time, i'm trying to 1) show the hidden 'input' which is fixed on top, 2) scroll the page to 'table' section 3) focus on input so that soft keyboard pops up on mobiles – sakhyamedha Aug 09 '20 at 04:06
  • So the input is fixed on top of the viewport? Then what about [waiting for the table is in view](https://stackoverflow.com/a/57867348/3702797) before calling input.focus()? – Kaiido Aug 09 '20 at 04:11
  • 1
    That may work.. i still have to try. Currently, I've disabled "smooth scrolling" and it worked. Only problem is user is not aware of scrolling taking place, it just feels like the page magically changed – sakhyamedha Aug 12 '20 at 06:00