How to store JavaScript in a JavaScript array - javascript

I'm making a game in JavaScript. The basic idea is to have several buttons that use on.click to perform actions (Fight Monster, Dig for Treasure, etc).
One button loads the next adventure. I have an array containing all the adventures with the values "description" (d), "illustration" (i), and "buttons" (b). The description and illustration HTML show up just fine, but the javascript in the new "Get Flask" button does nothing. Escaping characters doesn't seem to help. Is there a better way to do this?
"Load next adventure" button code: (first couple of lines pick a number randomly up to 5, it has problems that I'll work on next)
<button type="button"
onclick="highLevel = y-1;
while (y >highLevel){ y = Math.round(Math.random() * 5)};
document.getElementById('description').innerHTML = adventure[y].d;
document.getElementById('illustration').innerHTML = adventure[y].i;
document.getElementById('buttons').innerHTML = adventure[y].b"
>Begin</button>
Array code:
adventure[y++]={
d:"Adventure 1",
i:"<img src='cave_entrance.jpg' alt='cave entrance' /><figcaption></figcaption>",
b:"<button type="button" onclick="window.alert('Ye cannot get flask')">Get Flask</button>"
}
For more details, see the code at: https://gist.github.com/janchor/5063f56da41d3e32c825ff154c6bd3be

I didn't change your code much, just fixed what you said :)
function beginClick() {
var highLevel = y - 1;
y = Math.floor(Math.random() * highLevel);
document.getElementById('description').innerHTML = adventure[y].d;
document.getElementById('illustration').innerHTML = adventure[y].i;
document.getElementById('buttons').innerHTML = adventure[y].b
}
var adventure = [];
var y = 0;
adventure[y++] = {
d: "Adventure 1",
i: "<img src='cave_entrance.jpg' alt='cave entrance' /><figcaption></figcaption>",
b: "<button type='button'; onclick='adventure[y].actionGetFlask()'>Get Flask</button>",
actionGetFlask: function() {
alert('Ye cannot get flask');
}
}
<button type="button" onclick="beginClick()">Begin</button>
<div id="description"></div>
<div id="illustration"></div>
<div id="buttons"></div>

Have onclick call a function and move your logic into that.
var adventure = {
d: "Adventure 1",
i: "<img src='cave_entrance.jpg' alt='cave entrance' /><figcaption></figcaption>",
b: "<button type="button" onclick="window.alert('Ye cannot get flask')">Get Flask</button>"
}
function loadHtml() {
document.getElementById('description').innerHTML = adventure.d;
document.getElementById('illustration').innerHTML = adventure.i;
document.getElementById('buttons').innerHTML = adventure.b
}
<button type="button" onclick="loadHtml()">Begin</button>
<div id="description"></div>
<div id="illustration"></div>
<div id="buttons"></div>

Related

How do I insert text into respective HTML buttons from the value of JavaScript object properties?

I am building a trivia app that loads random questions (from a series of objects I have stored in a Javascript file). Each question has four answers, 3 of them being wrong and 1 right. I am trying to get the possible answers for each question to load into the buttons. Right now all the buttons are loading the first item of the array for each question.
How is this done? I have experimented with forEach and a few other array methods, and I am thinking that the answers must be iterated over and then something with the indexes of each.
<div class="answers-container">
<button id="answers-btn-1" class="answers-btn"></button>
<button id="answers-btn-2" class="answers-btn"></button>
<button id="answers-btn-3" class="answers-btn"></button>
<button id="answers-btn-4" class="answers-btn"></button>
</div>
randomQuestion.answers.forEach(answer => {
answersButton1.innerHTML = answer.text;
answersButton2.innerHTML = answer.text;
answersButton3.innerHTML = answer.text;
answersButton4.innerHTML = answer.text;
});
Also, is there a way to consolidate the code with one answer-btn?
What I understand from your descriptions this could be a possible solution:
randomQuestions.answer.forEach((answer, index) => {
document.getElementById(`answers-btn-${index + 1}`).textContent = answer;
});
Example pure JS to control random answers list and use in buttons:
let answersUsed = [];
let answers = [
'All variables in JavaScript are object data types',
'Netscape is the software company that developed JavaScript',
'isNan function returns true if the argument is not a number',
'JavaScript is a client-side and server-side scripting language',
'Negative Infinitycan be derived by dividing negative number by zero'
];
function getRandomAnswer() {
let answerUsed = answers[Math.floor(Math.random() * answers.length)];
answersUsed.push(answerUsed);
const index = answers.indexOf(answerUsed);
if (index > -1) {
answers.splice(index, 1);
}
return answerUsed;
}
answers.forEach(answer => {
document.getElementById("answers-btn-1").innerHTML = getRandomAnswer();
document.getElementById("answers-btn-2").innerHTML = getRandomAnswer();
document.getElementById("answers-btn-3").innerHTML = getRandomAnswer();
document.getElementById("answers-btn-4").innerHTML = getRandomAnswer();
});
button {
margin: 8px;
display: block;
}
<div class="answers-container">
<button id="answers-btn-1" class="answers-btn"></button>
<button id="answers-btn-2" class="answers-btn"></button>
<button id="answers-btn-3" class="answers-btn"></button>
<button id="answers-btn-4" class="answers-btn"></button>
</div>
You can do this by building a list of options and setting the innerHTML of a select element or build an input[type="radio"] for each answer.
const randomQuestion = {answers: [{text: 'one'},{text: 'two'},{text: 'three'},{text: 'four'}]}
const opts = ['<option disabled>Choose one</option>']
randomQuestion.answers.forEach(answer => {
opts.push(`<option value="${answer.text}">${answer.text}</option>`)
});
const answerSelect = document.querySelector('#answer-select')
answerSelect.innerHTML = opts.join("\n")
answerSelect.size = opts.length // shows all options
answerSelect.value = ""
const radio_opts = []
randomQuestion.answers.forEach(answer => {
radio_opts.push(`<label><input type="radio" name="answerRadio" value="${answer.text}" />${answer.text}</label>`)
});
document.querySelector('#answers-container').innerHTML = radio_opts.join("\n")
<select class="answer-select" name="answer" id="answer-select">
<option>answer</option>
</select>
<div class="answers-container" id="answers-container">
<input type="radio" name="answerRadio">
</div>

Generate n words from a json server by user input using Javascript

I just started to practice Javascript and I have a json file with a bunch of words. I want to display as many words as the given user input. If user input is 4 then 4 words will be displayed randomly from the server. I can successfully get the data from te server and display all of them in a table but the logic of displaying random words from the server is a little difficult for the firs try and I would like to get a better understanding how to approach it in my case. The getRandomWords() function is where I was trying to approach something.
words.json
{
"words":
[
"a",
"abandon",
"ability",
"able",
"abortion",
"about",
"above",
"abroad",
"absence",
"absolute",
"absolutely",
"absorb",
"abuse",
"academic"
]
}
snippet from project.js
function getServerData(url) {
let fetchOptions = {
method: "GET",
mode: "cors",
cache: "no-cache"
};
return fetch(url, fetchOptions).then(
response => response.json(),
err => console.error(err)
);
}
document.querySelector("#server-button").addEventListener("click", function() {
getServerData("http://localhost:3000/words").then(
data => fillDataTable(data, "wordTable")
);
});
function getRandomWords() {
let words = getServerData("http://localhost:3000/words").then(
data => randomWordExample(data)
);
var howManyWords = document.querySelector("#words-to-memorize");
const randomElement = words[Math.floor(Math.random() * words.length)];
console.log("random words: ", randomElement);
}
index.html
<div class="row">
<div class="col-2"></div>
<div class="col-8">
<div class="form-group">
<label for="words-to-memorize">How many words you want to see?</label>
<input type="text" class="form-control" id="words-to-memorize">
</div>
<button id="get-words-button" class="button btn btn-block btn-primary">
Get the words
</button>
</div>
<div class="col-2"></div>
</div>
function getRandomWords () {
let words = getServerData("http://localhost:3000/words").then(
data => randomWorldExample(data)
);
let howManyWords = document.querySelector("#words-to-memorize");
let randomElement = words[0].words.sort(() => 0.5 - Math.random())
console.log("random words: ", randomElement.slice(0, howManyWords));
}
This should get ya there. What we are doing is randomly sorting the array then we are slicing the array to the n value.
My working solution finally was the following:
function getRandomWords() {
let words = getServerData('http://localhost:3000/words').then(data => {
const wordsToMemorize = document.querySelector('#words-to-memorize');
document.querySelector("#wordsInput").addEventListener("click", function() {
let temp = wordsToMemorize.value;
selectedtombelemek.innerHTML = "";
for(let i = 0; i < temp; i++) {
let rander = Math.floor(Math.random() * 3000);
selectedtombelemek.innerHTML += data[rander] + "</br>";
}})
});
}

Set variable to $scope value

EDIT: Following previous answers the JS has been amended to run all the code within the http.get. I have also added the HTML.
The current page can be viewed at: http://www.kamac.co.uk/wordplay3/#/gamecontrol
I have an AngularJS app with the following code in the controller:
var vm = this;
$http.get('data/data.json').success(function(data) {
$scope.entries = data;
var rand = Math.floor(Math.random()*$scope.entries.length);
$scope.selectedWord = $scope.entries[rand].word;
$scope.selectedDefinition = $scope.entries[rand].definition;
vm.topsecret = "TopSecret";
vm.letter = [];
vm.checkLetter = function(index){
if(vm.topsecret[index] === vm.letter[index]){
vm.result = "letter was correct"
} else {
vm.letter[index] = "";
vm.result = "nope";
}
}
Both parts of the code do as expected. The $http.get function reads a JSON file and sets $scope.selectedWord to a randomly chosen word.
The second part creates a number of input boxes for each letter in the word saved in vm.topsecret.
My problem is this only works if vm.topsecret is hard coded. How can I get vm.letter to equal $scope.selectedWord ?
I have tried the obvious: vm.topsecret = $scope.selectedWord but this results in an empty value.
HTML
<section class="spellbound container-fluid">
<div class="jumbotron">
<h1>SpellBound</h2>
<p>Below you will see a definition of one of the words in the dictionary. Enter a correct letter and the square turns green - enter a wrong letter and it turns red.</p>
</div>
<div class="panel panel-info">
<div class="panel-heading">How do you spell the word that means</div>
<div class="panel-body">{{selectedDefinition}}</div>
</div>
<p>Answer: {{selectedWord}}</p>
<p>VM: <span>{{vm.topsecret}}</span>
<div ng-controller="GamecontrolController as vm">
<input type="text" ng-model="vm.letter[$index]" ng-repeat="letter in vm.topsecret track by $index" ng-change="vm.checkLetter($index)"/>
<p><span>{{vm.result}}</span></p>
</div>
<div>
<a ng-click="reloadPage()" class="btn btn-info btn-lg" role="button">Play Again</a>
Back To Menu
</div>
Try moving vm.topsecret like below:
var vm = this;
$http.get('data/data.json').success(function(data) {
$scope.entries = data;
var rand = Math.floor(Math.random()*$scope.entries.length);
$scope.selectedWord = $scope.entries[rand].word;
$scope.selectedDefinition = $scope.entries[rand].definition;
vm.topsecret = $scope.selectedWord;
});
vm.letter = [];
vm.checkLetter = function(index){
if(vm.topsecret[index] === vm.letter[index]){
vm.result = "letter was correct"
} else {
vm.letter[index] = "";
vm.result = "nope";
}
}
This is just a guess since I cannot see your HTML and how you are using vm.topsecret.

Making a quiz with Javascript. Getting array values from and object.

Im trying to create a simple quiz with Javascript. I am struggling to grasp the concept of how to iterate over the values of an array from an object. I eventually want to display a radio button with its value as the choice of answers. If someone could point me in the right direction i would really appreciate it.
Fiddle: http://jsfiddle.net/Renay/eprxgxhu/
Here is my code:
HTML
<h1> General Knowledge Quiz </h1>
<h2 id='questionTitle'> </h2>
<ul id ='selectionList'> </ul>
<p> Click the next button to go to the next question! </p>
<button type="button" id = nextButton> Next </button>
</div>
Javascript
var allQuestions = [{
question: 'What is the capital city of Australia?',
choices: ['Sydney', 'Melbourne', 'Canberra', 'London'],
correctAnswer: 2
},
{
question: 'Who won the 2014 FIFA World Cup?',
choices: ['Brazil', 'England', 'Germany', 'Spain'],
correctAnswer: 2
},
{
question: 'What book series is authored by J.K Rowling?',
choices: ['Game of Thrones', 'Hunger Games', 'Twilight', 'Harry Potter'],
correctAnswer: 3
},
{
question: 'The Eiffel Tower is located in which following country?',
choices: ['Italy', 'France', 'Iceland', 'Mexico'],
correctAnswer: 1
}];
//Reference to tags
var questionTitle = document.getElementById('questionTitle');
var selectionList = document.getElementById('selectionList');
var nextButton = document.getElementById('nextButton');
//Initiating some variables
var i = 0;
var length1 = allQuestions.length;
var correctAnswer = 0;
function populateQuestion() {}
Firstly attach click event to next button and give call to populateQuestion() using counter to iterate through allQuestions array and use i as counter variable.
nextButton.onclick = function() {
/*itterate through questions*/
if(i>allQuestions.length -1){/*go to first when reached last*/
i=0;
}
populateQuestion(i);
i++;
};
Iterate through allQuestions array for question title and choices as:
function populateQuestion(qNum) {
var individualQuestion = allQuestions[i];
questionTitle.innerText = individualQuestion.question;
selectionList.innerHTML = ""; //reset choices list
for(key in individualQuestion.choices){
var radioBtnName = "question"+i+"_choice";
var choiceText = individualQuestion.choices[key];
selectionList.appendChild(createLi(radioBtnName,choiceText));
}
}
Write dynamic li and radio button creation function as:
function createLi(name, choiceText) {
var e = document.createElement('li');
var radioHtml = '<input type="radio" name="' + name + '"';
radioHtml += '/>';
radioHtml += choiceText;
e.innerHTML = radioHtml;
return e;
}
Please refer to this fiddle for same.
You need to associate an onClick event with your button to call the relevant part of the JavaScript. Go through the example here
On another note, using JavaScript for a quiz might not be a good idea as one can see the answers using view-source. I would suggest using PHP to fetch results from a database.

Is javascript namespace polluted?

I do not have a good grasp of the js namespace and am WAGing* re the title, but that's one of my guesses about what's happening.
WAG = Wild Guess
My app is crashing (dramatically); trying to figure out why. In fact, after 3 Q/A pairs, it blows up the entire Chrome tab..! I'm beginning to suspect I've done something wrong in my code...
Warning: Save your browsing session before running these jsFiddles. (In Chrome, the jsFiddle only blows up its own tab but I can't comment on other browsers)
jsFiddle One
jsFiddle Two - dupe in case jsFiddle One blown away
Please help me to understand exactly which spectacular moronism I've committed today.
HTML:
<div id="result">
<div class="truth tr0"><h2>---</h2></div>
<div class="truth tr1"><h2>answer to one</h2></div>
<div class="truth tr2"><h2>answer to two</h2></div>
<div class="truth tr3"><h2>answer to three</h2></div>
<div class="truth tr4"><h2>answer to four</h2></div>
</div>
<div id="replaceLink">
<div class="youcould yc1">
<h2>QUESTION ONE</h2>
</div>
<div class="youcould yc2">
<h2>QUESTION TWO</h2>
</div>
<div class="youcould yc3">
<h2>QUESTION THREE</h2>
</div>
<div class="youcould yc4">
<h2>QUESTION FOUR</h2>
</div>
<div class="youcould yc5">
<h2>THANK YOU</h2>
</div>
</div>
<div id="response"></div>
<input type="button" id="mybutt" value="Start Test" />
Javascript/jQuery:
var cnt = 0;
var window = {};
window.arrDone = [];
function nextQues() {
if (window.arrDone.length == 4) return 5;
success = 0;
while (success == 0) {
nn = Math.floor(Math.random() * 3) + 1;
if (window.arrDone.indexOf(nn) == -1 && nn != 5) {
success++;
window.arrDone.push(nn);
}
}
return nn;
}
$('.youcould, .truth').hide();
$('.tr0').show();
$('.youcould').click(function() {
$(this).hide();
thisA = window.arrDone[window.arrDone.length -1];
$('.tr'+thisA).show();
});
$('.truth').click(function() {
$(this).hide();
nextQ = nextQues();
$('.yc'+nextQ).show();
});
$('#mybutt').click(function () {
$(this).hide();
$('.tr0').hide();
nextQ = nextQues();
$('.yc'+nextQ).show();
});
My guess would be
var window = {};
window is special, so creating a global variable named window is begging for trouble.
Your while loop runs infinitely on the third pass because it doesn't meet the condition.
At some point, arrDone will contain the numbers 1, 2, and 3, as produced by your random generator (which will never produce 5, btw). In that case, nextQues() does not abort and return five (as arrDone.lenght == 3), and will enter the loop. Your random generator produces nothing but the numbers 1, 2, and 3, which always are already in the array, so the if-condition (that would end the loop) is never fulfilled. You have an infinite loop generating random numbers.
I guess you want
function nextQues() {
var l = 4;
if (window.arrDone.length >= l)
return l+1;
while (true) {
var nn = Math.floor(Math.random() * l) + 1; // generate 1, 2, 3 or 4
if (window.arrDone.indexOf(nn) == -1) {
window.arrDone.push(nn);
return nn;
}
}
}

Categories