ボタンの二度押しをwait画面でガードしてみた。
以前フォームの二重送信をガードする方法について書いた記事があります。
これは、ブラウザの更新ボタン(F5ボタン)連打をガードする方法です。
ただこの方法でもガードできない事象があります。
それは「送信ボタン連打」です。
画面が切り替わる前に送信ボタンを連打すると、重複起動が発生し誤動作することがあります。
しかもページが重いと余計にボタン連打されやすくなります。
利用される方の身になって考えれば、ボタンを押しても画面が切り替わらなかったら、失敗したのかと思って再度ボタンを押すものです。
今回はこのボタン連打を、どうすればガードできるかについて考え実践しました。
またご参考になれば幸いです。
ひらめいたのは「お待ちください画面表示」でボタンを押せなくする方法
やり方はいろいろ考えられます。
例えばボタンを1回押したらJqueryで無効化して押せなくする、1回押したら非表示にするなどです。
でもこれだと、aタグ(リンクタグ)での対応が難しいです。
そこで思いついたのが、「お待ちください画面」を最前面に表示して強制的にボタンが押せなくする方法です。
表示ページの最前面に、強制的に別の内容で覆いかぶせれば操作ができなくなります。
スマートホンでホームページを見ている際に、メニューボタンを押した後に表示されるメニューボタンのイメージです。(メニューは押せるけれどもともとのリンク等は押せなくなる)
これなら上手くいくのではないかと思い、実践しました。
実際にできたものがこちらです
サンプルは、ボタンを押すと「お待ちください」画面が表示されます。
その間はもともとのボタンが押せなくなります。
切り替わったページ表示時に「お待ちください画面」を出す手法がありますが、今回はページ切り替え前に先に「お待ちください画面」を出すという方法です。
※サンプルは効果がわかりやすいように、2秒間のwait処理が入っています。
ボタンを押したらお待ちくださいを表示する仕組み
今回の仕掛けについて解説いたします。
まずは原理について解説します。
今回の方法は以下の2つの仕掛けがあります
- CSSで「お待ちください」画面を「非表示状態」で作っておく
- Jqueryでボタンが押されたら「お待ちください画面」を表示状態にする
これだけです。
Jqueryには.show()関数があります。
この関数は「非表示状態」のものを「表示状態」にします。
ボタンが押されたタイミングで.show()をコールするだけです。
Jqueryの処理としては、基本的な処理だけでできます。
ソースはこちらです
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
<!doctype html> <html> <head> <meta charset="shift_jis"> <title>wait切り替え</title> <style type="text/css"> #wait { /** 全画面に強制表示する部分 */ position: fixed; z-index: 999999; top: 0px; left: 0px; width: 100%; height: 100%; /** 最初は非表示にしておく */ display: none; /** 全画面の背景色 */ background-color: rgba(0, 0, 0, 0.8); padding-top: 70px; text-align: center; } #wait .wak { font-size: 24px; font-weight: normal; line-height: 140%; color: #FFF; display: inline-block; text-align: center; padding-top: 20px; padding-right: 40px; padding-bottom: 20px; padding-left: 40px; border: 1px solid #999; border-radius: 6px; -webkit-border-radius: 6px; -moz-border-radius: 6px; } body { text-align: center; } a { background: #ffffff; /* Old browsers */ background: -moz-linear-gradient(top, #ffffff 0%, #f1f1f1 50%, #e1e1e1 51%, #f6f6f6 100%); /* FF3.6-15 */ background: -webkit-linear-gradient(top, #ffffff 0%,#f1f1f1 50%,#e1e1e1 51%,#f6f6f6 100%); /* Chrome10-25,Safari5.1-6 */ background: linear-gradient(to bottom, #ffffff 0%,#f1f1f1 50%,#e1e1e1 51%,#f6f6f6 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#f6f6f6',GradientType=0 ); /* IE6-9 */ display: inline-block; padding-top: 20px; padding-right: 30px; padding-bottom: 20px; padding-left: 30px; border: 1px solid #333; color: #333; text-decoration: none; border-radius: 6px; -webkit-border-radius: 6px; -moz-border-radius: 6px; } a:hover { background: #ffffff; /* Old browsers */ background: -moz-linear-gradient(top, #ffffff 0%, #f3f3f3 50%, #ededed 51%, #ffffff 100%); /* FF3.6-15 */ background: -webkit-linear-gradient(top, #ffffff 0%,#f3f3f3 50%,#ededed 51%,#ffffff 100%); /* Chrome10-25,Safari5.1-6 */ background: linear-gradient(to bottom, #ffffff 0%,#f3f3f3 50%,#ededed 51%,#ffffff 100%); /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#ffffff',GradientType=0 ); /* IE6-9 */ } </style> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script> <script> $(document).ready(function() { $("a").click(function() { $("#wait").show(); }); }); </script> </head> <body> <h1>1ページ目</h1> <p>下のボタンを押すと2秒後に次の画面へ移動します。</p> <a href="02.html">次の画面へ移動</a> <!-- お待ちください画面 --> <div id="wait"> <div class="wak"> <div class="icon"><img src="default.svg" width="100" height="100"></div> <p>処理しています<br>少々お待ちください</p> </div></div> <!-- お待ちください画面ここまで --> </body> </html> |
部分的に解説いたします
ソースは全体を見るとよくわかりませんが、部分的にみるとわかりやすくなります。
部分的に解説いたします。
(1)お待ちください画面
お待ちください画面は、CSSだけで作ります。
fixedにすることで、強制的に前面に表示させています。
■HTML部分
1 2 3 4 5 6 7 |
<!-- お待ちください画面 --> <div id="wait"> <div class="wak"> <div class="icon"><img src="default.svg" width="100" height="100"></div> <p>処理しています<br>少々お待ちください</p> </div></div> <!-- お待ちください画面ここまで --> |
■CSS部分
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
#wait { /** 全画面に強制表示する部分 */ position: fixed; z-index: 999999; top: 0px; left: 0px; width: 100%; height: 100%; /** 最初は非表示にしておく */ display: none; /** 全画面の背景色 */ background-color: rgba(0, 0, 0, 0.8); padding-top: 70px; text-align: center; } #wait .wak { font-size: 24px; font-weight: normal; line-height: 140%; color: #FFF; display: inline-block; text-align: center; padding-top: 20px; padding-right: 40px; padding-bottom: 20px; padding-left: 40px; border: 1px solid #999; border-radius: 6px; -webkit-border-radius: 6px; -moz-border-radius: 6px; } |
お待ちください画面で重要なのは以下の7行のcssです。
position: fixed;
z-index: 999999;
top: 0px;
left: 0px;
width: 100%;
height: 100%;
display: none;
これを記述しておけばOKです。
あとは好みの装飾をするだけです。
最初は「非表示」にしておくことも肝要です。
(2)Jquery部分
1 2 3 4 5 6 7 |
$(document).ready(function() { $("a").click(function() { $("#wait").show(); }); }); |
aタグがクリックされたら「お待ちください画面」を表示に切り替えています。
この2つの仕掛けでボタン連打をガードできるようになります。
なぜならば、1回押したあとに「お待ちください画面」が最前面に表示されるため、ボタンが強制的に押せなくなるためです。
疑問:_blankリンクをクリックした場合wait画面が表示中のままになりませんか?
今回の方法は、ボタンクリックで強制的に「お待ちください画面」を表示します。
これは、ページが切り替わることが前提のため「お待ちください画面」を消す必要がないからです。
ところが、target=”_blank” (別ウィンドウで表示)にしてしまうと、元画面は「お待ちください画面」表示中のまま固まってしまいます。
_blankを使わなければそれでよいのですが、それでも具合の悪い現象です。
これを何とかする方法はないものでしょうか?
今回、二度押しガード処理を作っていく中で、_blankで「お待ちください画面」で固まる現象についても確認しました。
これに関しても、うまい対処方法があります。
そのやり方については、次回解説いたします。