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

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

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

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

JavaScript

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

jQuery

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

Q&A

解決済

3回答

4576閲覧

JavaScript/jQueryでローカルにあるjsonファイルの中身を配列として取得できない

kisuke-09

総合スコア13

JSON

JSON(JavaScript Object Notation)は軽量なデータ記述言語の1つである。構文はJavaScriptをベースとしていますが、JavaScriptに限定されたものではなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しが行えるように設計されています。

JavaScript

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

jQuery

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

HTML

HTMLとは、ウェブ上の文書を記述・作成するためのマークアップ言語のことです。文章の中に記述することで、文書の論理構造などを設定することができます。ハイパーリンクを設定できるハイパーテキストであり、画像・リスト・表などのデータファイルをリンクする情報に結びつけて情報を整理します。現在あるネットワーク上のほとんどのウェブページはHTMLで作成されています。

CSS

CSSはXMLやHTMLで表現した色・レイアウト・フォントなどの要素を指示する仕様の1つです。

0グッド

0クリップ

投稿2018/11/02 08:03

編集2018/11/05 00:11

前提・実現したいこと

お世話になっております。
現在、HTML/JavaScript/CSSを用いて、4択式の問題アプリを作成しております。
参考として以下のサイトのソースコードを使用しています。
参考サイト
上記参考サイトではconst myQuestions = [];の中にハードコーディングで
問題文を記述しておりますが、これをJSON形式で別だしにしたいと考えています。
JavaScriptは現在勉強中であり、皆様の知恵をお借りしたく、ここに投稿させていただきます。
何卒よろしくお願い申し上げます。

発生している問題・エラーメッセージ

現在、以下のエラーメッセージが出ています。

Uncaught TypeError: Cannot read property 'classList' of undefined

該当のソースコード

JavaScript

1(function() { 2 var myQuestions = []; 3 function jsonLoader(){ 4 $.ajax({ 5 type: 'GET', 6 url: 'ローカルにあるjsonファイルのフルパス', 7 dataType: 'json', 8 }).done(function(json, textStatus, jqXHR) { 9 jsonArray = JSON.parse(json); 10 for(var i = 0; i < jsonArray.length; i++){ 11 myQuestions.push({ 12 'question': jsonArray[i].question, 13 'answers': jsonArray[i].answers, 14 'correctAnswer': jsonArray[i].correctAnswer 15 }); 16 }; 17 console.log(myQuestions); 18 }).fail(function(jqXHR, textStatus, errorThrown){ 19 alert(errorThrown); 20 }); 21 } 22 23 24 function buildQuiz() { 25 jsonLoader() 26 const output = []; 27 console.log(myQuestions); 28 // for each question... 29 myQuestions.forEach((currentQuestion, questionNumber) => { 30 // we'll want to store the list of answer choices 31 const answers = []; 32 33 // and for each available answer... 34 for (letter in currentQuestion.answers) { 35 // ...add an HTML radio button 36 answers.push( 37 `<label> 38 <input type="radio" name="question${questionNumber}" value="${letter}"> 39 ${letter} : 40 ${currentQuestion.answers[letter]} 41 </label>` 42 ); 43 } 44 45 // add this question and its answers to the output 46 output.push( 47 `<div class="slide"> 48 <div class="question"> ${currentQuestion.question} </div> 49 <div class="answers"> ${answers.join("")} </div> 50 </div>` 51 ); 52 }); 53 54 // finally combine our output list into one string of HTML and put it on the page 55 quizContainer.innerHTML = output.join(""); 56 } 57 58 function showResults() { 59 // gather answer containers from our quiz 60 const answerContainers = quizContainer.querySelectorAll(".answers"); 61 62 // keep track of user's answers 63 let numCorrect = 0; 64 65 // for each question... 66 myQuestions.forEach((currentQuestion, questionNumber) => { 67 // find selected answer 68 const answerContainer = answerContainers[questionNumber]; 69 const selector = `input[name=question${questionNumber}]:checked`; 70 const userAnswer = (answerContainer.querySelector(selector) || {}).value; 71 72 // if answer is correct 73 if (userAnswer === currentQuestion.correctAnswer) { 74 // add to the number of correct answers 75 numCorrect++; 76 77 // color the answers green 78 answerContainers[questionNumber].style.color = "lightgreen"; 79 } else { 80 // if answer is wrong or blank 81 // color the answers red 82 answerContainers[questionNumber].style.color = "red"; 83 } 84 }); 85 86 // show number of correct answers out of total 87 resultsContainer.innerHTML = `${numCorrect} out of ${myQuestions.length}`; 88 } 89 90 function showSlide(n) { 91 slides[currentSlide].classList.remove("active-slide"); 92 slides[n].classList.add("active-slide"); 93 currentSlide = n; 94 95 if (currentSlide === 0) { 96 previousButton.style.display = "none"; 97 } else { 98 previousButton.style.display = "inline-block"; 99 } 100 101 if (currentSlide === slides.length - 1) { 102 nextButton.style.display = "none"; 103 submitButton.style.display = "inline-block"; 104 } else { 105 nextButton.style.display = "inline-block"; 106 submitButton.style.display = "none"; 107 } 108 } 109 110 function showNextSlide() { 111 showSlide(currentSlide + 1); 112 } 113 114 function showPreviousSlide() { 115 showSlide(currentSlide - 1); 116 } 117 118 const quizContainer = document.getElementById("quiz"); 119 const resultsContainer = document.getElementById("results"); 120 const submitButton = document.getElementById("submit"); 121 122 // display quiz right away 123 buildQuiz(); 124 125 const previousButton = document.getElementById("previous"); 126 const nextButton = document.getElementById("next"); 127 const slides = document.querySelectorAll(".slide"); 128 let currentSlide = 0; 129 130 showSlide(0); 131 132 // on submit, show results 133 submitButton.addEventListener("click", showResults); 134 previousButton.addEventListener("click", showPreviousSlide); 135 nextButton.addEventListener("click", showNextSlide); 136})();

json

1[ 2 { 3 "question": "Who is the strongest?", 4 "answers": { 5 "a": "Superman", 6 "b": "The Terminator", 7 "c": "Waluigi, obviously" 8 }, 9 "correctAnswer": "c" 10 }, 11 { 12 "question": "What is the best site ever created?", 13 "answers": { 14 "a": "SitePoint", 15 "b": "Simple Steps Code", 16 "c": "Trick question; they're both the best" 17 }, 18 "correctAnswer": "c" 19 }, 20 { 21 "question": "Where is Waldo really?", 22 "answers": { 23 "a": "Antarctica", 24 "b": "Exploring the Pacific Ocean", 25 "c": "Sitting in a tree", 26 "d": "Minding his own business, so stop asking" 27 }, 28 "correctAnswer": "d" 29 } 30]

HTML

1<!DOCTYPE html> 2<html> 3<head> 4<meta http-equiv="content-type" charset="UTF-8"> 5<link rel="stylesheet" href="css/teraQuizApp.css"> 6<script src="../script/jquery-3.3.1.min.js"></script> 7<title>QuizApp</title> 8</head> 9<body> 10<h1>Quiz</h1> 11<div class="quiz-container"> 12 <div id="quiz"></div> 13</div> 14<button id="previous">前の問題</button> 15<button id="next">次の問題</button> 16<button id="submit">解答を送信</button> 17<div id="results"></div> 18</body> 19<script src="../script/quizScript.js"></script> 20</html>

CSS

1@import url(https://fonts.googleapis.com/css?family=Work+Sans:300,600); 2 3body{ 4 font-size: 20px; 5 font-family: 'Work Sans', sans-serif; 6 color: #333; 7 font-weight: 300; 8 text-align: center; 9 background-color: #f8f6f0; 10} 11h1{ 12 font-weight: 300; 13 margin: 0px; 14 padding: 10px; 15 font-size: 20px; 16 background-color: #444; 17 color: #fff; 18} 19.question{ 20 font-size: 30px; 21 margin-bottom: 10px; 22} 23.answers { 24 margin-bottom: 20px; 25 text-align: left; 26 display: inline-block; 27} 28.answers label{ 29 display: block; 30 margin-bottom: 10px; 31} 32button.start{ 33 padding: 20px; 34} 35button{ 36 font-family: 'Work Sans', sans-serif; 37 font-size: 22px; 38 background-color: #279; 39 color: #fff; 40 border: 0px; 41 border-radius: 3px; 42 padding: 20px; 43 cursor: pointer; 44 margin-bottom: 20px; 45} 46button:hover{ 47 background-color: #38a; 48} 49.slide{ 50 position: absolute; 51 left: 0px; 52 top: 0px; 53 width: 100%; 54 z-index: 1; 55 opacity: 0; 56 transition: opacity 0.5s; 57} 58.active-slide{ 59 opacity: 1; 60 z-index: 2; 61} 62.quiz-container{ 63 position: relative; 64 height: 200px; 65 margin-top: 40px; 66} 67

試したこと

Chromeのデバッカーを用いて、ソースを追ってみました。
結果根本原因はmyQuestionsの中にデータがうまく入っておらず、
エラーが出ているということはわかりました。
JSコードのbuildQuiz()内でjsonLoader()は正常に呼び出されており、
jsonLoader()内で取得後、ループを回してpushし、
抜けた後のconsole.log(myQuestions);ではコンソール内に
(3) [{…}, {…}, {…}]0: {question: "Who is the strongest?", answers: {…}, correctAnswer: "c"}1: {question: "What is the best site ever created?", answers: {…}, correctAnswer: "c"}2: {question: "Where is Waldo really?", answers: {…}, correctAnswer: "d"}length: 3__proto__: Array(0)
というように値は入っているように思われますが、jsonLoader()実行後に
console.log(myQuestions);をすると以下のようになってしまいます。
[]
length: 0
proto: Array(0)

補足情報(FW/ツールのバージョンなど)

HTML5/jQuery3.3.1/Chrome 70.0.3538.77
Chromeは--allow-file-access-from-filesパラメータ付きで起動しています。

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

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

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

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

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

guest

回答3

0

ベストアンサー

JSON形式で別だしにしたい
url: 'ローカルにあるjsonファイルのフルパス'

単純に別ファイルのjsにしてロードするのではなく、
各クライアントPCのローカルに保存されているものを読み込むという認識であってますか?

下記のようにファイル選択ダイアログで選択させるのであればできました。
https://jsfiddle.net/8ruLeoxw/

投稿2018/11/02 10:51

runny_nose

総合スコア280

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

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

kisuke-09

2018/11/05 00:19 編集

ご回答ありがとうございます。 また、実際の例まで提示してくださったにもかかわらず、 こちらの言葉足らずで申し訳ありません。 ローカルにある問題のデータ(ファイルは1つのみ)を 読み込むというものです。 1つのみなので選択してロードではなく、jsコード上で指定したパスにあるファイルをロードという形にしたいと考えています。
runny_nose

2018/11/05 01:31 編集

普通、セキュリティ的にファイル選択ダイアログなどのユーザ操作を経由しないと、ローカルファイルにアクセスすることはできません。 (他にも例えばフルスクリーン操作などもユーザがボタンを押すなどしないと、ロード時に自動で行うのは無理) ただ、上の回答でありますが、chromeで`--allow-file-access-from-files`で起動すればajaxで出来るようですね。 それでいいのであれば、x_xさんがおっしゃられているとおり、スライドの作成処理をajaxの完了後に行うか、ajaxを非同期ではなく同期的に実行してください。 前者は具体的には以下のような感じですね。 https://jsfiddle.net/ypd6csqn/
kisuke-09

2018/11/05 02:01

追加のご回答と具体例の提示ありがとうございます。 ただ真似るだけではなく、こちらで動作とかを調べながら実装したところ 無事に動作いたしました! ご指導感謝いたします。
guest

0

Ajaxで非同期に取得してくるのであれば、buildQuiz()直後にはまだmyQuestionsができていません。
slidesもゼロのはずです。

投稿2018/11/02 08:54

x_x

総合スコア13749

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

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

kisuke-09

2018/11/02 09:29

x_x様 ご回答ありがとうございます。 $.ajax以外での取得となりますとgetJSONとかでしょうか? 一応先ほど試してみたところ結果変わらずのようです。。。 初心者故、誤っていた場合はご指摘いただければ幸いです。
x_x

2018/11/05 00:27

使わないようにするのではなく、取得後に処理するようにするのです。 取得後にdone()に渡した関数が実行されます。 https://api.jquery.com/jQuery.ajax/
kisuke-09

2018/11/05 02:03

追加のご回答と具体例の提示ありがとうございます。 ただ真似るだけではなく、こちらで動作とかを調べながら実装したところ 無事に動作いたしました! また、非同期ではなく、async:falseとして実装してもうまくいきました。 ご指導感謝いたします。
guest

0

Chromeでローカルファイルに対してAjaxを行うには、--allow-file-access-from-filesパラメーター付きでChromeを起動する事が必要となります(Qiita)。

投稿2018/11/02 08:18

maisumakun

総合スコア145183

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

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

kisuke-09

2018/11/02 08:28

maisumakun様 ご回答ありがとうございます。 --allow-file-access-from-filesパラメータ付きで起動に関しましては すでに実行しております。 こちら側で記載が漏れており、大変申し訳ございません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問