Before I start, I would like to say that if this question has already been answered please direct me to the appropriate answer.
I am having an issue with my Java Script function not returning an expected value. I am trying to use it to validate text input for a number range, and, if the input is outside that range, return a custom error message.
here is the HTML for one of the fields within a the form which I am trying to validate:
<td><input name="bottomair" type="text" required id="bottomair"
size="3" onChange="bottomAirF()"></td>
<td class="noborder" id="bottomairerror"></td>
And here is the associated Javascript:
function bottomAirF() {
var x, text;
x = document.getElementById("bottomair");
if (isNaN(x) || x < 33 || x > 40) {
text = "Temp Out of Tolerance";
} else {
text = " ";
}
document.getElementById("bottomairerror").innerHTML = text;
}
What I am trying to accomplish is to have the function check to see if the entered number is between 33 and 40. If the number is not between these two numbers, the code should return the error message "Temp Out of Tolerance" but if the number is between 33 and 40 it should return nothing. As it stands right now, any number (or lack there of) returns the error message.
This code is modified from W3School's Comparison function.
I have tried everything that I can think of and it is still not working properly so any help would be greatly appreciated.
Although all the posted answers are technically correct, I believe this solution is neither maintenable nor scalable.
You have hard dependency on element ids which are static.
Imaging if, in future, you want to add more of these tds that perform such validation, are you going to keep track of newly added rows?
Although, technically you can but anthropologically its mentally draining and things like this deny to make use of the very purpose the computers and software is designed - Automation.
Something that lets you do creative tasks and have the mechanical stuff done by the computer.
For this philosophical reason, I believe this piece of code is a much better solution.
HTML - Get rid of Ids and pass this meaning current element (which is input in this case) as a parameter to the function.
<table>
<tr>
<td><input type="text" required size="3" onChange="bottomAirF(this)"></td>
<td class="noborder"></td>
</tr>
</table>
JS - use DOM accessors to find next td and update it's innerHTML
function bottomAirF(elem) {
var x, text;
x = +elem.value; // Prepended + sign will parse whatever follows to integer.
if (isNaN(x) || x < 33 || x > 40) {
text = "Temp Out of Tolerance";
} else {
text = " ";
}
elem.parentNode.nextElementSibling.innerHTML = text;
}
EDIT: For the updated requirements
To add new validations and conditions.
Let's say you have 3 textboxes which you need validation on. Each of these textboxes have different validation parameters.
First Should only accept values between 1 and 10
Second should only accept values between 11 and 33
Third should only accept values between 33 and 41
So the updated code would be, (the name of the function will be changed to something generic, like, validate)
Notice that there are two additional attributes on the input element viz val-min and val-max that specify the range.
<table>
<tr>
<td><input type="text" required val-min="1" val-max="10" size="3" onChange="validate(this)"></td>
<td class="noborder"></td>
</tr>
<tr>
<td><input type="text" required val-min="11" val-max="33" size="3" onChange="validate(this)"></td>
<td class="noborder"></td>
</tr>
<tr>
<td><input type="text" required val-min="33" val-max="40" size="3" onChange="validate(this)"></td>
<td class="noborder"></td>
</tr>
</table>
JS Code
function validate(elem) {
var x, text;
x = +elem.value; // Prepended + sign will parse whatever follows to integer.
var min = elem.getAttribute('val-min');
var max = elem.getAttribute('val-max')
if (isNaN(x) || x < min || x > max) {
text = "Temp Out of Tolerance";
} else {
text = " ";
}
elem.parentNode.nextElementSibling.innerHTML = text;
}
Working Fiddle
you are missing .value
x = document.getElementById("bottomair").value;
please instead this line:
document.getElementById("bottomair");
write this line:
document.getElementById("bottomair").value;
It should be like this
x = document.getElementById("bottomair").value;
if (isNaN(x) || parseInt(x,10) < 33 || parseInt(x) > 40) {
text = "Temp Out of Tolerance";
} else {
text = " ";
}
You've done very well all you needed was to add
value to document.getElementById("bottomair")
Here is the solution I've just added the .value
x = document.getElementById("bottomair").value;
Definitely Missing .value
$(document).ready(function () {
$("#btnCalc").click(
function () {
bottomAirF();
}
);
});
function bottomAirF() {
var x, text;
x = document.getElementById("bottomair").value;
if (isNaN(x) || x < 33 || x > 40) {
text = "Temp Out of Tolerance";
} else {
text = " ";
}
document.getElementById("bottomairerror").innerHTML = text;
}
See
Simple JSFiddle Example
Related
I am generating input fields dynamically, hoping to parse any text entered in a field and process in the keydownFunc later. No text avail in the DOM after the key event occurred.
Here is my code:
for (i = 1; i < 7; i++) {
var element = document.createElement("input");
element.setAttribute("style", "width:33px;");
element.setAttribute("name", i);
element.setAttribute("onkeydown", "keydownFunc(event);");
var tempID = document.getElementById(i)
tempID.appendChild(element);
}
function keydownFunc(event) {
var x = event.keyCode;
if (x == 13 | x == 9) {
path = event.path[1].id
console.log(path);
// process input
}
}
<table id="table">
<tbody>
<td id="1"></td>
<td id="2"></td>
<td id="3"></td>
<td id="4"></td>
<td id="5"></td>
<td id="6"></td>
</tbody>
</table>
You should avoid assigning event handlers using on... attributes. You should use addEventListener instead:
element.addEventListener("keydown", keydownFunc);
Also path is a quite obscure and not a standard property of the Event object. What are you trying to access? If it's the input itself, then use event.target (for example event.target.value to get its value), or if you want to get the table cell, then use event.target.parentNode.
I'm not entirely sure what your question is, but I think you want to access the text someone has entered in the textbox and do something with it. You can access this inside of your keydownFunc as
event.path[0].value
Here event.path[0] will be the input element.
Incidentally you don't need to name the input element, unless you're using the name for something else.
I have an app where a user scans or types in a starting barcode, and the ending barcode is automatically calculated based on a quantity value.
It works fine when the starting barcode is entirely numeric, it does the math and includes leading zeroes so the end code is the correct length.
My problem is that some small percentage of the barcodes are not entirely numeric.
The barcodes are 14 characters long. The last 5 characters will always be numeric and quantities will rarely exceed a few hundred and never go high enough that we spill into the 6th digit.
I'm not a javascript expert by any means, and just getting what I have now working strained my skills -- I'm hoping the community here can help me out :)
Here's the code I'm working with:
$(document).ready(function() {
//leading zero fill function for barcodes
function pad(num, size) {
var s = "00000000000000" + num;
return s.substr(s.length - size);
}
//Function to do BC math: starting number + quantity -1 (since it's inclusive) = end.
function updateCode() {
var quantity = $(this).closest('tr').find('.quantity').val();
var barstart = $(this).closest('tr').find('.barstart').val();
var end = pad(parseInt(barstart, 10) + parseInt(quantity - 1, 10), 14);
$(this).parent().next().find('.barend').val(end);
}
$(document).on("change, keyup", ".barstart", updateCode);
});
Edit Trying to insert the HTML again:
<script src="//code.jquery.com/jquery-1.7.2.min.js"></script>
<table id="formtable">
<tr>
<td><input class="quantity" size="6" id="qty_1" name="qtyid_1" value="123" type="text"></td>
<td><input class="barstart" size="15" maxlength="14" id="barstartid_1" name="barstart_1" value="" placeholder="Barcode Start" type="text"></td>
<td><input class="barend" size="15" maxlength="14" id="barendid_1" name="barend_1" value="" placeholder="Barcode End" type="text"></td>
</tr>
</table>
Here's a jsfiddle: https://jsfiddle.net/g1p2xh6y/1/
The users can live without it, but it'll save them some headaches (and help me make a good impression - this is a new gig) if I can get it working, so I greatly appreciate any help the community can offer :)
Thanks!
Many thanks to #admcfajn - I didn't know the slice() function existed, and that resolved it for me. I had to move the zero padding to the suffix, and remove it from the end value, but since it's pulling the prefix instead of doing math, that's no problem.
Here's the updated function:
function updateCode() {
var quantity = $(this).closest('tr').find('.quantity').val();
var barstart = $(this).closest('tr').find('.barstart').val();
var barprefix = barstart.slice(0,barstart.length-5);
var barendsuffix = pad(parseInt(barstart.slice(-5),10)+parseInt(quantity-1,10),5);
$(this).parent().next().find('.barend').val(barprefix+barendsuffix);
}
I've been trying for a bit to find a good way to go about this. Here's the trick this is being developed for IE6, so HTML5 is not supported (which is what is making this a pain, and why the button is actually a span). I need to allow all input into the input element but on submit i need to verify that the input is an integer and if it contains alpha characters or decimals throw an error.
<table id="studentIdInputTable">
<tr><td colspan="3"><hr class="style-hr" /></td></tr>
<tr><td><span class="underline bold">Selection 1</span></td>
<td class="center"><span class="small-text">Employee ID</span></td>
</tr>
<tr><td>Please enter your Student ID to <span class="bold italic">start your registration process</span></td>
<td class="center"><input type="text" maxlength="11" id="tbNewStudentId" /></td>
<td> <span id="btnNewStudent" class="validation-button">Start</span></td></tr>
</table>
I have javascript native to the HTML page as below
function CheckNewStudentId(){
var newStudentID = $("tbNewStudentId").val();
newEmployeeID = parseInt(newEmployeeID, 10);
var isNum = /^\d+$/.test(IDnumber);
if (isNum == false) {
alert(IDnumber + " is not a valid student number. Please enter only numbers 0-9, containing no alphabetical characters.");
}
}
It would be easier if this was for a more updated browser platform. Any ideas how I can go about this?
Edit***
For reference to other users this was solved using this function
function validIdCheck(Input){
if(Number.isInteger(Input)==false){
alert("This is not a valid ID");
}
}
connected to this jQuery click function
$("#btnNewStudent").click(function(){
var newStuId = $("#tbNewStudentId").val();
newStuId=parseInt(newStuId);
validIdCheck(newStuId);
});
To check if a number is an integer try this. It returns a boolean.
Number.isInteger(yourNumber)
docs: https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests
Using part of your code:
function validateStudentId(id) { return /^\d+$/.test(id) }
This will return true if it is a number or combination of numbers from 0 to 9.
If the id can not start with a 0, try this:
function validateStudentId(id) { return /^([1-9]|[1-9]\d+)$/ }
Quick explanation:
^ starts with
[1-9] digit between 1 and 9
| or
\d digit (0 to 9)
+ occurs at least once and up to unlimited times
$ ends with
Test it here
I am trying to make a sum total of all the html inside of <td> elements with name='gross_val'. I have following <td> elements:
<tr><td name="gross_val" align="right" title="gross_val1" ></td></tr>
<tr><td name="gross_val" align="right" title="gross_val2" ></td></tr>
<tr><td name="gross_val" align="right" title="gross_val3" ></td></tr>
<tr><td name="gross_val" align="right" title="gross_val4" ></td></tr>
<tr><td name="gross_val" align="right" title="gross_val5" ></td></tr>
All of these <td> elements have been dynamically populated with values in them. Some of these <td> elements have gross total values of the <tr> they are inside and some of them have not been populated yet. I just want to sum those <td> elements who have been populated with gross total values. And then show that value in another <td> element.
I have written the following JQuery and Javascript for this:
function computeGrossValTotal() {
var x = $("td[name='gross_val']");
var gValues = [];
$(x).each(function(index) {
// this line takes up the raw html inside of that td element
var valc = $(this).html();
// this line strips all the currency and other characters and symbols
// off the 'valc' variable and makes it in an integer format
var val = Number(WC(valc));
if (val) {
gValues.push(val);
}
});
// this line adds the values inside of gValues array
sum = Number(gValues.reduce(add, 0));
alert(sum);
}
$(document).on("keyup", function() {
computeGrossValTotal();
});
function WC(x) { return Number(x.match(/(?:\d+|\.)/g).join("")); }
function add(a, b) {return a + b;}
The problem I am facing is that sum does not alert unless all the <td> elements have some html inside of them. I cannot get to remove the empty td elements from the equation. Please can someone guide me as to how to only sum the <td> elements who have some value inside of them.
WC needs to check that x.match() finds something, so it doesn't call join on null.
function WC(x) {
var nums = x.match(/(?:\d+|\.)/g);
if (nums) {
return Number(nums.join(''));
} else {
return null;
}
}
x.match([[regex]]) will either return an array of matches or null if it doesn't match the regex.
When you have an element without html, you and you do $(element).html(), you will get an empty string so x.match([[regex]]) will not match your empty string and return null.
Then you will try to do .join("") on a null and you will get an error.
As I posted in a comment, you can either do something like:
var valc = $(this).html() || "0";
Or, In your case, I would modify the WC function to guard it from trying to execute .join on a null and make it return a 0 (since it won't affect your addition) in the case that .match returns null.
So the short version of this is: Can I traverse only the elements within the matched element of the selectors before the each()? Or is there a simpler way of getting what I want without an each() loop?
I thought this would be much easier, which makes me think I'm just missing some fundamental principle of element traversing with jquery.
So here's the scenario:
I have a table (and it is appropriate in this case), where each cell has a text input. The last input is read-only and is supposed to be the total sum of the other values entered on that row. I have a really messy js script for finding both the totals of each row and then the grand total of each row total.
Here's the basic HTML:
<table>
<thead>
<tr><th>Col 1</th><th>Col 2</th><th>Col 3</th><th>Total</th></tr>
</thead>
<tbody>
<tr id="row1"><td><input type="text" /></td><td><input type="text" /></td><td><input type="text" /></td><td class="total"><input type="text" readonly="readonly" /></td></tr>
<tr id="row2"><td><input type="text" /></td><td><input type="text" /></td><td><input type="text" /></td><td class="total"><input type="text" readonly="readonly" /></td></tr>
<tr id="row3"><td><input type="text" /></td><td><input type="text" /></td><td><input type="text" /></td><td class="total"><input type="text" readonly="readonly" /></td></tr>
</tbody>
</table>
The javascript will validate that the data entered is numerical, just to be clear.
So I have a event listener for each input for onchange that updates the total when the user enters data and moves to the next cell/input. Then I have a function called updateTotal that currently uses for loops to loop through each row and within that loop, each cell, and finally sets the input in the total cell to sum.
Quick note: I have included the code below to show that I'm not just looking for a hand out and to demonstrate the basic logic of what I have in mind. Please feel free to skim or skip this part. It works and doesn't need any debugging or critique.
This is what that looks like:
function updateTotal() {
table = document.getElementsByTagName("tbody")[0];
allrows = table.getElementsByTagName("tr");
grandtotal = document.getElementById("grand");
grandtotal.value = "";
for (i = 0; i < allrows.length; i++) {
row_cells = allrows[i].getElementsByTagName("input");
row_total = allrows[i].getElementsByTagName("input")[allrows.length - 2];
row_total.value = "";
for (ii = 0; ii < row_cells.length - 1; ii++) {
row_total.value = Number(row_total.value) + Number(row_cells[i][ii].value);
grandtotal.value = Number(grandtotal.value) + Number(row_cells[i][ii].value);
}
}
}
Now I am trying to re-write the above with jquery syntax, but I'm getting stuck. I thought the best way to go would be to use each() loops along the lines of:
function findTotals() {
$("tbody tr").each(function() {
row_total = 0;
$($(this) + " td:not(.total) input:text").each(function() {
row_total += Number($(this).val());
});
$($(this) + " .total :input:text").val(row_total);
});
}
But using $(this) doesn't seem to work in the way I thought. I read up and saw that the use of $(this) in an each loop points to each matched element, which is what I expected, but I don't get how I can traverse through that element in the each() function. The above also leaves out the grand_total bit, because I was having even less luck with getting the grand total variable to work. I tried the following just to get the row_totals:
$($(this).attr("id") + " td:not(.total) input:text").each(function() {
with some success, but then managed to break it when I tried adding on to it. I wouldn't think I'd need each row to have an id to make this work, since the each part should point to the row I have in mind.
So the short version of this is: Can I use the each loop to traverse only the elements within the matches, and if so, what is the correct syntax? Or is there a simpler way of getting what I want without an each loop?
Oh, one last thought...
Is it possible to get the numerical sum (as opposed to one long string) of all matched elements with jquery? I'll research this more myself, but if anyone knows, it would make some of this much easier.
You are trying to set your context incorrectly try this:
function findTotals() {
$("tbody tr").each(function() {
row_total = 0;
$("td:not(.total) input:text",this).each(function() {
row_total += Number($(this).val());
});
$(".total :input:text",this).val(row_total);
});
}
For more information about the context check out the jquery docs: http://docs.jquery.com/Core/jQuery#expressioncontext
There can be two parameters for a selector. The second parameter is the context htat that the search is to take place in. Try something like the following:
$('#tableID tbody tr).each(function(){
//now this is a table row, so just search for all textboxes in that row, possibly with a css class called sum or by some other attribute
$('input[type=text]',this).each(function(){
//selects all textbosxes in the row. $(this).val() gets value of textbox, etc.
});
//now outside this function you would have the total
//add it to a hidden field or global variable to get row totals, etc.
});