In Blogger, Hide/Show Quiz Answers based on button click with javascript - javascript

I have a quiz blog/website on blogger. To show the answers of questions I have following html code:
<button class="acc">Show Answer</button>
<div class="pnl">
<p>Correct Answer</p>
</div>
<button class="acc">Show Answer</button>
<div class="pnl">
<p>Correct Answer</p>
</div>
<button class="acc">Show Answer</button>
<div class="pnl">
<p>Correct Answer</p>
</div>
And JavaScript like this:
<script type='text/javascript'>
//<![CDATA[
var acc = document.getElementsByClassName("acc");
var i;
for (i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
this.classList.toggle("active");
var pnl = this.nextElementSibling;
if (pnl.style.display === "block") {
pnl.style.display = "none";
} else {
pnl.style.display = "block";
}
});
}
//]]>
</script>
And CSS like this:
.acc {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
.active, .acc:hover {
background-color: #ccc;
}
.pnl {
padding: 0 18px;
display: none;
background-color: white;
overflow: hidden;
}
If some one clicks on all of the buttons, the buttons are acting as toggles rather than, showing one answer, then when the next button is clicked, hiding the previous answer and showing the new one in its place. What needs to be changed to enable this?
Thanks

Remove the buttons.
Add the following over each .pnl
<!-- #ids must be unique so btn* = btn1, btn2, etc -->
<!-- [for] of label must match #id of input -->
<input id='btn*' class="acc" name='acc' type='radio' hidden>
<label for='btn*'>Show Answer</label>
Explination: A label and a form control (ex. <input>, <select>, etc) can be associated with each other if the form control has an #id and the label has a [for] that match. If one gets clicked, checked, etc then the other one does as well.
Add the following CSS:
.acc:checked+label+.pnl {
display: block
}
Explination: If an input is checked then the .pnl that is front of the label that is in front of the input. Note, when a group of radio buttons share a [name] only one may be checked at a time. Also, the radio buttons are hidden so it looks as if the label is the only tag interacting with the user.
.acc {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
.active,
.acc:hover {
background-color: #ccc;
}
.pnl {
padding: 0 18px;
display: none;
background-color: white;
overflow: hidden;
}
.acc:checked+label+.pnl {
display: block
}
label {
display: block
}
<input id='btn1' class="acc" name='acc' type='radio' hidden>
<label for='btn1'>Show Answer</label>
<div class="pnl">
<p>Correct Answer</p>
</div>
<input id='btn2' class="acc" name='acc' type='radio' hidden>
<label for='btn2'>Show Answer</label>
<div class="pnl">
<p>Correct Answer</p>
</div>
<input id='btn3' class="acc" name='acc' type='radio' hidden>
<label for='btn3'>Show Answer</label>
<div class="pnl">
<p>Correct Answer</p>
</div>

Try this one by using a forEach.
var acc = document.getElementsByClassName("acc");
let pn1 = document.getElementsByClassName("pnl");
for (let i = 0; i < acc.length; i++) {
acc[i].addEventListener("click", function() {
this.classList.toggle("active");
[...acc].forEach((item,index) =>{
if(item == acc[i]){
pn1[index].style.display = "block";
}else{
pn1[index].style.display = "none";
}
})
})
}
.acc {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
.active, .acc:hover {
background-color: #ccc;
}
.pnl {
padding: 0 18px;
display: none;
background-color: white;
overflow: hidden;
}
<button class="acc">Show Answer</button>
<div class="pnl">
<p>Correct Answer</p>
</div>
<button class="acc">Show Answer</button>
<div class="pnl">
<p>Correct Answer</p>
</div>
<button class="acc">Show Answer</button>
<div class="pnl">
<p>Correct Answer</p>
</div>

Related

How can I make a "board of tiles" for this game?

I want to make a board consisting of tiles but I do not know how to fill up the entire board area. I have only gotten up to 1 column of the board, as shown in the image. How can I fill this board so that each tile can be changed if clicked on or such?
body {
font-family: Arial, Helvetica, sans-serif;
text-align: center;
}
hr {
width: 500px;
}
#board {
width: 1000px;
height: 1000px;
float: center;
display: grid;
background-color: rgb(126, 124, 122);
border: 6px solid rgb(0, 0, 0);
}
.tile {
width: 200px;
height: 200px;
border: 5px solid bisque;
border-radius: 10%;
font-size: 40px;
font-weight: bold;
display: flex;
justify-content: center;
align-items: center;
}
.picker {
width: 100px;
height: 100px;
border: 5px solid bisque;
margin: 0 auto;
border-radius: 10%;
align-content: left;
align-self: left;
}
.tile {
background-color: rgb(255, 255, 255);
color: black;
}
.float-child {
width: 10%;
padding: 10px;
border: 2px solid rgb(0, 0, 0);
vertical-align: left;
}
<body>
<h1>Play-Color</h1>
<hr>
<div class="game">
<div class="float-child">
<button class="picker" style="background-color: red"></button>
<h4>count = 0</h4>
<br>
<button class="picker" style="background-color: blue"></button>
<h4>count = 0</h4>
<br>
<button class="picker" style="background-color: green"></button>
<h4>count = 0</h4>
<br>
<button class="picker" style="background-color: yellow"></button>
<h4>count = 0</h4>
<br>
<button class="picker" style="background-color: grey"></button>
<h4>count = 0</h4>
<br>
<button class="picker"></button>
<br>
</div>
<div id="board" class="float-child" style="position:relative; left:900px; top:-1000px" >
<button class="tile"></button>
<button class="tile"></button>
<button class="tile"></button>
<button class="tile"></button>
<button class="tile"></button>
</div>
</div>
</div>
</body>
[2]UpdatedImage
........................................................................................................................................................................................
There are many steps to achieve the wanted result. Normally I wouldn't code this on SO. I just did it because I had fun it it. For the feature dont expect others to code a whole game for you for free!
See the comments within HTML, CSS and JS for furtehr info.
You have to create your color to pick from. The smartest solution IMHO is the use of radio-buttons. The Radio button will even without a script only allow the selection of one choice:
<input type="radio" name="color" value="color-name" id="color-name">
To not break the game you should always have one color selected. To ensure that on start one color is already selected you add the checked-attribtue to one color such as:
<input type="radio" ... checked>
Next you have to hide the checkboxes to be invisible and not cunsumign any space which you do through CSS:
input { display: none; }
Then you have to add the color as visual box by adding a <label>. That has the advantage that you can click on the label and it will select the correct radio button:
<label for="color-name">
After that you color the label with the color you want. While you do that, you can also set a CSS-Class to the same color in the same instance to allow the painting with that color:
label[for=color-name],
.color-name {
background-color: color-name;
}
Finally you have to create a grid. You can do that easily through JS or hardcode it to HTML. Sicne I dont want to explain you on how to do it correctly through JS (which would cost me another 30 minutes of my lifetime) I will hardcode it through HTML. In my case I used a grid-container: <div class="game-board">. Then I added 25x child elements: <div class="card"></div>. To make the grid 5x5 dimensions I used CSS on the Grid-Container to create 5 columns:
.game-board {
display: grid;
grid-template-columns: repeat(5, 1fr);
}
As said already in the comments, you don't need buttons to be clickable for JS. The label of the radio buttons are clickable already (as they are labels). You can run a script even when not being clickable by simply usign the EventListener to check for a click-event by using JS:
element.addEventListener('click', e => {
// statements
});
To only select the grid-cards and not the container itself or possibel other content you can check if the element that was clicked on contains a specific class:
if (e.target.classList.contains('card')) {
// statements
}
In case that grid-card already has a color as CSS-Class applied to, we have to remove all potencial classes that would prevent the CSS to work correctly (it would only show the color of the class that is listed last in CSS):
e.target.className = ''
Unfortunatly the last step also removed the card class and as such we have to re-add this class:
e.target.classList.add('card');
Once we did that, we use a switch-case-statement which is cleaner then writing tons of if/else-statements. You can google guides and tutorials on your own. That switch-statement now checks what radio-button is checked and applies a class to the element you clicked on that adds the background-color:
e.target.classList.add('color-name');
EDIT
To include a counter you can use the JS lenght-statement:
document.querySelectorAll('.game-board .color-name').length. this statement will count the number of elements that contain a specific class.
Then simply use innerHTML-statement to display the count:
element.innerHTML = document.querySelectorAll('.game-board .color-name').length
var board = document.querySelector('.game-board')
// eventListener to listen to click events on the game board
board.addEventListener('click', e => {
console.clear();
// checks if a card and not the agme baord itself was clicked on
if (e.target.classList.contains('card')) {
const card = e.target.classList;
// checks which color has been selected
var color = document.querySelector('.color-picker input:checked').value;
// removes all classes from the clicked on element to allow re-painting
e.target.className = '';
// re-adds the "card" class to the clicked element
card.add('card');
// switch statement to add the class with the selected color to paint the grid-card
switch (color) {
case "red":
card.add('red');
break;
case "blue":
card.add('blue');
break;
case "green":
card.add('green');
break;
case "yellow":
card.add('yellow');
break;
case "gray":
card.add('gray');
break;
}
// color-counter
var countRed = document.querySelectorAll('.game-board .red').length,
countBlue = document.querySelectorAll('.game-board .blue').length,
countGreen = document.querySelectorAll('.game-board .green').length,
countYellow = document.querySelectorAll('.game-board .yellow').length,
countGray = document.querySelectorAll('.game-board .gray').length;
// displaying the counter
var labelRed = document.querySelector('#count-red span'),
labelBlue = document.querySelector('#count-blue span'),
labelGreen = document.querySelector('#count-green span'),
labelYellow = document.querySelector('#count-yellow span'),
labelGray = document.querySelector('#count-gray span');
labelRed.innerHTML = countRed;
labelBlue.innerHTML = countBlue;
labelGreen.innerHTML = countGreen;
labelYellow.innerHTML = countYellow;
labelGray.innerHTML = countGray;
}
});
/* aligning the color picker and game board next to each other */
body {
margin: 0;
padding: 10px;
box-sizing: border-box;
display: flex;
gap: 10px;
min-height: 100vh;
}
/* box for the color */
.color-picker {
border: 1px solid black;
display: flex;
flex-direction: column;
padding: 5px 30px;
gap: 10px;
}
/* hides the radio button */
.color-picker > input {
display: none;
}
/* creatign a visual border to see what color has been selected */
input:checked + label {
border: 3px solid black;
}
/* setting a "color-box" to the radio-button */
.color-picker > label {
display: block;
box-sizing: border-box;
aspect-ratio: 1 / 1;
min-width: 50px;
}
/* settign the color of the color picker and classes for painting */
label[for=red],
.red {
background-color: red;
}
label[for=blue],
.blue {
background-color: blue;
}
label[for=green],
.green {
background-color: green;
}
label[for=yellow],
.yellow {
background-color: yellow;
}
label[for=gray],
.gray {
background-color: gray;
}
/* game board that creates a board of 5x5 with equal dimensions */
.game-board {
flex-grow: 1;
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-gap: 5px;
}
/* Setting the grid-cards to be squares */
.game-board > .card {
aspect-ratio: 1 / 1;
border: 1px solid red;
border-radius: 5px;
display: flex;
justify-content: center;
align-items: center;
}
/* To make the grid-cards and label appear like buttons on hover */
.color-picker > label:hover,
.card:hover {
cursor: pointer;
}
<!-- Letting you select the color -->
<div class="color-picker">
<input type="radio" name="color" value="red" id="red" checked>
<label for="red"></label>
<div id="count-red">Count: <span>0</span></div>
<input type="radio" name="color" value="blue" id="blue">
<label for="blue"></label>
<div id="count-blue">Count: <span>0</span></div>
<input type="radio" name="color" value="green" id="green">
<label for="green"></label>
<div id="count-green">Count: <span>0</span></div>
<input type="radio" name="color" value="yellow" id="yellow">
<label for="yellow"></label>
<div id="count-yellow">Count: <span>0</span></div>
<input type="radio" name="color" value="gray" id="gray">
<label for="gray"></label>
<div id="count-gray">Count: <span>0</span></div>
</div>
<!-- The game board as a grid -->
<div class="game-board">
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
<div class="card"></div>
</div>

HTML collapsible closed by default

I am currently working on a website and am currently up to adding collapsibles.
I am having some difficulty with collapsibles as shown:
body {
align-self: center;
}
h1, p , body > ul, ol{
text-align: center;
align-self: center;
background-color: rgba(255, 255, 255, 0.6);
width: 40%;
margin: 20px 29%;
padding: 5px 3%;
}
h1 {
font-family: 'Press Start 2P';
font-size: 40px;
}
p, ul, ol {
font-family: "Turret Road";
font-size: 20px;
}
.collapsible {
background-color: #eee;
color: #000;
cursor: pointer;
padding: 8px;
width: 90%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
margin: 10px 5%;
}
.active, .collapsible:hover {
background-color: rgba(255, 255, 255, 1);
}
<body>
<button type="button" class="collapsible"><h1>Basic Rundown</h1></button>
<div class="content">
<p>Vaporfest is inspired by internet music genres like vaporwave, future funk and eccojams.</p>
<p>At Vaporfest, several artists will be performing music that will take you back to a better time.</p>
</div>
<button type="button" class="collapsible"><h1>What to bring</h1></button>
<div class="content">
<ol>
<li>Enough clothes for 5 days</li>
<li>Recording equipment (if you want)</li>
<li>Basic toiletries</li>
<li>Anything else you think is neccesary</li>
</ol></div>
<button type="button" class="collapsible"><h1>Security measures</h1></button>
<div class="content">
<p>Attendees will be tested for COVID every day.</p>
<p>You have to be older than 18 to attend. </p>
</div>
<button type="button" class="collapsible"><h1>Rules about camping</h1></button>
<div class="content">
<ol>
<li>Be respectful at all times.</li>
</ol></div>
<button type="button" class="collapsible"><h1>Prohibited items</h1></button>
<div class="content">
<ol>
<li>Cutlery or hard plates</li>
<li>Metal blades</li>
<li>Gas tanks, gas cylinders, jerry cans</li>
<li>Glass</li>
<li>BBQ sets</li>
<li>Unperscribed stimulants</li>
</ol></div>
<button type="button" class="collapsible"><h1>Getting there</h1></button>
<div class="content">
<p>The festival site is roughly 1 hour away from Kansai International Airport.</p>
</div>
<script>
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
}
</script>
</body>
When the page loads, the collapsibles are open by default, which isn't desired. I want it to be closed by default.
How do I make the collapsibles closed by default when the page is loaded?
Try using JavaScript and Jquery
<body onload=“$("#myModal").modal('hide');”>
add this CSS:
.content {
display: none;
}

Hide certain inputs and show others using a switch button in jQuery

Hello Stackoverflow community, hope that you're doing well, what I'm trying to do is when I click the switch button I want it to hide certain inputs and show others, my code is a form to add students and teachers, since there are cummon inputs I tought about hide the uncummon one when I press the switch button and when I click it again do the opposite but all of that seem to be failed, I can only hide some and when I click it again it won't work, here what I did:
The Jquery code:
$(document).ready(function(){
$('.teacher').hide();
$('.switch').click(function(){
$('.student').hide();
$('.teacher').show();
});
});
The HTML code:
<label>Student </label>
<label class="switch">
<input type="checkbox" id="switchVal" value="0">
<span class="slider"></span>
</label>
<label> Teacher</label>
$('.teacher').hide();
$('.switch').click(function() {
$('.student').toggle();
$('.teacher').toggle();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='student'>Student</div>
<div class="switch">
<input type="checkbox" id="switchVal" value="0">
<span class="slider"></span>
</div>
<div class='teacher'>Teacher</div>
Use $(".teacher, .student").toggle();
Or, if needed, for more granular control you could always get the current checkbox state using
const isChecked = this.checked; // boolean`
Example:
jQuery($ => {
$(".teacher").hide();
$("#switchVal").on("input", function() {
$(".teacher, .student").toggle();
});
});
.toggler {
display: inline-flex;
gap: 0 5px;
cursor: pointer;
}
.toggler-checkbox {
display: inline-block;
width: 35px;
height: 15px;
background: #444;
border-radius: 1.2em;
}
.toggler-checkbox::before {
content: "";
position: relative;
display: inline-block;
width: 15px;
height: 15px;
background: #0bf;
border-radius: 1em;
transition: transform 0.3s;
}
.toggler input:checked ~ .toggler-checkbox::before {
transform: translateX(20px);
}
.toggler-label {
user-select: none;
}
.toggler-label:nth-of-type(1) {
order: -1;
color: #0bf;
}
.toggler input:checked ~ .toggler-label:nth-of-type(1) {
color: inherit;
}
.toggler input:checked ~ .toggler-label:nth-of-type(2) {
color: #0bf;
}
<label class="toggler">
<input type="checkbox" id="switchVal" value="0" hidden>
<span class="toggler-checkbox"></span>
<b class="toggler-label">Student</b>
<b class="toggler-label">Teacher</b>
</label>
<ul>
<li class="student">Student: Anna</li>
<li class="student">Student: John</li>
<li class="teacher">Teacher: Mark</li>
<li class="student">Student: Tara</li>
<li class="teacher">Teacher: Zack</li>
</ul>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

How can i select a specific element after i've clicked another element in the same div [duplicate]

This question already has answers here:
Cleanest way to get the next sibling in jQuery
(3 answers)
Closed 2 years ago.
I have a h3 element and a p element which are inside a div element ,like this:
<div class="question">
<h3> *a question* <img class="arrow" src="" alt="an-arrow-img"> </img> </h3>
<p> *an answer* </p>
</div>
And I have a class named "show" in my css file, which looks like this:
//shows the answer when I click the h3 element
.show{
display: block;
}
on the website, I'm trying to make the questions-answers look like this:
show-hide p element
I've used javascript to toggle the class "show" when I click the questions (h3 elements) but I toggle them all and can't figure out how i can select the one I've clicked. My javascript code is this one till now:
$("h3").on("click", function(){
$("p").toggleClass("show");
});
Is it my HTML structure that's wrong, or is there a way to combine the $(this) selector to show the answer only to the question I've clicked?
var question = document.getElementsByClassName("question");
var i;
for (i = 0; i < question.length; i++) {
question[i].addEventListener("click", function() {
this.classList.toggle("active");
var answer = this.nextElementSibling;
if (answer.style.maxHeight) {
answer.style.maxHeight = null;
} else {
answer.style.maxHeight = answer.scrollHeight + "px";
}
});
}
.question {
background-color: #2d6596;
color: #f1f1f1;
cursor: pointer;
padding: 18px;
width: 100%;
border: 1px solid white;
text-align: left;
outline: none;
font-size: 15px;
transition: 0.4s;
}
.active, .question:hover {
background-color: #1a364f;
}
.question:after {
content: '\002B';
color: #f1f1f1;
font-weight: bold;
float: right;
margin-left: 5px;
}
.active:after {
content: "\2212";
}
.answer {
padding: 0 18px;
background-color: #f2f2f2;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
}
<button class="question">The question</button>
<div class="answer">
<p>The answer</p>
</div>
<button class="question">The question</button>
<div class="answer">
<p>The answer</p>
</div>
<button class="question">The question</button>
<div class="answer">
<p>The answer</p>
</div>
Use JQuery.next() to select sibling of $this.
$("h3").on("click", function(){
$(this).next("p").toggleClass("show");
});

Updating js variables

I have dynamically updated list. Each list element has text input and delete button. I have 2 problems:
when I delete a list item, leninputs in cloneLi doesn't change
when I enter a text value in the first list item, it is copied also to the new one (i tried also elmtInput.reset(), but no change)
Do you have an idea what's wrong?
html code:
<ul id="sortable">
<li>
<div class="row">
<input type="text" id="item1" name="item1" value="">
<div>
<a class="btn" onclick="this.parentElement.parentElement.parentElement.style.display = 'none';"><i class="fas fa-trash"></i></a>
</div>
</div>
</li>
</ul>
<input type="submit" value="New item" class="btn" onclick="cloneLi()">
js:
function cloneLi() {
leninputs = document.getElementsByTagName("input").length;
if (leninputs < 5) {
var ul = document.getElementById("sortable");
var elmnt = ul.getElementsByTagName("li")[0];
var cln = elmnt.cloneNode(true);
document.getElementById("sortable").appendChild(cln);
var elmtInput = document.getElementsByTagName("input")[leninputs];
elmtInput.setAttribute("name", "item"+(leninputs+1).toString());
elmtInput.setAttribute("id", "item"+(leninputs+1).toString());
elmtInput.setAttribute("value", "");
} else {
alert('Max number of items reached!');
}
}
You need to exclude the button input from gettting selected with the other input elements, so be more precise in your selecting, and that will make your condition to have only five inputs as max instead of four correct because you were counting one plus input, you need to delete the li element instead of just hiding it and that keeps its input element as it is, you need to change the value of each new input cloned to avoid cloning the value as well
var listsContainer = document.querySelector("#sortable");
document.querySelector("#add_item").onclick = function() {
var inputLen = document.querySelectorAll("#sortable input").length, newList;
if(inputLen === 5) {
return alert('Max number of items reached!');
}
newList = document.createElement("li");
newList.innerHTML = `
<div class="row">
<input type="text" id="item${++inputLen}" name="item${inputLen}" value="">
<div>
<a class="btn" onclick="this.parentElement.parentElement.parentElement.remove();"><i class="fas fa-trash"></i></a>
</div>
</div>`;
listsContainer.appendChild(newList);
}
ul {
list-style-type: none;
margin: 0 0 10px 0;
padding: 0;
width: 300px;
}
.row {
background-color: lightgreen;
display: flex;
align-items: center;
border-radius: 10px;
padding: 10px;
margin-bottom: 5px;
}
.row div {
display: inline-block;
}
.row div i {
font-size: 20px;
color: white;
text-shadow: 0 0 5px green;
cursor: pointer;
}
.row input {
width: 85%;
margin-right: 10px;
border: none;
border-bottom: 1px solid #777;
}
#add_item {
display: none;
}
label {
background-color: #ccc;
color: white;
font: bold 24px monospace;
padding: 5px;
border-radius: 5px;
box-shadow: inset 1px 1px 3px #fff;
cursor: pointer;
}
<script src="https://kit.fontawesome.com/a076d05399.js"></script>
<ul id="sortable">
<li>
<div class="row">
<input type="text" id="item1" name="item1" value="">
<div>
<a class="btn" onclick="this.parentElement.parentElement.parentElement.remove();"><i class="fas fa-trash"></i></a>
<div>
</div>
</li>
</ul>
<label for="add_item"><input id="add_item" type="submit" class="btn">New item <i class='far fa-plus-square'></i></label>

Categories

Resources