I have a working code of a 10 text questions' trivia game with a timer (html, javascript, css).
How the questions can be served from a simple .txt file (so I can scale)?
How the javascript can choose the questions in a random order, every time the games starts?
I have studied 1 to get an idea. However, my javascript coding skills are very limited. I would appreciate if you can point me to the right direction.
(function() {
const playButton = document.querySelector("#play");
const letsstartButton = document.querySelector("#lets-start");
const playagainButton = document.querySelector("#play-again");
const howToPlayButton = document.querySelector("#how-to-play-button");
const closeHowToButton = document.querySelector("#close-how-to");
const howToPlayScreen = document.querySelector(".how-to-play-screen");
const mainScreen = document.querySelector(".main-screen");
const triviaScreen = document.querySelector(".trivia-screen");
const resultScreen = document.querySelector(".result-screen");
playButton.addEventListener("click", startTrivia);
letsstartButton.addEventListener("click", startTrivia);
playagainButton.addEventListener("click", startTrivia);
howToPlayButton.addEventListener("click", function() {
howToPlayScreen.classList.remove("hidden");
mainScreen.classList.add("hidden");
});
closeHowToButton.addEventListener("click", function() {
howToPlayScreen.classList.add("hidden");
mainScreen.classList.remove("hidden");
});
const questionLength = 10;
let questionIndex = 0;
let score = 0;
let questions = [];
let timer = null;
function startTrivia() {
//show spinner
questionIndex = 0;
questions = [];
score = 0;
window.setTimeout(function() {
//get questions from server
mainScreen.classList.add("hidden");
howToPlayScreen.classList.add("hidden");
resultScreen.classList.add("hidden");
triviaScreen.classList.remove("hidden");
questions = [{
answers: ["Roma", "Athens", "London", "Japan"],
correct: "Roma",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma1", "Athens1", "London1", "Japan1"],
correct: "Athens1",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma2", "Athens2", "London2", "Japan2"],
correct: "London2",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma3", "Athens3", "London3", "Japan3"],
correct: "London3",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma4", "Athens4", "London4", "Japan4"],
correct: "Athens4",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma5", "Athens5", "London5", "Japan5"],
correct: "Athens5",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma6", "Athens6", "London6", "Japan6"],
correct: "Roma6",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma7", "Athens7", "London7", "Japan7"],
correct: "Japan7",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma8", "Athens8", "London8", "Japan8"],
correct: "London8",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma9", "Athens9", "London9", "Japan9"],
correct: "Japan9",
text: "YOUR TEXT HERE."
}
];
const questionCount = document.getElementById("question-count");
questionCount.innerHTML = questionLength.toString();
displayNextQuestion();
}, 50);
}
const isTriviaCompleted = function() {
return questionLength === questionIndex;
};
function displayNextQuestion() {
const answersContainer = document.getElementById("answers-container");
const answerButtons = answersContainer.querySelectorAll(".default-button");
answerButtons.forEach(function(element) {
element.disabled = false;
element.classList.remove("correct");
element.classList.remove("wrong");
});
if (isTriviaCompleted()) {
showScores();
} else {
startProgressbar();
timer = window.setTimeout(function() {
guess(null);
}, 10000);
setQuizText("This is from");
const textElement = document.getElementById("question-placement");
textElement.innerHTML = questions[questionIndex].text;
const choices = questions[questionIndex].answers;
for (let i = 0; i < choices.length; i++) {
const element = document.getElementById(`answer${i}`);
element.innerHTML = choices[i];
element.addEventListener("click", handleAnswerClick);
}
showProgress();
}
}
function handleAnswerClick(e) {
const el = e.currentTarget;
const answer = el.innerHTML;
el.removeEventListener("click", handleAnswerClick);
guess(answer);
}
function showProgress() {
const questionIndexElement = document.getElementById("question-index");
const index = questionIndex + 1;
questionIndexElement.innerHTML = index.toString();
}
function guess(answer) {
clearTimeout(timer);
const answersContainer = document.getElementById("answers-container");
const answerButtons = answersContainer.querySelectorAll(".default-button");
answerButtons.forEach((element) => {
element.disabled = true;
if (element.innerHTML === questions[questionIndex].correct) {
element.classList.add("correct");
}
});
stopProgressbar();
if (questions[questionIndex].correct === answer) { // correct answer
score++;
setQuizText("Fantastic … Correct!");
} else if (answer) { // incorrect answer
setQuizText("Nice try … You were close.");
answerButtons.forEach((element) => {
if (element.innerHTML === answer) {
element.classList.add("wrong");
}
});
} else {
setQuizText("Your time is out! Oh no!");
}
questionIndex++;
window.setTimeout(function() {
displayNextQuestion();
}, 2500);
}
function setQuizText(text) {
const el = document.getElementById("trivia-text");
el.innerHTML = text;
}
function showScores() {
const scoreElement = document.getElementById("score");
const scoreTotalElement = document.getElementById("score-total");
const scoreNameElement = document.getElementById("score-name");
scoreElement.innerHTML = score.toString();
scoreTotalElement.innerHTML = questionLength.toString();
if (score < 4) {
scoreNameElement.innerHTML = "Newbie";
} else if (score < 7) {
scoreNameElement.innerHTML = "Rookie";
} else if (score < 10) {
scoreNameElement.innerHTML = "Expert";
} else {
scoreNameElement.innerHTML = "Grandmaster";
}
triviaScreen.classList.add("hidden");
resultScreen.classList.remove("hidden");
}
function startProgressbar() {
// select div turn into progressbar
const progressbar = document.getElementById("progress-bar");
progressbar.innerHTML = "";
// create div changes width show progress
const progressbarInner = document.createElement("span");
// Append progressbar to main progressbardiv
progressbar.appendChild(progressbarInner);
// When all set start animation
progressbarInner.style.animationPlayState = "running";
}
function stopProgressbar() {
const progressbar = document.getElementById("progress-bar");
const progressbarInner = progressbar.querySelector("span");
progressbarInner.style.animationPlayState = "paused";
}
}());
*,
*:after,
*:before {
box-sizing: border-box;
}
body {
margin: 0;
font-family: 'Verdana', cursive;
text-transform: uppercase;
color: #ccc;
letter-spacing: 2px;
}
.container {
background: #999999;
}
.wrapper {
max-width: 800px;
margin: auto;
}
.screen-section {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
padding: 20px 20px 70px;
position: relative;
}
.hidden {
display: none;
}
.trivia-screen-step {
color: #ccc;
}
.trivia-image-wrapper {
max-width: 100%;
margin: 50px auto;
position: relative;
}
.trivia-image {
max-width: 100%;
width: 300px;
position: relative;
z-index: 1;
}
.trivia-timer {
width: 550px;
max-width: 100%;
height: 20px;
border-radius: 3em;
margin-bottom: 50px;
padding: 5px 6px;
}
.trivia-timer span {
display: inline-block;
background: linear-gradient(90deg, #fff, #06c);
height: 10px;
vertical-align: top;
border-radius: 3em;
animation: progressbar-countdown;
animation-duration: 10s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
animation-play-state: paused;
animation-timing-function: linear;
}
#keyframes progressbar-countdown {
0% {
width: 100%;
}
100% {
width: 0%;
}
}
.trivia-question {
margin-bottom: 50px;
}
.how-to-play-screen .default-button {
margin-bottom: 60px;
margin-top: 30px;
}
.button-container {
display: flex;
flex-wrap: wrap;
margin-bottom: 50px;
width: 600px;
max-width: 100%;
}
.button-outer {
flex-basis: 100%;
text-align: center;
margin-bottom: 20px;
max-width: 100%;
}
.default-button {
background: #333333;
border-radius: 3em;
font-family: 'Verdana', cursive;
font-size: 18px;
color: #fff;
letter-spacing: 2.45px;
padding: 10px 8px;
text-transform: uppercase;
transition: background .2s;
outline: none;
width: 250px;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
.default-button:hover {
background: #222;
}
.default-button[disabled] {
background: transparent;
color: #222;
cursor: default;
}
.default-button[disabled]:hover {
background: transparent;
}
.default-button.correct {
cursor: default;
background: #2bb24a;
color: #fff;
}
.default-button.correct:hover {
background: #2bb24a;
color: #fff;
}
.default-button.wrong {
cursor: default;
background: #F6484C;
color: #fff;
}
.default-button.wrong:hover {
background: #F6484C;
color: #fff;
}
.title {
font-size: 32px;
margin-top: 100px;
}
.text {
line-height: 24px;
font-size: 16px;
font-family: 'Verdana', sans-serif;
text-align: center;
color: #ffffff;
text-transform: none;
}
.trivia-logo {
position: absolute;
bottom: 20px;
}
.trivia-corner-logo {
position: absolute;
left: 0;
top: 15px;
width: 100px;
}
.close-button {
position: absolute;
top: 50px;
right: 0;
background: transparent;
border: none;
color: #fff;
font-family: 'Verdana', cursive;
font-size: 34px;
outline: none;
text-transform: none;
cursor: pointer;
transition: color .2s;
}
.close-button:hover {
color: #eee;
}
.score-name {
margin: 0 0 28px;
font-size: 46px;
}
.score {
font-size: 18px;
margin-bottom: 10px;
}
.description {
text-align: center;
font-family: Verdana, sans-serif;
font-size: 16px;
color: #fff;
text-transform: none;
line-height: 24px;
display: inline-block;
margin-bottom: 30px;
}
#media screen and (min-width: 700px) {
.screen-section {
padding: 50px;
}
<div class="container">
<div class="wrapper">
<div class="screen-section main-screen">
<div class="trivia-image-wrapper">
<img alt="LOGO" src="./assets/Game-Logo.png" class="trivia-image">
</div>
<h1>Trivia</h1>
<div class="button-container">
<div class="button-outer">
<button class="default-button" id="play" type="button">Play</button>
</div>
<div class="button-outer">
<button class="default-button" id="how-to-play-button" type="button">How to play?</button>
</div>
</div>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden how-to-play-screen">
<img alt="LOGO" src="./assets/Game-Logo.png" class="trivia-corner-logo">
<button class="close-button" id="close-how-to" type="button">X</button>
<h2 class="title">How to Play</h2>
<p>Answer questions to score points.</p>
<button class="default-button" id="lets-start" type="button">Ok. Let's start</button>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden trivia-screen">
<div class="trivia-screen-step"><span id="question-index">1</span> out of <span id="question-count">10</span></div>
<div class="trivia-image-wrapper">
<p id="question-placement"></p>
</div>
<div class="trivia-timer" id="progress-bar"></div>
<div class="trivia-question" id="trivia-text"></div>
<div class="button-container" id="answers-container">
<div class="button-outer">
<button class="default-button" id="answer0" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer1" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer2" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer3" type="button"></button>
</div>
</div>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden result-screen">
<div class="trivia-image-wrapper">
<img alt="Trivia LOGO" src="./assets/Game-Logo.png" class="trivia-image">
</div>
<p class="score"><span id="score">0</span> out of <span id="score-total">10</span></p>
<h1 class="score-name" id="score-name">Trivia</h1>
<span class="description">you will learn more.</span>
<button class="default-button" id="play-again" type="button">Play again</button>
<div class="trivia-logo">
<img alt=" logo" src="./assets/-Logo.png">
</div>
</div>
</div>
</div>
In your case the best way would be to create an API (for example https://fastapi.tiangolo.com/) that would return a random question, but if you want to have it in a separate file you would simply have to move the variable questions to another javascript file and import it into the <head> of your web page.
To randomize the JSON you can use the following function:
function shuffleQuestions(questions) {
for (let i = questions.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[questions[i], questions[j]] = [questions[j], questions[i]];
}
}
(function() {
const playButton = document.querySelector("#play");
const letsstartButton = document.querySelector("#lets-start");
const playagainButton = document.querySelector("#play-again");
const howToPlayButton = document.querySelector("#how-to-play-button");
const closeHowToButton = document.querySelector("#close-how-to");
const howToPlayScreen = document.querySelector(".how-to-play-screen");
const mainScreen = document.querySelector(".main-screen");
const triviaScreen = document.querySelector(".trivia-screen");
const resultScreen = document.querySelector(".result-screen");
playButton.addEventListener("click", startTrivia);
letsstartButton.addEventListener("click", startTrivia);
playagainButton.addEventListener("click", startTrivia);
howToPlayButton.addEventListener("click", function() {
howToPlayScreen.classList.remove("hidden");
mainScreen.classList.add("hidden");
});
closeHowToButton.addEventListener("click", function() {
howToPlayScreen.classList.add("hidden");
mainScreen.classList.remove("hidden");
});
const questionLength = 10;
let questionIndex = 0;
let score = 0;
let questions = [];
let timer = null;
function startTrivia() {
//show spinner
questionIndex = 0;
questions = [];
score = 0;
window.setTimeout(function() {
//get questions from server
mainScreen.classList.add("hidden");
howToPlayScreen.classList.add("hidden");
resultScreen.classList.add("hidden");
triviaScreen.classList.remove("hidden");
questions = [{
answers: ["Roma", "Athens", "London", "Japan"],
correct: "Roma",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma1", "Athens1", "London1", "Japan1"],
correct: "Athens1",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma2", "Athens2", "London2", "Japan2"],
correct: "London2",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma3", "Athens3", "London3", "Japan3"],
correct: "London3",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma4", "Athens4", "London4", "Japan4"],
correct: "Athens4",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma5", "Athens5", "London5", "Japan5"],
correct: "Athens5",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma6", "Athens6", "London6", "Japan6"],
correct: "Roma6",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma7", "Athens7", "London7", "Japan7"],
correct: "Japan7",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma8", "Athens8", "London8", "Japan8"],
correct: "London8",
text: "YOUR TEXT HERE."
},
{
answers: ["Roma9", "Athens9", "London9", "Japan9"],
correct: "Japan9",
text: "YOUR TEXT HERE."
}
];
shuffleQuestions(questions);
const questionCount = document.getElementById("question-count");
questionCount.innerHTML = questionLength.toString();
displayNextQuestion();
}, 50);
}
const isTriviaCompleted = function() {
return questionLength === questionIndex;
};
function displayNextQuestion() {
const answersContainer = document.getElementById("answers-container");
const answerButtons = answersContainer.querySelectorAll(".default-button");
answerButtons.forEach(function(element) {
element.disabled = false;
element.classList.remove("correct");
element.classList.remove("wrong");
});
if (isTriviaCompleted()) {
showScores();
} else {
startProgressbar();
timer = window.setTimeout(function() {
guess(null);
}, 10000);
setQuizText("This is from");
const textElement = document.getElementById("question-placement");
textElement.innerHTML = questions[questionIndex].text;
const choices = questions[questionIndex].answers;
for (let i = 0; i < choices.length; i++) {
const element = document.getElementById(`answer${i}`);
element.innerHTML = choices[i];
element.addEventListener("click", handleAnswerClick);
}
showProgress();
}
}
function handleAnswerClick(e) {
const el = e.currentTarget;
const answer = el.innerHTML;
el.removeEventListener("click", handleAnswerClick);
guess(answer);
}
function showProgress() {
const questionIndexElement = document.getElementById("question-index");
const index = questionIndex + 1;
questionIndexElement.innerHTML = index.toString();
}
function guess(answer) {
clearTimeout(timer);
const answersContainer = document.getElementById("answers-container");
const answerButtons = answersContainer.querySelectorAll(".default-button");
answerButtons.forEach((element) => {
element.disabled = true;
if (element.innerHTML === questions[questionIndex].correct) {
element.classList.add("correct");
}
});
stopProgressbar();
if (questions[questionIndex].correct === answer) { // correct answer
score++;
setQuizText("Fantastic … Correct!");
} else if (answer) { // incorrect answer
setQuizText("Nice try … You were close.");
answerButtons.forEach((element) => {
if (element.innerHTML === answer) {
element.classList.add("wrong");
}
});
} else {
setQuizText("Your time is out! Oh no!");
}
questionIndex++;
window.setTimeout(function() {
displayNextQuestion();
}, 2500);
}
function setQuizText(text) {
const el = document.getElementById("trivia-text");
el.innerHTML = text;
}
function showScores() {
const scoreElement = document.getElementById("score");
const scoreTotalElement = document.getElementById("score-total");
const scoreNameElement = document.getElementById("score-name");
scoreElement.innerHTML = score.toString();
scoreTotalElement.innerHTML = questionLength.toString();
if (score < 4) {
scoreNameElement.innerHTML = "Newbie";
} else if (score < 7) {
scoreNameElement.innerHTML = "Rookie";
} else if (score < 10) {
scoreNameElement.innerHTML = "Expert";
} else {
scoreNameElement.innerHTML = "Grandmaster";
}
triviaScreen.classList.add("hidden");
resultScreen.classList.remove("hidden");
}
function startProgressbar() {
// select div turn into progressbar
const progressbar = document.getElementById("progress-bar");
progressbar.innerHTML = "";
// create div changes width show progress
const progressbarInner = document.createElement("span");
// Append progressbar to main progressbardiv
progressbar.appendChild(progressbarInner);
// When all set start animation
progressbarInner.style.animationPlayState = "running";
}
function stopProgressbar() {
const progressbar = document.getElementById("progress-bar");
const progressbarInner = progressbar.querySelector("span");
progressbarInner.style.animationPlayState = "paused";
}
function shuffleQuestions(questions) {
for (let i = questions.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[questions[i], questions[j]] = [questions[j], questions[i]];
}
}
}());
*,
*:after,
*:before {
box-sizing: border-box;
}
body {
margin: 0;
font-family: 'Verdana', cursive;
text-transform: uppercase;
color: #ccc;
letter-spacing: 2px;
}
.container {
background: #999999;
}
.wrapper {
max-width: 800px;
margin: auto;
}
.screen-section {
display: flex;
flex-direction: column;
align-items: center;
min-height: 100vh;
padding: 20px 20px 70px;
position: relative;
}
.hidden {
display: none;
}
.trivia-screen-step {
color: #ccc;
}
.trivia-image-wrapper {
max-width: 100%;
margin: 50px auto;
position: relative;
}
.trivia-image {
max-width: 100%;
width: 300px;
position: relative;
z-index: 1;
}
.trivia-timer {
width: 550px;
max-width: 100%;
height: 20px;
border-radius: 3em;
margin-bottom: 50px;
padding: 5px 6px;
}
.trivia-timer span {
display: inline-block;
background: linear-gradient(90deg, #fff, #06c);
height: 10px;
vertical-align: top;
border-radius: 3em;
animation: progressbar-countdown;
animation-duration: 10s;
animation-iteration-count: 1;
animation-fill-mode: forwards;
animation-play-state: paused;
animation-timing-function: linear;
}
#keyframes progressbar-countdown {
0% {
width: 100%;
}
100% {
width: 0%;
}
}
.trivia-question {
margin-bottom: 50px;
}
.how-to-play-screen .default-button {
margin-bottom: 60px;
margin-top: 30px;
}
.button-container {
display: flex;
flex-wrap: wrap;
margin-bottom: 50px;
width: 600px;
max-width: 100%;
}
.button-outer {
flex-basis: 100%;
text-align: center;
margin-bottom: 20px;
max-width: 100%;
}
.default-button {
background: #333333;
border-radius: 3em;
font-family: 'Verdana', cursive;
font-size: 18px;
color: #fff;
letter-spacing: 2.45px;
padding: 10px 8px;
text-transform: uppercase;
transition: background .2s;
outline: none;
width: 250px;
cursor: pointer;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}
.default-button:hover {
background: #222;
}
.default-button[disabled] {
background: transparent;
color: #222;
cursor: default;
}
.default-button[disabled]:hover {
background: transparent;
}
.default-button.correct {
cursor: default;
background: #2bb24a;
color: #fff;
}
.default-button.correct:hover {
background: #2bb24a;
color: #fff;
}
.default-button.wrong {
cursor: default;
background: #F6484C;
color: #fff;
}
.default-button.wrong:hover {
background: #F6484C;
color: #fff;
}
.title {
font-size: 32px;
margin-top: 100px;
}
.text {
line-height: 24px;
font-size: 16px;
font-family: 'Verdana', sans-serif;
text-align: center;
color: #ffffff;
text-transform: none;
}
.trivia-logo {
position: absolute;
bottom: 20px;
}
.trivia-corner-logo {
position: absolute;
left: 0;
top: 15px;
width: 100px;
}
.close-button {
position: absolute;
top: 50px;
right: 0;
background: transparent;
border: none;
color: #fff;
font-family: 'Verdana', cursive;
font-size: 34px;
outline: none;
text-transform: none;
cursor: pointer;
transition: color .2s;
}
.close-button:hover {
color: #eee;
}
.score-name {
margin: 0 0 28px;
font-size: 46px;
}
.score {
font-size: 18px;
margin-bottom: 10px;
}
.description {
text-align: center;
font-family: Verdana, sans-serif;
font-size: 16px;
color: #fff;
text-transform: none;
line-height: 24px;
display: inline-block;
margin-bottom: 30px;
}
#media screen and (min-width: 700px) {
.screen-section {
padding: 50px;
}
<div class="container">
<div class="wrapper">
<div class="screen-section main-screen">
<div class="trivia-image-wrapper">
<img alt="LOGO" src="./assets/Game-Logo.png" class="trivia-image">
</div>
<h1>Trivia</h1>
<div class="button-container">
<div class="button-outer">
<button class="default-button" id="play" type="button">Play</button>
</div>
<div class="button-outer">
<button class="default-button" id="how-to-play-button" type="button">How to play?</button>
</div>
</div>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden how-to-play-screen">
<img alt="LOGO" src="./assets/Game-Logo.png" class="trivia-corner-logo">
<button class="close-button" id="close-how-to" type="button">X</button>
<h2 class="title">How to Play</h2>
<p>Answer questions to score points.</p>
<button class="default-button" id="lets-start" type="button">Ok. Let's start</button>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden trivia-screen">
<div class="trivia-screen-step"><span id="question-index">1</span> out of <span id="question-count">10</span></div>
<div class="trivia-image-wrapper">
<p id="question-placement"></p>
</div>
<div class="trivia-timer" id="progress-bar"></div>
<div class="trivia-question" id="trivia-text"></div>
<div class="button-container" id="answers-container">
<div class="button-outer">
<button class="default-button" id="answer0" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer1" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer2" type="button"></button>
</div>
<div class="button-outer">
<button class="default-button" id="answer3" type="button"></button>
</div>
</div>
<div class="trivia-logo">
<img alt="logo" src="./assets/-Logo.png">
</div>
</div>
<div class="screen-section hidden result-screen">
<div class="trivia-image-wrapper">
<img alt="Trivia LOGO" src="./assets/Game-Logo.png" class="trivia-image">
</div>
<p class="score"><span id="score">0</span> out of <span id="score-total">10</span></p>
<h1 class="score-name" id="score-name">Trivia</h1>
<span class="description">you will learn more.</span>
<button class="default-button" id="play-again" type="button">Play again</button>
<div class="trivia-logo">
<img alt=" logo" src="./assets/-Logo.png">
</div>
</div>
</div>
</div>
// Add an external book
let inupt = document.getElementById("external-book");
let ptn = document.getElementById("add-external-book");
let settings = document.getElementById("add-settings");
// _____________________start add_____________________________________
let myAddText = [];
function textAddSettings() {
settings.innerHTML = "";
let index = 0;
for (task of myAddText) {
let content = `
<div class="settings">
<h4 class="book-name">${task.name}</h4>
<button id ="asx" onclick="missionCompleted(${index})" class="button-css">ending</button>
</div>
`;
settings.innerHTML += content;
index++;
}
};
ptn.addEventListener("click", function () {
let textBk = inupt.value;
let myAddTextObjkt = {
name: textBk,
removeLeFather: ""
};
myAddText.push(myAddTextObjkt);
//innerHTML
textAddSettings();
inupt.value = '';
});
// ___________________Department of Executed Tasks____________________
let executedTasks = document.getElementById("executed-tasks");
let execute = [];
function textAddExecute() {
executedTasks.innerHTML = "";
let index = 0;
for (task of execute) {
let content =
`
<div class="all-tasks-box">
<div class="my-list">
<h4 class="book-name">${task.name}</h4>
<div class="all-star">
<button onclick="changeColorPnt(${index})" id = "nx" class="button-css">Notes</button>
</div>
</div>
<div class="text-box-m xxxxx ${task.showAndNoneBox ? "show-none" : ""}">
<textarea id = "taw" class="${task.colorArea ? "color-green" : "color-white"}" type ="text" ${task.textAreaReadonly ? "readonly" : ""} > ${task.textareaValue}</textarea>
<button onclick="editAndSave(${index})" >${task.editTextArea ? "Edit" : "save"}</button>
</div>
</div>
`;
executedTasks.innerHTML += content;
index++;
}
};
// Adds the element to the new array while deleting the element from the old array
function missionCompleted(index) {
// task name
let element = myAddText[index].name;
let myexecute = {
name: element,
showAndNoneBox: "false",
textAreaReadonly: "true",
colorArea: "true",
textareaValue: "false",
editTextArea: "false"
};
execute.push(myexecute);
textAddExecute();
// delete the element from the old array
// We will get the index of the item and delete it
myAddText.splice(index, 1);
//innerHTML Updates the old text data
textAddSettings();
};
// ________________Notes button__________________________
function changeColorPnt(index) {
let element = execute[index];
if (element.showAndNoneBox) {
// text area
element.showAndNoneBox = false;
element.textAreaReadonly = false;
} else {
// text area
element.showAndNoneBox = true;
}
textAddExecute();
};
//_____________________________
function editAndSave(index) {
let btn = execute[index];
if (btn.editTextArea) {
// edit or save button
btn.editTextArea = false;
// The text area is allowed to write in
btn.textAreaReadonly = false;
// Change the color of the text area
btn.colorArea = false;
btn.textareaValue = document
.querySelector(`.text-box-m textarea`)
.value.trim();
} else {
btn.textareaValue = document
.querySelector(`.text-box-m textarea`)
.value.trim();
// Modify button
btn.editTextArea = true;
// The text area is not allowed to be written in
btn.textAreaReadonly = true;
// Change the color of the text area
btn.colorArea = true;
}
textAddExecute();
};
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
direction:rtl;
}
.contnire {
margin: 0 auto;
min-height: 100vh;
width: 900px;
background-color: #176a63;
}
/* Start title */
.contnire .title {
width: 100%;
height: 70px;
background-color: #176a63;
display: flex;
align-items: center;
justify-content: space-around;
}
.contnire .title .add-book {
display: flex;
width: 200px;
height: 25px;
}
.contnire .title .add-book input:focus {
background-color: aquamarine;
outline: none;
}
.contnire .title h1 {
text-align: center;
margin-right: 200px;
color: white;
padding: 20px;
font-size: 40px;
}
/* End title */
/* Start box-body */
.box-body {
display: flex;
flex-direction: column;
padding: 20px;
background-color: #3F51B5;
width: 100%;
}
/* Start content */
.content {
padding: 20px;
background-color: white;
border-bottom: 2px solid #7044b2;
box-shadow: 0px -1px 13px 4px #b9b3b3;
}
/* Start box */
.content .box {
text-align: center;
background-color: #009688;
width: 100%;
}
.box .mybox {
display: flex;
align-items: center;
justify-content: center;
background-color: #3F51B5;
}
.box .mybox h3 {
padding: 20px;
}
.content .control-book .settings {
display: flex;
align-items: center;
height: 50px;
border-bottom: 2px solid #ccc;
padding: 5px;
}
/* End box */
/* End content */
/* Start box-down */
.box-down .add-list {
display: flex;
padding-top: 20px;
justify-content: space-around;
}
.add-list .Waiting-list-two {
width: calc(100% - 10px);
}
.add-list .my-list-one {
background-color: #7044b2;
}
.add-list .my-list-one h2 {
padding: 20px;
}
.add-list .my-list {
padding: 5px;
background-color: #009688;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 2px solid #ccc;
}
/* End box-down */
/* all */
.button-css {
padding: 4px 10px;
margin-right: 4px;
}
.book-name {
padding: 10px;
width: 220px;
background-color: #f9f3f3fa;
}
textarea {
padding: 5px;
line-height: 1.6;
word-spacing: -6px;
overflow: auto;
width: 100%;
height: 100px;
font-size: 18px;
}
textarea:disabled {
color: #000000e6;
background-color: #8bc34a57;
}
.show-none {
display: none;
}
textarea.color-green {
background-color: #4caf505e;
}
textarea.color-white {
background-color: white;
}
<div class="contnire">
<!-- Start title -->
<div class="title">
<div class="add-book">
<input id="external-book" class="book-name" type="text">
<button id="add-external-book" class="button-css">add</button>
</div>
<h1>My tasks</h1>
</div>
<!-- End title -->
<!-- Start box-body -->
<div class="box-body">
<!-- Start content -->
<div class="content">
<!-- Start box -->
<div class="box">
<div class="mybox">
<h3>required tasks</h3>
</div>
<div id="add-settings" class="control-book"></div>
</div>
<!-- End box -->
</div>
<!-- End content -->
<!-- Start box-down -->
<div class="box-down">
<div class="add-list">
<div class="Waiting-list-two">
<div class="my-list-one">
<h2>The tasks that were performed</h2>
</div>
<div id="executed-tasks" class="all-list">
</div>
</div>
</div>
<!-- End box-down -->
</div>
</div>
</div>
I write the name of the task, then press the "Add" button, the item appears, and next to it the "Finish" button. When I press Finish, the item appears in the To Do section, and next to the item, the Notes button. When I press the notes button, the text area appears and disappears, and in the text area there is an edit button. When I click on it I can type a comment inside the text area, and by pressing the save button the edit is locked into the problematic text area? When I add more than one element the entire text area takes the same as the first comment and I want each element to be stable writing the text area so I can modify the comment in any element without affecting the rest
I created a 16 x 16 grid where I can etch a sketch on that grid. It's working with the default colour that I use. When I try adding buttons to change colours to sketch. I can't seem to make it work. I've tried various methods and writing it with various ways but again and again I failed. I want when I click on the buttons, it changes colour when I sketch. I'll include below the previous code that's working and one of the ways that I've tried. Any expert/master please have a look on my code.
let container = document.querySelector('.container');
let rows = document.getElementsByClassName('gridRow');
let columns = document.getElementsByClassName('gridColumn');
const blue = document.getElementsByClassName('blue');
const eraser = document.getElementsByClassName('eraser');
const black = document.getElementsByClassName('black');
let reset = document.getElementById('reset');
function createGrid(number) {
makeRow(number);
makeColumn(number);
changeColours();
}
function makeRow(numberOfRow) {
for (let i = 0; i <numberOfRow; i++) {
let row = document.createElement('div');
container.appendChild(row);
row.classList.add('gridRow');
}
}
function makeColumn(numberOfColumn, selection) {
for ( let i = 0; i < rows.length; i++) {
for ( let j = 0; j < numberOfColumn; j++) {
let column = document.createElement('div');
The part below is what I tried, erase it if you want it to work with just one colour
if (selection == 'blue') {
column.addEventListener('mouseenter', function() {
column.classList.add('blue');
})
} else if (selection == 'eraser') {
column.addEventListener('mouseenter', function() {
column.classList.add('eraser');
})
} else if (selection == 'black') {
column.addEventListener('mouseenter', function() {
column.classList.add('black');
})
} else {
column.addEventListener('mouseenter', function() {
column.classList.add('colored');
})
}
// column.addEventListener('mouseleave', () => {
// column.classList.remove('colored');
// })
Just erase part of the code above if you want to make it work
rows[j].appendChild(column);
column.classList.add('gridColumn');
}
}
}
The part below is what I tried, erase it if you want it to work with just one colour
blue.addEventListener('click', function() {
makeColumn(number, 'blue');
})
eraser.addEventListener('click', function() {
makeColumn(number, 'white');
})
black.addEventListener('click', function() {
makeColumn(number, 'black');
})
Just erase part of the code above if you want to make it work
createGrid(16);
#importurl('https://fonts.googleapis.com/css2family=Asap:wght#400;600;700&display=swap');
body {
display: flex;
height: 100%;
width: 100%;
flex-direction: column;
background-color: beige;
font-family: Asap, sans-serif;
margin: 0;
padding: 0;
justify-content: center;
align-content: center;
align-items: center;
}
.header {
display: flex;
flex: 1;
justify-content: center;
}
#setGridSize {
display: inline-flex;
justify-content: center;
flex: 1;
gap: 12px;
}
#guide {
text-align: center;
margin: 1px;
font-family: Asap, sans-serif;
color: red;
font-size: 13px;;
}
.container {
display: flex;
justify-content: center;
align-content: center;
align-items: center;
border: 1px solid black;
width: 550px;
height: 550px;
}
.gridColumn {
display: inline-flex;
border: 1px solid beige;
margin: -1px 0;
width: 30px;
height: 30px;
}
.colored{
background: red;
}
.buttons {
display: flex;
flex: 1;
gap: 20px;
margin: 10px;
}
.blue {
background: blue;
}
.eraser {
background: white;
}
.black {
background: black;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>DOM Manipulation and Events</title>
<script src="javascript.js" defer></script>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1 class="header"> Let's sketch ! </h1>
<div id="setGridSize">
<p> Grid size </p> <input type="text" placeholder="Size of Board" class="size-box">
<button id="submit" > Submit </button>
</div>
<p id="guide"> Enter a number between 2 to 99</p>
<div class="container"></div>
<div class="buttons">
<button class="blue"> Blue </button>
<button class="eraser" > Eraser </button>
<button class="black"> Black </button>
<button class="rainbow" > Rainbow </button>
<button class="reset" > Reset</button>
</div>
</body>
</html>
Maybe this small example will help you
const grid = document.querySelector('.grid');
const colorSelector = document.querySelector('input[type="color"]')
const COUNT = 8
for (let i = 0; i < COUNT; i++) {
for (let j = 0; j < COUNT; j++) {
const btn = document.createElement('button')
grid.appendChild(btn)
}
}
const btns = Array.from(grid.children)
btns.forEach(btn => {
btn.addEventListener('mouseenter', event => {
btn.style.backgroundColor = colorSelector.value;
})
})
#import "https://cdn.jsdelivr.net/gh/KunalTanwar/normalize/css/normalize.inter.min.css";
body {
height: 100%;
display: grid;
place-items: center;
}
.grid {
--btn-count: 8;
--btn-size: 24px;
display: grid;
grid-template-columns: repeat(var(--btn-count), var(--btn-size));
grid-template-rows: repeat(var(--btn-count), var(--btn-size));
}
.grid button {
border: 1px solid #d1d1d1;
}
<input type="color">
<div class="grid"></div>
So I'm making an Etch-a-Sketch with a range slider to change the grid size, but the slider keeps resetting to its default size (16x16) as soon as I move the mouse after changing the value (if I change the value and don't move the mouse, the size doesn't reset). For some reason this doesn't happen on Chrome: the value and grid size both change and stay that way until I change them again.
Here's the JSFiddle: https://jsfiddle.net/CamiCoding/7zpt14cs/
HTML:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Etch-a-Sketch</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<div class="title">
<h1>Etch-a-Sketch</h1>
</div>
<div class="btns">
<button id="blackBtn">Black</button>
<button id="rainbowBtn">Rainbow</button>
<button id="colorBtn">Color</button>
<button id="eraserBtn">Eraser</button>
<button id="resetBtn">Reset</button>
<div class="colorPicker">
<input type="color" id="color" value="#000000">
<span>Pick a color</span>
</div>
<div class="sliderAndValue">
<input type="range" min="2" max="100" value="16" id="slider">
<p class="value">16</p>
</div>
</div>
<div class="grid">
</div>
<script src="script.js" defer></script>
</body>
</html>
CSS:
#font-face {
src: url("../fonts/sf-atarian-system.regular.ttf");
font-family: Atarian;
}
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-family: Atarian;
background-color: #D1D1D1;
}
.title h1 {
font-size: 80px;
margin: 0px;
}
.btns {
display: flex;
flex-direction: row;
width: 700px;
height: 50px;
justify-content: space-evenly;
margin-top: 20px;
margin-bottom: 20px;
}
.btns button {
font-family: Atarian;
font-size: 24px;
height: 40px;
width: 80px;
border-radius: 5px;
transition: transform 0.2s ease-in-out;
}
.btns button:hover {
transform: scale(1.2);
}
.btns .active {
background-color: #505050;
color: white;
}
.colorPicker {
display: flex;
flex-direction: column;
align-items: center;
font-size: 20px;
}
.color span {
text-align: center;
}
#color {
width: 90px;
}
.sliderAndValue {
-webkit-appearance: none;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
font-size: 24px;
}
#slider {
-webkit-appearance: none;
width: 150px;
height: 10px;
background: #000;
outline: none;
border: 4px solid gray;
border-radius: 4px;
}
/* for firefox */
#slider::-moz-range-thumb {
width: 5px;
height: 20px;
background: #000;
cursor: pointer;
border: 4px solid gray;
border-radius: 4px;
}
/* for chrome/safari */
#slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 5px;
height: 20px;
background: #000;
cursor: pointer;
border: 4px solid gray;
border-radius: 4px;
}
.cell {
border: 1px solid black;
}
.cell.active {
background-color: black;
}
.grid {
display: inline-grid;
grid-template-columns: repeat(16, 2fr);
grid-template-rows: repeat(16, 2fr);
border: 5px solid gray;
border-radius: 5px;
height: 700px;
width: 700px;
background-color: white;
}
JS:
const grid = document.querySelector('.grid');
const resetBtn = document.getElementById('resetBtn');
const eraserBtn = document.getElementById('eraserBtn');
const blackBtn = document.getElementById('blackBtn');
const colorBtn = document.getElementById('colorBtn')
const colorValue = document.getElementById('color');
const slider = document.getElementById('slider');
const sliderValue = document.querySelector('.value');
const DEFAULT_COLOR = '#000000';
const DEFAULT_MODE = 'black';
const DEFAULT_SIZE = 16;
let currentColor = DEFAULT_COLOR;
let currentMode = DEFAULT_MODE;
let mouseDown = false
document.body.onmousedown = () => (mouseDown = true)
document.body.onmouseup = () => (mouseDown = false)
function setCurrentColor(newColor) {
currentColor = newColor;
}
function setCurrentMode(newMode) {
activateButton(newMode);
currentMode = newMode;
}
blackBtn.onclick = () => setCurrentMode('black');
rainbowBtn.onclick = () => setCurrentMode('rainbow');
eraserBtn.onclick = () => setCurrentMode('eraser');
colorBtn.onclick = () => setCurrentMode('color');
resetBtn.onclick = () => createGrid();
function createGrid() {
removeCells(grid);
let val = document.getElementById('slider').value;
sliderValue.textContent = val;
grid.style.gridTemplateColumns = (`repeat(${val}, 2fr`);
grid.style.gridTemplateRows = (`repeat(${val}, 2fr`);
for(let i = 0; i < val * val; i++) {
const cell = document.createElement('div');
cell.classList.add('cell');
cell.addEventListener('mouseover', changeColor);
cell.addEventListener('mousedown', changeColor);
grid.appendChild(cell);
}
}
function activateButton(newMode) {
if (currentMode === 'rainbow') {
rainbowBtn.classList.remove('active');
} else if (currentMode === 'color') {
colorBtn.classList.remove('active');
} else if (currentMode === 'eraser') {
eraserBtn.classList.remove('active');
} else if (currentMode === 'black') {
blackBtn.classList.remove('active');
}
if (newMode === 'rainbow') {
rainbowBtn.classList.add('active');
} else if (newMode === 'color') {
colorBtn.classList.add('active');
} else if (newMode === 'eraser') {
eraserBtn.classList.add('active');
} else if (newMode === 'black') {
blackBtn.classList.add('active');
}
}
function changeColor(e) {
if (e.type === 'mouseover' && !mouseDown) return;
if (currentMode === 'rainbow') {
const randomR = Math.floor(Math.random() * 256);
const randomG = Math.floor(Math.random() * 256);
const randomB = Math.floor(Math.random() * 256);
e.target.style.backgroundColor = `rgb(${randomR}, ${randomG}, ${randomB})`;
} else if (currentMode === 'color') {
e.target.style.backgroundColor = colorValue.value;
} else if (currentMode === 'eraser') {
e.target.style.backgroundColor = '#ffffff';
} else if (currentMode === 'black') {
e.target.style.background = '#000000';
}
}
slider.addEventListener('input', function(){
let val = document.getElementById('slider').value;
sliderValue.textContent = val;
removeCells(grid);
grid.style.gridTemplateColumns = (`repeat(${val}, 2fr`);
grid.style.gridTemplateRows = (`repeat(${val}, 2fr`);
for (let i = 0; i < val * val; i++) {
const cell = document.createElement('div');
cell.classList.add('cell');
cell.addEventListener('mouseover', changeColor);
cell.addEventListener('mousedown', changeColor);
grid.appendChild(cell);
}
});
function removeCells(parent){
while(grid.firstChild){
grid.removeChild(grid.firstChild);
}
}
window.onload = () => {
createGrid(DEFAULT_SIZE);
activateButton(DEFAULT_MODE);
}
I do have another question regarding this same project, but about a different issue, please let me know if I should post a different question for it or if I should post it here too!
Thanks a lot in advance :).
I was able to track down the source of the issue, and fix it. Sounds weird, but document.body.onmousedown and document.body.onmouseup were creating the issue.
Replacing them with addEventListener seems to fix it.
I also removed some repeated code (in slider's input listener), by making maximum use of createGrid() function.
const grid = document.querySelector('.grid');
const resetBtn = document.getElementById('resetBtn');
const eraserBtn = document.getElementById('eraserBtn');
const blackBtn = document.getElementById('blackBtn');
const colorBtn = document.getElementById('colorBtn')
const colorValue = document.getElementById('color');
const slider = document.querySelector('#slider');
const sliderValue = document.querySelector('.value');
const DEFAULT_COLOR = '#000000';
const DEFAULT_MODE = 'black';
const DEFAULT_SIZE = 16;
let currentColor = DEFAULT_COLOR;
let currentMode = DEFAULT_MODE;
let mouseDown = false
document.body.addEventListener("mousedown", () => (mouseDown = true))
document.body.addEventListener("mouseup", () => (mouseDown = false))
function setCurrentColor(newColor) {
currentColor = newColor;
}
function setCurrentMode(newMode) {
activateButton(newMode);
currentMode = newMode;
}
blackBtn.onclick = () => setCurrentMode('black');
rainbowBtn.onclick = () => setCurrentMode('rainbow');
eraserBtn.onclick = () => setCurrentMode('eraser');
colorBtn.onclick = () => setCurrentMode('color');
resetBtn.onclick = () => createGrid();
function createGrid(val = 16) {
slider.value = val;
sliderValue.textContent = val;
removeCells(grid);
grid.style.gridTemplateColumns = (`repeat(${val}, 2fr`);
grid.style.gridTemplateRows = (`repeat(${val}, 2fr`);
for (let i = 0; i < val * val; i++) {
const cell = document.createElement('div');
cell.classList.add('cell');
cell.addEventListener('mouseover', changeColor);
cell.addEventListener('mousedown', changeColor);
grid.appendChild(cell);
}
}
function activateButton(newMode) {
if (currentMode === 'rainbow') {
rainbowBtn.classList.remove('active');
} else if (currentMode === 'color') {
colorBtn.classList.remove('active');
} else if (currentMode === 'eraser') {
eraserBtn.classList.remove('active');
} else if (currentMode === 'black') {
blackBtn.classList.remove('active');
}
if (newMode === 'rainbow') {
rainbowBtn.classList.add('active');
} else if (newMode === 'color') {
colorBtn.classList.add('active');
} else if (newMode === 'eraser') {
eraserBtn.classList.add('active');
} else if (newMode === 'black') {
blackBtn.classList.add('active');
}
}
function changeColor(e) {
if (e.type === 'mouseover' && !mouseDown) return;
if (currentMode === 'rainbow') {
const randomR = Math.floor(Math.random() * 256);
const randomG = Math.floor(Math.random() * 256);
const randomB = Math.floor(Math.random() * 256);
e.target.style.backgroundColor = `rgb(${randomR}, ${randomG}, ${randomB})`;
} else if (currentMode === 'color') {
e.target.style.backgroundColor = colorValue.value;
} else if (currentMode === 'eraser') {
e.target.style.backgroundColor = '#ffffff';
} else if (currentMode === 'black') {
e.target.style.background = '#000000';
}
}
slider.addEventListener('input', function(e) {
let val = parseInt(document.getElementById('slider').value);
createGrid(val);
});
function removeCells(parent) {
while (grid.firstChild) {
grid.removeChild(grid.firstChild);
}
}
window.onload = () => {
createGrid(DEFAULT_SIZE);
activateButton(DEFAULT_MODE);
}
#font-face {
src: url("../fonts/sf-atarian-system.regular.ttf");
font-family: Atarian;
}
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-family: Atarian;
background-color: #D1D1D1;
}
.title h1 {
font-size: 80px;
margin: 0px;
}
.btns {
display: flex;
flex-direction: row;
width: 700px;
height: 50px;
justify-content: space-evenly;
margin-top: 20px;
margin-bottom: 20px;
}
.btns button {
font-family: Atarian;
font-size: 24px;
height: 40px;
width: 80px;
border-radius: 5px;
transition: transform 0.2s ease-in-out;
}
.btns button:hover {
transform: scale(1.2);
}
.btns .active {
background-color: #505050;
color: white;
}
.colorPicker {
display: flex;
flex-direction: column;
align-items: center;
font-size: 20px;
}
.color span {
text-align: center;
}
#color {
width: 90px;
}
.sliderAndValue {
-webkit-appearance: none;
display: flex;
flex-direction: row;
justify-content: center;
align-items: center;
font-size: 24px;
}
#slider {
-webkit-appearance: none;
width: 150px;
height: 10px;
background: #000;
outline: none;
border: 4px solid gray;
border-radius: 4px;
}
/* for firefox */
#slider::-moz-range-thumb {
width: 5px;
height: 20px;
background: #000;
cursor: pointer;
border: 4px solid gray;
border-radius: 4px;
}
/* for chrome/safari */
#slider::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 5px;
height: 20px;
background: #000;
cursor: pointer;
border: 4px solid gray;
border-radius: 4px;
}
.cell {
border: 1px solid black;
}
.cell.active {
background-color: black;
}
.grid {
display: inline-grid;
grid-template-columns: repeat(16, 2fr);
grid-template-rows: repeat(16, 2fr);
border: 5px solid gray;
border-radius: 5px;
height: 700px;
width: 700px;
background-color: white;
user-select: none;
}
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="x-ua-compatible" content="ie=edge">
<title>Etch-a-Sketch</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<div class="title">
<h1>Etch-a-Sketch</h1>
</div>
<div class="btns">
<button id="blackBtn">Black</button>
<button id="rainbowBtn">Rainbow</button>
<button id="colorBtn">Color</button>
<button id="eraserBtn">Eraser</button>
<button id="resetBtn">Reset</button>
<div class="colorPicker">
<input type="color" id="color" value="#000000">
<span>Pick a color</span>
</div>
<div class="sliderAndValue">
<input type="range" min="2" value="16" id="slider">
<p class="value">16</p>
</div>
</div>
<div class="grid">
</div>
<script src="script.js" defer></script>
</body>
</html>
I am have this div here which I'm using with the drag and drop API:
<div class="box student" draggable="true" style="background-color: #1DDBCA;margin:10px" id="5"><span>Seymen Ege</span></div>
If I drag this element:
<div class="box c1r1" draggable="true" style="background-color: #1DDBCA;margin:10px;display:inline-block" id=" "><span>Boş</span></div>
and drop it on the div it works fine but I want it to hide itself if it has this " " id and has the student class. But it shouldn't hide it otherwise.
I need to add something to it so that it hides the element if it has the " " id and the "student" class after being dropped. How can I do that?
const boxElements = document.querySelectorAll(".box");
boxElements.forEach(elem => {
elem.addEventListener("dragstart", dragStart);
// elem.addEventListener("drag", drag);
elem.addEventListener("dragend", dragEnd);
elem.addEventListener("dragenter", dragEnter);
elem.addEventListener("dragover", dragOver);
elem.addEventListener("dragleave", dragLeave);
elem.addEventListener("drop", drop);
});
// Drag and Drop Functions
function dragStart(event) {
event.target.classList.add("drag-start");
event.dataTransfer.setData("text", event.target.id);
}
function dragEnd(event) {
event.target.classList.remove("drag-start");
}
function dragEnter(event) {
if (!event.target.classList.contains("drag-start")) {
event.target.classList.add("drag-enter");
}
}
function dragOver(event) {
event.preventDefault();
}
function dragLeave(event) {
event.target.classList.remove("drag-enter");
}
function drop(event) {
event.preventDefault();
event.target.classList.remove("drag-enter");
const draggableElementId = event.dataTransfer.getData("text");
const droppableElementId = event.target.id;
if (draggableElementId !== droppableElementId) {
const draggableElement = document.getElementById(draggableElementId);
const droppableElementBgColor = event.target.style.backgroundColor;
const droppableElementTextContent = event.target.querySelector("span").textContent;
event.target.style.backgroundColor = draggableElement.style.backgroundColor;
event.target.querySelector("span").textContent = draggableElement.querySelector("span").textContent;
event.target.id = draggableElementId;
draggableElement.style.backgroundColor = droppableElementBgColor;
draggableElement.querySelector("span").textContent = droppableElementTextContent;
draggableElement.id = droppableElementId;
}
}
#import url('https://fonts.googleapis.com/css?family=Montserrat');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Montserrat', sans-serif;
background-color: #eee;
color: #333;
}
.box {
width: 80px;
border: 3px solid #333;
border-radius: 0.5rem;
margin: 1.25rem;
display: inline-block;
justify-content: center;
align-items: center;
text-align: center;
font-weight: bold;
user-select: none;
cursor: move;
transition: 0.5s;
}
.box span {
pointer-events: none;
}
/* Drag and Drop Related Styling */
.drag-start {
opacity: 0.4;
}
.drag-enter {
border-style: dashed;
}
.box:nth-child(odd).drag-enter {
transform: rotate(15deg);
}
.box:nth-child(even).drag-enter {
transform: rotate(-15deg);
}
.box:nth-child(odd).drag-start {
transform: rotate(15deg) scale(0.75);
}
.box:nth-child(even).drag-start {
transform: rotate(-15deg) scale(0.75);
}
#media (max-width: 600px) {
html {
font-size: 14px;
}
.box {
width: 4rem;
height: 4rem;
margin: 0.5rem;
}
}
<div class="box student" draggable="true" style="background-color: #1DDBCA;margin:10px" id="5"><span>Seymen Ege</span></div>
<div class="box c1r1" draggable="true" style="background-color: #1DDBCA;margin:10px;display:inline-block" id=" "><span>Boş</span></div>
As #connexo said, working with space characters within ids or classes leads to invalid HTML, so to get the desired result you can use another class (e.g. 'drag-end') to set the desired properties:
.student.drag-end {
display: none;
}
For instance, the above css will apply to the element <element class="student drag-end">
Having empty IDs or IDs with space is not a good way. I would use a data attribute
Anyway:
function dragEnd(event) {
const tgt = event.target
if (tgt) {
tgt.classList.remove("drag-start");
if (tgt.id.trim() === "" && tgt.classList.contains("student")) {
tgt.remove()
}
}
}
const boxElements = document.querySelectorAll(".box");
boxElements.forEach(elem => {
elem.addEventListener("dragstart", dragStart);
// elem.addEventListener("drag", drag);
elem.addEventListener("dragend", dragEnd);
elem.addEventListener("dragenter", dragEnter);
elem.addEventListener("dragover", dragOver);
elem.addEventListener("dragleave", dragLeave);
elem.addEventListener("drop", drop);
});
// Drag and Drop Functions
function dragStart(event) {
event.target.classList.add("drag-start");
event.dataTransfer.setData("text", event.target.id);
}
function dragEnd(event) {
const tgt = event.target
if (tgt) {
tgt.classList.remove("drag-start");
console.log(tgt.className)
if (tgt.id.trim() === "" && tgt.classList.contains("student")) {
tgt.remove()
}
}
}
function dragEnter(event) {
if (!event.target.classList.contains("drag-start")) {
event.target.classList.add("drag-enter");
}
}
function dragOver(event) {
event.preventDefault();
}
function dragLeave(event) {
event.target.classList.remove("drag-enter");
}
function drop(event) {
event.preventDefault();
event.target.classList.remove("drag-enter");
const draggableElementId = event.dataTransfer.getData("text");
const droppableElementId = event.target.id;
if (draggableElementId !== droppableElementId) {
const draggableElement = document.getElementById(draggableElementId);
const droppableElementBgColor = event.target.style.backgroundColor;
const droppableElementTextContent = event.target.querySelector("span").textContent;
event.target.style.backgroundColor = draggableElement.style.backgroundColor;
event.target.querySelector("span").textContent = draggableElement.querySelector("span").textContent;
event.target.id = draggableElementId;
draggableElement.style.backgroundColor = droppableElementBgColor;
draggableElement.querySelector("span").textContent = droppableElementTextContent;
draggableElement.id = droppableElementId;
}
}
#import url('https://fonts.googleapis.com/css?family=Montserrat');
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Montserrat', sans-serif;
background-color: #eee;
color: #333;
}
.box {
width: 80px;
border: 3px solid #333;
border-radius: 0.5rem;
margin: 1.25rem;
display: inline-block;
justify-content: center;
align-items: center;
text-align: center;
font-weight: bold;
user-select: none;
cursor: move;
transition: 0.5s;
}
.box span {
pointer-events: none;
}
/* Drag and Drop Related Styling */
.drag-start {
opacity: 0.4;
}
.drag-enter {
border-style: dashed;
}
.box:nth-child(odd).drag-enter {
transform: rotate(15deg);
}
.box:nth-child(even).drag-enter {
transform: rotate(-15deg);
}
.box:nth-child(odd).drag-start {
transform: rotate(15deg) scale(0.75);
}
.box:nth-child(even).drag-start {
transform: rotate(-15deg) scale(0.75);
}
#media (max-width: 600px) {
html {
font-size: 14px;
}
.box {
width: 4rem;
height: 4rem;
margin: 0.5rem;
}
}
<div class="box student" draggable="true" style="background-color: #1DDBCA;margin:10px" id="5"><span>Seymen Ege</span></div>
<div class="box c1r1" draggable="true" style="background-color: #1DDBCA;margin:10px;display:inline-block" id=" "><span>Boş</span></div>