JavaScript Input Field Not Being Recognized - javascript

I have a basic word scramble game (not styled yet), that works fine on an HTML page.
When I bring that exact code over to a blogger post it stops working.
I can enter text into the text field but on pressing the "Check Word" button it throws back a "Please enter the word to check" even though I have entered a word to check.
Everything else seems to work correctly on blogger (Refresh button, counter, hint, etc.)
The code is as follows...
let words = [
{
word: "addition",
hint: "The process of adding numbers"
},
{
word: "meeting",
hint: "Event in which people come together"
},
{
word: "number",
hint: "Math symbol used for counting"
},
{
word: "exchange",
hint: "The act of trading"
},
]
const wordText = document.querySelector(".word"),
hintText = document.querySelector(".hint span"),
timeText = document.querySelector(".time b"),
inputField = document.querySelector("input"),
refreshBtn = document.querySelector(".refresh-word"),
checkBtn = document.querySelector(".check-word");
let correctWord, timer;
const initTimer = maxTime => {
clearInterval(timer);
timer = setInterval(() => {
if(maxTime > 0) {
maxTime--;
return timeText.innerText = maxTime;
}
alert(`Time off! ${correctWord.toUpperCase()} was the correct word`);
initGame();
}, 1000);
}
const initGame = () => {
initTimer(20);
let randomObj = words[Math.floor(Math.random() * words.length)];
let wordArray = randomObj.word.split("");
for (let i = wordArray.length - 1; i > 0; i--) {
let j = Math.floor(Math.random() * (i + 1));
[wordArray[i], wordArray[j]] = [wordArray[j], wordArray[i]];
}
wordText.innerText = wordArray.join("");
hintText.innerText = randomObj.hint;
correctWord = randomObj.word.toLowerCase();;
inputField.value = "";
inputField.setAttribute("maxlength", correctWord.length);
}
initGame();
const checkWord = () => {
let userWord = inputField.value.toLowerCase();
if(!userWord) return alert("Please enter the word to check!");
if(userWord !== correctWord) return alert(`Oops! ${userWord} is not a correct word`);
alert(`Congrats! ${correctWord.toUpperCase()} is the correct word`);
initGame();
}
refreshBtn.addEventListener("click", initGame);
checkBtn.addEventListener("click", checkWord);
<div class="Gamecontainer">
<h2>Word Scramble</h2>
<div class="content">
<p class="word"></p>
<div class="details">
<p class="hint">Hint: <span></span></p>
<p class="time">Time Left: <span><b>20</b>s</span></p>
</div>
<input spellcheck="false" type="text" />
<div class="buttons">
<button class="refresh-word">Refresh Word</button>
<button class="check-word">Check Word</button>
</div>
</div>
</div>
Any suggestions?

This is because you use querySelector("input") which selects first found input element on the page. Blogger post has multiple input elements therefore your code selects a wrong element. Use IDs or classes to better identify your html elements.
For example you can narrow the query to your html part by using:
inputField = document.querySelector(".Gamecontainer input")

Related

How to disable a button until all the input fields are filled using only JavaScript?

I am creating a quiz game, but I only want the user to be able to submit if all of the input fields are filled out using only JavaScript. I saw other similar questions on StackOverflow that used jquery, but I want to only use JavaScript.
html (Django template)
<h1 class="all_headings" id="quiz_title">{{ quiz.title }}</h1>
<h4 class="quiz_description">By: {{ quiz.user }}</h4>
<h4 class="quiz_description">Created On: {{ quiz.date_and_time }}</h4>
<br>
{% for q in quiz_questions %}
<h3 class="quiz_questions">{{q.1}}
<input type="text" id="id_question{{q.0}}" class="input">
</h3>
<div id="div{{ q.0 }}"></div>
<br>
<br>
{% endfor %}
<input type="submit" value="Submit" class="button quiz_button" id="{{ quiz.id }}">
<h2 id="score"></h2>
<input type="hidden" id="user_id" value="{{ request.user.id }}">
<input type="hidden" id="user_points" value="{{ request.user.points }}">
{% if request.user.is_anonymous %}
<h3 class="all_headings">Join now to earn 10 points for every question you answer correctly!</h3>
{% endif %}
Update: I added the entire Django template code so that you can see what is going on.
current JavaScript
function bindText(e){
const required = [...document.querySelectorAll(".inputs")];
required.forEach(input => input.oninput = checkText);
}
function checkText(e){
const required = [...document.querySelectorAll(".inputs")];
const button = document.getElementsByClassName(".quiz_button");
button.disabled = !required.every(input => input.value.length > 0);
}
document.addEventListener('DOMContentLoaded', function(){
//gets all the quiz_buttons enableChecking();
const quizButton = document.querySelectorAll('.quiz_button');
for (const button of quizButton){
button.addEventListener('click', (event) => check_quiz(event.target.id));
}
})
function check_quiz(id){
console.log("button is clicked");
//get answers
let response1 = document.getElementById('id_question1').value.toUpperCase().replace(/\s/g, "");
let response2 = document.getElementById('id_question2').value.toUpperCase().replace(/\s/g, "");
//repeats 8 more times
//get divs
let div1 = document.getElementById('div1');
let div2 = document.getElementById('div2');
//repeats 8 more times
var correctAnswers = 0;
//get quiz
fetch(`/check/${id}`)
.then(response => response.json())
.then(quiz => {
rightM = "You got this correct. Great job!";
//checking if the answers are right
//#1
let answ1 = quiz.answer1.toUpperCase().replace(/\s/g, "");
if(answ1 === response1){
div1.innerHTML = rightM;
div1.classList.add("correct");
correctAnswers++;
} else{
div1.innerHTML = `The correct answer is ${quiz.answer1}. Nice try!`;
div1.classList.add("incorrect");
}
//#2
let answ2 = quiz.answer1.toUpperCase().replace(/\s/g, "");
if(answ2 === response2){
div2.innerHTML = rightM;
div2.classList.add("correct");
correctAnswers++;
} else{
div2.innerHTML = `The correct answer is ${quiz.answer2}. Nice try!`;
div2.classList.add("incorrect");
}
//repeats 8 more times
console.log(correctAnswers)
//display score
let score = document.getElementById("score");
score.innerHTML = `Your score is ${correctAnswers}. Great job! :)`;
score.classList.add("score_style");
//points
let newPoints = correctAnswers * 10;
let currentUser = parseInt(document.getElementById("user_id").value);
let currentPoints = parseInt(document.getElementById("user_points").value);
let numOfPoints = currentPoints + newPoints;
console.log(numOfPoints);
fetch(`/points/${currentUser}`,{
method: "PUT",
body: JSON.stringify({
points: numOfPoints
})
})
})
}
I updated this with my current code and fixed all the errors from Update 2 of the answer, but the submit button still does not work when it is pressed.
Update 2
You need to go to JSHint and debug your code frequently. In Update 2 I have corrected as much as I care to. Before I can help you any further, you need to address the issues marked with a ❓.
Mark
Description
Corrected
❌
There are 12 typos, even if there was only one ❌ it would FUBAR whatever follows it.
Yes
❓
There are 5 questionable areas which will most likely need to be addressed because it may cause problems later on, or is pointless, etc.
No
🚩
Areas that could be modified to be more efficient, succinct, etc.
No
⭕
Areas that are modified to be more efficient, succinct, etc.
Yes
In Example D I placed where my code should go. There's always the chance that none of it may work because of Django. I have no idea, but on the surface it doesn't look debilitating.
Concerning <form>s, they are the the backbone of most interactive webpages but not necessary if you have other means such as fetch(). That is true in your case which means that you don't trigger "submit" events and you don't need a type="submit" unless there's something Django does that I'm ignorant to.
It isn't obvious to me how the HTML layout is exactly. I'm not certain whether there's one button (good) or multiple buttons (a very critical detail to know from the start).
Example D
document.addEventListener('DOMContentLoaded', bindText);
function bindText(e) {
const required = [...document.querySelectorAll(".inputs")];
required.forEach(input => input.oninput = checkText);
}
function checkText(e) {
/*❌: = Does not belong at end of line */
const required = [...document.querySelectorAll(".inputs")];
/*❌: `${id}` NOT "${id}"|BUT `${id}` === id */
/*❓: Is id declared elsewhere? If not, use it's actual "idOfButton".
If you have multiple submit buttons then you should reassess
your strategy.
*/
const button = document.getElementById(id);
/*❌: = missing */
button.disabled = !required.every(input => input.value.length > 0);
}
/*❌: '...' or "..." NOT "...' */
document.addEventListener('DOMContentLoaded', function() {
/*❌: = : ' missing */
const quizButton = document.querySelectorAll('.quiz_button');
for (const button of quizButton) {
/*⭕: In event handlers/listeners if it is a named function that's
defined separately, remove the ()
*/
button.addEventListener('click', (event) => checkQuiz);
}
});
/*⭕: Event handlers pass the (e)vent object by default */
function checkQuiz(e) {
const id = e.target.id;
/*❌: / missing a \ needs to be escaped: \\ */
/*❌: response* number 1 NOT letter l */
let response1 = document.getElementById('id_question1').value.toUpperCase().replace(/\\/g, "");
/*❌: / missing a \ needs to be escaped: \\ */
let response2 = document.getElementById('id_question2').value.toUpperCase().replace(/\\/g, "");
/*❓: Are sure there's a <div id="div">? */
let div1 = document.getElementById('div');
/*❌: '...' or '..." NOT '..." */
let div2 = document.getElementById('div2');
/*❓: var hoists to be global use let or const. In this case let
is the best choice
*/
var correctAnswers = 0;
fetch(`/check/${id}`)
.then(response => response.json())
.then(quiz => {
/*❓: Is rightM declared elsewhere? If not,
use let or const
*/
rightM = "You got this correct. Great job!";
let answ1 = quiz.answer1.toUpperCase().replace(/\s/g, "");
if (answ1 === response1) {
div1.innerHTML = rightM;
div1.classList.add("correct");
correctAnswers++;
} else {
div1.innerHTML = `The correct answer is ${quiz.answer1}. Nice try!`;
div1.classList.add("incorrect");
}
let answ2 = quiz.answer1.toUpperCase().replace(/\s/g, "");
if (answ2 === response2) {
div2.innerHTML = rightM;
div2.classList.add("correct");
correctAnswers++;
} else {
div2.innerHTML = `The correct answer is ${quiz.answer2}. Nice try!`;
div2.classList.add("incorrect");
}
/*🚩: DRY = Don't Reapeat Yourself. Iterate through quiz.answer1 with
a loop or an array method.
*/
//this repeats 8 more times
console.log(correctAnswers);
let score = document.getElementById("score");
/*❌: ` missing */
/*❌: $' '{ space between $ and { breaks interpolation */
score.innerHTML = `
Your score is ${correctAnswers}.Great job!:)`;
score.classList.add("score_style");
/*❓: is newPoint declare elsewhere? If not use let or const */
newPoints = correctAnswers * 10;
let currentUser = parseInt(document.getElementById("user_id").value);
let currentPoints = parseInt(document.getElementById("user_points").value);
let numOfPoints = currentPoints + newPoints;
/*❌: ` missing*/
fetch(`/points/${currentUser}`, {
method: "PUT",
body: JSON.stringify({
points: numOfPoints
})
});
});
}
Update 1
As requested examples B and C include JavaScript that'll enable a disabled <button> when all <input>have text.
If you have a <form> wrapped around everything (which is very simple to do if you don't), add required to all of the <input> -- that'll prevent the <form> from being submitted should there be any blank <input>s (see Example A).
Example A - Has no JavaScript or CSS -- just HTML. The <button> isn't disabled, but the <form> will not allow itself to be submitted if any <input> is blank.
Example B - Has a <form> and uses HTMLFormElement and HTMLFormControlsCollection interfaces which facilitates the use of form controls.
Example C - Is a less elegant solution involving standard DOM manipulation.
Note that in Example B the event handler is bound to the <form> and that it is shared by each <input>. Should any form control be added to the <form> later on, the event handling will apply to it as well. In Example C each <input> has the input bound to them individually. Should any form control be added later on they'll need to have their own event handler/listener attached after they have been created.
Examples B and C have commented details
Example A
<form>
<input required value='XXXXXXXXXXX'><br>
<input required value='XXXXXXXXXXX'><br>
<input required placeholder='Enter text here'><br>
<button>Submit</button>
</form>
Example B
// Reference the <form>
const F = document.forms[0];
// Reference all form controls
const fc = F.elements;
// Collect all name='required' into a HTMLCollection, convert it into an array
const required = [...fc.required];
// Reference the <button>
const done = fc.done;
/**
* Bind input event to <form>...
* ...enable the <button> if .every() <input> has a value
*/
F.oninput = e =>
done.disabled = !required.every(input => input.value.length > 0);
<form>
<input name='required' value='XXXXXXXXXXX'><br>
<input name='required' value='XXXXXXXXXXX'><br>
<input name='required' placeholder='Enter text here'><br>
<button id='done' disabled>Done</button>
</form>
Example C
// Collect all .required into a NodeList, convert it into an array
const required = [...document.querySelectorAll('.required')];
// Reference the <button>
const done = document.getElementById('done');
/**
* Bind the input event to each <input>...
* ...<button> is enabled if .every() <input> has a value
*/
required.forEach(input => input.oninput = e =>
done.disabled = !required.every(input => input.value.length > 0));
<form>
<input class='required' value='XXXXXXXXXXX'><br>
<input class='required' value='XXXXXXXXXXX'><br>
<input class='required' placeholder='Enter text here'><br>
<button id='done' disabled>Done</button>
</form>

Each click add some data from object to div

I have a button and empty div in HTML.
<button id="add_sentence">Click here!</button>
<div id="parent"></div>
In JS, I have data in array
let data = [{ sentence: "Hi, I'm from Azerbaijan" }, {sentence: "I'm 36 years old"}, { sentence: "I learn front-end development}]
I need a function that when I click on button ("#add_sentence"), it takes only one sentence from array ("data") and adds to div ("#parent").
I can add all array to empty div with 1 click. But I want 1st click adds 1st sentence. Then, 2nd click adds 2nd sentence. 3rd click adds 3rd sentence and so on.
Can anyone help?
let data = [{ sentence: "Hi, I'm from Azerbaijan" }, {sentence: "I'm 36 years old"}, { sentence: "I learn fron-end development"}];
const button = document.querySelector("#add_sentence");
const parent = document.querySelector("#parent");
let clickCount = 0;
button.addEventListener('click', () => {
if (clickCount < data.length) {
const nextSentence = document.createElement('p');
nextSentence.innerText = data[clickCount].sentence;
parent.appendChild(nextSentence);
clickCount++;
}
})
<button id="add_sentence">Click here!</button>
<div id="parent"></div>
Without clickcount...
var data = [{ sentence: "Hi, I'm from Azerbaijan" }, {sentence: "I'm 36 years old"}, { sentence: "I learn front-end development"}],
prnt = document.getElementById("parent"),
bttn = document.getElementById("add_sentence");
bttn.addEventListener("click", _ => data.length && (prnt.textContent += `${data.shift().sentence}
`));
#parent { white-space: pre;
}
<button id="add_sentence">Click here!</button>
<div id="parent"></div>

Word js : matchCase search option is not working as expected

I am trying to search a word which is initial caps but matchCase search option is not working as expected. below is my code :
textToHighlight = "Deed";
var rangeCol = para.search(textToHighlight, { matchCase: true});
Paragraph Text : Seller shall convey title to the Property to Buyer by grant deed in the form of letter("Deed").
It always returns first instance of deed which is non caps.
Thanks
See the snippet below, it's working as expected. Are you trying to do something else?
let para = "[...] to Buyer by grant deed in the form of letter"
textToHighlight = "Deed";
var rangeCol = para.search(textToHighlight, { matchCase: true});
console.log(rangeCol); // -1, not found
para = "[...] to Buyer by grant Deed in the form of letter"
textToHighlight = "Deed";
var rangeCol = para.search(textToHighlight, { matchCase: true});
console.log(rangeCol); // 24, found
In terms of highlighting the text with vanilla JavaScript, I've come up with the following:
let _text = text.innerText;
button.addEventListener("click", () => {
text.innerText = _text;
let textToHighlight = input.value;
var rangeCol = text.innerText.search(textToHighlight, {
matchCase: true,
});
let node = text.childNodes[0];
let spaces = node.textContent.match(/^\s*/)[0].length;
let range = new Range();
range.setStart(node, spaces + rangeCol);
range.setEnd(node, spaces + rangeCol + textToHighlight.length);
const mark = document.createElement("mark");
range.surroundContents(mark);
});
#text {
margin: 10px 0;
}
mark {
background-color: yellow;
}
<div id="text">
Seller shall convey title to the Property to Buyer by grant deed in the form of letter("Deed").
</div>
<input id="input" type="text" />
<button id="button">Highlight</button>

How to add task to current method?

I am trying to do a web app similar to google calendar. I have done the object and methods within it but now it's time to be able to add what I want as a task. My idea is for the user to add something to the input and that input being console.logged for now.
Any idea?
HTML
<div class="new-task" id="task-input">
<div id="add-new-task">Task: <input type="text"></div>
<div id="add-time">Time: <input type="text"></div>
<button class ="save-task" onclick="">Save task</button>
</div>
Javascript
var idCounter = 0
var tasksManager = {
array: [],
add: function(task){
taskObject = {
title: task,
idVerification: idCounter ++
}
tasksManager.array.push(taskObject)
},
show:function(id){
var i;
for (i = 0; i < tasksManager.array.length; i++) {
if(id === tasksManager.array[i].idVerification){
return tasksManager.array[i]
}
}
},
delete:function(task){
if(this.show){
tasksManager.array.splice(task)
}
}
}
var newTask = document.getElementById("add-new-task")
newTask.addEventListener('click',tasksManager.add())
console.log(tasksManager.array)
As you can see with console.log above the array index [0] is logged as undefined but I wanted the user to write in the input " Go to the gym" and this to be logged within the array.
Thanks
Some issues:
You are not assigning the click handler. Instead you execute it immediately (not on click).
When you call .add() you don't provide an argument: the name of the task
The click handler should be on the button element, not on the div that has the input element. And so it will be useful to give that button an id attribute.
You should retrieve the value from the input element, and so it would be more appropriate to give that element an id and not so much the div that wraps it.
The console.log at the end of your script is executed immediately. It should be done only when the user has clicked the button.
Snippet with some corrections (also in the HTML!):
var idCounter = 0
var tasksManager = {
array: [],
add: function(task){
let taskObject = {
title: task,
idVerification: idCounter ++
}
tasksManager.array.push(taskObject)
},
show:function(id){
var i;
for (i = 0; i < tasksManager.array.length; i++) {
if(id === tasksManager.array[i].idVerification){
return tasksManager.array[i]
}
}
},
delete:function(task){
if(this.show){
tasksManager.array.splice(task)
}
}
}
var button = document.getElementById("save-task"); // <-- the button
var input = document.getElementById("add-new-task"); // <-- the input (move the ID attribute to the input!)
button.addEventListener('click', () => {
tasksManager.add(input.value);
console.log(tasksManager.array)
})
<div class="new-task" id="task-input">
<div >Task: <input id="add-new-task" type="text"></div>
<div id="add-time">Time: <input type="text"></div>
<button class ="save-task" id ="save-task" onclick="">Save task</button>
</div>

setting variable value on click

Im new in programming and im trying to make my first project in js - hangman game (https://en.wikipedia.org/wiki/Hangman_(game))
So basically i got two buttons in my HTML file, lets say its look like this:
<button id="movies">Movies</button>
<button id="animals">Animals</button>
i want this buttons to be responsible for changing categories in my game. In js i got:
var movies = ["Shawshank Redemption","Alice in a Wonderland"];
var animals = ["Blue whale","Raspberry Crazy-Ant"];
var choice = 1;
if (choice === 0){
var pwdDraw = Math.floor(Math.random() * movies.length);
var pwd = movies[pwdDraw];
pwd = pwd.toUpperCase();
document.write(pwd);
}
else if (choice === 1){
var pwdDraw = Math.floor(Math.random() * animals.length);
var pwd = animals[pwdDraw];
pwd = pwd.toUpperCase();
document.write(pwd);
}
and this is the place where im stucked, i dont know how change var choice by clicking button (also i want to reload page after click). Im at the beginning on my way with js, so i want this code to be pure js, not any customized library.
<button onclick="changeCategory(number)">Click me</button>
<script>
function changeCategory() {
//[..]
}
</script>
https://www.w3schools.com/jsref/event_onclick.asp
thanks a lot for feedback, but i still have some troubles of implementing this js changes, When im doing it on new file with only category changer everything is running smooth. But when i try to add this to my existing code its doesnt work at all. Here you got my code:
codepen.io/iSanox/project/editor/DGpRrY/
First of all, don't put those <br> in JS code like that.
If you want to try to get the choice by clicking on the button then here's how you can do it:
HTML
<button id="movies" class="choice" value="0">Movies</button>
<br/>
<button id="animals" class="choice" value="1">Animals</button>
JS
var buttons = document.querySelectorAll(".choice");
function doSomething(e)
{
// You can get choice value by either doing:
var choice = e.target.value;
// OR
var choice = this.value;
// Continue your work here
}
for(var i = 0; i < buttons.length; i++)
{
buttons[i].addEventListener("click", doSomething);
}
Feel free to ask any questions.
Simply you can use onclick event. After some changes your code should look like this.
var movies = ["Shawshank Redemption", "Alice in a Wonderland"];
var animals = ["Blue whale", "Raspberry Crazy-Ant"];
var catname = document.getElementById('cat-name');
function selectCategory(choice) {
var pwd, pwdDraw;
if (choice === 0) {
pwdDraw = Math.floor(Math.random() * movies.length);
pwd = movies[pwdDraw];
} else if (choice === 1) {
pwdDraw = Math.floor(Math.random() * animals.length);
pwd = animals[pwdDraw];
}
pwd = pwd.toUpperCase();
catname.innerText = pwd;
}
<p>Choose Category</p>
<button id="movies" onclick="selectCategory(0)">Movies</button>
<button id="animals" onclick="selectCategory(1)">Animals</button>
<div id="cat-name"></div>
Even better with Object and Arrays
var categories = {
movies: ["Shawshank Redemption", "Alice in a Wonderland"],
animals: ["Blue whale", "Raspberry Crazy-Ant"]
};
var catname = document.getElementById('cat-name');
function selectCategory(choice) {
var pwdDraw = Math.floor(Math.random() * categories[choice].length);
var pwd = categories[choice][pwdDraw];
pwd = pwd.toUpperCase();
catname.innerText = pwd;
}
<p>Choose Category</p>
<button id="movies" onclick="selectCategory('movies')">Movies</button>
<button id="animals" onclick="selectCategory('animals')">Animals</button>
<div id="cat-name"></div>

Categories

Resources