実装したいこと
クリックすると要素が変化し、要素外をクリックすると要素が元に戻るという機能を実装します。
今回の例は、自分のオリあぷに実装したものです。
検索フォームにホバーするとアンダーバーが表示されます。
検索フォームをクリックすると、アンダーバーの表示が維持されます。
検索フォーム以外をクリックすると、アンダーバーが消えます。
わかりにくいですがGifを参照ください。
https://gyazo.com/a36d20cbf9d2dd2b66f00d4b73b437b3
結論
JavaScriptを利用します。
JavaScript
function search_box() {
const search_box = document.querySelector("#search-box"); // クリックした時にイベントを発火させるための要素を取得
if (!search_box) return null; // 目的の要素がないページでは何も処理しないようにする。⇨ページの挙動がよくなる
const line = document.querySelector(".search-form"); // 今回挙動を変えるターゲットを取得
// ページをクリックした時の処理
document.addEventListener("click", (e) => { //クリックの時に発火
// ifではクリックした要素("document")の親要素に("#search-box")があるかどうかを判定している
if (e.target.closest("#search-box")) {
// "#search-box";がある場合の処理
line.classList.remove("search-form");
line.classList.add("is-fixed");
} else {
// "#search-box";がない場合の処理
line.classList.add("search-form");
line.classList.remove("is-fixed");
}
});
}
window.addEventListener("load", search_box);
eとはイベントオブジェクトのこと。今回の場合、document(ページ全体のこと)をクリックした時に得られるさまざまな情報を含んでいる。どのような情報かというと、e.typeとすると発生したイベントの型を返し、e.timestampとするとイベントの発生時間を返す。e.targetはイベントの発生源を返すので、今回はdocumentのことを示す。要素.closest("aaa")は要素の親要素にaaaがあるかどうかを判定する。詳しくは参考サイトを参照。
以下はjsで取得した要素を載せたhtmlと、バーを表示させるため記述したcss。念の為置いておきます。
html.erb
<%= form_with(url: search_rooms_path, local: true, method: :get, class: "search-form") do |form| %>
<%= form.button type:"submit",class: 'search-button' do%>
<i class="fas fa-search"></i>
<%end%>
<%= form.text_field :keyword, placeholder: "検索する", class: "input-box",id:'search-box',autocomplete: 'off',value:params[:keyword] %>
<% end %>
.search-form,
.is-fixed {
margin-left: 20px;
position: relative;
}
.search-form::after {
position: absolute;
left: 0;
content: "";
width: 100%;
height: 2px;
background: var(--font-color);
bottom: -1px;
transform: scale(0, 1);
transform-origin: left top;
transition: transform 0.5s;
}
/* js用に使用、クリックした際バーがずっと表示されるように */
.is-fixed::after {
position: absolute;
left: 0;
content: "";
width: 100%;
height: 2px;
background: var(--font-color);
bottom: -1px;
transform: scale(1, 1);
transform-origin: left top;
transition: transform 0.5s;
}
.search-form:hover::after {
transform: scale(1, 1);
}
参考サイト