Disable decrement button if input field reaches initial value - javascript

I used the code below to increment and decrement an input field by 1. I need to disable the minus (-) button by default. If the initial value is 5, the user should not decrease the value less than 5. If they go to 6, enable the minus button to decrease. But, they should not decrease less than 5.
The code works sometimes. Randomly, the button is disabled and isn’t able to decrease even from 10 to 9, 8, 7.
Please let me know whether this solution will work or need to change any other.
let $noofpaxinput = $('#txtnoofpax');
$noofpaxinput.val(5);
let intialvalue = $noofpaxinput.val();
$('.noofpax').click(function() {
if ($(this).hasClass('increasepax')) {
$noofpaxinput.val(parseInt($noofpaxinput.val()) + 1);
$('.decreasepax').prop('disabled', false);
} else if ($noofpaxinput.val() >= intialvalue) {
let getPaxVal = $noofpaxinput.val(parseInt($noofpaxinput.val()) - 1);
if (getPaxVal <= intialvalue) {
$('.decreasepax').prop('disabled', true);
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="fee-amount">
<button type="button" disabled="disabled" class="noofpax decreasepax">-</button>
<input id="txtnoofpax" type="text" value="5">
<button type="button" class="noofpax increasepax">+</button>
</div>

You could listen to input change and detect whether to disable the decrease button
Remember to parseInt because your input type is text. If you not parse it, '10' < '5' will return true
let $noofpaxinput = $("#txtnoofpax")
$noofpaxinput.val(5)
let intialvalue = $noofpaxinput.val()
$noofpaxinput.on('change', function () {
if (Number($noofpaxinput.val()) <= Number(intialvalue)) {
$(".decreasepax").prop("disabled", true)
} else {
$(".decreasepax").prop("disabled", false)
}
})
$(".noofpax").click(function () {
if ($(this).hasClass("increasepax")) {
$noofpaxinput.val(Number($noofpaxinput.val()) + 1).trigger("change")
}
if ($(this).hasClass("decreasepax")) {
$noofpaxinput.val(Number($noofpaxinput.val()) - 1).trigger("change")
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="fee-amount">
<button type="button" disabled="disabled" class="noofpax decreasepax">-</button>
<input id="txtnoofpax" type="text" value="5">
<button type="button" class="noofpax increasepax">+</button>
</div>

You need to check the value of .txtnoofpax inside the click function event to get it everytime the user click.
And then you need to use a else in your last condition.
var noofpaxinput = $('#txtnoofpax'), noofpaxinputInitVal = $(noofpaxinput).val();
$(noofpaxinput).on("input", function(){
checkNoofpaxinput($(noofpaxinput).val(), noofpaxinputInitVal);
});
$('.noofpax').click(function(){
var txtnoofpaxValue = $(noofpaxinput).val();
if ($(this).hasClass('increasepax')){
$(noofpaxinput).val(parseInt(txtnoofpaxValue)+1);
} else if ($(this).hasClass('decreasepax')){
$(noofpaxinput).val(parseInt(txtnoofpaxValue)-1);
}
checkNoofpaxinput($(noofpaxinput).val(), noofpaxinputInitVal);
});
function checkNoofpaxinput(fromValue, Tovalue) {
if (parseInt(fromValue) <= parseInt(Tovalue)) {
$('.decreasepax').prop('disabled', true);
} else {
$('.decreasepax').prop('disabled', false);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.1/jquery.min.js"></script>
<div class="fee-amount">
<button type="button" disabled="disabled" class="noofpax decreasepax">-</button>
<input id="txtnoofpax" type="text" value="5">
<button type="button" class="noofpax increasepax">+</button>
</div>

Related

Increment and update value in the total number after insert new rows dynamically

EDIT: I have updated the code with the answers.
I have a increment function that is working fine. However:
1. I would like to set some limits based on the total number available in one of the span. For example, 10. So the incrementing can't be more than 10. #DONE
Another issue is that I am planning to have multiple rows and before I save I want to make sure if we count the increments in every row it should not be more than 10 as well. If it decrease the total number (span) dynamically would be nice.
I'm adding rows dynamically with the ADD button, how can I add news rows that actually work with the current functions? Mine rows just clone the first one and the increment function is disabled.
document.addEventListener('DOMContentLoaded', async function() {
document.querySelector('#addlocationdest').addEventListener('click', add);
});
function add() {
var x = 1;
var container = document.getElementById('destination');
var detail = document.getElementById('row');
var clone = detail.cloneNode(true);
clone.id = "destination" + x;
x++;
container.appendChild(clone);
}
window.addEventListener("load", () => {
let elTotalQuantity = document.querySelector("#totalqty");
let totalQuantity = parseInt(elTotalQuantity.innerHTML);
function getSumOfRows() {
let sum = 0;
for (let input of document.querySelectorAll("form .row > input.quantity"))
sum += parseInt(input.value);
return sum;
}
for (let row of document.querySelectorAll("form .row")) {
let input = row.querySelector("input");
row.querySelector(".increment").addEventListener("click", () => {
if (getSumOfRows() >= totalQuantity) return;
input.value++;
elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
});
row.querySelector(".decrement").addEventListener("click", () => {
if (input.value <= 0) return;
input.value--;
elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
});
}
});
<div id="location" class="hide">
<div class="title">Transfer details</div><br>
<div class="line padded-s">Total Quantity: <span>10</span></div>
<br>
<form>
<label>New Total Quantity at this location: <span id="totalqty">10</span></label>
<br>
<div id="destination">
<div id="row" class="row">
<button type="button" class="decrement">-</button>
<input type="text" class="quantity" value="0" readonly/>
<button type="button" class="increment">+</button>
<a>Location: </a>
<input type="text" class="location" value="0" readonly/>
</div>
</div>
</form>
<label>Total being transfer: <p id="total-sum"></p></label>
<br>
<button type="button" id="addlocationdest">ADD</button>
<button type="button" id="removelocationdest">REMOVE</button>
</div>
Prologue
As long as the total quantity is fixed at the beginning of the script-execution, this works. Otherwise, it would be best to save the actual allowed total quantity as an attribute, and observe it using a MutationObserver. That way you can update your max. value in your code dynamically, when the total quantity-attribute changes. You can define custom attributes by naming them "data-*" where "*" is a custom name.
Solution for your problem
You are using the same ID on multiple elements. What you meant were classes, so change id="increment" to class="increment", and the same for decrement.
Since we don't want to input something with the buttons, but add listener to them, I'd say it is better to actually use <button>. In forms, buttons act as type="submit", which we don't want, so we need to change it to type="button".
Since the rows and the total quantity actually belong together, it is wiser to place them together into one <form>-element. However, you can still group the buttons and inputs as a row together using <div>.
Now regarding the in-/decrementing of the row's values and the total quantity:
Save the allowed total quantity in a variable
Add event-listener to the corresponding buttons
If action is valid, change row's value
Update total quantity number to totalQuantity - getSumOfRows()
To add new rows dynamically, we create and setup such an element, and append it to the form. See the appendNewRow()-function below.
Sidenote
I have added the readonly attribute to the input-fields so that you cannot enter numbers via keyboard.
window.addEventListener("load", () => {
let elTotalQuantity = document.querySelector("#totalqty");
let totalQuantity = parseInt(elTotalQuantity.innerHTML);
function getSumOfRows() {
let sum = 0;
for (let input of document.querySelectorAll("form .row > input.quantity"))
sum += parseInt(input.value);
return sum;
}
function updateTotalQuantity() {
elTotalQuantity.innerHTML = totalQuantity - getSumOfRows();
}
function appendNewRow() {
let row = document.createElement("div");
row.classList.add("row");
let child;
// input.quantity
let input = document.createElement("input");
input.classList.add("quantity");
input.value = "0";
input.setAttribute("readonly", "");
input.setAttribute("type", "text");
row.append(input);
// button.increment
child = document.createElement("button");
child.classList.add("increment");
child.innerHTML = "+";
child.setAttribute("type", "button");
child.addEventListener("click", () => {
if (getSumOfRows() >= totalQuantity) return;
input.value++;
updateTotalQuantity();
});
row.append(child);
// button.increment
child = document.createElement("button");
child.classList.add("decrement");
child.innerHTML = "-";
child.setAttribute("type", "button");
child.addEventListener("click", () => {
if (input.value <= 0) return;
input.value--;
updateTotalQuantity();
});
row.append(child);
// button.remove-row
child = document.createElement("button");
child.classList.add("remove-row");
child.innerHTML = "Remove";
child.setAttribute("type", "button");
child.addEventListener("click", () => {
row.remove();
updateTotalQuantity();
});
row.append(child);
document.querySelector("form .rows").append(row);
}
document.querySelector("form .add-row").addEventListener("click", () => appendNewRow());
appendNewRow();
});
<form>
<label>Total Quantity: <span id="totalqty">10</span></label>
<br>
<div class="rows">
</div>
<button type="button" class="add-row">Add new row</button>
</form>
QuerySelector only selects the first occurrence so you haven't really added a listener to the second "row". You should use querySelectorAll but, instead of unique ids, use classes.
<input class="increment" type="button" value="+" />
Now you can use document.querySelectorAll(".increment") to get all elements in an array.
You can traverse in the DOM by using parentElement. By knowing which button you clicked, you can traverse up to the form element and then select the first child - which is an input. A more dynamic way would be to use querySelector to select the input, in case the HTML change in the future. Anyway, that's how you can know which input to manipulate based on where the buttons are in the DOM.
I added two global variables, totalSum and maxSum. maxSum is fetched from your span element (which I assigned an unique id to). totalSum makes sure that all inputs combined doesn't exceed maxSum.
You had some duplicate code, so I refactored it into a new method: changeValue.
In all, I think the code speaks for itself.
Oh, this code doesn't take into account that the user can change the value inside the input. I will leave that for you to figure out with an "oninput" listener on each text input.
var totalSum = 0; // 3
var maxSum = 0
var totalSumElement = null;
document.addEventListener('DOMContentLoaded', async function() {
totalSumElement = document.getElementById('total-sum');
maxSum = document.getElementById('max-sum').innerText;
var incrementElements = document.querySelectorAll('.increment'); // 1
var decrementElements = document.querySelectorAll('.decrement');
addListener('click', incrementElements, incrementValue);
addListener('click', decrementElements, decrementValue);
});
function addListener(type, elementArr, func) {
for (element of elementArr) {
element.addEventListener(type, func);
}
}
function withinRange(newValue) {
var maxReached = newValue > maxSum; // 3
var zeroReached = newValue < 0;
return !maxReached && !zeroReached;
}
function changeValue(event, change) { // 4
if (withinRange(totalSum + change)) {
let parent = event.currentTarget.parentElement; // 2
let input = parent.children[0];
let value = parseInt(input.value) || 0;
if (withinRange(value + change)) {
input.value = value + change;
totalSum = totalSum + change;
}
}
totalSumElement.textContent = `Total: ${totalSum}`;
}
function incrementValue(event) {
changeValue(event, 1);
}
function decrementValue(event) {
changeValue(event, -1);
}
#totalqty {
padding-bottom: 1rem;
}
<div id="totalqty" class="line padded-s">Total Quantity: <span id="max-sum">10</span></div>
<form>
<input type="text" value="0" />
<input class="increment" type="button" value="+" />
<input class="decrement" type="button" value="-" />
</form>
<form>
<input type="text" value="0" />
<input class="increment" type="button" value="+" />
<input class="decrement" type="button" value="-" />
</form>
<p id="total-sum"></p>

How can I make it so that when input field is empty, button does nothing?

I'm making a simple searcher in which the user enters a query, clicks search, and the program returns either the location of said element, or a "No results found" line.
I'm having trouble with the search button itself. It works perfectly fine when the element that is being searched exists, but if I click on it while the input is blank, it returns the "No results found" message. I would like it so that it does nothing.
I'm using mainly JavaScript. What I've tried so far is make an if statement to check the length of the input, and then select the element from the DOM and make it disabled when length is 0.
I have tried adding both console.log and alert() to check the state of the button (enabled/disabled), and they both work equally, no matter the length of the input value.
<button value="submit" id="button" data-key="13" onclick="clickFunction()">
</button>
function clickFunction() {
var input = document.getElementById('input_id').value;
var input = input.toLowerCase();
/* disables button if there is no input */
if ( input.length === 0 ) {
document.getElementById("button").disabled = true;
console.log("disabled");
} else if (input.length > 0) {
document.getElementById("button").disabled = false;
console.log("enabled");
}
}
I have also tried using jQuery ($("#button").attr("disabled", true)), but it's not working either.
Am I missing something?
You need to stop the click, disabling the button with click means you will not be able to enable it.
function clickFunction(evt) {
var input = document.getElementById('input_id').value.trim();
// if (!input.length) { evt.preventDefault(); }
if (!input.length) return false; // cancel click
return true
}
<form>
<input type="search" id="input_id" name="input_id" />
<button value="submit" id="button" data-key="13" onclick="clickFunction(event)">
</button>
</form>
but why use JavaScript, let HTML do it for you.
<form>
<input type="search" name="search" required />
<input type="submit" />
</form>
this should work
function validate(obj) {
if (obj.value.length > 0) {
document.getElementById("btnSave").disabled = false;
} else {
document.getElementById("btnSave").disabled = true;
}
}
<input type="text" id="txtName" onkeyup="validate(this)"/>
<button disabled id="btnSave">save</button>
You can modify your code in this manner:
function clickFunction() {
var input = document.getElementById('input_id').value;
input = input.toLowerCase();
if (input.length) {
// write your search logic here
} else {
// won't do anything
return false;
}
}
I hope it will help.

Is there a javascript function that I can make to give radiobuttons a value?

So I have a small issue with getting some values on radiobuttons. I've made a foreach loop in where the html makes radiobuttons. These are Yes/No buttons and Each yes/no set needs a value.
Like question 1 will have value 1, 2 will have 2, 3 will have 4, 4 will have 8 etc.
In the end it needs to add up to a total score, BUT if NO is selected (eg. question 4 with value of 8 is NO, then the value becomes 0)
Ive tried doing a Javascript function shown below that makes it sort of work. But if all answers are NO and you make question 4 YES(which should have a value of 8) then it just says that my value is 2. I knew that this wouldnt work but I'm wondering if I can change this in a way that I can make it work the way that I want to
#foreach (var item in Model)
{
<div class="box">
<p>#Html.DisplayFor(modelItem => item.Question)</p>
<label>
<input id="yes" type="radio" name="#item.Id" checked="">
<span class=" yes randobtn">Ja</span>
</label>
<label>
<input id="no" type="radio" name="#item.Id">
<span class="no randobtn">Nee</span>
</label>
</div>
}
<button class="btn btn-primary" onclick="GetCount()">check</button>
#section Scripts{
<script type="text/javascript">
$(document).on('click',
'#btn',
function() {
console.log('test');
location.href = "/Symptom/GetProblems?TotalPoints=" +
count;
});
var count = 1;
$(document).on('click',
'.randobtn',
function() {
GetCount();
});
function GetCount() {
var checkedRadioBtns = $('input[type="radio"]:checked');
count = 1;
for (var i = 0; i < checkedRadioBtns.length; i++) {
if (checkedRadioBtns[i].id === 'no') {
console.log('in de if');
continue;
} else {
count = count * 2;
}
}
alert(count);
}
</script>
}
This is what I want: http://prntscr.com/o6zrqd
But as you can see in the alert it just says 1 when NO is selected
put value of true and false in the array
and then
value="#item.true_value"

How can I disable an HTML button until another button is clicked?

I'm trying to make a game where you enter a number into a textbox and then click on Lock In.
You can then not change your answer.
After that you click on Random Number and it will give you a random number 1-50.
But the problem is that I want to make it where you have to click Lock In before you can find out the random number.
This is because you can just not click Lock In and then change it so that it is right.
My code for this is below:
function numFunction() {
var x = Math.floor((Math.random() * 50) + 1);
document.getElementById("randnum").innerHTML = x;
start.disabled = true;
reload.disabled = true;
}
function btnFunction() {
document.getElementById("answerbox").readOnly = true;
}
function revFunction() {
document.getElementById("rnum").disabled = false;
}
<div id="randbutton">
<button id="rnum" onclick="numFunction()">Random Number</button>
<p id="randnum"></p>
<input type="text" name="answerbox" size="20" id="answerbox">
<div id="lockbtn">
<button onclick="btnFunction();revFunction();">LockIn</button>
<div id="resetbtn"></div>
<button id="relbtn" onclick="relFunction()">Reset</button>
</div>
</div>
You are really close. You can just add "disabled" to your button, and then when the user locks in their answer, enable it again.
Additionally, it's not best practice to split your JavaScript into a bunch of different script tags. Put them all in one place.
function numFunction() {
var x = Math.floor((Math.random() * 50) + 1);
document.getElementById("randnum").innerHTML = x;
start.disabled = true;
reload.disabled = true;
}
function btnFunction() {
document.getElementById("answerbox").readOnly = true;
}
function revFunction() {
document.getElementById("rnum").disabled = false;
}
function relFunction() {
location.reload();
}
<div id="randbutton">
<button id="rnum" onclick="numFunction()" disabled>Random Number</button>
<p id="randnum"></p>
<input type="text" name="answerbox" size="20" id="answerbox">
<div id="lockbtn">
<button onclick="btnFunction();revFunction();">LockIn</button>
<div id="resetbtn"></div>
<button id="relbtn" onclick="relFunction()">Reset</button>
</div>
</div>
you could use the disabled property on the button to start.
<button type="button"id="lock" onclick="enableNum()">Lock in</button>
<button type="button"id="randomNum" disabled>Random Number</button>
Then when someone enters the number, you would have a function that detects the input and enables the button.
function enableNum() {
document.getElementById("randomNum").disabled = false;
}

Retrieve unique value of a button

I have several buttons belonging to the same class. I want to retrieve the value of the button I click on.
Here is my code:
var battons = document.getElementsByClassName("converting_video");
var number_of_buttons = battons.length;
function actual_url() {
while (number_of_buttons > 0) {
for (i = 1; i <= number_of_buttons; i++) {
function getting_url() {
battons[i].addEventListener("click", video_url)
}
function video_url(url) {
alert(url);
}
}
}
}
var battons = document.getElementsByClassName("class_btns");
var number_of_buttons = battons.length;
function actual_url() {
while (number_of_buttons > 0) {
for (i = 1; i <= number_of_buttons; i++) {
function getting_url() {
battons[i].addEventListener("click", video_url)
}
function video_url(url) {
alert(url);
}
}
}
}
<button class="class_btns" value='1'> results </button>
<button class="class_btns" value='2'> results </button>
<button class="class_btns" value='3'> results </button>
<button class="class_btns" value='4'> results </button>
This will allow you to get the value of any of the buttons clicked. Using jQuery's .click() event handler and $(this).val() will allow the value of the clicked button to be the value in the alert. Not sure what you are actually looking for with video_url etc, but this should point you in the right direction. You can then use the value from the click to do pass to your function rather than jusrt alerting i eg: ... video_url(btnVal) ...
$(document).ready(function(){
$('.class_btns').click(function(){
var btnVal = $(this).val();
alert(btnVal);
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button class="class_btns" value='1'>results</button>
<button class="class_btns" value='2'>results</button>
<button class="class_btns" value='3'>results</button>
<button class="class_btns" value='4'>results</button>

Categories

Resources