I've just started to learn some basics of javascript so I'm still confused about several concepts.
I'm hoping some of you can kindly help me with this simple question about nodelist and everything.
I was trying to write code to make a program similar to 'wordle' and I got curious how the code below work well.
<input class="input">
<input class="input">
<input class="input">
<input class="input">
<input class="input">
<button>submit</button>
<script>
let answer = 'abcde';
document.querySelector('button').addEventListener('click', function () {
var input = document.querySelectorAll('.input');
for (let i = 0; i < 5; i++) {
if (input[i].value == answer[i]) {
input[i].style.background = 'green';
} else if (answer.includes(input[i].value)) {
input[i].style.background = 'yellow';
} else {
input[i].style.backgrouond = 'lightgrey';
}
</script>
I thought that querySelectorAll('.input') would return a nodelist composed of 5 input elements.
So I was going to put a code like input[0][0] to access the first character of the first string of the list, but without an extra [0] it worked fine.
That's what confuses me now.
And plus, can anyone tell me what .value does?
what is this property (or method maybe..?) doing here?
To get the first character of the first input value, you need to use the following:
const inputs = document.querySelectorAll('.input');
const firstInputValue = inputs[0].value;
const firstCharacter = firstInputValue[0];
After getting all the elements with class "input", you get the value of the first element in the NodeList and then take the first character of that input.
The value property is used to get or set the input value of the input field. Take a look at this for more information.
Related
I'm new to programming and I made a sort of quiz thingy that has 10 input areas on a page. Using javascript I want to be able to verify the typed answer and give a point for correct and no point for incorrect.
html:
<div>
<h1>Postal knowledge test. Write all the answers in lowercase, no spaces!</h1><br><br>
<h5>Who do you play as in Postal 2?</h5><br>
<input type="text" id="maincharacter"><br>
<h5>Who is the voice actor for the character you play as?</h5><br>
<input type="text" id="voiceactor"><br>
<h5>How many days are there in Postal 2?</h5><br>
<input type="number" id="days"><br>
<h5>What do you need to retrieve from the Factory?</h5><br>
<input type="text" id="factory"><br>
<h5>On what day do you need to piss on your dads grave?</h5><br>
<input type="text" id="dadgrave"><br>
<h5>What weapon spawns in the shed in front of you on Monday?</h5><br>
<input type="text" id="weapon"><br>
<h5>What female animal is the wife named after?</h5><br>
<input type="text" id="wife"><br>
<h5>What's uncles name?</h5><br>
<input type="text" id="uncle"><br>
<h5>What item gives you 125 health?</h5><br>
<input type="text" id="health"><br>
<h5>How many official Postal games are there?</h5><br>
<input type="number" id="games"><br><br>
<button id="checkanswers" type="button" onclick="answer()">Check how many questions you got correct</button><br>
<h5 id="answer"></h5>
</div>
javascript:
function answer() {
const q1 = document.getElementById("maincharacter");
let qq1 = q1.value;
const q2 = document.getElementById("voiceactor");
let qq2 = q1.value;
const q3 = document.getElementById("days");
let qq3 = q1.valueAsNumber;
const q4 = document.getElementById("factory");
let qq4 = q1.value;
const q5 = document.getElementById("dadgrave");
let qq5 = q1.value;
const q6 = document.getElementById("weapon");
let qq6 = q1.value;
const q7 = document.getElementById("wife");
let qq7 = q1.value;
const q8 = document.getElementById("uncle");
let qq8 = q1.value;
const q9 = document.getElementById("health");
let qq9 = q1.value;
const q10 = document.getElementById("games");
let qq10 = q1.valueAsNumber;
}
What my original plan was, was to check the answer using an if statement i.e.:
//first question checker
var p1;
if (qq1 == "postaldude") {
p1 = 1;
}
else {
p1 = 0;
}
document.getElementById("answer").innerHTML = p1;
p1 being given the value 1 or 0 depending if the answer is correct or not, then being added up with the other question results in the innerHTML i.e.: p1 + p2 + p3 + p4 + p5... ;
but this doesn't work as you can't have more than 1 if statement, so if I try to add more of these it simply doesn't work. I tried using else if but I can't get it to work.
I am unsure if there is a way to what I'm trying to do work or if there is a fully different method of doing it. Sorry if my code is very basic, this is what I've learned so far. Anyhow any tips or explanation would be greatly appreciated, Thanks!
What I tried:
I tried adding 10 if else statements for each question i.e.:
if (...) {
...;
}
else {
...;
}
if (...) {
...;
}
else {
...;
}
if (...) {
...;
}
else {
...;
}
if (...) {
...;
}
else {
...;
}
...
but unsurprisingly that didn't work. I also tried doing what I did above but making them all 'else if' but that didn't work either.
Hi
There is no problem in adding multiple if statements, but you can do the same in a scalable way.
Save question input ids and answers in an object (you can use Map also)
const idAnswersMap = {
"maincharacter": "postaldude",
"voiceactor": "answer"
}
checkout for-in loop for looping through objects
get answer for each input, compare with actual answer and sum in the same loop
Don't ever forget to name variables based on their use, it will help you afterwards big time.
let totalCorrect = 0;
for (let id in idAnswersMap) {
// get answer for each input
const answer = document.getElementById(id).value;
if (answer === idAnswersMap[id]) {
totalCorrect++;
}
}
totalCorrect now holds what you need.
First, add a class to each of the inputs so you can simplify the checking.
E.G <input type="text" class="question" id="maincharacter">
Now, javascript canlook like this. Where answer_sheet will have a key for each input matching the ID.
// Select all elements with class 'question' and assign them to the variable 'questions'
const questions = document.querySelectorAll(".question");
// Define a constant object 'answer_sheet' containing key-value pairs of questions and answers
const answer_sheet = {
"maincharacter": "postaldude"
};
function answer() {
// Initialize score to 0
var score = 0;
// Iterate through each question element
questions.forEach((question) => {
// Check if the question id exists in the answer sheet
if(!(question.id in answer_sheet)) return;
// Store the value of question in lowercase
var questionValue = question.value.toLowerCase();
// Store the value of answer in lowercase
var answerValue = answer_sheet[question.id].toLowerCase();
// Compare the question value and answer value
if(questionValue == answerValue) {
// if they match increase the score
score++;
}
});
// Show the score using an alert
alert("Score: " + score);
}
Please note that anyone can inspect the code on the page and see the answer sheet as given, so this isn't very secure.
To get around this, you would probably utilize a technology like Ajax to send a list of the answers the user provided to a separate PHP script to process the answers, but it's a bit out of scope of your question.
There is an object with keys whose values are text, and this text should appear in the placeholder of the search page on the site. The first key is written one letter at a time until the whole word is created, and then, one letter at a time, it is completely deleted, and the second key is written in the same way in placeholder. The dialing speed does not matter.
I am enclosing my work. Now the problem is that all the keys are written, but they must take turns, deleting the previous one by letter.
let types={
phrase1:"Words",
phrase2:"has been",
phrase3:"deleted",
};
function writer() {
let curr = 0;
let text = Object.values(types)
let elem = document.getElementsByClassName('topnav');
elem.textContent += text.charAt(curr);
curr++
if (curr < text.length )
window.setInterval(writer,60);
}
writer();
<div class="topnav">
<input type="text" placeholder=" ">
</div>
Solution
call setTimeout() because it will call the method once whereas setIntervall() will call it repetitive what doesn't make sense here because you will call it in your next function call again.
use recursion to get the next word of your array
Defined three cases here
current letter < wordsArray.length apply method on the same element of the array
When 1 is false and value < wordsArray apply method on the next array element writer(value+1)
1 and 2 are false then print out the content of the array as string
let types = {
phrase1: "Words",
phrase2: "has been",
phrase3: "deleted",
};
var curr = 0;
function writer(value) {
let inp = document.getElementById("text");
let wordArray = Object.values(types)
let sentence = wordArray[value];
inp.placeholder = sentence.charAt(curr);
curr++;
if (curr < sentence.length){
window.setTimeout(function() {
writer(value);
}, 500);
}else if(value < wordArray.length-1){
window.setTimeout(function() {
curr = 0;
inp.placeholder = " ";
writer(value+1);
}, 500)
}else {
inp.placeholder = wordArray.join().replaceAll(",", " ");
}
}
writer(0);
<div class="topnav">
<input id="text" type="text" placeholder=" ">
</div>
I've made a demo, from the very little you could piece together from your question. You really didn't specify anything... BUT I would like to add that the types variable should be an Array and not an Object which makes it much easier to work with. Nonetheless, I did work with your provided code:
const types = {
phrase1:"Words",
phrase2:"has been",
phrase3:"deleted",
}
const inputElm = document.querySelector('.topnav > input')
function iteratePlaceholder(place = 1) {
inputElm.placeholder = types[`phrase${place||1}`];
// call this function again only if "place" is less than the length of keys (3)
(place < Object.keys(types).length) && setTimeout(iteratePlaceholder, 500, ++place)
}
iteratePlaceholder()
<div class="topnav">
<input type="text" placeholder=" ">
</div>
I'm having a problem trying to iterate through an array of questions properly when I try to write them to the document.
The first block of code I have included below is essentially what I'm trying to achieve except I'd like to it without prompts.
I created an array called question[] that stores 3 question strings right now. The for loop with prompt(question[i]) takes each question in question[] and prompts the user to answer it. It then pushes that value to another array I made called character[].
I've tried a couple different methods to get this done using the .append method, but to no avail unfortunately and I think I can pinpoint my pitfalls to a few different areas.
In the the last blocks of code, I attempted to append the questions from question[] onto the page, and to then have the document listen for the input value to be changed, or for the Enter (key 13) to be pressed.
Also, let it be known that I have wrapped all of this in the following function:
$(document).ready(function(){...}
var question = [
'<br> What is your name?',
'<br> Are you man or woman?',
'<br> What is your class?'
];
var character = [];
//For Loop Using prompt()
for (i = 0; i < question.length; i++) {
var input = prompt(question[i]);
character.push(input);
alert(character[i]);
}
//For Loop Attempting to Use HTML '<input>'
<input id="user-input" placeholder="Type Here"></input>
for (i = 0; i < question.length; i++) {
$('#game-text').append(question[i]);
$('#user-input').onchange = function() {
var userInput = input.value;
character.push(userInput);
}
}
OR
for (i = 0; i < question.length; i++) {
$('#game-text').append(question[i]);
$(document).keypress(function(key){
if(key.which === 13 && $('#user-input').is(':focus')) {
var input = $('#user-input').val();
character.push(input);
}
})
Instead of getting the loop displaying one question at a time, I'll have the loop display all questions at once and I can't seem to get it take in user input either.
I'm really not sure how to approach or what exactly the knowledge I'm missing is as I can't seem to find an answer to this online.
Again, to summarize my question is this:
How can I ask a question from an array on the page itself, have the page wait for a response, store that response in another array then do that again until I've gone through the entire array?
Thank you so much for your time! I would very much appreciate the help!
You could use a recursive approach, wrapping the logic to ask a question inside a function, and when this process is done, then call again this function with the next question. Please, note I have removed the alert dialogs and replaced they by the console.log() at the end of all the process just to clean the logic a bit.
var question = [
'<br> What is your name?',
'<br> Are you man or woman?',
'<br> What is your class?'
];
var character = [];
const askQuestion = (idx) =>
{
if (idx >= question.length)
{
console.log(character);
return;
}
character.push(prompt(question[idx]));
askQuestion(idx + 1);
}
askQuestion(0);
Since you want to get the questionnaire on the page itself (without prompts), you can use jQuery events to control the flash of questions on the main page and also record the answers sequentially in an array.
Here's what you can do:
var question = [
'What is your name?',
'Are you man or woman?',
'What is your class?'
];
var i = 0;
var ans = [];
$(document).ready(function() {
$("#ques").html(question[i]);
});
$("#answer").click(function() {
ans.push($("#ans").val());
$("#ans").val("");
i++;
$("#ques").html(question[i]);
$("#answered").html(JSON.stringify(ans));
if (i == question.length) {
$("#ans").hide();
$("#answer").hide();
$("#ques").html("You've answered all the questions!");
}
});
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<div id="ques"></div>
<input type="text" id="ans" placeholder="Your Answer">
<button id="answer">Answer</button>
<pre id="answered"></pre>
<script src="script.js"></script>
</body>
</html>
I'm learning how to program so bear with me. I pretty much need to verify if there are empty spaces in a form that needs to be filled out, I'm using javascript. I did the following but for some reason even if I fill out all the spaces it still tells me that there are empty spaces.
(This his how the HMTML for each id looks like)
<label for="txtNombre">Name</label>
<input type="text" id="txtName" placeholder="Name">
let inputName = document.querySelector('#txtName').value;
let inputLastName = document.querySelector('#txtLastName').value;
let inputPassword = document.querySelector('#txtPassword').value;
let inputConfirm = document.querySelector('#txtConfirm').value;
let inputDate = document.querySelector('#dDate').value;
function validateForm(){
let bError = false;
if(inputPassword === '' || inputConfirm === '' || inputName ==='' || inputLastName === '' || inputDate === ''){
bError = true;
showMessage(bError);
}else if (inputPassword === inputConfirm) {
inputPassword.classList.remove('borderError');
showMessage(bError);
} else{
inputPassword.classList.add('borderError');
bError = true;
showMessage2(bError);
}
}
function showMessage(pbError){
divMessage.innerHTML = '';
divMessage.classList.remove('error');
divMessage.classList.remove('correct');
let spanMessage = document.createElement('span');
let nodeMessage;
if(pbError === true){
divMessage.classList.add('error');
nodeMessage = document.createTextNode('Missing fields to be filled out');
}else{
divMessage.classList.add('correcto');
nodeMessage = document.createTextNode('Data saved');
}
spanMessage.appendChild(nodeMessage);
divMessage.appendChild(spanMessage);
divMessage.classList.remove('invisible');
}
Since your questions doesn't hold any of your html code, and since Im unsure if you javascript is the entire script, or if there is anything defined outside the scope of your functions, my answer is limited to the information you have provided.
First off, since you are a new developer. You should first of, learn
how to use the developer tools of the browser you are using (most
browsers have them). There should be a console there, which will log
all the errors that occurs in your javascript. This is the most
efficient way to debug your code.
As someone have commented on your question here, the most likely error, is that the variables you are trying validate as blank or not, are undefined variables. Thus, they will never match ""
You should refer to the value of the input fields before you check them.
Lets say you have a input field:
<input name="test" type="text" id="testinput" />
Then you define the variable that refers to the value of this input, and check its value:
var testInput = document.getElementById('testinput').value
if( testInput === "" ) //Do something
Note, there are several methods to refer to a DOM-element in javascript, getElementById is just one of them. You should do some research, and choose the solution that fits you best
assuming that you are storing the input value in those varialiables like inputPassword for example:
const inputPassword = document.getElementById('myInput').value
Your code should work as far as I can tell from what you have posted.
Hope it helps
How can I get an input element whose name attribute ends with a particular value using just javascript?
I found this $('input[name$="value"]') method available in jQuery.
Is there a function like that available in javascript? I cannot use jQuery for some reason.
I'm surprised that nobody has mentioned this yet. Have you tried:
var elements = document.querySelectorAll('input[name$="value"]');
This will only work if the browser supports the querySelectorAll method but it is what jQuery uses underneath if support is found.
Here's the table that lists browser support for the method:
When can I use querySelector/querySelectorAll?
You can do this:
console.log(document.getElementsByName("value")[0]);
Or if you want to find the first input element with "value" in its name:
var searchString = "value";
var elems = document.getElementsByTagName('input'), wantedElem;
for(var i = 0, len = elems.length; i < len; i++) {
if(elems[i].name.lastIndexOf(searchString) == elems[i].name.length-searchString.length) {
wantedElem = elems[i];
break;
}
}
console.log(wantedElem);
I'm going to assume that you've placed these <input> elements where they belong (in a <form> element).
The easiest way to traverse form controls via the DOM API is via the HTMLFormElement::elements HTMLCollection. It allows named traversal, which is very handy for specific elements.
For example, consider the following markup:
<form action="./" method="post" name="test"
onsubmit="return false;">
<fieldset>
<legend>Test Controls</legend>
<input name="control_one" type="text"
value="One">
<input name="control_two" type="text"
value="Two">
<input name="control_three" type="text"
value="Three">
</fieldset>
</form>
Following that, some simple document tree traversal is required. Here's the entirety of it:
var test = document.forms.test,
controls = test.elements;
function traverseControl(control)
{
var patt = /one$/,
match = patt.test(control.name);
if (match) {
// do something
console.log(control);
}
}
function traverseControls(nodes)
{
var index;
if (typeof nodes === "object" &&
nodes.length) {
index = nodes.length - 1;
while (index > -1) {
traverseControl(
nodes[index]
);
index -= 1;
}
}
}
traverseControls(controls);
As you can see, it really isn't too difficult. The upshot of using HTMLCollections is the support of browsers old and new. Since HTMLCollections were implemented in DOM 0, they're widely supported.
In the future, I'd suggest using traversal that's far less vague. If you're in control of the document tree being traversed (i.e. you wrote the markup), you should already know the names of controls. Otherwise, vague approaches like the preceding must be used.
Working example: http://jsbin.com/epusow
For more, this article can be perused.
This method returns an array of elements
var elements = document.getElementsByName("value");