I am writing some code for some functionality
My first text box
<asp:TextBox ID="txtLeasePaymentFixed" type="text" runat="server" class="number" CssClass="form-control" Style="text-align: right" TabIndex="101" placeholder="e.g 123,456,789" onKeyUp="fncCalculateSum()" onBlur="fncCalculateSum()"></asp:TextBox>
My second text Box is
<asp:TextBox ID="txtLeasePaymentVairable" type="text" runat="server" CssClass="form-control" Style="text-align: right" TabIndex="102" placeholder="e.g 123,456,789" onKeyUp="fncCalculateSum()" onBlur="fncCalculateSum()"></asp:TextBox>
Label On which Toltal shows is like this
<asp:Label ID="lbltotal" runat="server" Text=""></asp:Label>
Function calling onblur and onkeyUp is like this:
function fncCalculateSum() {
var LeasePaymentFixed = $('#MainContent_txtLeasePaymentFixed');
var LeasePaymentVariable = $('#MainContent_txtLeasePaymentVairable');
if (LeasePaymentFixed.val() == '' || LeasePaymentFixed.val() == null) {
PaymentFixed = 0;
}
else {
PaymentFixed = parseFloat(LeasePaymentFixed.val());
}
if (LeasePaymentVariable.val() == '' || LeasePaymentVariable.val() == null) {
PaymentVariable = 0;
}
else {
PaymentVariable = parseFloat(LeasePaymentVariable.val());
}
(Sum) = PaymentFixed + PaymentVariable
if ((LeasePaymentFixed.val().trim() == '' && LeasePaymentVariable.val().trim() == '') || (LeasePaymentFixed.val() == null && LeasePaymentVariable.val() == null)) {
$("#MainContent_lbltotal").text('');
}
else {
$("#MainContent_lbltotal").html(parseFloat(Sum));
}
}
Now I am using jQuery code to apply comma in international format after every 3 digits like this
$('#MainContent_txtLeasePaymentFixed,#MainContent_txtLeasePaymentVairable,#MainContent_lbltotal').keyup(function(event){
// skip for arrow keys
if(event.which >= 37 && event.which <= 40){
event.preventDefault();
}
var $this = $(this);
var num = $this.val().replace(/,/gi, "").split("").reverse().join("");
var num2 = RemoveRougeChar(num.replace(/(.{3})/g,"$1,").split("").reverse().join(""));
console.log(num2);
// the following line has been simplified. Revision history contains original.
$this.val(num2);
});
function RemoveRougeChar(convertString){
if(convertString.substring(0,1) == ","){
return convertString.substring(1, convertString.length)
}
return convertString;
}
When I write digits in the first text box it comes with commas, that's fine.
Same when I write in the second text box, but it don't show sum of all the digits on label.
Watch out! You're losing data with your comma to parseFloat conversion:
let foo = 21231323.246;
let bar = foo.toLocaleString("en-US"); // "21,231,323.246"
console.log(parseFloat(bar)); // 21
You should check your conversions and make sure you're working on the right numbers.
Related
I'm creating a numeric input mask/value pair by showing the user a text input to give it several stylings (i.e. dividing thousands with a comma), and storing the real value to be sent to the form in a hidden number input.
Right now I'm noticing that editing the value of the visible input updates the selection index to the very end, which is unintuitive when you edit the input from i.e. the middle of the value. I understand that the position has been lost since the value is being completely rewritten, but how can I manually keep track of it to update it back, given that the on.('input') event handler triggers "after" the value has already changed and the keydown event happens before the modification takes place?
$("#foo").on('change paste input mouseup', function() {
const validation_decimals = 3 //allowed decimal places
const $mask = $('#foo')
const $value = $('#baz')
let hasDot = $mask.val().includes('.')
let nValue = $mask.val().replace(/[a-zA-Z]/g, "").replace(/[!¡##$%^&\/+*()=¿?":;\[\]\-_~`\\{}'|<>]/g, "")
// only one period allowed
if (hasDot) {
if ($mask.val().match(/\./g).length > 1) {
let newVal = $mask.val()
const lastDot = newVal.lastIndexOf('.')
newVal = newVal.slice(0, lastDot) + newVal.slice(lastDot + 1)
$mask.val(newVal)
}
}
$value.val(parseFloat($mask.val().replace(/,/g, "")))
// adding comma-based thousands grouping
let [integers, decimals] = $value.val().toString().split('.')
if (integers.length > 3) {
for (let iReverse = -3; iReverse > -integers.length; iReverse -= 4) {
integers = integers.slice(0, iReverse) + ',' + integers.slice(iReverse)
}
}
let fValue = integers
if (hasDot) {
fValue += '.'
}
if (decimals !== undefined) {
fValue += decimals
}
$('#foo').val(fValue)
})
// preventing more decimal places than allowed and user-inputted commas.
$("#foo").on('select click keydown', function(e) {
let selStart = e.target.selectionStart;
let selEnd = e.target.selectionEnd;
const isComma = e.keyCode == 188
const isNumber = (e.keyCode >= 48 && e.keyCode <= 57) || (e.keyCode >= 96 && e.keyCode <= 105)
const validation_decimals = 3
if ($(this).val().includes('.')) {
const value = $(this).val()
const decimals = value.split('.')[value.split('.').length - 1]
const decimalLengthReached = decimals.length == validation_decimals
const selectionBeforePeriod = selStart < value.indexOf('.') || selEnd > selStart
if (isNumber && decimalLengthReached && !selectionBeforePeriod) {
e.preventDefault()
}
}
if (isComma) {
e.preventDefault()
}
})
.input-group {
margin: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class='form-group'>
<label for='foo'>User Field (type here)</label>
<div class="input-group mb-3">
<input type="text" class="form-control" id='foo' step='0.01' aria-label="Amount (to the nearest dollar)">
</div>
<label for='baz'><em>Hidden field</em></label>
<div class="input-group mb-3">
<input type="number" id='baz' aria-label="Amount (to the nearest dollar)" step='0.1'>
</div>
</div>
You can use the selectionStart property of the input fields to determine where the caret was before you completely rewrite the input field.
document.querySelector("#my-input").addEventListener("change", function() {
// Get the position of the caret before you rewrite the input field
let caretPosition = document.querySelector("#my-input").selectionStart;
// Rewrite the input field here
// Put the caret back to where it was
document.querySelector("#my-input").selectionStart = caretPosition;
});
i am trying to put validation on a textbox onkeyup. Textbox should contain only 5 digit value and after decimal only upto 4 decimal places. eg,12345 ,12345.2345
if user enter value other than regex then the texbox should become blank and i want it to be done in function and this function should be generic so that any other can use this function
.Aspx
<input type="number" id='inpSurfIndN' value='' runat="server" onkeyup="isFloatNumber(this.value)" />
Script function
<script type="text/javascript">
function isFloatNumber(value) {
var regex = /^[0-9]\d{0,4}(\.\d{1,4})?%?$/
var regmatch = regex.test(value);
if (regmatch == null|| regmatch==false) {
alert("Please fil correct expression");
value = "";
return false;
}
return true;
}
</script>
function isFloatNumber(elem) {
var regex = /^[0-9]\d{0,4}(\.\d{1,4})?%?$/
var regmatch = regex.test(elem.value);
if (regmatch == null|| regmatch==false) {
alert("Please fil correct expression");
elem.value = "";
return false;
}
return true;
}
<input type="number" id='inpSurfIndN' value='' runat="server" onkeyup="isFloatNumber(this)" />
<input type="number" id='inpSurfIndN1' value='' runat="server" onkeyup="isFloatNumber(this)" />
<input type="number" id='inpSurfIndN2' value='' runat="server" onkeyup="isFloatNumber(this)" />
You can use above snippet which will work for n numbers of inputs.
Updating value = ""; doesn't update the UI element. You should access the UI Element object by passing this and update the value like this.value = " " else you should use the selectors like document.getElementbyId() to access those object like document.getElementbyId('inpSurfIndN').value = ""
One of way you can use below logic,
function isFloatNumber(obj) {
var regex = /^[0-9]\d{0,4}(\.\d{1,4})?%?$/
var regmatch = regex.test(obj.value);
if (regmatch == null || regmatch == false) {
alert("Please fil correct expression");
obj.value = "";
return false;
}
return true;
}
<input type="number" id='inpSurfIndN' value='' runat="server" onkeyup="isFloatNumber(this)" />
var n = document.getElementById("numPeople"),
r = document.getElementById("result");
n.addEventListener("keyup", function(e) {
var regex = /^[0-9]\d{0,4}(\.\d{1,4})?%?$/
var regmatch = regex.test(n.value);
if (regmatch == null|| regmatch==false) {
alert("Please fil correct expression");
n.value='';
return false;
}
}, false);
<input id="numPeople" type="number" min="0" value="" placeholder="Pick a number" />
You cannot access the value variable which is passed as a parameter, it doesnt reference to the value of the input box
Instead you can access the element and change the value like below:
function isFloatNumber(eve) {
var regex = /^[0-9]\d{0,4}(\.\d{1,4})?%?$/
var regmatch = regex.test(value);
if (regmatch == null|| regmatch==false) {
alert("Please fil correct expression");
var elem = eve.currentTarget;
elem.value = "";
return false;
}
return true;
}
I'm in the begin fase of learning JS. I'm trying to make a page were the user can put numbers in a text field. The user can press enter to add another number. When the user pressed enter the input field need to be cleared
The amounts entered must be added together and their total must be shown in a second text box.
my HTML:
<input type="text" id="input">
<p>Uw totaal:</p>
<input type="text" id="output">
My JS:
input = document.getElementById("input");
input.onkeypress = function(event) {
ceckKey(event);
};
function ceckKey(e) {
// check for enter: e.key is for Firefox
// if true, make input empty
if (e.keyCode == 13 || e.key == 13) {
input.value = "";
}
var number = +input.value;
return number;
}
var total = 0
total += checkKey();
document.getElementById("output").value = total;
The keypress works in every browser. The problem is that i cannot sum the numbers. If i put it in the keypress function, the number will be cleared everytime you hit enter again.
I hope you guys can help!
Get the value before your clear it.
var input = document.getElementById("input");
var output = document.getElementById("output");
var total = 0;
input.onkeypress = function(e) {
if (e.keyCode == 13 || e.key == 13) {
total += +input.value;
output.value = total;
input.value = "";
}
};
<input type="number" id="input">
<p>Uw totaal:</p>
<input type="number" id="output">
Give this a shot -
var total = 0;
input = document.getElementById("input");
output = document.getElementById("output");
input.onkeypress = function(e) {
total = total + input.value * 1;
if(e.keyCode == 13) {
input.value = "";
}
output.value = total;
};
<input type="text" id="input">
<p>Uw totaal:</p>
<input type="text" id="output">
And hey, welcome to JS!
you clear your input field too early.
var number = 0
function ceckKey(e) {
// check for enter: e.key is for Firefox
// if true, make input empty
if (e.keyCode == 13 || e.key == 13) {
number += input.value;
input.value = "";
}
return number;
}
document.getElementById("output").value = number;
note that your number variable may not be declared inside of the checkKey function. Greetings
You are updating the output element outside of the ceckKey function.
This update IS not automatic. You must trigger it.
Also, check carefully that function. Callbacks can return a value but using the dame function for a callbacks and getting that output contents does not look good.
You are clearing the value of input before calculating the total. I have updated your code little bit to work as you intended.
input = document.getElementById("input");
output = document.getElementById("output");
input.onkeypress = function(event) {
checkKey(event);
};
function checkKey(e) {
// check for enter: e.key is for Firefox
// if true, make input empty
if (e.keyCode == 13 || e.key == 13) {
// Note : in the begining the output text box is empty, so while output is empty i have assign 0 as its value.
outputValue = (output.value == '') ? 0 : output.value;
total = parseInt(outputValue) + parseInt(input.value);
input.value = "";
// To update the total in output text box
document.getElementById("output").value = total;
}
}
I've got a form with three inputs. I want to be able to fill out two of the fields and automaticly fill the third field.
So, it should work like this:
- I fill out the first and second, the third gets calculated
- I fill out the first and last, the second gets calculated
- I fill out the second and last, the first gets calculated
I came up with this code:
$(document).on('keyup change', '[data-calc]', function() {
var a = $('[data-calc=a]') ,
aV = a.val() ,
b = $('[data-calc=b]') ,
bV = b.val() ,
c = $('[data-calc=c]') ,
cV = c.val();
if(aV.length != 0 && bV.length != 0) {
cV = parseInt(aV) + parseInt(bV);
c.val(cV).prop('disabled',true);
}
else if(aV.length != 0 && cV.length != 0) {
bV = parseInt(cV) - parseInt(aV);
b.val(bV).prop('disabled',true);
}
else if(bV.length != 0 && cV.length != 0) {
aV = parseInt(cV) - parseInt(bV);
a.val(aV).prop('disabled',true);
}
else {
$('[data-calc]').prop('disabled',false);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" data-calc="a" /><br />
+<br />
<input type="text" data-calc="b" /><br />
=<br />
<input type="text" data-calc="c" />
Now the works fine when I fill out the first and second field.
But if I fill out the first, and the third after that, the third field gets disabled.
Any ideas?
This is how it should be, you should check which element was edited
$(document).on('keyup change', '[data-calc]', function(event) {
var $this = $(event.target || event.srcElement),
calc = $this.data('calc'),
$newCalc,
$a,
$b,
$c,
aV,
bV,
cV;
if (!calc) {
return;
}
$a = $('input[data-calc=a]');
$b = $('input[data-calc=b]');
$c = $('input[data-calc=c]');
$('input[data-calc]').prop('disabled', false);
aV = Number($a.val());
bV = Number($b.val());
cV = Number($c.val());
if (calc === 'a') {
if (!!aV && !!bV) {
$newCalc = $c.val(aV + bV);
} else if (!!aV && !!cV) {
$newCalc = $b.val(cV - aV);
}
} else if (calc === 'b') {
if (!!aV && !!bV) {
$newCalc = $c.val(aV + bV);
} else if (!!bV && !!cV) {
$newCalc = $a.val(cV - bV);
}
} else if (calc === 'c') {
if (!!aV && !!cV) {
$newCalc = $b.val(cV - aV);
} else if (!!bV && !!cV) {
$newCalc = $a.val(cV - bV);
}
}
if ($newCalc) { $newCalc.prop('disabled', true); }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" data-calc="a" />
<br />+
<br />
<input type="text" data-calc="b" />
<br />=
<br />
<input type="text" data-calc="c" />
The problem lies in you double binding to both keyup & change events. Remove the change from your code and you're set to go :-)
When you type a value into the 3rd field, first the keyup event fired, and all was well, and when the focus moved out of the 3rd field it fired the change event- which in turn disabled it since the 1st & 2nd fields both had values.
$(document).on('blur', '[data-calc]', function() {
var a = $('[data-calc=a]') ,
aV = a.val() ,
b = $('[data-calc=b]') ,
bV = b.val() ,
c = $('[data-calc=c]') ,
cV = c.val();
if(aV.length != 0 && bV.length != 0) {
cV = parseInt(aV) + parseInt(bV);
c.val(cV).prop('disabled',true);
}
else if(aV.length != 0 && cV.length != 0) {
bV = parseInt(cV) - parseInt(aV);
b.val(bV).prop('disabled',true);
}
else if(bV.length != 0 && cV.length != 0) {
aV = parseInt(cV) - parseInt(bV);
a.val(aV).prop('disabled',true);
}
else {
$('[data-calc]').prop('disabled',false);
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" data-calc="a" /><br />
+<br />
<input type="text" data-calc="b" /><br />
=<br />
<input type="text" data-calc="c" />
I have multiple controls that need validation based on one condition: if one of the three controls have values, the fourth one must also contain a value. I have 4 sets of 4 controls, each numbered from one to four. I've written a quick and dirty function for validation, but it the code itself is unholy and defies most of the principal of good code design, its really ugly.
JavaScript Validation
$(document).ready(function () {
$("#<%= submitBtn.ClientID%>").click(function () {
var errorMessage = "";
var error = false;
var firstname1 = document.getElementById("<%=child1FN.ClientID%>").value;
var surname1 = document.getElementById("<%=child1LN.ClientID%>").value;
var relation1 = document.getElementById("<%=ddlRelationship1.ClientID%>").value;
var dob1 = document.getElementById("<%=DoB1.ClientID%>");
if ((firstname1 != "" || surname1 != "" || relation1 != "") && dob1.value == "") {
errorMessage += "First DoB needs to be filled. \n";
error=true;
}
var firstname2 = document.getElementById("<%=child2FN.ClientID%>").value;
var surname2 = document.getElementById("<%=child2LN.ClientID%>").value;
var relation2 = document.getElementById("<%=ddlRelationship2.ClientID%>").value;
var dob2 = document.getElementById("<%=DoB2.ClientID%>");
if ((firstname2 != "" || surname2 != "" || relation2 != "") && dob2.value == "") {
errorMessage += "Second DoB needs to be filled. \n";
error=true;
}
var firstname3 = document.getElementById("<%=child3FN.ClientID%>").value;
var surname3 = document.getElementById("<%=child3LN.ClientID%>").value;
var relation3 = document.getElementById("<%=ddlRelationship3.ClientID%>").value;
var dob3 = document.getElementById("<%=Dob3.ClientID%>");
if ((firstname3 != "" || surname3 != "" || relation3 != "") && dob3.value == "") {
errorMessage += "Third DoB needs to be filled. \n";
error=true;
}
var firstname4 = document.getElementById("<%=child4FN.ClientID%>").value;
var surname4 = document.getElementById("<%=child4LN.ClientID%>").value;
var relation4 = document.getElementById("<%=ddlRelationship4.ClientID%>").value;
var dob4 = document.getElementById("<%=DoB4.ClientID%>");
if ((firstname4 != "" || surname4 != "" || relation4 != "") && dob4.value == "") {
errorMessage += "Fourth DoB needs to be filled. \n";
error=true;
}
if (error) {
alert(errorMessage);
return false;
}
});
});
The problem is, that I cannot use a for loop as asp doesn't accept a javascript value for the following source
<tr>
<th>
Child one:
</th>
</tr>
<tr>
<td>
<asp:TextBox ID="child1FN" runat="server" />
</td>
<td>
<asp:TextBox ID="child1LN" runat="server" />
</td>
<td>
<asp:DropDownList ID="ddlRelationship1" runat="server" ></asp:DropDownList>
</td>
<td>
<telerik:RadDatePicker ID="DoB1" runat="server" Culture="English (Australia)" MinDate="1 Jan 1920" class="datePickerDOB">
</telerik:RadDatePicker>
</td>
</tr>
<tr>
<th>
Child two:
</th>
</tr>
<tr>
<td>
<asp:TextBox ID="child2FN" runat="server" />
</td>
<td>
<asp:TextBox ID="child2LN" runat="server" />
<td>
<asp:DropDownList ID="ddlRelationship2" runat="server"></asp:DropDownList>
</td>
<td>
<telerik:RadDatePicker ID="DoB2" runat="server" Culture="English (Australia)" MinDate="1 Jan 1920" class="datePickerDOB">
</telerik:RadDatePicker>
</td>
</tr> . . .
I've only shown the first two rows of the source which has been simplified and removed styling tags for legibility. Like I wrote; there's 4 rows and they're similar to the above code but with just a different ID.
I was wondering if anybody had any suggestions to improve this code?
Rendered Telerick Code
<span class="riSingle RadInput RadInput_MetroTouch" id="ctl00_cphBody_DoB1_dateInput_wrapper" style="width: 100%; display: block;">
<input name="ctl00$cphBody$DoB1$dateInput" class="riTextBox riEnabled" id="ctl00_cphBody_DoB1_dateInput" style="padding-left: 2px; font-size: 12px;" type="text">
<input name="ctl00_cphBody_DoB1_dateInput_ClientState" id="ctl00_cphBody_DoB1_dateInput_ClientState" type="hidden" value='{"enabled":true,"emptyMessage":"","validationText":"","valueAsString":"","minDateStr":"20202020-JanJan-0101-0000-0101-0000","maxDateStr":"99999999-DecDec-3131-0000-1212-0000","lastSetTextBoxValue":""}' autocomplete="off">
</span>
Giv the container an ID, this will make your life easier with jQuery (and is a little more efficient than using classes etc as selectors). Also, add a class to your "data" rows
<table id="formElements">
<tr><th>Child 1</th></tr>
<tr class="data"><!-- Form Elelemt Cells --></tr>
<!-- etc -->
</table>
Javascript
$(document).ready(function () {
var formTable = $("#formElements");
/*console.log(formTable); */
$("#submitBtn").click(function (index) {
var errorMessage = "";
var error = false;
//Use the fact we have the elements in a row to our advantage
$(formTable).find("tr.data").each(function (index) {
var firstName = $(this).find("td:nth-child(1) input").val();
var lastName = $(this).find("td:nth-child(2) input").val();
var relationship = $(this).find("td:nth-child(3) select").val();
//Taking a punt the value is in the hidden form field for DOB;
var dob = $(this).find("td:nth-child(4) input[type='hidden']").val();
//Use console to try and work out what telrik uses to hold the data
console.log($(this).find("td:nth-child(4) input[type='hidden']"));
console.log($(this).find("td:nth-child(4) input[type='text']"));
if ((firstName != "" || lastName != "" || relationship != "") && dob == "") {
errorMessage += "DoB " + (index + 1) + " needs to be filled. \n";
error = true;
}
});
if (error) {
alert(errorMessage);
return false;
}
});
});
This is a little quick and dirty and handling the telrick control could be tricky.
Demo
If you can use ASP.net inbuild validators to validate the telrik control you may be better off using them. Even stil, using a custom ASP.net validator should work in a similar fasion.
Update
I've added a couple of debug lines using console.log to try and help with the telrik controls.
Slighly hacky version
Keep the HTML as per above.
Javascript
$(document).ready(function () {
var formTable = $("#formElements");
/*console.log(formTable); */
//Create an array of the DatePicker controls
//You could replace the jQuery selectro with:
//document.getElementById("<%=DoB1.ClientID%>")
var arrDoB = new Array(
$("#<%=DoB1.ClientID%>"),
$("#<%=DoB2.ClientID%>"),
$("#<%=DoB3.ClientID%>"),
$("#<%=DoB4.ClientID%>")
);
$("#submitBtn").click(function (index) {
var errorMessage = "";
var error = false;
//Use the fact we have the elements in a row to our advantage
$(formTable).find("tr.data").each(function (index) {
var firstName = $(this).find("td:nth-child(1) input").val();
var lastName = $(this).find("td:nth-child(2) input").val();
var relationship = $(this).find("td:nth-child(3) select").val();
//Get the value of the datepicker control from the array
var dob = arrDoB[index].value;
if ((firstName != "" || lastName != "" || relationship != "") && dob == "") {
errorMessage += "DoB " + (index + 1) + " needs to be filled. \n";
error = true;
}
});
if (error) {
alert(errorMessage);
return false;
}
});
});