I have an ecommerce product that I sell a box of assorted flavor bagels. The max amount of flavors per box is 12. I have a number input field for each of the 12 flavors as shown in the screenshot below.
I was able to use JavaScript to limit each individual number field from exceeding 12 but I am trying to make it where the other input fields disable once the total of all fields reaches the max of 12.
The code below is what I am using to get the total of all the fields.
but at the moment It only prevents the increase of number on an individual field once it reaches 12.
I want to prevent from adding more than 12 in total from all fields combined which will complete the box of 12 bagels
const totalMaxQty = 12;
getAllInputs.forEach(allInputs);
function allInputs(value) {
value.addEventListener("input", function(e) {
e.preventDefault();
sumTotal();
});
}
function sumTotal() {
let sumValue = document.querySelectorAll('.wapf-field-input input[type=number]');
let currentTotal = 0;
for (let i = 0; i < sumValue.length; i++) {
if (parseInt(sumValue[i].value)) {
currentTotal += parseInt(sumValue[i].value);
};
}
}
for (let i = 0; i < getAllInputs.length; i++) {
getAllInputs[i].max = totalMaxQty;
}
Vanilla JavaScript only, please.
I see that you are actually returning nothing in the sumTotal(), so simply calling it inside allInputs doesn't have any effect.
function sumTotal() {
let sumValue = document.querySelectorAll('.wapf-field-input input[type=number]');
let currentTotal = 0;
for (let i = 0; i < sumValue.length; i++) {
if (parseInt(sumValue[i].value)) {
currentTotal += parseInt(sumValue[i].value);
};
}
return currentTotal
}
About disabling the input fields, I suggest you use event delegation.
Put all the input fields and their labels in a container and set the event listener on it. So you don't need to set an event listener on each of the input fields in a for loop.
const container = document.getElementById("container")
container.addEventListener("input", handleInputs )
function handleInputs() {
let currentTotal=sumTotal()
if (currentTotal===12) {
for (let i = 0; i < getAllInputs.length; i++) {
getAllInputs[i].disabled = true;
}
}
}
Related
I have a small app that should get two price values from elements on a website.
This is achieved by iterating over the .textContent of the two querySelectors (cardStartBidValueString and cardCurrentBidValuesString).
Then I also get all elements with a specific CSS selector (cardBg).
What I want to do is to check if the start price and the current bid price are both < userInputBidPrice (which is the cap of what a user wants to bid) and if this is true, then change the background color of that item so the user can directly see a potential deal. In sum there are 20 elemenets that include those two prices. So basically I want to change the background of all elements for which above condition is true.
Unfortunately its nor working. if I say cardBg[i].style['background-color'] = '#0311c3'then it only changes the color when the CurrentBidPrice is < userInputBidPrice and if I change it to cardBg[x].style['background-color'] = '#0311c3' then it colors all item if the startBidPrice is < userInputBidPrice
For some reason it is not checking if both conditions are true.
This is my code:
function deals() {
let userInputBidPrice = prompt('Set max Bid Price:');
let cardCurrentBidValuesString = document.querySelectorAll('.auction > .auctionValue:nth-child(2) > .currency-coins.value');
let cardStartBidValueString = document.querySelectorAll('.auction > .auctionStartPrice.auctionValue > .currency-coins.value');
let cardBg = document.querySelectorAll('.rowContent.has-tap-callback');
for (let i = 0; i < cardCurrentBidValuesString.length; i++) {
cardsCurrentBidPrice = cardCurrentBidValuesString[i].textContent.toString().split(',').join('');
if (cardsCurrentBidPrice === '---') {
cardsCurrentBidPrice = 0;
}
parsedCardsCurrentBidPrice = parseInt(cardsCurrentBidPrice);
for (let x = 0; x < cardStartBidValueString.length; x++) {
cardsStartBidPrice = cardStartBidValueString[x].textContent.toString().split(',').join('');
if (cardsStartBidPrice === '---') {
cardsStartBidPrice = 0;
}
parsedCardsStartBidPrice = parseInt(cardsStartBidPrice);
}
if (parsedCardsCurrentBidPrice < parseInt(userInputBidPrice) && parsedCardsStartBidPrice < parseInt(userInputBidPrice)) {
cardBg[i].style['background-color'] = '#0311c3';
}
}
}
deals();
So I had to include this part in one of our class projects. We were asked to create a quiz webpage with radios and checkboxes, and then to write a JavaScript function to validate the radios. Now, I know that these radios can be verified easily by individuals for loops for each group, but that doesn't sound practical when I have a large number of these groups in my code. So I tried the following code:-
function quizRadioFilled()
{
var check = false;
var c = 0;
var x = 0;
var radiob = [];
radiob[0] = document.getElementsByName('q1');
radiob[1] = document.getElementsByName('q2');
radiob[2] = document.getElementsByName('q3');
radiob[3] = document.getElementsByName('q4');
radiob[4] = document.getElementsByName('q5');
radiob[5] = document.getElementsByName('q9');
radiob[6] = document.getElementsByName('q10');
for(var i = 0; i <= 6; i++)
{
for(var j = 1; j <= radiob[i].length; j++)
{
if(radiob[i].checked)
{
c = 1;
break;
}
}
if(c == 0)
{
check = false;
}
}
if(!check)
{
alert('Please attempt all the questions....');
}
}
I first stored the names of each group in an array. Then looped through this to validate each of these groups. I want to display the alert if a group has no radio button selected. But I am not getting the required result. Though I have completed this project now, I would still like to get this function to work. Kindly provide some suggestions.
You never set check to true anywhere, so it is always false.
radiob[i] is an array (or, more precisely, a NodeList), so radiob[i].checked is always undefined.
Arrays in JavaScript start indexing at 0, and this applies to NodeList as well. So your for (var j = 1; j <= radiob[i].length; j++) loop is not correct.
If you fix these problems then your function should work correctly.
Currently I am taking a value from a textbox and I want to ad all the integers below that value until you hit it. For example, if someone entered 3, I would want to add 3+2+1 then display that output.
function number4() {
box4 = document.getElementById('box4').value;
var total = 0;
for (var i = 0; i <= box4; i++) {
total += i;
};
alert(box4);
}
TYPE A NUMBER IN INPUT BOX: <input id='box4'>
<button onclick='number4()'>Alert sum of all integers from zero to box value
You're getting a string instead of a number
box4 = document.getElementById('box4').value; // -> '4'
Instead you would want to do this
box4 = Number(document.getElementById('box4').value); // -> 4
Also, You would want to alert total not box4 because total is the one being updated to have sum.
Box4 is storing the value of the input field.
alert(total)
Here's the working code:
function number4() {
const box4 = Number(document.getElementById('box4').value);
let total = 0;
for (let i = 0; i <= box4; i++) {
total += i;
};
alert(total);
}
TYPE A NUMBER IN INPUT BOX: <input id='box4'>
<button onclick='number4()'>Alert sum of all integers from zero to box value</button>
I'm still working on my word filter. I've tried different things, but I'm always getting stuck with putting my updated words back into the DOM. The goal is to collect all bad words, replace them with a string (like ****) and output that in place of the original term. E.g. having the text "this is a text with a bad word" that would get turned into "this is a text with a **** word". I have an array of bad words stored in and declared as badStuff.
First, I get all inputs type = text and turn that HTML collection into an array. Same with the textareas. Then I merge these arrays into submittedWords.
I use a function that compares and replaces words as follows:
function validateText() {
// get the values from all input fields
for (let i = 0; i < inputs.length; i++) {
submittedWords.push(inputs[i].value);
}
// add the values from all textareas
for (let i = 0; i < textareas.length; i++) {
submittedWords.push(textareas[i].value);
}
// loop through the submitted words and if one matches an item in badStuff,
// replace the original term with a censored version
for ( let i = 0; i < submittedWords.length; i++) {
if (badStuff.includes(submittedWords[i].toLowerCase())) {
submittedWords[i] = submittedWords[i].replace(submittedWords[i], "****");
//return submittedWords[i] into DOM
// return? print?
}
}
// clear submittedWords array after each check
submittedWords = [];
}
validateText();
Now my problem is that I'm not sure how to output my results into the DOM, so that every bad word gets replaced with **** whenever validateText() runs and encounters one. I know how to replace text within, say, some <p> or other tag or exchange/update CSS classes via JS to display results. But here, I have an array with elements from various input fields and textareas that need to be replaced.
Maybe I can't see the obvious.
You do not need to store everything in array and then loop twice. Doing so you will leave control to the DOM element.
Shorten your code to:
for (let i = 0; i < inputs.length; i++) {
if (badStuff.includes(inputs[i].value.toLowerCase())) {
inputs[i].value = inputs[i].value.replace(inputs[i].value, "****");
}
}
for (let i = 0; i < textareas.length; i++) {
if (badStuff.includes(textareas[i].value.toLowerCase())) {
textareas[i].value = textareas[i].value.replace(textareas[i].value, "****");
}
}
On the other hand
input and textarea fields may have many words that are in badStuff array so badStuff.includes(full_value) will not be sufficient for you, instead your approach should be
var badStuff = ["bad1", "bad2", "bad3"];
var str = "hello bad1, how bad2"
badStuff.some(v => {
if (str.includes(v)) {
str = str.replace(v, "****")
}
})
console.log(str);
UPDATE
Final code for you can be:
for (let i = 0; i < inputs.length; i++) {
badStuff.some(v => {
if (inputs[i].value.toLowerCase().includes(v)) {
inputs[i].value = inputs[i].value.replace(v, "****")
}
})
}
for (let i = 0; i < textareas.length; i++) {
badStuff.some(v => {
if (textareas[i].value.toLowerCase().includes(v)) {
textareas[i].value = textareas[i].value.replace(v, "****")
}
})
}
As long as your element are form fields, you should push the elements instead of their value to the array and the, in your for loop, update their value property if needed. Here is an example:
const badStuff = [
'censure',
'blacklist',
'reprehend'
];
let submittedWords = [];
function validateText() {
const inputs = document.querySelectorAll('input');
// get all the input fields
for (let i = 0; i < inputs.length; i++) {
submittedWords.push(inputs[i]);
}
const textareas = document.querySelectorAll('textarea');
// add all the textareas
for (let i = 0; i < textareas.length; i++) {
submittedWords.push(textareas[i]);
}
// loop through the form field elements and if their value matches an item in badStuff, replace the original value with a censored version
for (let i = 0; i < submittedWords.length; i++) {
const element = submittedWords[i];
if (badStuff.includes(element.value.toLowerCase())) {
element.value = element.value.replace(element.value, "****");
}
}
// clear submittedWords array after each check
submittedWords = [];
}
document.querySelector('form').addEventListener('submit', function(e) {
e.preventDefault();
submittedWords = [];
validateText();
})
<form>
<input name="test" type="text" value="" />
<textarea type="text" value=""></textarea>
<input type="submit" value="submit" />
</form>
I want to be able to take the value from the calcOrderTotal input and then divide it and display the divided output in another input (for example, to show the Order Total price, and then what the order total 36 monthly lease price would be). I sort of attempted to do it with the "calc36Month" function, but I know it's not right.
function calcOrderTotal() {
var orderTotal = 0;
var productSubtotal = $("#product-subtotal").val() || 0;
var serverPrice = $('.server-radio:checked').val() || 0;
var equipmentPrice = $('.equipment-radio:checked').val() || 0;
var underTotal = $("#under-box").val() || 0;
var orderTotal = parseFloat(CleanNumber(productSubtotal)) + parseFloat(CleanNumber(serverPrice)) + parseFloat(CleanNumber(equipmentPrice));
$("#order-total").val(CommaFormatted(orderTotal));
$("#fc-price").attr("value", orderTotal);
}
The calcOrderTotal function is then redirected to this HTML input and displays a dollar value (this does work):
<input type="text" class="total-box" value="$0" id="order-total" disabled="disabled" name="order-total"></input>
I want to be able to take the OrderTotal dollar value and divide it by 36 months and input the 36 month lease value into another input. Here is an example of what I'm looking for (I know this does not work):
function calc36Month() {
var 36Month = 0;
var orderTotal = $("#order-total").val() || 0;
var 36Month = parseFloat(CleanNumber(orderTotal)) / 36;
$("#36-monthly-total").val(CommaFormatted(36Month));
$("#fc-price").attr("value", 36Month);
}
How can I do this?
Here ya go:
function calcOrderTotal() {
var orderTotal = 0;
var productSubtotal = $("#product-subtotal").val() || 0;
var serverPrice = $('.server-radio:checked').val() || 0;
var equipmentPrice = $('.equipment-radio:checked').val() || 0;
var underTotal = $("#under-box").val() || 0;
var orderTotal = parseFloat(CleanNumber(productSubtotal)) + parseFloat(CleanNumber(serverPrice)) + parseFloat(CleanNumber(equipmentPrice));
$("#order-total").val(CommaFormatted(orderTotal));
$("#fc-price").attr("value", orderTotal);
if (orderTotal > 0) {
calcMonthly(orderTotal);
}
}
EDIT: Edited per request.
function calcMonthly(total) {
var pmt1 = total / 36;
var pmt2 = total / 24;
var pmt3 = total / 12;
$("#monthly-36").val(CommaFormatted(pmt1));
$("#monthly-24").val(CommaFormatted(pmt2));
$("#monthly-12").val(CommaFormatted(pmt3));
//$("#fc-price").attr("value", pmt1); // what is the purpose of this?
}
Avoid using numeric digits as variable names, element ID's or CSS classes, or beginning any of the aforementioned references with a number. Begin all variable names, ID's and classes with a letter.