何を血迷ったか、サジェストのUIを自作しようとしてしまってつらい目にあった話。

フォーカスアウトしたらサジェストを消したい

入力欄もしくはサジェストからフォーカスアウトした時はサジェストを消したい。 でもフォーカスアウトした先にフォーカスしたものが入力欄もしくはサジェストだったらそれは消したくない。

だからこんなコードを書いた。

<input type="text" id="search-text">
<div id="suggest-list">
  <a href="#">suggest</a>
  <a href="#">suggest</a>
  <a href="#">suggest</a>
</div>

<script>
$("#search-text").on("focusout", function() {
  if ($("#suggest-list").find(":focus").length !== 0) {
    console.log("Not hide!");
    return;
  }
  console.log("hide!");
});
</script>

実際はこの処理を入力だけじゃなくアンカーにも適用したんだけど面倒だから省略。 しかしこれだとifの中には入らずサジェストの非表示処理が通ってしまう・・・。

フォーカス処理は一度ブラウザに返してあげる

どうやらJavaScriptの処理が進んでる間はフォーカス処理が行われないらしい。 なので一度ブラウザに処理が返るような処理を挟んでやる必要がある。

こんなかんじに。

$("#search-text").on("focusout", function() {
  setTimeout(function() {
    if ($("#suggest-list").find(":focus").length !== 0) {
      console.log("Not hide!");
      return;
    }
    console.log("hide!");
  }, 0);
});

setTimeoutはJavaScriptの処理を通した後に、ブラウザ側からまた呼び出されるとのこと。

参考にさせていただきました。

JavaScript - setTimeout(…,0)などの使いドコロ - Qiita