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

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

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

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

Q&A

解決済

1回答

912閲覧

javascriptでユーザーに求めた作業が終了するまでループを止める方法を知りたい

pig_hedas

総合スコア7

JavaScript

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

0グッド

0クリップ

投稿2019/09/10 11:36

ループ中にボタンを表示し、ボタンが押されるまでループを止める方法について教えてください。

こちらの記事を参考にして、javascriptでボットプログラムを作成しています。

起動されると、ボットはあらかじめ用意されたJsonファイルをajaxで読み出し、配列に代入して順に処理していきます。取り出したデータには"id"や"type"などのオブジェクトがあり、それぞれ処理の順番や要求される動作についてのタグになっています。

下が作成中のプログラムです。

json

1[ 2 { 3 "id":"1", 4 "type":"choice", 5 "value":["hoge1","hoge2","hoge3"], 6 "inline":[ 7 "id1":"1", 8 "id2":"hoge1", 9 "type":"text", 10 "value":"hoge1が押されました" 11 ] 12 }, 13 { 14 "id":"2", 15 "type":"text", 16 "value":"hogehoge" 17 } 18] 19

javascript

1let jdatatmp=[]; 2let num = 0; 3$(document).ready(function(){ 4 5 //文字列(html要素)を格納できる配列を定義 6 var chatDom =[]; 7 //文字列(この場合は引数のdom)を配列の要素として格納できる関数 8 var p = function(dom){ 9 chatDom.push(dom); 10 }; 11 12 //配列の要素として一つ一つ格納していき、最後にjoin関数で結合する 13 //チャットの外側部分① 14 p('<div id="bms_messages_container">'); 15 16 //ヘッダー部分② 17 p('<div id="bms_chat_header">'); 18 p('<div id="bms_chat_user_status">'); 19 p('<div id="bms_status_icon">●</div>') 20 p('<div id="bms_chat_user_name">ユーザー</div>'); 21 p('</div>'); 22 p('</div>'); 23 //タイムライン部分③ 24 p('<div id="bms_messages">'); 25 26 //メッセージ1(左側) 27 p('<div class="bms_message bms_left">'); 28 p('<div class="bms_message_box">'); 29 p('<div class="bms_message_content">'); 30 p('<div class="bms_message_text">ほうほうこりゃー便利じゃないか</div>'); 31 p('</div>'); 32 p('</div>'); 33 p('</div>'); 34 p('<div class="bms_clear"></div>'); 35 p('</div>'); 36 37 p('<div id="PushMore">'); 38 p('</div>'); 39 40 // テキストボックス、送信ボタン④ 41 p('<div id="bms_send">'); 42 p('<textarea id="bms_send_message"></textarea>'); 43 p('<div id="bms_send_btn">送信</div>'); 44 p('</div>'); 45 46 //jQueryのappend関数を使って、your_containerの直下にhtml要素を書き加える 47 $('#your_container').append(chatDom.join('')); 48 49 $.ajax({url:'json',datatype'json'}) 50 .done(function(data){ 51 $(data).each(function(){ 52 jdatatmp[num] = data; 53 num=num+1; 54 }); 55 mainBot(jdatatmp); 56 }); 57}); 58 59function mainBot(jdata){ 60 for(var i = 0,i<=jdata.length-1,i++){ 61 dataTypeCheck(jdata[i]); 62 } 63} 64 65function dataTypeCheck(jdata){ 66 switch(jdata.type){ 67 case "text": 68 $('#PushMore').append('<div class="bms_message bms_left"><div class="bms_message_box"> 69 <div class="bms_message_content"><div class="bms_message_text">'+jdata.value); 70 $('#PushMore').append('<div class="bms_clear">') 71 break; 72 73 case "choice": 74 ボタンを表示する処理 75 var str=[]; 76 for(var i = 0 ;i<jdata.value.length;i=i+1){ 77 str[i]= '<div class="bms_message_btn" onclick="ButtonClickedMove(\''+jdata.value[i]+'\');>' + jdata.value[i] + '</div>'; 78 } 79 var a=""; 80 for(var i = 0 ;i<str.length;i++){ 81    a = a + str[i]; 82 } 83 84 $("#PushMore").append('<div class="bms_message bms_left"><div class="bms_message_box"><div class="bms_message_content"><div class="bms_message_text">' + jdata.text + '<br>' + a); 85 $("#PushMore").append('<div class="bms_clear">'); 86 break; 87 } 88} 89 90function ButtonClickedMove(i){ 91 92 console.log("gt"+i); 93 var text=[]; 94 text=textChoice(i); 95 96 for(var i = 0 ;i<text.length;i++){ 97 //左側 回答要素 98 $("#PushMore").append('<div class="bms_message bms_left"><div class="bms_message_box"><div class="bms_message_content"><div class="bms_message_text">' + text[i]); 99 } 100 101 $("#PushMore").append('<div class="bms_clear">'); 102 103 104 if(i==0){ 105 return 106 } 107} 108

取り出したJsonオブジェクトのtypeがtextの場合、プログラムはValueの値をそのまま表示します。しかしchoiceだった場合は、Valueの値をButtonClickedMoveファンクションでボタン化し、表示します。

この時、今のままではJsonから取り出したすべての処理を一気にやってしまいます。typeがtextの場合はそれでもいいのですが、choiceの場合は一時停止し、ユーザーがボタンを押してから改めて次の配列を処理したいです。色々と調べて非同期通信やSleep機能での一時停止などは見つかりましたが、今回の場合はどうも使えそうにありません。

この場合、どんな技術をどのように使えば望む結果が出せるでしょうか?

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

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

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

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

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

guest

回答1

0

ベストアンサー

こういうことですかね?

javascript

1<script> 2var json=[ 3 {"id":"1", "type":"text",}, 4 {"id":"2", "type":"choice",}, 5 {"id":"3", "type":"text",}, 6 {"id":"4", "type":"text",}, 7 {"id":"5", "type":"choice",}, 8 {"id":"6", "type":"choice",}, 9 {"id":"7", "type":"choice",}, 10 {"id":"8", "type":"text",}, 11 {"id":"9", "type":"text",}, 12 ]; 13$(function(){ 14 $('#continue').on('click',function(){ 15 $(this).hide(); 16 }); 17 (async()=>{ 18 for(var x of json){ 19 console.log(x); 20 $('#continue').toggle(x.type=="choice") 21 await new Promise(resolve=>{ 22 /* var c=0;//ゴミでした */ 23 var timerId=setInterval(()=>{ //timerIdはグローバルでなくても良かったので調整 24 if($('#continue').is(':hidden')){ 25 clearInterval(timerId); 26 resolve(); 27 } 28 },100); 29 }); 30 } 31 })(); 32}); 33</script> 34<input type="button" value="continue" id="continue">

流れの解説

  • async処理を宣言
  • jsonからデータをxとして取り出す
  • xを表示
  • #continueボタンをxのtypeがchoiceだったとき表示する、そうでないときは非表示
  • awaitでpromiseを呼び出し
  • promise内部では1/10秒ごとに#continueボタンの表示状態をチェック
  • 表示時=ユーザーからの入力待ち=promiseが進行しないので同期する
  • 非表示時=インターバル処理をとめ(clearInterval),promiseから復帰(resolve)
  • promiseから戻るとforループが進行しjsonの次のデータをチェック

投稿2019/09/11 02:08

編集2019/09/12 01:05
yambejp

総合スコア114742

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

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

pig_hedas

2019/09/11 12:18 編集

遅くなってすいません。試してみましたが、確かにこれでできそうです。ありがとうございました。 ところでもう少し質問をしたいのですが、いいでしょうか? このプログラムの動作は、 「async() 以降の処理を起動時に行い、xのタイプがchoiceだった場合にのみcontinueボタンを表示し、ボタンが非表示だった場合はループを停止する。ボタンがクリックされるとボタンを非表示にし、async()以降の処理に続ける」 という理解でよいですか? また、resolve();はどのように働いているのですか? よろしくお願いします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問