「同意ボタン」を実装してみた話
前回に続き、CREATIVE SURVEYでJavaScript、CSSを使ったアンケート画面作成について書いていきたいと思います。
前回の記事はこちら↓
同意ボタンについて
さて、今回は「同意ボタン」を実装してみたという話なのですが、
「同意ボタン」、スマホやPCで何かのサービスを利用したり登録する際によく見ますよね。リンク化された「利用規約」や「個人情報の取り扱い」の下、もしくはテキストで表示されている場合はそれらの長い文言をスクロールした最後に待ち構えているあのボタンです。
CREATIVE SURVEYでは「個人情報の取り扱い」など長文のテキストを記載する場合に利用できる機能として「テキストエリア」機能があり、また単に「同意ボタン」を設置するのであればテキスト選択タイプの設問を利用することで簡単に作成できるのですが、(以下画像参照)
時々、「文言を全て読まないと(下までスクロールしないと)ボタンを押せないようにしたい。」といったご意見をいただきます。
そこで!今回はCSSとJavaScriptを利用して上記ご要望を実現してみた、と言う話です。
CSS、Javascriptの記述その1
さて、まず私が目指したのは「テキストエリア内の文言をスクロールすると同意するボタンが表示される」アンケートです。
これを実現するため大まかに以下3つの要件を整理しました。
「同意する」のボタンはカスタムCSSでデフォルトで非表示
テキストエリアのスクロールを判定
スクロール完了すると非表示の「同意ボタン」を表示
早速CSSを記述します。
非表示自体はクラスを指定して「display:none」を記述すればOKなのですが、テキスト選択の「選択肢」のクラス「.stage__inner__page__section__answer__checkboxes__checkbox 」にそのまま以下のようなCSSを充てると、アンケート内全てのテキスト選択設問の選択肢が非表示になってしまいます。これでは回答者が困ります。
.stage__inner__page__section__answer__checkboxes__checkbox {
display:none;
}
その為、「同意ボタン」を設置している設問の選択肢のみを非表示にするCSSの記述が必要です。
CREATIVE SURVEYではアンケート及び設問ごとに異なった設問IDが割り振られていますので、該当設問のIDを指定することでこの問題をクリアしました。IDはソースから確認できます。
この設問のIDは上記画像の「2041213」となりますので、こちらを元に以下のようにCSSに記述すると該当の設問のみ選択肢が非表示になります。
.question-2041213 .stage__inner__page__section__answer__checkboxes__checkbox {
display:none;
}
これで要件の1つ目はクリアしました。
次に要件2つ目のスクロールの判定ですが、
これは持っている知識だけでは難しかったのでこちらの記事を参考に、以下のコードを活用させていただきました。
const element = document.getElementById('scroll-area');
const clientHeight = element.clientHeight;
const scrollHeight = element.scrollHeight;
element.onscroll = function() {
if (scrollHeight - (clientHeight + this.scrollTop) == 0) {
alert('一番下です!');
}
};
コードの説明は上記記事をご参考ください!
上記のコードを含めて全体では以下のようなJavascriptの記述を行いました。
//設問IDを格納
let sectionNo= '.question-2017381';
$(function(){
//テキストエリアの要素にidを付与
$(sectionNo).find('.stage__inner__page__section__question__description').each(function(i){
$(this).attr('id','box1');
});
//一番下にスクロールした際にdisplay:noneで非表示にしたテキスト選択エリアを表示)
const element = document.getElementById('box1');
const clientHeight = element.clientHeight;
const scrollHeight = element.scrollHeight;
element.onscroll = function() {
if (scrollHeight - (clientHeight + this.scrollTop) == 0) {
$(sectionNo).find('.stage__inner__page__section__answer__checkboxes__checkbox').fadeIn().css({
"display": "inline-block",
});
}
};
});
ざっと説明すると、以下のようになります。
CSSで指定したものと同じ設問IDを変数に格納
次にスクロール判定時に指定するidをテキストエリアの要素に付与します。
最後にidを指定した要素(テキストエリア)でスクロールが完了すると、選択肢を表示する処理を実行する。
※1行目に記述している設問IDはアンケートごとに異なるため、上記CSSで記述している設問IDも含め、アンケートごとに都度指定し直す必要があります。
※「"display": "inline-block",」の記述は詳細は割愛しますが、スクロールによって選択肢が表示された際に、正常に横並びで表示させるために記述しています。
以上の設定を反映させたアンケートがこちら
意図した通り、スクロールで選択肢が表示されることが確認できますね。
これで完成です!
チーム内での共有で…
さて、これで実装完了!と言うことで、意気揚々とチームメンバーに共有したところ、「最初から選択肢が消えていると回答者はどうして良いか迷うかも」と言う意見が…確かに、ぱっと見わからない(OMG)。
文言で「全て読んでいただくと、選択肢が表示されます。」と補足説明することで理解はしていただけますが、あまりスマートではありません。
と言うことで、もうひとつパターンを作成することに。
CSS、JavaScriptの記述その2
次に私が目指したのは「非活性状態の同意ボタンがスクロールすると活性状態になる」アンケートです。(なぜ最初から思いつかなかったのか…)
要件は以下の通り。
「同意する」のボタンは表示されているが、クリックしても選択状態にできない(非活性の状態)
テキストエリアのスクロールを判定
スクロールが完了すると「同意する」ボタンが活性状態になる
上記要件に沿って記述したものがこちら
//設問Noを格納
let sectionNo= '.question-2041219';
$(function(){
//sectionNo配下のチェックボックス(選択肢)を非活性にする
$(sectionNo).find('.stage__inner__page__section__answer__checkboxes__checkbox').prop('disabled', true);
//sectionNo配下のテキストエリアのクラスにid(box1)を付与
$(sectionNo).find('.stage__inner__page__section__question__description').each(function(i){
$(this).attr('id','box1');
});
//一番下にスクロールした際に非活性解除
const element = document.getElementById('box1');
const clientHeight = element.clientHeight;
const scrollHeight = element.scrollHeight;
element.onscroll = function() {
if (scrollHeight - (clientHeight + this.scrollTop) == 0) {
$(sectionNo).find('.stage__inner__page__section__answer__checkboxes__checkbox').prop('disabled', false);
}
};
});
ざっくり解説すると以下のようなイメージ。
設問IDを変数に格納
選択肢の要素にdisabled属性を付与して非活性化
次に、スクロール判定時に指定するidをテキストエリアの要素に付与。
最後に3で付与したidを指定しスクロールが完了すると、disabledを解除して、活性状態に戻す処理を実行。
※その1で記述したCSSは削除しています。
全体で見ると先ほど記述したJavaScriptを応用しているので内容はあまり変わりません。
上記JavaScriptを反映させたアンケートがこちら
はい、お気づきでしょうか。この設定だとスクロールする前でもクリックできそうな見た目なので、「なぜかクリックしても反応しない!」と言う声が上がりそうです。
視覚的にわかりやすい回答画面を目指して
実際、スクロール前は非活性状態の為、選択肢をクリックしても選択できないのですが、視覚的にも非活性状態(クリックしても押せない)が判断できる状態にしなければなりません。
そこで要素の不透明度を指定するCSSプロパティ「opacity」を利用します。
記述するCSSが以下。こちらも設問のIDを指定しています。
.question-2041225 .stage__inner__page__section__answer__checkboxes__checkbox {
opacity:0.2;
}
記述すると選択肢の不透明度が下がり、視覚的にも選択肢が非活性っぽい見た目になりますね。
あとはJavascriptで、スクロール完了した際に上記不透明度を0.2→1に変更する処理を加えるだけでOKです。実際の記述が以下。
//設問Noを格納
let sectionNo= '.question-2041225';
$(function(){
//sectionNo配下のチェックボックスを非活性にする
$(sectionNo).find('.stage__inner__page__section__answer__checkboxes__checkbox').prop('disabled', true);
//sectionNo配下のテキストエリアのクラスにid(box1)を付与
$(sectionNo).find('.stage__inner__page__section__question__description').each(function(i){
$(this).attr('id','box1');
});
//一番下にスクロールした際に非活性&CSSで指定したopacity0.2を1に変更
const element = document.getElementById('box1');
const clientHeight = element.clientHeight;
const scrollHeight = element.scrollHeight;
element.onscroll = function() {
if (scrollHeight - (clientHeight + this.scrollTop) == 0) {
$(sectionNo).find('.stage__inner__page__section__answer__checkboxes__checkbox').prop('disabled', false).css({
"opacity": "1",
});
}
};
});
スクロールした際の実行処理の記述を以下のように記述していて、
$(sectionNo).find('.stage__inner__page__section__answer__checkboxes__checkbox').prop('disabled', false).css({
"opacity": "1",
});
スクロール完了すると選択肢を活性状態にする&opacityを1にする処理が実行されます。
以上を反映させたアンケートがこちら!
スクロールする前は「同意する」ボタンは押せないことが視覚的にもよくわかるようになりました。
ようやく全ての問題をクリアしてアンケート作成が完了しました。長い道のりでした。
最後に
今回こだわったポイントは設問IDだけを書き換えることで利用できるCSSとJavaScriptの記述です。
ご案内した通り、各コードでは冒頭の設問IDのみを変更することで
どのアンケートでも実装できるようにしました。
最初は選択肢ごとに割り振られたIDを指定したり、いろいろと試行錯誤したのですが、最終的にご紹介したコードがシンプルに纏まって、簡単に運用できるものになりました!
今回の経験で5レベルくらいは上がった気がします。
またご紹介できるものがあれば記事にしたいと思います!
※本記事で紹介しているコードはあくまでも私個人的が記述してご紹介しているものになりますので、CREATIVE SURVEYのサポート窓口へお問い合わせいただいてもご返答できないものになります。
また、動作の保証もしておりませんので予めご了承いただけますと幸いです。