How to add a button that becomes active after conditions are met js - javascript

I continue to make a game on js game "Believe / Don't Believe". Assertion titles appear on the screen one by one. The user responds to each statement in turn. There are 5 statements in total. If the user clicked on the False button then the following statement appears. And if it's true then a description appears. You can go to the next question by clicking on the white circle under the headings, which turns into red if an answer has already been given to it (any), or by clicking on the Next button.
Question:
How do I add a Next button to go to the next question? Until the user has answered the question, it is not active until he gives an answer.
How to add a button that appears after the user answers all the questions (all the balls below are filled)
const data = [
{stmt: "question 1", desc: "text 1"},
{stmt: "question 2", desc: "text 2"},
{stmt: "question 3", desc: "text 3"},
];
let curStmt = 0;
function showStmt(idx) {
document.getElementById('progress-item-' + curStmt).classList.remove('current');
curStmt = idx;
document.getElementById('stmt').innerText = data[idx].stmt;
document.getElementById('desc').innerText = data[idx].desc;
document.getElementById('progress-item-' + idx).classList.add('current');
applyComplete(data[idx].complete);
}
function applyComplete(val) {
val = (val) ? true : false;
document.getElementById('desc').style.visibility = (val) ? 'visible' : 'hidden';
document.getElementById('btnTrue').disabled = val;
document.getElementById('btnFalse').disabled = val;
}
function createProgressBar() {
const parent = document.getElementById('progress');
parent.innerHTML = '';
for (let i = 0; i < data.length; i++) {
const item = document.createElement('div');
item.setAttribute('data-idx', i);
item.id = 'progress-item-' + i;
item.classList.add('item');
if (data[i].complete)
item.classList.add('complete');
parent.appendChild(item);
}
}
function btnClick(val) {
data[curStmt].complete = true;
document.getElementById('progress-item-' + curStmt).classList.add('complete');
if (val || (curStmt === data.length - 1)) {
applyComplete(true);
} else {
showStmt(curStmt + 1);
}
}
document.getElementById('progress').addEventListener(
'click',
function (e) {
if (e.target.classList.contains('item')) {
const newIdx = e.target.getAttribute('data-idx') - 0;
if (newIdx != curStmt) {
showStmt(newIdx);
}
}
},
true
);
createProgressBar();
showStmt(0);
.section {
margin: 10px 0;
}
#progress .item {
height: 10px;
width: 10px;
margin: 0 5px;
border: 2px solid red;
border-radius: 50%;
display: inline-block;
cursor: pointer;
}
#progress .item.current {
border-color: blue;
}
#progress .item.complete {
background-color: green;
}
#progress .item:not(.complete):hover {
background-color: lime;
}
<div class="section">
<div id="stmt"></div>
<div id="desc"></div>
</div>
<div class="section buttons">
<button id="btnTrue" onclick="btnClick(true)">True</button>
<button id="btnFalse" onclick="btnClick(false)">False</button>
<div>
<div id="progress" class="section"></div>

const data = [
{stmt: "question 1", desc: "text 1"},
{stmt: "question 2", desc: "text 2"},
{stmt: "question 3", desc: "text 3"},
];
let curStmt = 0;
let answered =[];
function btnNext() {
console.log('Next button clicked');
document.getElementById('btnTrue').disabled = false;
document.getElementById('btnFalse').disabled = false;
}
function btnAfterComplete() {
console.log('Completed button clicked');
}
function showStmt(idx) {
document.getElementById('progress-item-' + curStmt).classList.remove('current');
curStmt = idx;
document.getElementById('stmt').innerText = data[idx].stmt;
document.getElementById('desc').innerText = data[idx].desc;
document.getElementById('progress-item-' + idx).classList.add('current');
applyComplete(data[idx].complete);
}
function applyComplete(val) {
val = (val) ? true : false;
document.getElementById('desc').style.visibility = (val) ? 'visible' : 'hidden';
document.getElementById('btnTrue').disabled = val;
document.getElementById('btnFalse').disabled = val;
}
function createProgressBar() {
const parent = document.getElementById('progress');
parent.innerHTML = '';
for (let i = 0; i < data.length; i++) {
const item = document.createElement('div');
item.setAttribute('data-idx', i);
item.id = 'progress-item-' + i;
item.classList.add('item');
if (data[i].complete)
item.classList.add('complete');
parent.appendChild(item);
}
}
function btnClick(val) {
data[curStmt].complete = true;
answered.push(val);
document.getElementById('progress-item-' + curStmt).classList.add('complete');
if (val || (curStmt === data.length - 1)) {
applyComplete(true);
} else {
showStmt(curStmt + 1);
document.getElementById('btnTrue').disabled = true;
document.getElementById('btnFalse').disabled = true;
}
document.getElementById('btnNext').style.visibility = ((curStmt == answered.length) && (answered.length != data.length)) ? 'visible' : 'hidden';
document.getElementById('btnAfterComplete').style.visibility = (answered.length == data.length) ? 'visible' : 'hidden';
}
document.getElementById('progress').addEventListener(
'click',
function (e) {
if (e.target.classList.contains('item')) {
const newIdx = e.target.getAttribute('data-idx') - 0;
if (newIdx != curStmt) {
showStmt(newIdx);
}
}
},
true
);
createProgressBar();
showStmt(0);
.section {
margin: 10px 0;
}
#progress .item {
height: 10px;
width: 10px;
margin: 0 5px;
border: 2px solid red;
border-radius: 50%;
display: inline-block;
cursor: pointer;
}
#progress .item.current {
border-color: blue;
}
#progress .item.complete {
background-color: green;
}
#progress .item:not(.complete):hover {
background-color: lime;
}
#btnNext{
visibility: hidden;
}
#btnAfterComplete{
visibility: hidden;
}
<div class="section">
<div id="stmt"></div>
<div id="desc"></div>
</div>
<div class="section buttons">
<button id="btnTrue" onclick="btnClick(true)">True</button>
<button id="btnFalse" onclick="btnClick(false)">False</button>
<button id="btnNext" onclick="btnNext()">Next</button>
<button id="btnAfterComplete" onclick="btnAfterComplete()">Complted</button>
<div>
<div id="progress" class="section"></div>
Please check the snippet

You can do it either by modifying the disabled attribute or by adding/removing a class.I recommend using the disabled attribute.
Modifying attribute
You will want to switch between <button disabled="true"> and <button disabled="false">
With javascript, it could look like this:
if flag=1:
document.getElementById("your-btn").disabled = true;
else:
document.getElementById("your-btn").disabled = false;
Example for the same
const myFunction=()=>{
document.getElementById("your-btn").disabled = false;
}
<h1>Activate the disabled button conditionally</h1>
<button type="button" id="your-btn" disabled="false">Click Me!</button>
<button type="button" onclick="myFunction()">Click me to Activate the previous button</button>
Do tell me wether I was of any help :)

Related

How to remove an event listener and add the listener back on another element click

I am creating a simple picture matching game and I will love to make sure when the picture is clicked once, the event listener is removed, this will help me stop the user from clicking on the same image twice to get a win, and then when the user clicks on another element the listener should be added back, I tried doing this with an if statement but the listener is only removed and never added back, I decided to reload the page which somehow makes it look like a solution but I need a better solution that can help me not to reload the page but add the listener back so that the element can be clicked again after the last else if statement run.
here is the sample code below.
//Selecting query elements
const aniSpace = document.querySelector(".container");
const firstCard = document.querySelector("#fstcard");
const secondCard = document.querySelector("#sndcard");
const thirdCard = document.querySelector("#thrdcard");
const playGame = document.querySelector('#play');
const scores = document.querySelector('.scoreboard');
count = 0;
var firstIsClicked = false;
var isCat = false;
var isElephant = false;
var isDog = false;
var isButterfly = false;
var isEmpty = false;
const animatchApp = () => {
const animals = {
cat: {
image: "asset/images/cat.png",
name: "Cat"
},
dog: {
image: "asset/images/puppy.png",
name: "Dog"
},
elephant: {
image: "asset/images/elephant.png",
name: "Elephant"
},
butterfly: {
image: "asset/images/butterfly.png",
name: "butterfly"
}
}
var score = 0;
firstCard.addEventListener('click', function firstBtn() {
var type = animals.cat.name;
if (firstIsClicked === true && isCat === true) {
firstCard.innerHTML = `<img src="${animals.cat.image}">`;
firstCard.classList.add('display');
alert("You won");
score = score + 50;
console.log(score);
document.getElementById('scores').innerHTML = score;
firstIsClicked = false;
isElephant = false;
if (score >= 200){
alert("You are unstoppable, Game won.");
count = 0;
score = 0;
document.getElementById('scores').innerHTML = score;
document.getElementById('attempts').innerHTML = count;
}
firstCard.removeEventListener('click', firstBtn);
} else if (firstIsClicked === false) {
firstCard.innerHTML = `<img src="${animals.cat.image}">`;
firstCard.classList.add('display');
firstIsClicked = true;
isCat = true;
firstCard.removeEventListener('click', firstBtn);
} else if (firstIsClicked === true && isCat != true) {
alert("Not Matched");
count++;
document.getElementById('attempts').innerHTML = count;
firstCard.innerHTML = '';
secondCard.innerHTML = '';
thirdCard.innerHTML = '';
firstCard.classList.remove('display');
secondCard.classList.remove('display');
thirdCard.classList.remove('display');
firstIsClicked = false;
isCat = false;
isDog = false;
isElephant = false;
isButterfly = false;
score = 0;
document.getElementById('scores').innerHTML = score;
location.reload(true);
}
})
secondCard.addEventListener('click', function secondBtn() {
var type = animals.elephant.name;
if (firstIsClicked === true && isElephant === true) {
secondCard.innerHTML = `<img src="${animals.elephant.image}">`;
secondCard.classList.add('display');
alert("You won");
score = score + 50;
console.log(score);
document.getElementById('scores').innerHTML = score;
firstIsClicked = false;
isElephant = false;
if (score >= 200){
alert("You are unstoppable, Game won.");
count = 0;
score = 0;
document.getElementById('scores').innerHTML = score;
document.getElementById('attempts').innerHTML = count;
}
secondCard.removeEventListener('click', secondBtn);
} else if (firstIsClicked === false) {
secondCard.innerHTML = `<img src="${animals.elephant.image}">`;
secondCard.classList.add('display');
firstIsClicked = true;
isElephant = true;
secondCard.removeEventListener('click', secondBtn);
} else if (firstIsClicked === true && isElephant != true) {
alert("Not Matched");
count++;
document.getElementById('attempts').innerHTML = count;
firstCard.innerHTML = '';
secondCard.innerHTML = '';
thirdCard.innerHTML = '';
firstCard.classList.remove('display');
secondCard.classList.remove('display');
thirdCard.classList.remove('display');
firstIsClicked = false;
isCat = false;
isDog = false;
isElephant = false;
isButterfly = false;
score = 0;
document.getElementById('scores').innerHTML = score;
location.reload(true);
}
})
thirdCard.addEventListener('click', function thirdBtn() {
var type = animals.dog.name;
if (firstIsClicked === true && isDog === true) {
thirdCard.innerHTML = `<img src="${animals.dog.image}">`;
thirdCard.classList.add('display');
alert("You won");
score = score + 50;
console.log(score);
document.getElementById('scores').innerHTML = score;
firstIsClicked = false;
isDog = false;
if (score >= 200){
alert("You are unstoppable, Game won.");
count = 0;
score = 0;
document.getElementById('scores').innerHTML = score;
document.getElementById('attempts').innerHTML = count;
}
thirdCard.removeEventListener('click', thirdBtn);
} else if (firstIsClicked === false) {
thirdCard.innerHTML = `<img src="${animals.dog.image}">`;
thirdCard.classList.add('display');
firstIsClicked = true;
isDog = true;
thirdCard.removeEventListener('click', thirdBtn);
} else if (firstIsClicked === true && isDog != true) {
alert("Not Matched");
count++;
document.getElementById('attempts').innerHTML = count;
firstCard.innerHTML = '';
secondCard.innerHTML = '';
thirdCard.innerHTML = '';
firstCard.classList.remove('display');
secondCard.classList.remove('display');
thirdCard.classList.remove('display');
firstIsClicked = false;
isCat = false;
isDog = false;
isElephant = false;
isButterfly = false;
score = 0;
document.getElementById('scores').innerHTML = score;
location.reload(true);
}
})
document.getElementById('attempts').innerHTML = count;
}
animatchApp();
.h1 {
text-align: center;
background-color: azure;
background-image: url("");
}
* {
box-sizing: border-box;
}
.container {
width: 500px;
}
.card1 {
background-color: blue;
float: left;
width: 30%;
padding: 10px;
height: 150px; /* Should be removed. Only for demonstration */
border: 1px solid rgb(179, 177, 177);
transition: transform 0.8s;
transform-style: preserve-3d;
}
.card2 {
background-color: blue;
float: left;
width: 30%;
padding: 10px;
height: 150px; /* Should be removed. Only for demonstration */
border: 1px solid rgb(179, 177, 177);
transition: transform 0.8s;
transform-style: preserve-3d;}
.card3 {
background-color: blue;
float: left;
width: 30%;
padding: 10px;
height: 150px; /* Should be removed. Only for demonstration */
border: 1px solid rgb(179, 177, 177);
transition: transform 0.8s;
transform-style: preserve-3d;
}
.scoreboard {
float: left;
width: 100%;
padding: 10px;
height: 150px; /* Should be removed. Only for demonstration */
}
img {
width: 100%;
height: 100%;
background-color: white;
}
.display {
background-color: white;
transform: rotateY(180deg);
}
<div class="container">
<h1 class="h1">Animatch</h1>
<div class="first">
<div class="card1" id="fstcard"></div>
<div class="card1" id="sndcard"></div>
<div class="card1" id="thrdcard"></div>
</div>
</div>
<div class="scoreboard">
<p>
<button id="play" onclick="animatchApp()">Play</button>
<br>
Score: <span id="scores">0</span>
<br>
Failed attempts: <span id="attempts"></span>
</p>
</div>
you have to define function outside of onclick because you will need this function reference to remove or add it to eventlistener later
see a example below
function onload(){
var main = document.querySelector(".main"),
btns = main.querySelectorAll(".buttons input"),
box = main.querySelector(".box")
btns[0].addEventListener("click",function(){
box.addEventListener("click",functionForEvent)
})
btns[1].addEventListener("click",function(){
box.removeEventListener("click",functionForEvent)
})
function functionForEvent(e){
console.log("clicked")
}
}
onload()
<div class="main">
<div class="box" style="height:120px;width:120px;border:1px solid black;">Click Me</div>
<div class="buttons">
<input type="button" value="Add Event">
<input type="button" value="Remove Event">
</div>
</div>
Here is an example, that shows how to remove the click event from the item clicked and add it to the other items.
It colors the items that can be clicked green, and the item that can't be clicked red.
To keep the example short, it doesn't check, if the elements it operates on, are well defined.
function myonload() {
let elems = document.querySelectorAll('.mydiv');
for(let i = 0; i < elems.length; ++i) {
let elem = elems[i];
elem.addEventListener('click', mydiv_clicked);
}
}
function mydiv_clicked(e) {
let elems = document.querySelectorAll('.mydiv');
for(let i = 0; i < elems.length; ++i) {
let elem = elems[i];
if(elem == e.target) {
elem.removeEventListener('click', mydiv_clicked);
elem.classList.add('mycolor_clicked');
elem.classList.remove('mycolor');
// Do additional logic here
} else {
elem.addEventListener('click', mydiv_clicked);
elem.classList.remove('mycolor_clicked');
elem.classList.add('mycolor');
// Do additional logic here
}
}
}
.mydiv {
height:30px;
width: 200px;
border:1px solid black;
margin-bottom:2px;
}
.mycolor {
background-color:#00ff00;
}
.mycolor_clicked {
background-color:#ff0000;
}
<body onload="myonload()">
<div class="mydiv mycolor">First area</div>
<div class="mydiv mycolor">Second area</div>
<div class="mydiv mycolor">Third area</div>
</body>
The example shown here does not need to check if an event handler already exists, as adding the same event handler twice, replaces the existing one.
You could also add a custom attribute to your elements and toggle it, instead of adding and removing event listeners as shown here and name your attribute data-something, for example data-can-be-clicked.

Show images in quiz javascript

I'm trying to create a quiz that tests users awareness of real and fake emails. What I want to do is have the question displayed at the top saying "Real or Fake", then have an image displayed underneath which the user needs to look at to decided if it's real or fake. There are two buttons, real and fake, and regardless of whether they choose the right answer I want to swap the original image with annotated version - showing how users could spot that it was fake or real.
But I'm not sure how to show the annotated version once the answer has been submitted. Could someone help?
function Quiz(questions) {
this.score = 0;
this.questions = questions;
this.questionIndex = 0;
}
Quiz.prototype.getQuestionIndex = function() {
return this.questions[this.questionIndex];
}
Quiz.prototype.guess = function(answer) {
if (this.getQuestionIndex().isCorrectAnswer(answer)) {
this.score++;
}
this.questionIndex++;
}
Quiz.prototype.isEnded = function() {
return this.questionIndex === this.questions.length;
}
function Question(text, choices, answer) {
this.text = text;
this.choices = choices;
this.answer = answer;
}
Question.prototype.isCorrectAnswer = function(choice) {
return this.answer === choice;
}
function populate() {
if (quiz.isEnded()) {
showScores();
} else {
// show question
var element = document.getElementById("question");
element.innerHTML = quiz.getQuestionIndex().text;
// show options
var choices = quiz.getQuestionIndex().choices;
for (var i = 0; i < choices.length; i++) {
var element = document.getElementById("choice" + i);
element.innerHTML = choices[i];
guess("btn" + i, choices[i]);
}
showProgress();
}
};
function guess(id, guess) {
var button = document.getElementById(id);
button.onclick = function() {
quiz.guess(guess);
populate();
}
};
function showProgress() {
var currentQuestionNumber = quiz.questionIndex + 1;
var element = document.getElementById("progress");
element.innerHTML = "Question " + currentQuestionNumber + " of " + quiz.questions.length;
};
function showScores() {
var gameOverHTML = "<h1>Result</h1>";
gameOverHTML += "<h2 id='score'> Your scores: " + quiz.score + "</h2>";
var element = document.getElementById("quiz");
element.innerHTML = gameOverHTML;
};
// create questions here
var questions = [
new Question("<img src= 'netflix_fake.jpg' />", ["Real", "Fake"], "Fake"),
new Question("<img src= 'dropbox_real.jpg' />", ["Real", "Fake"], "Real"),
new Question("<img src= 'gov_real.jpg' />", ["Real", "Fake"], "Real"),
new Question("<img src= 'paypal_fake.jpg' />", ["Real", "Fake"], "Fake"),
new Question("<img src= 'gmail.jpg' />", ["Real", "Fake"], "Fake")
];
//create quiz
var quiz = new Quiz(questions);
// display
populate();
body {
background-color: #538a70;
}
.grid {
width: 600px;
height: 500px;
margin: 0 auto;
background-color: #fff;
padding: 10px 50px 50px 50px;
border: 2px solid #cbcbcb;
}
.grid h1 {
font-family: "sans-serif";
font-size: 60px;
text-align: center;
color: #000000;
padding: 2px 0px;
}
#score {
color: #000000;
text-align: center;
font-size: 30px;
}
.grid #question {
font-family: "monospace";
font-size: 30px;
color: #000000;
}
.buttons {
margin-top: 30px;
}
#btn0,
#btn1,
#btn2,
#btn3 {
background-color: #a0a0a0;
width: 250px;
font-size: 20px;
color: #fff;
border: 1px solid #1D3C6A;
margin: 10px 40px 10px 0px;
padding: 10px 10px;
}
#btn0:hover,
#btn1:hover,
#btn2:hover,
#btn3:hover {
cursor: pointer;
background-color: #00994d;
}
#btn0:focus,
#btn1:focus,
#btn2:focus,
#btn3:focus {
outline: 0;
}
#progress {
color: #2b2b2b;
font-size: 18px;
}
<div class="grid">
<div id="quiz">
<h1>Can you spot the fake email?</h1>
<hr style="margin-bottom: 20px">
<p id="question"></p>
<div class="buttons">
<button id="btn0"><span id="choice0"></span></button>
<button id="btn1"><span id="choice1"></span></button>
</div>
<hr style="margin-top: 50px">
<footer>
<p id="progress">Question x of y</p>
</footer>
</div>
</div>
When user clicks button I trigger class and I add it second name, on second I have written to get swapped, I wrote you basically full project, and please read the whole comments, to understand logic
//Calling Elements from DOM
const button = document.querySelectorAll(".check");
const images = document.querySelectorAll(".image");
const answer = document.querySelector("h1");
//Declaring variable to randomly insert any object there to insert source in DOM Image sources
let PreparedPhotos;
//Our Images Sources and With them are its fake or not
//fake: true - yes its fake
//fake: false - no its real
const image = [
[
{
src:
"https://upload.wikimedia.org/wikipedia/commons/thumb/e/ec/Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg/1200px-Mona_Lisa%2C_by_Leonardo_da_Vinci%2C_from_C2RMF_retouched.jpg",
fake: true
},
{
src:
"http://graphics8.nytimes.com/images/2012/04/13/world/europe/mona-lisa-like-new-images/mona-lisa-like-new-images-custom4-v3.jpg",
fake: false
}
],
[
{
src:
"https://cdn.shopify.com/s/files/1/0849/4704/files/Creacion_de_Adan__Miguel_Angel_f5adb235-bfa8-4caa-8ffb-c5328cbad953_grande.jpg?12799626327330268216",
fake: false
},
{
src:
"https://cdn.shopify.com/s/files/1/0849/4704/files/First-image_Fb-size_grande.jpg?10773543754915177139",
fake: true
}
]
];
//Genrating Random Photo on HTML
function setRandomPhoto() {
//Random Number which will be length of our array of Object
//if you array includes 20 object it will generate random number
// 0 - 19
const randomNumber = Math.floor(Math.random() * image.length);
//Decalaring our already set variable as Array Object
PreparedPhoto = image[randomNumber];
//Our first DOM Image is Variables first object source
images[0].src = PreparedPhoto[0].src;
//and next image is next object source
images[1].src = PreparedPhoto[1].src;
}
//when windows successfully loads, up function runs
window.addEventListener("load", () => {
setRandomPhoto();
});
//buttons click
//forEach is High Order method, basically this is for Loop but when you want to
//trigger click use forEach - (e) is single button whic will be clicked
button.forEach((e) => {
e.addEventListener("click", () => {
//decalring variable before using it
let filtered;
//finding from our DOM image source if in our long array exists
//same string or not as Image.src
//if it exists filtered variable get declared with that found obect
for (let i = 0; i < image.length; i++) {
for (let k = 0; k < 2; k++) {
if (image[i][k].src === images[0].src) {
filtered = image[i][k];
}
}
}
//basic if else statement, if clicked button is Fake and image is true
//it outputs You are correct
//if clicked button is Real and Image is false it outputs Correct
//Else its false
//Our image checking comes from filtered variable
if (e.innerText === "Fake" && filtered.fake === true) {
answer.innerText = "You Are Correct";
images.forEach((image) => {
image.classList.toggle("hidden");
});
} else if (e.innerText === "Real" && filtered.fake === false) {
answer.innerText = "You Are Correct";
images.forEach((image) => {
image.classList.toggle("hidden");
});
} else {
answer.innerHTML = "You are Wrong";
images.forEach((image) => {
image.classList.toggle("hidden");
});
}
});
});
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.container {
width: 100%;
min-height: 100vh;
display: flex;
justify-content: space-around;
align-items: center;
flex-direction: column;
}
.image-fluid {
display: flex;
}
.image-fluid .image {
width: 200px;
margin: 0 10px;
transition: 0.5s;
}
.image-fluid .image:nth-child(1).hidden {
transform: translateX(110px);
}
.image-fluid .image:nth-child(2).hidden {
transform: translateX(-110px);
}
<div class="container">
<div class="image-fluid">
<img src="" class="image hidden">
<img src="" class="image hidden">
</div>
<div class="button-fluid">
<button class="check">Fake</button>
<button class="check">Real</button>
</div>
</div>
<h1></h1>

JavaScript Todo List - When I click 'edit' button, it doesn't show input to be able to change a todo

I'm building a todo list in vanilla JavaScript as a part of the exercise. I'm trying to get the 'edit' option to function properly. When I click the 'edit' button, the corresponding text input should be enabled, and auto-selected, then the user should be able to press 'enter' to submit changes.
The problem is that I cannot make Edit functional. Two of the other buttons are working well.
I know that there is similar question allready, and I have tried what was in that question, and still cannot get it done. Please help guys.
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>To-do List</h1>
</header>
<input type="text" id="addTodoTextInput" onkeyup="todoButtons.addTodo()" placeholder="Add new todo" maxlength="80" autofocus>
<div>
<button onclick="todoButtons.toggleAll()">Toggle All</button>
<button onclick="todoButtons.deleteAll()">Delete All</button>
</div>
<ol>
</ol>
<script src="script.js"></script>
</body>
</html>
css
body {
display: flex;
flex-direction: column;
align-items: center;
background-color: #eee; /* Lightblue */
font-family: tahoma, sans-serif;
}
h1 {
font-weight: 100;
color: brown;
}
ol {
list-style-type: none;
padding-left: 0;
min-width: 30%;
}
li {
padding: 10px;
border-radius: 8px;
background-color: white;
box-shadow: 0 10px 50px black;
margin-top: 10px;
transition: all .3s ease;
overflow: hidden;
}
li:hover {
box-shadow: 0 10px 50px 3px black;
}
li button {
float: right;
}
button {
background-color: #bbb; /* Darkgrey */
font-weight: bold;
border-radius: 5px;
padding: 5px;
transition: all .3s ease;
cursor: pointer;
}
button:hover {
background-color: #d8d2d2; /* Grey */
color: brown;
}
/* Input for adding new todos */
#addTodoTextInput {
width: 30%;
margin-bottom: 20px;
}
js
var todoButtons = {
todos: [],
addTodo: function(e) {
// When Enter is pressed, new todo is made
if (e.keyCode === 13) {
var addTodoTextInput = document.getElementById('addTodoTextInput');
this.todos.push({
todoText: addTodoTextInput.value,
completed: false
});
// Reseting value after user input
addTodoTextInput.value = '';
todoView.displayTodos();
}
},
changeTodo: function(position, newTodoText) {
this.todos[position].todoText = newTodoText;
todoView.displayTodos();
},
deleteTodo: function(position) {
this.todos.splice(position, 1);
todoView.displayTodos();
},
toggleCompleted: function (position) {
var todo = this.todos[position];
todo.completed = !todo.completed;
todoView.displayTodos();
},
toggleAll: function() {
var totalTodos = this.todos.length;
var completedTodos = 0;
// Checks for a number of completed todos
this.todos.forEach(function(todo) {
if (todo.completed === true) {
completedTodos++;
}
});
this.todos.forEach(function(todo) {
// If all todos are true, they will be changed to false
if (completedTodos === totalTodos) {
todo.completed = false;
}
// Otherwise, they will be changed to true
else {
todo.completed = true;
}
});
todoView.displayTodos();
},
deleteAll: function() {
this.todos.splice(0, this.todos.length);
todoView.displayTodos();
}
};
// Function for displaying todos on the webpage
var todoView = {
displayTodos: function() {
var todosUl = document.querySelector('ol');
todosUl.innerHTML = '';
// Creating list element for every new todo
for (var i = 0; i < todoButtons.todos.length; i++) {
var todoLi = document.createElement('li');
var todoLiText = document.createElement('input');
todoLiText.type = "text";
todoLiText.disabled = true;
todoLiText.id = 'textInput';
var todoTextWithCompletion = todoButtons.todos[i].todoText;
if (todoButtons.todos[i].completed === true) {
todoLi.style.textDecoration = "line-through";
todoLi.style.opacity = "0.4";
todoLi.textContent = todoButtons.todoText + ' ';
}
else {
todoLi.textContent = todoButtons.todoText + ' ';
}
todoLi.id = i;
todoLiText.value = todoTextWithCompletion;
todoLi.appendChild(this.createDeleteButton());
todoLi.appendChild(this.createToggleButton());
todoLi.appendChild(this.createEditButton());
todoLi.appendChild(todoLiText);
todosUl.appendChild(todoLi);
};
},
// Method for creating Delete button for each todo
createDeleteButton: function() {
var deleteButton = document.createElement('button');
deleteButton.textContent = 'Delete';
deleteButton.className = 'deleteButton';
return deleteButton;
},
// Method for creating Toggle button for each todo
createToggleButton: function() {
var toggleButton = document.createElement('button');
toggleButton.textContent = 'Toggle';
toggleButton.className = 'toggleButton';
return toggleButton;
},
// Method for creating Edit button for each todo
createEditButton: function() {
var editButton = document.createElement('button');
editButton.textContent = 'Edit';
editButton.className = 'editButton';
return editButton;
},
// Event listeners gor the Delete, Edit and Toggle buttons
setUpEventListeners: function() {
var todosUl = document.querySelector('ol');
todosUl.addEventListener('click', function(event) {
var position = event.target.parentNode.id;
var elementClicked = event.target.className;
if (elementClicked === 'deleteButton') {
// Path to the ID of each created todo
todoButtons.deleteTodo(parseInt(position));
}
});
todosUl.addEventListener('click', function(event) {
var position = event.target.parentNode.id;
var elementClicked = event.target.className;
if (elementClicked === 'toggleButton') {
todoButtons.toggleCompleted(parseInt(position));
}
});
todosUl.addEventListener('click', function(event) {
var position = event.target.parentNode.id;
var elementClicked = event.target.className;
if (elementClicked === 'edit') {
var input = document.getElementById(position).childNodes[0];
input.disabled = false;
input.className = "activeTextInput";
input.focus();
input.select();
input.addEventListener('keyup', function(event) {
if(event.keyCode === 13) {
var textInput = input.value;
input.disabled = true;
input.classList.remove("activeTextInput");
todoButtons.changeTodo(position, textInput);
};
});
};
});
}
};
// Starting event listeners when the app starts
todoView.setUpEventListeners();
So, I looked at the code. The first problem is the condition:
if (elementClicked === 'edit') {
It should be:
if (elementClicked === 'editButton') {
The second problem was:
if (elementClicked === 'edit') {
var input = document.getElementById(position).childNodes[0]; //this line
input.disabled = false;
input.className = "activeTextInput";
It should be var input = document.getElementById(position).querySelector('input'); to get the correct element.
https://jsfiddle.net/nh9j6yw3/1/
Reason for "undefined" :
on line todoLi.textContent = todoButtons.todoText + ' ';
todoButtons.todoText is undefined.

Calculate the word amount from an <input>?

The following code converts text into equal paragraphs, based on the users input character amount.
Is it possible for the input box to calculate the amount of words for each paragraph instead of being based on the character amount?
JSFiddle
If an updated fiddle could please be provided, would be much appreciated, as I am still new to coding.
Thank You!
$(function() {
$('select').on('change', function() {
//Lets target the parent element, instead of P. P will inherit it's font size (css)
var targets = $('#content'),
property = this.dataset.property;
targets.css(property, this.value);
sameheight('#content p');
}).prop('selectedIndex', 0);
});
var btn = document.getElementById('go'),
textarea = document.getElementById('textarea1'),
content = document.getElementById('content');
chunkSize = 100;
btn.addEventListener('click', initialDistribute);
content.addEventListener('keyup', handleKey);
content.addEventListener('paste', handlePaste);
function initialDistribute() {
custom = parseInt(document.getElementById("custom").value);
chunkSize = (custom>0)?custom:chunkSize;
var text = textarea.value;
while (content.hasChildNodes()) {
content.removeChild(content.lastChild);
}
rearrange(text);
}
function rearrange(text) {
var chunks = splitText(text, false);
chunks.forEach(function(str, idx) {
para = document.createElement('P');
para.classList.add("Paragraph_CSS");
para.setAttribute('contenteditable', true);
para.textContent = str;
content.appendChild(para);
});
sameheight('#content p');
}
function handleKey(e) {
var para = e.target,
position,
key, fragment, overflow, remainingText;
key = e.which || e.keyCode || 0;
if (para.tagName != 'P') {
return;
}
if (key != 13 && key != 8) {
redistributeAuto(para);
return;
}
position = window.getSelection().getRangeAt(0).startOffset;
if (key == 13) {
fragment = para.lastChild;
overflow = fragment.textContent;
fragment.parentNode.removeChild(fragment);
remainingText = overflow + removeSiblings(para, false);
rearrange(remainingText);
}
if (key == 8 && para.previousElementSibling && position == 0) {
fragment = para.previousElementSibling;
remainingText = removeSiblings(fragment, true);
rearrange(remainingText);
}
}
function handlePaste(e) {
if (e.target.tagName != 'P') {
return;
}
overflow = e.target.textContent + removeSiblings(fragment, true);
rearrange(remainingText);
}
function redistributeAuto(para) {
var text = para.textContent,
fullText;
if (text.length > chunkSize) {
fullText = removeSiblings(para, true);
}
rearrange(fullText);
}
function removeSiblings(elem, includeCurrent) {
var text = '',
next;
if (includeCurrent && !elem.previousElementSibling) {
parent = elem.parentNode;
text = parent.textContent;
while (parent.hasChildNodes()) {
parent.removeChild(parent.lastChild);
}
} else {
elem = includeCurrent ? elem.previousElementSibling : elem;
while (next = elem.nextSibling) {
text += next.textContent;
elem.parentNode.removeChild(next);
}
}
return text;
}
function splitText(text, useRegex) {
var chunks = [],
i, textSize, boundary = 0;
if (useRegex) {
var regex = new RegExp('.{1,' + chunkSize + '}\\b', 'g');
chunks = text.match(regex) || [];
} else {
for (i = 0, textSize = text.length; i < textSize; i = boundary) {
boundary = i + chunkSize;
if (boundary <= textSize && text.charAt(boundary) == ' ') {
chunks.push(text.substring(i, boundary));
} else {
while (boundary <= textSize && text.charAt(boundary) != ' ') {
boundary++;
}
chunks.push(text.substring(i, boundary));
}
}
}
return chunks;
}
#text_land {
border: 1px solid #ccc;
padding: 25px;
margin-bottom: 30px;
}
textarea {
width: 95%;
}
label {
display: block;
width: 50%;
clear: both;
margin: 0 0 .5em;
}
label select {
width: 50%;
float: right;
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
body {
font-family: monospace;
font-size: 1em;
}
h3 {
margin: 1.2em 0;
}
div {
margin: 1.2em;
}
textarea {
width: 100%;
}
button {
padding: .5em;
}
p {
/*Here the sliles for OTHER paragraphs*/
}
#content p {
font-size: inherit;
/*So it gets the font size set on the #content div*/
padding: 1.2em .5em;
margin: 1.4em 0;
border: 1px dashed #aaa;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h3>Import Text below, then press the button</h3>
<textarea id="textarea1" placeholder="Type text here, then press the button below." rows="5">
</textarea>
<input style="width:200px;" id="custom" placeholder="Custom Characters per box">
<br>
<button style="width:200px;" id="go">Divide Text into Paragraphs</button>
</div>
<div>
<h3 align="right">Divided Text Will Appear Below:</h3>
<hr>
<div id="content"></div>
</div>
How about this? It uses jQuery, but as you used the library in your original submission, I hope that won't be an issue:
HTML
<textarea id="input"></textarea>
<br/>
<button id='divide'>Divide</button>
<div id="paras"></div>
CSS
#input {
resize: none;
height: 200px;
width: 100%;
}
JS
$(function() {
$("#divide").click(function() {
var text = $("#input").val();
var wpp = 10 // words per paragraph
var words = text.split(" ");
var paras = [];
for (i = 0; i < words.length; i += wpp) {
paras.push(words.slice(i, i + wpp).join(" "));
}
$.each(paras, function(i, para) {
$("#paras").append("<p>" + para + "</p>");
});
});
})
JSFiddle

How to Change JQuery Value Through <Input> Dynamically?

The following fiddle converts texts into paragraphs and the problem is the JQuery function attribute chunkSize = 100; currently defines the amount of characters for each divided paragraph to contain.
Is it possible for the user to be able to change this dynamically through the use of an <input> and <button> where the user would be able to type their desired characters for each dynamic paragraph and apply it?
Fiddle
If a new fiddle could please be provided, it would be very much appreciated, as I am still new to coding.
Thank You!
$(function() {
$('select').on('change', function() {
//Lets target the parent element, instead of P. P will inherit it's font size (css)
var targets = $('#content'),
property = this.dataset.property;
targets.css(property, this.value);
sameheight('#content p');
}).prop('selectedIndex', 0);
});
var btn = document.getElementById('go'),
textarea = document.getElementById('textarea1'),
content = document.getElementById('content'),
chunkSize = 100;
btn.addEventListener('click', initialDistribute);
content.addEventListener('keyup', handleKey);
content.addEventListener('paste', handlePaste);
function initialDistribute() {
var text = textarea.value;
while (content.hasChildNodes()) {
content.removeChild(content.lastChild);
}
rearrange(text);
}
function rearrange(text) {
var chunks = splitText(text, false);
chunks.forEach(function(str, idx) {
para = document.createElement('P');
para.classList.add("Paragraph_CSS");
para.setAttribute('contenteditable', true);
para.textContent = str;
content.appendChild(para);
});
sameheight('#content p');
}
function handleKey(e) {
var para = e.target,
position,
key, fragment, overflow, remainingText;
key = e.which || e.keyCode || 0;
if (para.tagName != 'P') {
return;
}
if (key != 13 && key != 8) {
redistributeAuto(para);
return;
}
position = window.getSelection().getRangeAt(0).startOffset;
if (key == 13) {
fragment = para.lastChild;
overflow = fragment.textContent;
fragment.parentNode.removeChild(fragment);
remainingText = overflow + removeSiblings(para, false);
rearrange(remainingText);
}
if (key == 8 && para.previousElementSibling && position == 0) {
fragment = para.previousElementSibling;
remainingText = removeSiblings(fragment, true);
rearrange(remainingText);
}
}
function handlePaste(e) {
if (e.target.tagName != 'P') {
return;
}
overflow = e.target.textContent + removeSiblings(fragment, true);
rearrange(remainingText);
}
function redistributeAuto(para) {
var text = para.textContent,
fullText;
if (text.length > chunkSize) {
fullText = removeSiblings(para, true);
}
rearrange(fullText);
}
function removeSiblings(elem, includeCurrent) {
var text = '',
next;
if (includeCurrent && !elem.previousElementSibling) {
parent = elem.parentNode;
text = parent.textContent;
while (parent.hasChildNodes()) {
parent.removeChild(parent.lastChild);
}
} else {
elem = includeCurrent ? elem.previousElementSibling : elem;
while (next = elem.nextSibling) {
text += next.textContent;
elem.parentNode.removeChild(next);
}
}
return text;
}
function splitText(text, useRegex) {
var chunks = [],
i, textSize, boundary = 0;
if (useRegex) {
var regex = new RegExp('.{1,' + chunkSize + '}\\b', 'g');
chunks = text.match(regex) || [];
} else {
for (i = 0, textSize = text.length; i < textSize; i = boundary) {
boundary = i + chunkSize;
if (boundary <= textSize && text.charAt(boundary) == ' ') {
chunks.push(text.substring(i, boundary));
} else {
while (boundary <= textSize && text.charAt(boundary) != ' ') {
boundary++;
}
chunks.push(text.substring(i, boundary));
}
}
}
return chunks;
}
#text_land {
border: 1px solid #ccc;
padding: 25px;
margin-bottom: 30px;
}
textarea {
width: 95%;
}
label {
display: block;
width: 50%;
clear: both;
margin: 0 0 .5em;
}
label select {
width: 50%;
float: right;
}
* {
box-sizing: border-box;
padding: 0;
margin: 0;
}
body {
font-family: monospace;
font-size: 1em;
}
h3 {
margin: 1.2em 0;
}
div {
margin: 1.2em;
}
textarea {
width: 100%;
}
button {
padding: .5em;
}
p {
/*Here the sliles for OTHER paragraphs*/
}
#content p {
font-size: inherit;
/*So it gets the font size set on the #content div*/
padding: 1.2em .5em;
margin: 1.4em 0;
border: 1px dashed #aaa;
overflow: hidden;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<h3>Import Text below, then press the button</h3>
<textarea id="textarea1" placeholder="Type text here, then press the button below." rows="5">
</textarea>
<input style="width:200px;" placeholder="Custom Characters per box">
<button>
Go
</button>
<br>
<button style="width:200px;" id="go">Divide Text into Paragraphs</button>
</div>
<div>
<h3 align="right">Divided Text Will Appear Below:</h3>
<hr>
<div id="content"></div>
</div>
Give an id for your input.
<input id="custom" placeholder="Custom Characters per box" style="width:200px;">
Add below code into initialDistribute function.
custom = parseInt(document.getElementById("custom").value); //Get value of the input.
chunkSize = (custom>0)?custom:100; //If Custom value is more than `0`, take that as `chunkSize` value else `100`
See Fiddle
You can use input type="number" element, button element; set chunkSize to input type="number" valueAsNumber property at click of button
html
<label>chunkSize:<input class="chunkSize" type="number" /></label>
<button class="chunkSize">
Set chunkSize
</button>
javascript
$("button.chunkSize").click(function(e) {
var _chunkSize = $("input.chunkSize")[0].valueAsNumber;
chunkSize = _chunkSize;
})
jsfiddle https://jsfiddle.net/csz0ggsw/11/

Categories