Javascript For Loop iteration multiple inputs number-limits - javascript

On a javascript homework assignment for my javascript class, the assignment requires a ".js" for loop iteration to list the names of the pets a user inputs (3 is the limit).
There are three horizontally spaced text-input boxes and regardless of what text boxes the user inputs pet names into, the "message" (id) output below the submit button will display pets' names inputted up to the limit imposed by the user (<= 3). Once the pets' names are inputted and submit button clicked, the page will display the pets' names starting from the left most text box the user has inputted in and going towards the right, until the user's chosen input limitation (<= 3) has reached its limit; therefore, if a user selects 2 as the limitation, only the left-most text boxes with pet names inputted will be displayed below the submit button.
So far I have tried referring to the pet id's and pet names as memberid ('pet' + 'cntr'), membername, and together in the for loop iteration they are given the id of members += membered + membername;
if (myNumPets == '' || myNumPets > 3) {
$('numpets_error').innerHTML = " Please enter the number of
pets you have ";
myTruth = true;
} else {
if (myNumPets < '4') {
$('numpets_error').innerHTML = "";
myTruth = false;
}
}
if (myNumPets == 0) {
myNumPetsEntered = 0;
} else {
if (myNumPets == 1) {
myNumPetsEntered = 1;
} else {
if (myNumPets == 2) {
myNumPetsEntered = 2;
} else {
if (myNumPets == 3) {
myNumPetsEntered = 3;
}
}
}
}
cntr = '';
members = "";
for (cntr = 1; cntr <= myNumPetsEntered; cntr++) {
var memberid = "pet" + cntr;
console.log("MID " + memberid);
var membername = $(memberid).value;
members += memberid + membername;
}
$('message').innerHTML = members;
In this present code, when the number limitation is '1', only the first input box displays the inputted pet's name in the 'message' area below the submit button; however, I would like the inputted pet's name to appear there regardless of whether the inputted pet's name is in the first and left-most input box or one of the two that are to the right of it, and I want the same to be true of the other number limitations (2 and 3).

In your for loop you're just blindly grabbing the value of N text inputs, where N = myNumPetsEntered.
If myNumPetsEntered == 1 and you've typed the pet's name into the second input box, the loop will never see that value. You'll want to do some validation to make sure you've actually grabbed a value.
I don't know how involved this homework assignment is, but you might also be interested in validating whether or not the number of text boxes with values is at least equal to (or greater than) the number of pets names the user said they were going to input.
You can also clean up those nested if statements - assuming you've got logic in place preventing myNumPets from being a negative value, you could just use:
if (myNumPets <= 3) {
myNumPetsEntered = myNumPets;
}

For a start, this chunk code can be cleaned up a lot. The current logic is messy. Just imagine if the limit was 8 instead of 3.
if (myNumPets == 0) {
myNumPetsEntered = 0;
} else {
if (myNumPets == 1) {
myNumPetsEntered = 1;
} else {
if (myNumPets == 2) {
myNumPetsEntered = 2;
} else {
if (myNumPets == 3) {
myNumPetsEntered = 3;
}
}
}
}
My suggestion is to change to a range like this:
if ((myNumPets >= 0) && (myNumPets <= 3)) {
myNumPetsEntered = myNumPets;
}
To be honest, I am trying to make sense of the rest of the question. Think you are after something like the following:
var petCount = 0;
function petAdd(e) {
// stop the default button function
e.stopPropagation();
e.preventDefault();
// make sure only 3 pet names are entered.
if (petCount >= 3) {
alert("There is a max of 3 pet names");
return;
}
// do we have a new pet name?
var pet = document.getElementById("petNameInput");
if ((pet.value) && (pet.value.trim())) {
// we do have a name, add the name to the display
var displayName = document.getElementById("petNameDisplay");
// is it the first name?
if (petCount == 0) {
displayName.textContent = "My pet name(s) are: "+ pet.value.trim();
} else {
displayName.textContent += ", "+ pet.value.trim();
}
// keep track of the number of names
petCount++;
// clear the old name, ready for the next
pet.value = "";
}
// have we reached 3 names yet? if so, remove the input
if (petCount >= 3) {
var petRow = document.getElementById("petNameRow");
if (petRow) {
petRow.style.display = "none";
}
}
}
// add the method call when the button is pressed
window.onload = function() {
var d = document.getElementById("petAddButton");
if (d) {
d.addEventListener("click",petAdd,false);
}
}
What are you pets' names? <i>max of 3</i><br />
<div id="petNameRow">
<input type="text" id="petNameInput" placeholder="Enter a name here" />
<button id="petAddButton">Add pet</button>
</div>
<div id="petNameDisplay"></div>

Just an observation: This entire block is unnecessary. Why not just myNumPetsEntered = myNumPets? Or better yet, eliminate myNumPetsEntered altogether and use myNumPets in the loop?
if (myNumPets == 0) {
myNumPetsEntered = 0;
} else {
if (myNumPets == 1) {
myNumPetsEntered = 1;
} else {
if (myNumPets == 2) {
myNumPetsEntered = 2;
} else {
if (myNumPets == 3) {
myNumPetsEntered = 3;
}
}
}
}
Anyway. Here's one way to do it. Not sure it satisfies the requirements of your homework assignment, but then I shouldn't be doing your homework anyway.
function onButtonClick () {
// get the pet name inputs
const inputs = document.querySelectorAll('input[name=petname]');
// get the max names value
const max = document.querySelector('input[name=max]').value;
const names =
Array.from(inputs.values()) // convert the 'inputs' NodeList to an array
.map(i => i.value.trim()) // extract the value of each input and strip white space
.filter(Boolean) // filter out anything 'falsy' to eliminate empty values
.slice(0, max); // chop off anything beyond the max number
// string the values together, separated by a comma, and insert the result into the message box.
document.getElementById('message').innerHTML = names.join(', ');
}
label, button {
display: block;
}
input {
margin: 1rem 0;
}
<div>
<label>Number of Pets: <input type="number" min="1" max="3" name="max" value="3" /></label>
<input name="petname" />
<input name="petname" />
<input name="petname" />
<button onClick="onButtonClick()">Go.</button>
<div id="message" />
</div>

Related

Get value of variable inside .each() function jQuery

I have code below.
The code works fine, but if I uncomment the "if" statement, alert will show up as soon as I enter something to input field.
I want the "sum" value to be checked (alert shows up) only after I entered all 3 input fields.
Please help me to fix it. Thanks.
<apex:inputField styleClass="Weight" value="{!EvaluationInformation__c.val1__c}" />
<apex:inputField styleClass="Weight" value="{!EvaluationInformation__c.val2__c}" />
<apex:inputField styleClass="Weight" value="{!EvaluationInformation__c.val3__c}" />
$(document).ready(function() {
$(document).on("input", ".Weight", function(e) {
var sum = 0;
$('.Weight').each(function() {
var num = $(this).val();
if (num != null && !isNaN(num)) {
sum += parseFloat(num);
} else {
alert("Accept number only");
}
});
//if (sum != 1){ // sum !=1 doesn't work
// alert("The total of Weight must be 1");
//}
});
});
You can use a status flag that will tell if all inputs are valid, see my example code below.
Also, AFAIK val() for an <input> element never returns null, it returns "" if there is no input. This is why I used if (num && ... instead, which in this situation means "only proceed if num contains text".
$(document).ready(function() {
$(document).on("change", ".Weight", function(e) {
var sum = 0;
var allInputsValid = true; // <-- flag variable
$('.Weight').each(function() {
var num = $(this).val();
if (num && !isNaN(num)) {
sum += parseFloat(num);
} else {
allInputsValid = false;
}
});
if (allInputsValid) {
console.log("All inputs have numbers.");
if (sum != 1) {
console.log("The total of Weight must be 1, but it is: " + sum);
} else {
console.log("The total of Weight is 1.");
}
} else {
console.log("Not all input have numbers yet.");
}
});
});
.Weight { width: 50px }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
#1: <input class="Weight" /> #2: <input class="Weight" /> #3: <input class="Weight" />
PS - Even then, you may have trouble making this work because of how Floating Point math works. Due to internal rounding, a sum of numbers that you would expect to be 1 will not always produce exactly 1:
var x = parseFloat("0.34") + parseFloat("0.56") + parseFloat("0.10");
console.log(x);
console.log(x === 1);

Sort User Input and Print It

I have this problem that I've been working on for a few hours with no luck. I'm supposed to write JavaScript code that prompts the user to enter 3 names (one at a time). The program should sort and display the names on different lines in ascending order.
I can get the program to prompt the user to enter the names but having difficulty sorting them and displaying them correctly.
<html>
<head>
<title>Day 3 - Example 1</title>
</head
<body>
<center>
<script language="javascript">
var na1,na2,na3;
na1=prompt("Enter your first name:","");
na2=prompt("Enter your second name:","");
na3=prompt("Enter your third name","");
var na1_na2 = compare(na1, na2);
var na1_na3 = compare(na1, na3);
var na2_na3 = compare(na2, na3);
var first, second, third;
if (na1_na2 === -1) {
if (na1_na3 === -1) {
first = na1;
if (na2_na3 === -1) {
second = na2;
third = na3;
} else {
second = na3;
third = na2;
}
} else {
first = na3
second = na1;
third = na2;
}
} else {
}
function compare(name1, name2) {
name1 = name1.toLowerCase();
name2 = name2.toLowerCase();
if (name1 === name2) return 0;
var lengthOfShorterName = Math.min(name1.length, name2.length)
for (var i = 0; i < lengthOfShorterName; i++) {
if (name1.charAt(i) > name2.charAt(i)) return 1;
if (name1.charAt(i) < name2.charAt(i)) return -1;
}
if (name1.lenght < name2.length) return -1;
return 1;
}
</script>
</center>
</body>
</html>
Just put the names into an array and use Array.sort to order them.
// Create a new, empty array
var names = [];
// Prompt for the names and put each into the array:
names.push(prompt("Enter your first name:",""));
names.push(prompt("Enter your middle name:",""));
names.push(prompt("Enter your last name:",""));
// Sort the names:
names.sort();
// Print the results:
names.forEach(function(value){
console.log(value);
});

How to force loop to wait until user press submit button?

I have simple function which checks if entered pin code is valid. But i don't know how to force for-loop to wait until i enter code again to check again it's validity.
So how it should be - i type PIN code, then click OK button and it checks whether it's correct (if it is, i can see my account menu; if it's not i have to type it again and i have 2 chances left). My code fails, because PIN when code is wrong program should wait until i type new code and press OK button again.
I tried setTimeout(), callback(), but it doesn't work. This is what i have - a function with for-loop that just runs 3 times (as it is suppose to, but not instantly) without giving a chance to correct the PIN code.
That's whole, unfinished yet, code: http://jsfiddle.net/j1yz0zuj/
Only function with for-loop, which checks validity of PIN code:
var submitKey = function(callback)
{
console.log("digit status" + digitStatus);
if (digitStatus == 0)
{
correctPIN = 1234;
var onScreen = document.getElementById("screen");
for (i=0; i<3; i++)
{
if (onScreen.innerHTML.slice(15, onScreen.innerHTML.length) == correctPIN)
{
setTimeout(accountMenu, 1250);
//break;
}
else
{
onScreen.innerHTML += "<br> Błędny kod PIN! Wpisz PIN ponownie. <br> Pozostało prób: " + (2-i);
callback();
//cardInserted = function(function(){console.log("Ponowne wpisanie PINu");});
}
if (i=2) console.log("blokada");
}
}
else if (digitStatus == 1)
{
}
}
Your approach is wrong. You should not make the user wait!!! You need 2 more variables at the top of your programm pincount=0 and pininputallowed. Increase pincount in the submit key function by 1 and then check if pincount<3.
Here is a corrected version of your code.
http://jsfiddle.net/kvsx0kkx/16/
var pinCount=0,
pinAllowed=true;
var submitKey = function()
{
console.log("digit status" + digitStatus);
if (digitStatus == 0)
{
correctPIN = 1234;
var onScreen = document.getElementById("screen");
pinCount++;
if(pinCount >= 3) {
pinAllowed = false;
onScreen.innerHTML = "<br>blokada";
}
if(pinAllowed){
if (onScreen.innerHTML.slice(15, onScreen.innerHTML.length) == correctPIN)
{
setTimeout(accountMenu, 1250);
//break;
}
else
{
onScreen.innerHTML += "<br> Błędny kod PIN! Wpisz PIN ponownie. <br> Pozostało prób: " + (3-pinCount);
inputLength = 0;
document.getElementById("screen").innerHTML += "<br>Wpisz kod PIN: ";
//callback();
//cardInserted = function(function(){console.log("Ponowne wpisanie PINu");});
}
}
}
else if (digitStatus == 1)
{
}
}
You need to create much more variables to control your machine. Your add/delete digit function had conditions that were badly written and only worked if the text on the screen was short enough.
var inputLength = 0;
addDigit = function(digit){
//numKeyValue = numKeyValue instanceof MouseEvent ? this.value : numKeyValue;{
if (inputLength < pinLength) {
onScreen.innerHTML += this.value;
inputLength++;
}
//if (onScreen.innerHTML == 1234) console.log("PIN został wprowadzony");
},
delDigit = function(){
if (inputLength >= 0) {
onScreen.innerHTML = onScreen.innerHTML.slice(0, -1);
inputLength--;
}
};
If you want to empty the screen at any moment you can insert onScreen.innerHTML = ''; anywhere
ps: Thanks for the exercise and nice automat you made there.

Combining Javascript Validation Functions

Alright I need help combining the two JavaScript Functions... I have tried multiple times and am not coming up with any luck. There almost identical functions except the fact that I change one number so that it thinks there different textboxes. I tried putting a variable in its place but then it always only validates to the ending number of the loop. Please show me how I may be able to combine these two functions. (Its my only work around and I can not find any examples similar to mine)
First:
<script type="text/javascript">
var QnoText = ['abc_1']; // add IDs here for questions with optional text input
function doSubmit_1() {
var ids_1 = '';
flag_1 = true;
for (i=0; i<QnoText.length; i++) {
CkStatus = document.getElementById(QnoText[i]).checked;
ids_1 = QnoText[i]+'Certificate_1';
if (CkStatus && document.getElementById(ids_1).value == '') {
alert('Please enter certificate number 1.');
document.getElementById(ids_1).focus();
flag_1 = false;
alert('return flag_1');
}
}
return flag_1;
}
</script>
Second:
<script type="text/javascript">
var QnoText = ['abc_2']; // add IDs here for questions with optional text input
function doSubmit_2() {
var ids_2 = '';
flag_2 = true;
for (i=0; i<QnoText.length; i++) {
CkStatus = document.getElementById(QnoText[i]).checked;
ids_2 = QnoText[i]+'Certificate_2';
if (CkStatus && document.getElementById(ids_2).value == '') {
alert('Please enter certificate number 2.');
document.getElementById(ids_2).focus();
flag_2 = false;
alert('return flag_2');
}
}
return flag_2;
}
</script>
You can pass a parameter in your function with the number of the textbox, like this:
var QnoText = ['abc_2']; // add IDs here for questions with optional text input
function doSubmit(n) {
var ids = '';
flag = true;
for (i=0; i<QnoText.length; i++) {
CkStatus = document.getElementById(QnoText[i]).checked;
ids = QnoText[i]+'Certificate_' + n;
if (CkStatus && document.getElementById(ids).value == '') {
alert('Please enter certificate number ' + n + '.');
document.getElementById(ids).focus();
flag = false;
alert('return flag_' + n);
}
}
return flag;
}
doSubmit(1); // for your submit 1
doSubmit(2); // for your submit 2
Is this what you wanted? because is not very clear. If is not feel free to explain.

Implementing a javascript function to search in a div, getting textrange for the search

How do I get the textrange to do a search for a div (or a form)? Are there scripts already available, or jquery functions that search the text of a div?
I append a form to a div with this code:
$('#'+card_id).append('<form id="frm_search" name="frm_search" class="editableToolbar frm_search_links"> <input type="text" placeholder="Type a string..." name="linkcard_search_string" class="txt_form"> </form>');
I'd like to have a search function that will only look for a string in that div. I specify the text range like this.
txt = window.document.body.getelementbyid(card_id).createTextRange();
The search function is one that I found on the net and that I am trying to update to search the div instead of the entire page. There will be several divs on the page and I want the search to be specific to each. I call that function from search_links(card_id);.
function search_links (card_id, form) {
var search_str = document.frm_search.linkcard_search_string.value;
/* alert('search_links '+search_str); */
return search_linkcard(search_str, card_id);
}
var IE4 = (document.all);
var n = 0;
function search_linkcard(str, card_id) {
alert (card_id + ' ' + str);
var txt, i, found;
if (str == "")
return false;
// Find next occurance of the given string on the page, wrap around to the
// start of the page if necessary.
if (IE4) {
txt = window.document.body.getelementbyid(card_id).createTextRange();
// Find the nth match from the top of the page.
for (i = 0; i <= n && (found = txt.findText(str)) != false; i++) {
txt.moveStart("character", 1);
txt.moveEnd("textedit");
}
// If found, mark it and scroll it into view.
if (found) {
txt.moveStart("character", -1);
txt.findText(str);
txt.select();
txt.scrollIntoView();
n++;
}
// Otherwise, start over at the top of the page and find first match.
else {
if (n > 0) {
n = 0;
search_linkcard(str, card_id);
}
// Not found anywhere, give message.
else
alert("Not found.");
}
}
return false;
}
My specific questions are those at the beginning of the question: How do I specify a text range for the div? Is the syntax I have right? Are there scripts that already do what I want, i.e. search the contents of a specific div?
Did the search with :contains. Did not do one match at a time. Highlighted all matches.
// Open search
function open_search(card_id) {
$('#'+card_id).append('<form id="frm_search" name="frm_search" class="editableToolbar frm_search_links"> <input type="text" placeholder="Type a string..." name="linkcard_search_string" class="txt_form" onclick="clear_search(\''+card_id+'\', this.form);"> </form>');
var frm_elements = frm_search_link.elements;
for(i=0; i<frm_elements.length; i++) {
field_type = frm_elements[i].type.toLowerCase();
switch (field_type)
{
case "text":
frm_elements[i].value = "";
break;
default:
break;
}
}
}
// Close search
function close_search(card_id, form) {
$('form.frm_search_links', $('#'+card_id)).remove();
var card_select = '#'+card_id;
$('.link',$(card_select)).removeClass('search_results');
}
// Search links
function search_links (card_id, form) {
var search_str = document.frm_search.linkcard_search_string.value;
var search_select = '.link:contains('+search_str+')';
var card_select = '#'+card_id;
var result = $(search_select,$(card_select)).addClass('search_results');
if (result.length == 0 || result.length == null) document.frm_search.linkcard_search_string.value = 'Not found.';
}
// Clear search
function clear_search (card_id, form) {
document.frm_search.linkcard_search_string.value = '';
var card_select = '#'+card_id;
$('.link',$(card_select)).removeClass('search_results');
}

Categories