質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

Q&A

解決済

1回答

4652閲覧

setInterval を使って増加減少のプログラムを作りましたがどうしてもバグが起きてしまいます。。。

space_sss

総合スコア81

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

jQuery

jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

Ajax

Ajaxとは、Webブラウザ内で搭載されているJavaScriptのHTTP通信機能を使って非同期通信を利用し、インターフェイスの構築などを行う技術の総称です。XMLドキュメントを指定したURLから読み込み、画面描画やユーザの操作などと並行してサーバと非同期に通信するWebアプリケーションを実現することができます。

0グッド

1クリップ

投稿2016/12/03 02:18

編集2016/12/03 02:56

下記のようなプログラムを組みました。
内容関しては数字の書いてあるものをチェックしたりすると数値が増加したり
はずすと現象したりするプログラムです。
今回困っていることが
例えば10000のチェックボックスをダブルクリックなどするとバグってしまいます。
バグの内容といたしましては
数字が加算された数値になる前に他のチェックボックスにクリックすると
中途半端な数字で止まってしまい場合によっては同じ数字をいったりきたりしてしまいます。
おそらく
setInterval
が停止していないのではないのかとは思いますが色々試してみましたがどれもうまくいきませんでした。

この対処法などはありませんでしょうか?
それともそもそもの組み方を見直すべきでしょうか?
ajaxに関しては、これ以降のプログラムで使う予定なので出来ればそのままにしておきたいです。
ajaxの返り値は単純にチェックボックスやラジオボタンの数値を足した合計値が返ってくるだけのものになります。
どうか宜しくお願いいたします。

javascript

1<script> 2var num,id,tgt,cnt; 3num=0; 4cnt=300; 5function loop_set(tgt){ 6 if(num<tgt){ 7 id=setInterval(function(){ 8 if(num<=tgt){ 9 $('#count').html(num); 10 num+=Math.floor(tgt/cnt); 11 }else{ 12 $('#count').html(tgt); 13 num=tgt; 14 clearInterval(id); 15 } 16 },1); 17 }else{ 18 id=setInterval(function(){ 19 if(num>=tgt){ 20 $('#count').html(num); 21 if(cnt>tgt){ 22 num-=Math.floor(num/30); 23 if(num<30){ 24 $('#count').html(tgt); 25 num=tgt; 26 clearInterval(id); 27 } 28 }else{ 29 num-=Math.floor(tgt/cnt); 30 } 31 }else{ 32 $('#count').html(tgt); 33 num=tgt; 34 clearInterval(id); 35 } 36 },1); 37 } 38}; 39function pay(){// Ajax通信 40 pay_01 = $('input[name="pay_01"]:checked').val(); 41 var pay_02=[]; 42 $('[name="pay_02[]"]:checked').each(function(){ 43 pay_02.push($(this).val()); 44 }); 45 $.ajax({ 46 url : 'inc/calculation.php', 47 type : 'post', 48 dataType : 'json', 49 data : { 50 pay_01 : pay_01, 51 pay_02 : pay_02 52 } 53 }) 54 //受信部分 55 .done(function(response){ 56 tgt=response['tgt'];//送ったデータのすべてが足された数値が戻ってきます。 57 loop_set(tgt); 58 }) 59 .fail(function() {//エラーが起きた場合 60 alert('通信失敗') 61 }) 62} 63</script> 64<ul> 65 <li><input type="radio" onClick="pay()" name="pay_01" value="10000" />10000</li> 66 <li><input type="radio" onClick="pay()" name="pay_01" value="20000" />20000</li> 67</ul> 68<ul> 69 <li><input type="checkbox" onClick="pay()" name="pay_02[]" value="500" />500</li> 70 <li><input type="checkbox" onClick="pay()" name="pay_02[]" value="10000" />10000</li> 71</ul> 72<div id="count"> 730 74</div>

inc/calculation.phpの詳細は下記になります。

php

1<?php 2$tgt=0; 3if(isset($_POST['pay_01'])){ 4 $tgt+= htmlspecialchars($_POST['pay_01']); 5} 6if(isset($_POST['pay_02'])){ 7 foreach($_POST['pay_02'] as $check) { 8 $tgt+=htmlspecialchars($check); 9 } 10} 11header('Content-type: application/json charset=utf-8'); 12$calculation=array('tgt' => $tgt); 13echo json_encode($calculation); 14?>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/12/03 02:25

inc/calculation.php の内容を追記してください。
kei344

2016/12/03 02:28

「バグ」というのは何のことでしょう。「何をしたときに」「どうなると思って」「どうなったのか」を、出ているエラーなどと併せて、具体的に記述されたほうが回答を得られやすいと思います。
space_sss

2016/12/03 02:30

こちらはただ単純に送信されたデータがすべて加算された数値が返ってくるだけになります!
退会済みユーザー

退会済みユーザー

2016/12/03 02:32 編集

inc/calculation.php の内容を追記してください。 あと、誤植が多くて読みにくいので修正してください。
space_sss

2016/12/03 02:45

誤字の修正とバグの具体的内容を記載いたしました。
退会済みユーザー

退会済みユーザー

2016/12/03 02:46

inc/calculation.php の内容を追記してください。計算処理の内容や、レスポンスの形式がわからないとデバッグできないから言っているんですよ。修正するとかしないの問題じゃありません。
space_sss

2016/12/03 02:51

phpに関しては今その部分を抜き出して記載するつもりでしたがお時間かかってしまい申し訳ありません。
space_sss

2016/12/03 02:57

たった今記載いたしました。
guest

回答1

0

ベストアンサー

else 以下には絶対に入らないから、if(num<tgt){} の処理は無駄。
描画の回数を減らす。/ 300 となると、1000分の1秒ごとに300回描画するので。
描画のインターバルを増やす。1000分の1秒だとクライアントのマシンのスペックによってもたつく。
冗長な処理を簡素化。
obClick はレガシーコードなので、削除。on('click', function(){})に置き換え。

html

1<!DOCTYPE HTML> 2<html lang="en-US"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 <style type="text/css"> 7 #count { 8 width: 200px; 9 border: 1px solid #CCC; 10 padding: .5em; 11 text-align: right; 12 } 13 </style> 14 </head> 15 <body> 16 <form action=""> 17 <ul> 18 <li> 19 <label> 20 <input class="item" type="radio" name="pay_01" value="10000" /> 21 10000 22 </label> 23 </li> 24 <li> 25 <label> 26 <input class="item" type="radio" name="pay_01" value="20000" /> 27 20000 28 </label> 29 </li> 30 </ul> 31 <ul> 32 <li> 33 <label> 34 <input class="item" type="checkbox" name="pay_02[]" value="500" /> 35 500 36 </label> 37 </li> 38 <li> 39 <label> 40 <input class="item" type="checkbox" name="pay_02[]" value="10000" /> 41 10000 42 </label> 43 </li> 44 </ul> 45 </form> 46 47 <div id="count"> 48 0 49 </div> 50 51 <script type="text/javascript" src="//code.jquery.com/jquery-3.1.1.min.js"></script> 52 <script> 53 function loop_set(tgt) { 54 55 // 初期値 56 var num = 0; 57 58 //描画回数 59 var refreshCount = 23; // 素数の方が演出的にいいかも 60 61 //描画インターバル 62 var interval = 10; 63 64 var id = setInterval(function () { 65 66 if (num <= tgt) { 67 num += Math.floor(tgt / refreshCount); 68 } else { 69 num = tgt; 70 clearInterval(id); 71 } 72 $('#count').text(num); 73 74 }, interval); 75 } 76 77 function pay() {// Ajax通信 78 $.ajax({ 79 url: 'inc/calculation.php', 80 type: 'post', 81 dataType: 'json', 82 data: $("form").serialize() 83 }).done(function (response) { 84 loop_set(response['tgt']); 85 }).fail(function () { 86 alert('通信失敗'); 87 }); 88 } 89 90 $('.item').on('click', function () { 91 pay(); 92 }); 93 </script> 94 </body> 95</html>

htmlspecialcharsを使うのは不適切。

php

1<?php 2 3function calculate(array $arr) 4{ 5 $sum = 0; 6 foreach ($arr as $val) { 7 if (is_array($val)) { 8 $sum += calculate($val); 9 } else { 10 $sum += $val; 11 } 12 } 13 return $sum; 14} 15 16header('Content-type: application/json'); 17$calculation = array('tgt' => calculate(filter_input_array(INPUT_POST))); 18echo json_encode($calculation);

#追記

減算方向の処理でも結構簡素化できました。

html

1<!DOCTYPE HTML> 2<html lang="en-US"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 <style type="text/css"> 7 #count { 8 width: 200px; 9 border: 1px solid #CCC; 10 padding: .5em; 11 text-align: right; 12 } 13 </style> 14 </head> 15 <body> 16 <form action=""> 17 <ul> 18 <li> 19 <label> 20 <input class="item" type="radio" name="pay_01" value="10000" /> 21 10000 22 </label> 23 </li> 24 <li> 25 <label> 26 <input class="item" type="radio" name="pay_01" value="20000" /> 27 20000 28 </label> 29 </li> 30 </ul> 31 <ul> 32 <li> 33 <label> 34 <input class="item" type="checkbox" name="pay_02[]" value="500" /> 35 500 36 </label> 37 </li> 38 <li> 39 <label> 40 <input class="item" type="checkbox" name="pay_02[]" value="10000" /> 41 10000 42 </label> 43 </li> 44 </ul> 45 </form> 46 47 <div id="count"> 48 0 49 </div> 50 51 <script type="text/javascript" src="//code.jquery.com/jquery-3.1.1.min.js"></script> 52 <script> 53 54 // 初期値 55 var num = 0; 56 57 function loop_set(tgt) { 58 59 //描画回数 60 var refreshCount = 37; 61 62 //描画インターバル 63 var interval = 10; 64 65 // 増減 66 var diff = tgt - $('#count').text(); 67 68 var id = setInterval(function () { 69 70 if ((diff > 0 && num <= tgt) || (diff < 0 && num > tgt)) { 71 num += Math.floor(diff / refreshCount); 72 } else { 73 num = tgt; 74 clearInterval(id); 75 } 76 $('#count').text(num); 77 78 }, interval); 79 } 80 81 function pay() {// Ajax通信 82 $.ajax({ 83 url: 'inc/calculation.php', 84 type: 'post', 85 dataType: 'json', 86 data: $("form").serialize() 87 }).done(function (response) { 88 loop_set(response['tgt']); 89 }).fail(function () { 90 alert('通信失敗'); 91 }); 92 } 93 94 $('.item').on('click', function () { 95 pay(); 96 }); 97 </script> 98 </body> 99</html>

#追記

html

1<!DOCTYPE HTML> 2<html lang="en-US"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 <style type="text/css"> 7 #count { 8 width: 200px; 9 border: 1px solid #CCC; 10 padding: .5em; 11 text-align: right; 12 } 13 </style> 14 </head> 15 <body> 16 <form action=""> 17 <ul> 18 <li> 19 <label> 20 <input class="item" type="radio" name="pay_01" value="10000" /> 21 10000 22 </label> 23 </li> 24 <li> 25 <label> 26 <input class="item" type="radio" name="pay_01" value="20000" /> 27 20000 28 </label> 29 </li> 30 </ul> 31 <ul> 32 <li> 33 <label> 34 <input class="item" type="checkbox" name="pay_02[]" value="500" /> 35 500 36 </label> 37 </li> 38 <li> 39 <label> 40 <input class="item" type="checkbox" name="pay_02[]" value="10000" /> 41 10000 42 </label> 43 </li> 44 </ul> 45 </form> 46 47 <div id="count" data-value="0"> 48 0 49 </div> 50 51 <script type="text/javascript" src="//code.jquery.com/jquery-3.1.1.min.js"></script> 52 <script> 53 function number_format(num) { 54 return num.toLocaleString(); 55 } 56 57 function loop_set(tgt) { 58 59 //描画回数 60 var refreshCount = 37; 61 62 //描画インターバル 63 var interval = 10; 64 65 // 変更前の値 66 var num = parseInt($('#count').attr('data-value')) + 0; 67 68 // 増減 69 var diff = tgt - num; 70 71 var id = setInterval(function () { 72 73 if ((diff > 0 && num <= tgt) || (diff < 0 && num > tgt)) { 74 num += Math.floor(diff / refreshCount); 75 } else { 76 num = tgt; 77 clearInterval(id); 78 } 79 $('#count').text(number_format(num)) 80 .attr('data-value', num); 81 82 }, interval); 83 } 84 85 function pay() {// Ajax通信 86 $.ajax({ 87 url: 'inc/calculation.php', 88 type: 'post', 89 dataType: 'json', 90 data: $("form").serialize() 91 }).done(function (response) { 92 loop_set(response['tgt']); 93 }).fail(function () { 94 alert('通信失敗'); 95 }); 96 } 97 98 $('.item').on('click', function () { 99 pay(); 100 }); 101 </script> 102 </body> 103</html>

#追記

html

1 2 <script> 3 function number_format(num) { 4 return num.toLocaleString(); 5 } 6 7 function loop_set(tgt) { 8 9 //描画回数 10 var refreshCount = 37; 11 12 //描画インターバル 13 var interval = 10; 14 15 // 変更前の値 16 var num = parseInt($('#count').attr('data-value')) + 0; 17 18 // 増減 19 var diff = tgt - num; 20 21 var id = setInterval(function () { 22 23 if ((diff > 0 && num <= tgt) || (diff < 0 && num > tgt)) { 24 num += Math.floor(diff / refreshCount); 25 } else { 26 num = tgt; 27 clearInterval(id); 28 } 29 $('#count').text(number_format(num)) 30 .attr('data-value', num); 31 32 }, interval); 33 } 34 35 function pay() {// Ajax通信 36 if ($("form").serialize() === '') { 37 loop_set(0); 38 return; 39 } 40 $.ajax({ 41 url: 'inc/calculation.php', 42 type: 'post', 43 dataType: 'json', 44 data: $("form").serialize() 45 }).done(function (response) { 46 loop_set(response['tgt']); 47 }).fail(function () { 48 alert('通信失敗'); 49 }); 50 } 51 52 $('.item').on('click', function () { 53 pay(); 54 }); 55 56 </script>

投稿2016/12/03 03:51

編集2016/12/03 16:13
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

space_sss

2016/12/03 11:45

ご回答ありがとうございます。 確認をさせていただいたのですがこれですと減少する際に0からの数え直しでの表示になってしまうので実際にやりたいものの表示された数値からの減少といった形をとるために if(num<tgt){}をつけていました。 例えば 10500から500になった場合 num="10500"; tgt="500"; だった場合ご提案いただいた処理ですと 0から500といった増加になりますが実際に行いたい処理は 10500から500といった処理を行いたくこの処理を分けていました。 phpファイルに関してご指摘ありがとうございます! htmlspecialcharsの関数に関して認識を誤っていました! 再度確認htmlspecialchars関しては勉強させていただきます。 ご機会ありがとうございます!
退会済みユーザー

退会済みユーザー

2016/12/03 13:26 編集

スクリプトの二行目、num=0; これが入っていると、どんな値から変更されても、0からカウントしてしまいますよ。と思ったけど、functionの外でしたね。
退会済みユーザー

退会済みユーザー

2016/12/03 13:35

(変更後の値)-(元の値)→(実際の増減) 増えるときは+になるし、減るときはーになるので、コードは簡潔になりそうですね。 条件式の入れ子が確実に1個減ると思います。
space_sss

2016/12/03 14:44

なるほどわかりやすいご回答ありがとうございます。 やりたいことがうまくいきました! 後もうひとつだけお伺いしたいのですが、 こちらで提示したエラーは一切出なくなりマイナスに関してもfunctionの外にnumを置いたことにより数値を保持できるようになっているので なのでこの部分をnumにして定義することに問題は起きますでしょうか? $('#count').text()でテキストの中身の数値を引数で取ることによりダブルクリックをした際に通信にエラーが起きるかと思います。 ただnumで定義することによりクリックした数だけsetIntervalが動くことになり何度も処理が行われることになります。 その際にstop()の関数を使いもし連続でボタンが押された際にはの処理を作った方がよろしいのでしょうか? あるいは$('#count').text()により引数で取得し通信エラーが起きた際にすべてのチェックボックスやラジオボタンを外しnumの数値に0を代入しリセット的な処理を行ったほうがよろしいのでしょうか? たびたびのご質問申し訳ありません。 万が一質問内容が趣旨とずれているようでしたらこちらの質問は一度終了させていただき再度新規で質問を立てさせていただきます。 非常に勉強になりました! ご回答ありがとうございます!
退会済みユーザー

退会済みユーザー

2016/12/03 14:54 編集

> $('#count').text()でテキストの中身の数値を引数で取ることによりダブルクリックをした際に通信にエラーが起きるかと思います $('#count').text() を numに置き換えるという意味なら、どちらでも良いと思います。 この現象については、こちらで再現しないので、なんとも言えない状況です。 予想では、ajax が前の処理か完了する前に次のイベントが発行された場合、レスポンスが前後することがあります。その場合に起こりうるかなとは思われますが、なんせ、再現しないので確証はありません。 ajax通信中にイベントを発行できないように、透明のレイヤーをページ全体に覆ってしまうとか、クリックをさせない工夫をするのが良いかもしれません。
space_sss

2016/12/03 14:56

環境の問題ということですね… チェックボックスを連続でクリックした際におそらく数値が確定していない際に起きてしまう現象でした。 ちなみに diff = tgt - $('#count').text(); この部分の $('#count').text() を num にして定義することにに関してはあまりよろしくないのでしょうか?
退会済みユーザー

退会済みユーザー

2016/12/03 15:06 編集

どちらでも、動作に変化はありません。 計算結果を3桁のカンマ区切りで出したいとかそういう場合には num 出なくてはいけませんので、num のほうかいいと思います。 変数はできるだけグローバル空間に定義したくないなーとは思うのですが、その一方で整合性のないコードだなと、モヤモヤ…
space_sss

2016/12/03 15:11

ご回答ありがとうございます! おそらくフォーマットをしカンマの切り出しを行うと思いますので今回はnumを使い進めていきたいと思います。 色々今回は勉強になりましたのでありがとうございました。 今回はこちらで質問を閉じさせていただきます! ご協力感謝いたします。
退会済みユーザー

退会済みユーザー

2016/12/03 15:30

モヤモヤな部分を解消したコードを追記しておきました。
space_sss

2016/12/03 15:47

わざわざフォーマットの部分も追記いただきましてありがとうございます! ちなみに num = parseInt($('#count').attr('data-value')) + 0; の .attr('data-value') に関しては一切思いつきませんでした… いろんな方法があり本当に勉強になりました。 お付き合いいただき感謝いたします。
退会済みユーザー

退会済みユーザー

2016/12/03 15:54

気になったので、調べてみたのですが、PCのスペックの件です。 そういえば、ディスプレイの性能表に応答速度って項目があったなぁーと思って、調査しました。 例えばこのページ http://kakaku.com/specsearch/0085/ 右側の方に「応答速度」という項目があります。「5ms」という値が多いようです、つまり1000分の1秒だと、ディスプレイの性能をオーバーしてしまいますね。CPUの処理なども影響するのでこれだけを指標にはできないと思いますが、やはり1000分の1秒で再描画するのは無理がありそうです。
space_sss

2016/12/03 16:02

そして最後に」トラブルが起きてしまいました。 すべてのチェックボックスを外すと送るものがなくなってしまうので送るものがなくfailになり通信エラーが発生いたします。 こういった場合はどのような対処をすればよろしいのでしょうか… 何度も申し訳ありません。。。
space_sss

2016/12/03 16:03

> やはり1000分の1秒で再描画するのは無理がありそうです。 わざわざそんなところまで調べていただきまして申し訳ありません。。。
space_sss

2016/12/03 16:06

function pay(){// Ajax通信 if($("#calculation_pay").serialize()){ $.ajax({ url: 'inc/calculation.php', type: 'post', dataType: 'json', data: $("#calculation_pay").serialize() }).done(function(response){ loop_set(response['tgt']); }).fail(function(){ alert('通信失敗'); }); }else{ tgt=0; loop_set(tgt); } } 一応無理やりですがこういったふうにpayの関数に記載しましたがこれはあまりにも雑な気がしまして…
退会済みユーザー

退会済みユーザー

2016/12/03 16:15

追記しておきましたよ。 if で大きく囲んでしまうと入れ子が深くなって可読性が悪くなっちゃいますね。
space_sss

2016/12/03 20:19

ありがとうございます!早速参考にさせていただきました!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問