I am building a simple javascript picture quiz for a project. I have only written the function for show question and possible answers but for some reason when i call the quiz the images aren't loading and i am getting an error re failing to load the resource. The img files work perfectly fine otherwise and i have tried both .png & .jpg and both display the same error.
I have a few elements to add in to the JS like checkAnswer and Display score but i need the images to work as they are the answer buttons.
Corresponding HTML
<section id="quiz">
<div id="quiz-question-card" class="container welcome-card shadow-lg text-dark mb-3 d-flex justify-content-center">
<div class="card-body">
<h3 class="question-title">Question</h3>
<p id="question-text"></p>
</div>
</div>
<div class="container d-flex justify-content-center">
<div id="answer-btns" class="row row-cols-1 row-cols-sm-2 row-cols-md-4">
</div>
</div>
Javascript two sample questions and answers & function;
let spQuiz = [
{
question: "What planet is closest to the Sun?",
answers: [
"../img/venus.png",
"../img/mercury.png",
"../img/mars.png",
"../img/earth.png"
],
correctAnswer: '1'
},
{
question: "Which planet has the highest mountain in our solar system, a volcano named Olympus Mons?",
answers: [
"../img/mars.png",
"../img/jupiter.png",
"../img/neptune.png",
"../img/earth.png"
],
correctAnswer: '0'
},
];
let newQuestion = 0;
function displayQuestion () {
let question = spQuiz[newQuestion];
document.getElementById("question-text").innerHTML = question.question;
let answers = question.answers;
for (let i = 0; i < answers.length; i++) {
let answer = answers[i];
let img = document.createElement("img");
img.src = answers;
img.onclick = function() {
checkAnswer(i);
};
document.getElementById("answer-btns").appendChild(img);
}
}
displayQuestion();
Related
I'm trying to make a some dynamically generated bootstrap cards with a button clearing the page and showing the info (which I have stored on a Firebase project). I managed to make the cards show properly but I'm blocked and can't find a way to make each button show a different information.
So basically I have this:
Cards
Content showing
It has to be something close to the eventListener or another way to write the code... I think the way I did it is why its showing all the information on the same card, but how can I write the code right? I'm trying for 2 days and can't work around it.
OBS: I know my code can be a little messy or could be best ways to do some stuff but I'm still learning.
import { getWikiTI } from './prevenirWiki.js'
const dataCard = document.getElementById('data');
async function loadData() {
let i = 0;
const data = await getWikiTI()
dataCard.innerHTML = data.map(d => `
<div class="card border-primary mb-3 fb-item" style="max-width: 20rem;">
<div class="card-header">${d.setor}</div>
<div class="card-body">
<h4 class="card-title">${d.descricao}</h4>
<button type="button" class="btn btn-lg btn-primary fb-item" id="carregar-card">Carregar</button>
</div>
</div>
`,
console.log(data),
console.log(i)
).join('')
const btnCarregar = document.getElementById('carregar-card')
btnCarregar.addEventListener('click', () => {
dataCard.innerHTML = data.map(function (d) {
return `${d.conteudo}`;
})
document.body.appendChild(dataCard)
})
}
document.onload = loadData();
EDIT: Alright ! I managed to get it working... not the best code in the world but it's something :) If anyone has any opinions or ideias on how to improve it, im all ears.
import { getWikiTI } from './prevenirWiki.js'
const dataCard = document.getElementById('data');
async function loadData() {
let i = 0;
const data = await getWikiTI()
dataCard.innerHTML = data.map(d => `
<div class="card border-primary mb-3 fb-item" style="max-width: 20rem;">
<div class="card-header">${d.setor}</div>
<div class="card-body">
<h4 class="card-title">${d.descricao}</h4>
<button type="button" class="btn btn-lg btn-primary fb-item" id="carregar-card${i++}">Carregar</button>
<p hidden class="card-text">${d.conteudo}</p>
</div>
</div>
`,
).join('')
for (let i = 0; i <= data.length; i++) {
let btnCarregar = document.getElementById(`carregar-card${i}`)
btnCarregar.addEventListener('click', () => {
dataCard.innerHTML = data[i].conteudo;
document.body.appendChild(dataCard)
})
}
}
document.onload = loadData();
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I have a currency converter for a gaming marketplace that I'm working on, I want the user to be able to generate the image in javascript. I'm not sure if this makes sense or not, but I have the majority of it done, I just need the images to show rather than broken image boxes
I've tried changing the path that the image is meant to be drawn from but I don't really know javascript too well
const data = [
{
currency: 'btc',
we_buy: 0.58,
we_sell: 0.77,
img_path: 'null',
icon: 'fab fa-btc'
},
{
currency: 'usd',
we_buy: 0.67,
we_sell: 0.82,
img_path: './united-states.svg',
icon: 'fas fa-dollar-sign'
},
{
currency: 'gbp',
we_buy: 0.50,
we_sell: 0.68,
img_path: './united_kingdom.svg',
icon: 'fas fa-pound-sign'
},
{
currency: 'eur',
we_buy: 0.59,
we_sell: 0.76,
img_path: './european-union.svg',
icon: 'fas fa-euro-sign'
}
];
const imagesContainer = document.getElementById("currencies");
let selectedCurrency = null;
var selectCurrency = function (index) {
const element = data[index];
selectedCurrency = data[index];
document.getElementById("currency-selected").innerHTML = `Currency selected: ${element.currency}`;
document.getElementById("data_icon").className = element.icon;
};
(() => {
for (let i = 0; i < data.length; i++) {
imagesContainer.innerHTML += `<div class="currency" onclick=selectCurrency(${i})><img id=${i} src=${data[i].img_path}></div>`;
}
selectCurrency(0);
const amount = document.getElementById("amount");
amount.onkeyup = () => {
const output_we_buy = document.getElementById("output_we_buy");
const output_we_sell = document.getElementById("output_we_sell");
if (amount.value === '') {
output_we_buy.innerHTML = 0;
output_we_sell.innerHTML = 0;
return;
}
if (!isNaN(amount.value)) {
output_we_buy.innerHTML = `${(+amount.value * selectedCurrency.we_buy).toFixed(2)}`;
output_we_sell.innerHTML = `${(+amount.value * selectedCurrency.we_sell).toFixed(2)}`;
}
}
})();
<div class="container-fluid">
<div class="currencies-container">
<div class="currencies" id="currencies">
</div>
<div class="currency-selected" id="currency-selected">
No currency selected.
</div>
<div class="output">
<div class="row">
<div class="col-6 input-group">
<input type="number" class="form-control" aria-label="Amount of GP in Millions" placeholder="Amount of GP (in millions)"
id="amount">
<div class="input-group-append">
<span class="input-group-text"><i id="data_icon"></i></span>
<span class="input-group-text" id="output_we_buy">.00</span>
<span class="input-group-text" id="output_we_sell">.00</span>
</div>
</div>
</div>
</div>
</div>
</div>
I expect images stored in my directory to be shown for the currency selection
I didn't specify the folder - rookie mistake
I would like to use javascript.
Before the br I have text too, which changes. It can be 4/20, or 10/20 etc.
var questionString = document.getElementsByClassName("question")[0].innerText;
console.log(questionString)
<DIV class="question">1/20
<BR>THIS IS A QUESTION?</DIV>
Here is your question.
var questionString = document.getElementsByClassName("question")[0].innerHTML.split('<br>')[1];
console.log(questionString)
<DIV class="question">1/20<BR>THIS IS A QUESTION?</DIV>
If you want the questions after the BR, try this:
let qs = [];
document.querySelectorAll(".question").forEach((d) =>
qs.push(d.innerText.replace(/\d{1,}\/\d{1,}\s+/, ""))
)
console.log(qs)
<DIV class="question">1/20
<BR>THIS IS QUESTION 1 of 20</DIV>
<DIV class="question">2/20
<BR>THIS IS QUESTION 2 of 20</DIV>
By 4/20 you mean the current question is the 4th question among a total of 20 questions, right?
I believe that your requirement is when the user click next button, you want the text "4/20" to change into "5/20".
// have a reference to the question text's DOM
var question_no_dom = document.getElementById("question_no");
var question_dom = document.getElementById("question");
// list of questions
var questions = ["1. How tall is mount everest?",
"2. What is the capital city of Russia?",
"3. How far way is the sun from the earth?"];
// start with the first question
var current_quest_no = 0;
var total_no_quest = 3
question_no_dom.innerText = (current_quest_no+1)+'/'+total_no_quest;
question_dom.innerText = questions[current_quest_no];
function onNext() {
if(current_quest_no < total_no_quest-1) {
current_quest_no++;
question_no_dom.innerText = (current_quest_no+1)+'/'+total_no_quest;
question_dom.innerText = questions[current_quest_no];
}
}
<div id="question_no"></div><br>
<div id="question"></div><br>
<button onclick="onNext()">Next ></button>
Grab the first child node of the div (which given your html will always be your desired text node) then trim it to remove the extra spacing and newline.
var questionString = document.getElementsByClassName("question")[0].childNodes[0].textContent.trim()
console.log(questionString)
<DIV class="question">1/20
<BR>THIS IS A QUESTION?</DIV>
Hi guys I am quite new in javascript,
I am using a chart.js chart that update itself based on a dropdown button.
I would like to update as well another div called explanation that give comment on the chart.
gogo is a an object that list explantation id. log.console(gogo) may output [15, 16] or [15, 16, 17, 18].
I would need for each explanation id create a new div within the explanation div
I tried :
$(".pick-chart").change(function(e) {
e.preventDefault();
var val = $(this).val();
if (val != 0) {
info_process.data.datasets[1].data = info_array[val];
info_process.update();
stringval = JSON.stringify(val)
gogo = opposed_model[val]
for(var x = 0; x < gogo.length; x++){
$("#explanation").append("<b>gogo[x]</b>");
}
document.getElementById('explanation').innerHTML = gogo;
} else {
info_process.data.datasets[1].data = [];
document.getElementById('explanation').innerHTML = "";
}
info_process.update();
});
HTML:
<div class="col">
<div class="card box-shad">
<h5 class="card-header text-center bg-dark text-white">Action</h5>
<div class="card-body">
Text - Test
<div id="explanation">
</div>
</div>
</div>
</div>
I do not manage to make it work, any idea ?
Couple of issues you have:
Instead of $("#explanation").append("<b>gogo[x]</b>"); do $("#explanation").append("<b>"+gogo[x]+"</b>");. Note the way string concatenation is happening.
Remove document.getElementById('explanation').innerHTML = gogo; this will overwrite the html of #explanation.
I am working on a browser game. I have lots of upgrades, crafting, planets, etc that I generate with jS (1 box (or square?) PER EACH item). Here is a mini snippet from my game, displaying my current method of generating HTML
JSFiddle example
I do a simple loop and insert as many boxes as there are upgrades
for(i = 0; i < 9; i ++)
Then, I put a gigantic HTML code block in a function, and use arrays to identify upgrades ID, name, info...
Is this a good practice to generate loads of HTML content? If not, what can I do to improve it?
Also, I started "coding" a game with one main goal to learn JS. If you have better solutions, but they include a lib (jQuery, etc) then you can post it, but I'm going pure jS here. Thanks!
-- Update --
I've been learning lots of JS in the past year. #DoXicK provided a great example a while ago but I didn't understand it then. This is the final rendering method I come up with, thanks to his examples, and I guess I'll stick with it:
JS:
const game = {};
// make our life easier
const $ = key => document.getElementById(key);
const render = (key, str) => $(key).insertAdjacentHTML("beforeend", str);
// a function that returns upgrades html content
const html = self => `
<div class="some-class" id="${self.id}">
<h2>${self.name}</h2>
<p>${self.damage}</p>
</div>
`;
// object containing each upgrades template
const template = {
laserGun: {
id: "laserGun",
name: "Laser Gun",
damage: 10
},
plasmaGun: {
id: "plasmaGun",
name: "Plasma Gun",
damage: 30
}
};
// Upgrade class
class Upgrade {
constructor(upg) {
this._id = upg.id;
this._name = upg.name;
this._damage = upg.damage;
}
get id() {return this._id;}
get name() {return this._name;}
get damage() {return this._damage;}
generate() {
// find div with upgrade id, and inject it's html content inside
render("upgrade", html(this));
}
static make(key) {
game.upgrade[key] = new Upgrade(template[key]);
game.upgrade[key].generate();
}
}
let laserGun = Upgrade.make("laserGun");
HTML:
<div class="upgrade-container" id="upgrade">
I hope you find it helpful!
As i already explained in comments, your code will become quite unmaintainable if you keep it as spaghetti code like that.
I've made an updated example which does the exact same thing as you did, just with a bit of updated javascript and by making a javascript-component out of your "template".
https://jsfiddle.net/7L8e5kmg/3/
class UpgradeBlock {
constructor(props) {
this.props = props;
}
render() {
let { Id, Name, Info, Res } = this.props;
// basically:
// let Id = this.props.Id;
// let Name = this.props.Name;
// etc
return (`
<div class="hud-item" id="${Id}">
<img src="client/img/${Id}.png" id="${Id}Img" />
<div class="hud-tooltip f16 fwhite">
<div class="hud-tt-header-container">
<div class="hud-tt-info-container">
<div class="col-full">${Name}</div>
<div class="col-half">
<img style="vertical-align: text-bottom;" src="img/${Res}16.png" />
<span id="${Id}Cost"></span>
</div>
<div class="col-half">
+<span id="${Id}dmgPerLv"></span>
<img style="vertical-align: text-bottom;" src="client/img/character/dps16.png" />
</div>
</div>
<div class="hud-tt-lv-container">
<canvas id="${Id}Bar" width="64px" height="64px"></canvas>
</div>
</div>
<hr/>
<div class="hud-tt-info-container">
<div class="col-half fwhite f16">
<img style="vertical-align: text-bottom" src="client/img/character/dps16.png" />
<span id="${Id}Dmg"></span>
</div>
<div class="col-half fgrey f10"><span class="fwhite f16" id="${Id}ofTotal"></span> of total</div>
<div class="col-full fgrey f10">${Info}</div>
<div class="col-full f10" id="${Id}click"></div>
</div>
</div>
</div>
`)
}
}
You use it by doing:
let upgrade = {
Id: 'id',
Name: 'name',
Info: 'info',
Res: 'res'
};
let html = new UpgradeBlock(upgrade).Render()
For people that do react: yes, it is intended to steer that way.