プロが教える店舗&オフィスのセキュリティ対策術

htmlやCSSで作ったカウントダウンがポップアップ中に止まる。

こんばんは。自作のTRPG(対話ゲーム)の演出のため「10分間をカウントダウンするタイマー」を作りたく、右も左もわからない初心者ですがひとつずつ調べながら以下のところまで作ることができました。

※現時点ではテスト用に30秒のカウントダウンで書いています。

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title data-ori="test">タイトル</title>
</head>

<body>
<br>
<h2 style="text-align:center"><font size="48">プログラムの削除状況の<br>進捗を表示しています</font><h2>
<hr>
<h2 style="text-align:center"><form name="test" onSubmit="return false;">
<input type="text" name="counter" style="width:300px;height:100px; font-size:50px; text-align:center">
<input type="button" name="b_start" size="20" value="停止" onlik="count_start"()>
</form><h2>

<script type="text/javascript">
//初期設定
def_count = 30;

timer_reset();
count_start();

function timer_reset() {
//タイマーの初期化
timerID = 0;
document.test.counter.value = def_count;
document.test.b_start.disabled = false;
}

function set_timer(num) {
//規定時間の設定
if (timerID > 0) {
count_stop();
}
document.test.counter.value = num;
count_start();
}

function count_start() {
//カウント開始
count = document.test.counter.value;
document.test.b_start.disabled = true;
timerID = setInterval('countdown()',1000);
}

function countdown() {
//カウント表示
count--;
document.test.counter.value = count_format(count);
if (count <= 0) {
count_stop();
}
}

function count_stop() {
//カウント停止
clearInterval(timerID);
timer_reset();
}

function count_format(num) {
//カウント表示の書式設定
var tm,ts;
tm = Math.floor(num / 60); //分
ts = num % 60; //秒
if (ts < 10) ts = "0" + ts;
return tm + ":" + ts;
}
</script>
</div>

<h2 style="text-align:center">
<script type = "text/javascript">
<!--

function matchPass() {

var inpass = document.forms[ "pass" ].elements[ "inpass" ].value;
var validpass = "正答";
if( inpass == validpass ) location.href = "goodplus.html";
else alert( "パスワードが認証できません" );

}
</script>
</head>
<body>
<form name = "pass">
<div>
<input type = "text" value = "" name = "inpass" placeholder="回数制限なし" >
<input type = "button" value = "認証" onclick = "matchPass();">
</div>

<br>
<font size="6">強制デリートを実行中です<br>
停止するにはパスワードを入力してください<br>
<br>
</font><h2>

<HTML>
<HEAD>
<font size="1">
<STYLE Type="text/css">
.txtstyle { border-style: none}
</STYLE>
<SCRIPT LANGUAGE="JavaScript">
<!--
var start=new Date();
var cnt_val=30;
start=Date.parse(start)/1000;
function count_down(){
var now=new Date();
now=Date.parse(now)/1000;
var x=parseInt(cnt_val-(now-start),10);
if(document.form1){document.form1.c_down.value = x;}
if(x>0){
timerID=setTimeout("count_down()", 100)
}else{
location.href="good.html"
}
}
window.setTimeout('count_down()',100);
//-->
</SCRIPT>
</HEAD>
<BODY>
<center>
<FORM NAME="form1">
<INPUT TYPE="text" NAME="c_down" SIZE="2" VALUE="30" class=txtstyle>seconds left</font>
</FORM>
</center>
</BODY>
</HTML>
</body>
</html>

・何月何日まで、ではなくURLアクセス時点から10分間を強制カウントダウン
・誤答をするとメッセージがポップアップ
・正答か時間切れで各リンク先へ

としたいのですが、ポップアップ中カウントダウンが停止してしまい、しかし内部では動いていて表示とズレが発生します。ポップアップを10秒表示させた場合『残り10秒』表示時点で時間切れリンクが作動したり。

これをポップアップ中もカウントダウンする、またはポップアップ終了時に経過時間を反映させるようにしたいです。自分でも調べましたが調べ方が悪いのか上手くわからず、お知恵を貸して頂けませんでしょうか。

質問者からの補足コメント

  • 皆様本当にありがとうございます。初心者すぎて一喝されるくらいかと思っていたのに、お手間を割いてくださり本当に嬉しく思っております。ありがとうございます。ここまでで『ダイアログの裏で減算をする』はひとまず解決しました。本当にありがとうございます。

    あまり人様に甘え過ぎてはいけないと思うので、これはもしお答え頂ければ、なのですが。追加で質問があります。

    パスワード入力をする際にスマホならいいのですが、PC環境でEnterキーで送信しようとすると『たとえ正答であっても入力したことにならず、カウントダウンが初期値に戻ってしまう』のです。これは回避できる問題でしょうか、また、回避できるとしたらどの辺りを修正するとよい問題でしょうか?

    ここまででも皆さま本当に助けて頂いて感謝しており、厚かましい追加質問なのですが、もしお気が向いたら、どうぞここもお知恵をお借りできたら嬉しく存じます。

      補足日時:2021/08/04 13:21

A 回答 (4件)

ダイアログ表示を window.alert 関数で行うと、


他のスクリプト実行がすべて停止するようです。

ページ内の DOM を操作して、
あたかもダイアログの様に表示を行う方式をご検討ください。

Web 標準の機能で実現
ただし、未対応ブラウザが多いのが欠点
https://developer.mozilla.org/ja/docs/Web/HTML/E …

外部 JS ライブラリを導入して実現
https://www.google.com/search?q=dialog+js+library
    • good
    • 0
この回答へのお礼

ダイアログのように表示するという発想はなかったので目から鱗でした。ただ、仰る通り非対応ブラウザが多いことで、今回は教えて頂いたこちらの方法については諦めることにしました。でも、いつか使うこともあると思うのでとても参考になりました。

初心者の質問にご丁寧にお答えくださり、ありがとうございます。

お礼日時:2021/08/04 13:02

var start=new Date();


var cnt_val=30;
var now=new Date();

この3つの変数を使って、
残り秒数を表示できるようにするのが
良いのではないかと思いました。

この直後にある、
timerID=setTimeout("count_down()", 100)
というところで、

setTimeoutの使い方がおかしいみたいです。
関数に""は要りませんが、
これをはずすと30秒間、ずっと無限ループを
繰り返してしまいます。
    • good
    • 0
この回答へのお礼

この3つを使って……とのことでしたが、「その3つとも含まれているつもりなんだけど何か違うのかな?」というレベルの初心者です。本当にすみません。

とはいえすぐに「どういうこと?」と聞くのもあまりに人様頼りだと思って試行錯誤してみたのですが、(自分がこうかなと思ったように)修正したら制限時間切れでもリンク先に遷移せず30秒に戻ってしまったり、予想しない挙動になったり……もう少し頑張ってみようと思います!

setTimeoutの使い方がおかしいとのことでしたが、仰る通りで無限ループしてしまい、""をつけると挙動的には一応狙いに近づいたので現状そのようになっていました。本当に初心者の見よう見まねレベルのため、何もかもめちゃくちゃな書き方で申し訳ないです。

お礼日時:2021/08/04 13:09

書いてみました。

動くとは思います。

<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
<title data-ori="test">タイトル</title>
<STYLE Type="text/css">
.txtstyle {
border-style: none
}
</STYLE>
</head>
<body>
<br>
<h2 style="text-align:center"><span size="48">プログラムの削除状況の<br>進捗を表示しています</span></h2>
<hr>
<div style="text-align:center">
<form name="test" onSubmit="return false;">
<input type="text" name="counter" style="width:300px;height:100px; font-size:50px; text-align:center">
<input type="button" name="b_start" size="20" value="停止" onlik="count_start" ()>
</form>
</div>
<div style="text-align:center">
<form name="pass">
<div>
<input type="text" value="" name="inpass" placeholder="回数制限なし">
<input type="button" value="認証" onclick="matchPass();">
</div>
</form>
<p>強制デリートを実行中です<br>
停止するにはパスワードを入力してください<br>
</p>
<br>
</div>
<div style="text-align:center">
<FORM NAME="form1">
<INPUT TYPE="text" NAME="c_down" SIZE="2" VALUE="30" class=txtstyle>seconds left</span>
</FORM>
</div>
<script>
//初期設定
const DEF_COUNT = 600; // カウントダウンする秒数
let start = null; // timer_reset() でアクセスした時点の秒数を入れる
let now = null; // count_start() で今の秒数を入れる

timer_reset();
count_start();

function timer_reset() {
//タイマーの初期化
start = Date.parse(new Date()) / 1000;
document.test.counter.value = count_format(DEF_COUNT);
document.test.b_start.disabled = false;
}

function count_start() {
//カウント開始
document.test.b_start.disabled = true;
timerID = window.setInterval(
// 1000msごとに実行
function () {
now = Date.parse(new Date()) / 1000;
if (DEF_COUNT + start - now > 0) {
document.test.counter.value = count_format(DEF_COUNT + start - now);
} else {
count_stop();
}
}, 1000);
}

function count_stop() {
//カウント停止
window.clearInterval(timerID);
location.href = "good.html";
}

function count_format(num) {
//カウント表示の書式設定
var tm, ts;
tm = Math.floor(num / 60); //分
ts = num % 60; //秒
if (ts < 10) ts = "0" + ts;
return tm + ":" + ts;
}

function matchPass() {
// パスワードがあっているか確認
var inpass = document.forms["pass"].elements["inpass"].value;
var validpass = "正答";
if (inpass == validpass) {
location.href = "goodplus.html"
} else {
alert("パスワードが認証できません")
}
}
</script>
</body>
</html>
    • good
    • 0
この回答へのお礼

動きました! ダイアログ表示中はカウントダウンが止まるけれど、表示をやめるとちゃんと減算ぶんが反映されます……!

求めていた挙動になって感動しています。初心者すぎて一喝されるくらいかと思っていたのに、お手間を割いて書き起こしてまでくださって本当に嬉しく思っております。ありがとうございます。

ちなみに……ちなみになのですが。あまり人様に甘えてはいけないと思うので、これはもしお答え頂ければ、なのですが。ひとつだけ追加で質問があります。

パスワード入力をする際にスマホならいいのですが、PC環境でEnterキーで送信しようとすると『たとえ正答であっても入力したことにならず、カウントダウンが初期値に戻ってしまう』のです。これは回避できる問題でしょうか、また、回避できるとしたらどの辺りを修正するとよい問題でしょうか?

ここまででも本当に助けて頂いて感謝しており、厚かましい追加質問なのですが、もしお気が向いたらここもお知恵をお借りできたら嬉しく存じます。

お礼日時:2021/08/04 13:18

No2です。



>その3つとも含まれているつもりなんだけど何か違うのかな?

書き方が悪くてすみません。

変数の定義はすでに含まれているのですが、
"good.html"に転送するかどうかの判断にのみ使われており、

document.test.counter.value
の表示には使われていなかったので、

この表示にも、3つの変数が使えるようになると
良いのではないかと考えました。
「残り秒数を表示できるようにする」というのは、
そういう意図でした。
その意図で書きかえたのが、No3になります。


次に、No3です。

>PC環境でEnterキーで送信しようとすると

https://techacademy.jp/magazine/31038

このページを参考にして、scriptの一番最後に、

document.getElementsByName("inpass")[0].onkeypress = (e) => {
// inpassに入力されたキーを取得
const key = e.keyCode || e.charCode || 0;
// 13はEnterキーのキーコード
if (key == 13) {
// アクションを行わない
e.preventDefault();
matchPass();
}
}

を追記したら、とりあえず動きました。

でもたぶん、もっときれいな方法はあるような気がします。
    • good
    • 0
この回答へのお礼

夜分にメール通知など鳴らしてしまったらすみません。今回は初心者の頓珍漢な質問にも根気よく教えてくださり、本当に助かりました。画面のこちら側で頭を下げております。

No.2補足
>"good.html"に転送するかどうかの判断にのみ使われており
書き方が悪いなどということはなく、私の知識と理解力の不足が原因です。この一文でようやく理解できました。

No.3補足
>追記したら、とりあえず動きました。
参考URLを教えてくださっただけでなく具体的対処法まで書いてくださり、本当にわかりやすかったです。

貴重なお時間を割いてくれて本当に本当にありがとうございました。おかげさまで理想の挙動として求めていたものが完成しました。

自作ゲームを演出するにあたり余所から類似のタイマーをお借りすることも出来たのですが、やるからにはそうしたツールも自作したいという初心者の挑戦でした。思い立って書き始めて悩んで詰まってこうしてお知恵を借りて、という一日半の短い体験でしたがとても楽しかったです。プログラムを書く方々はすごいですね。何かひとついじる度に思いもよらない挙動を返してきて、混乱しながらもとてもわくわくしました。

読んでくれてありがとう。お体などお大事に過ごされてください。

お礼日時:2021/08/05 02:31

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!