文章を全部読むまで押せないチェックボックスを作ってみよう
サイトに会員登録するとき、規約等の文章を下までスクロールしないと押せないチェックボックスやボタンってよくありますよね。
「文章をちゃんと全部読んで同意したよね?」ってさせるアレです。
(文章を最後までスクロールしないと次の画面へ進めないので、この仕組みを知らないとちょっと戸惑いますよね。)
こんな感じのやつです。
今回はこれを作ってみましょう。
HTML と CSS で画面を作る
まずは、文章を下までスクロールしなくてもチェックできるチェックボックスを作ってみましょう。
こんな感じです。
HTML と CSS はこんな感じになります。
<div>
<textarea>文章</textarea>
<div>
<label for="cb1"><input type="checkbox" id="cb1">同意する</label>
</div>
</div>
textarea {
width: 300px;
height: 100px;
resize: none;
}
文章を下までスクロールしないとチェックできない状態にするためには初期状態でチェックできないようにしておいて、下までスクロールした段階で JavaScript の処理でチェックできる状態に変更するという方法が考えられます。
チェックボックスをチェックできない状態にするには input 要素の disabled プロパティを有効にすればよいだけです。
具体的にいうと input タグの中に disabled を入れるだけで OK です。
<label for="cb1"><input type="checkbox" id="cb1" disabled>同意する</label>
チェックボックスを disabled にすると色が薄くなって視覚的にもチェックできない状態だと分かるかと思います。
もっと分かりやすくするためにラベル色も変えてしまいましょう。
label は disabled プロパティがないので、クラスを追加して CSS で色を変えるようにします。
<div>
<label for="cb1" class="disabled"><input type="checkbox" id="cb1" disabled>同意する</label>
</div>
.disabled {
color: lightgray;
}
ここで追加したクラスを JavaScript の処理で取り除けばラベルの色は元に戻ります。
JavaScript の処理を作る
JavaScript の処理は下記の 3 つが必要になります。
- 文章 (textarea) がスクロールしたときに処理を行う
- 最後までスクロールされたか判定する
- チェックボックスをチェックできる状態にする
1. 文章 (textarea) がスクロールしたときに処理を行う
「要素に何か変化があったとき」をトリガーにして処理を行うためには addEventListener を使用します。
「スクロール」をトリガーにする場合は scroll イベントを指定します。
const textArea = document.querySelector("textarea");
textArea.addEventListener("scroll", 実行したい処理(イベントハンドラ));
2. 最後までスクロールされたか判定する
要素の現在のスクロール位置 (表示されていない最上部から表示されている最上部まで) は scrollTop で取得できます。
要素の表示されていない部分も含めた高さは scrollHeight で取得できます。
要素の表示されている部分のうち、margin や border 等を抜いた高さは clientHeight で取得できます。
これらの関係は次のような感じです。
単純に考えれば判定式は次のようなものが考えられます。
if(scrollTop == scrollHeight - clientHeight){...}
ですが、scrollTop は小数点を含む実数値 (または整数値)、scrollHeight と clientHeight は小数点を丸めた整数値で返ってきます。
そのため上記の判定式では正しく判定できません。
上記サイトを参考に、次のようにしましょう。
if(Math.abs(element.scrollHeight - element.clientHeight - element.scrollTop) < 1){...}
3. チェックボックスをチェックできる状態にする
チェックボックスをチェックできない状態にするために、disabled を有効にしましたが内部的な状態は disabled プロパティが true になっているだけです。
つまり、これを無効にするには disabled を false にすればよいわけです。
const checkBox = document.querySelector("input[type='checkbox']");
checkBox.disabled = false;
また、チェックボックスをチェックできる状態に戻す段階でラベルの表示色も戻したいので、ラベルの色を変えるために追加したクラスを取り除きます。
クラスを取り除くには classList.remove を使用します。
const label = document.querySelector("label");
label.classList.remove("disabled");
まとめると
以上をまとめると次のようになります。
const textarea = document.querySelector("textarea");
const checkbox = document.querySelector("input[type='checkbox']");
const label = document.querySelector("label");
textarea.addEventListener("scroll", func=()=>{
if(Math.abs(textarea.scrollHeight-textarea.clientHeight-textarea.scrollTop)<1){
checkbox.disabled = false;
label.classList.remove("disabled");
}
});
チェックボックスではなくボタンにすることも出来ます。
チェックボックスをチェックしないと押せないボタンを作ることもできます。(詳しくはこの記事のソースを見てね)