I have a form with several fields, one of which is "counter", that gets changed constantly. When the form is edited I need to track if some fields are changed and set the "counter" field to the number of modified fields up on submission. For example, if the old value of counter is 10 and field1, field2 and field3 are modified, then on form submit counter should be incremented to 13.
Below is what I'm attempting to do just for one field but its not working correctly. I also need to check not only one field but a few other fields too. Any help is appreciated. Thanks!
$(document).ready(function(){
var oldVal = getOldValue("field1");
var oldCounter = parseInt(getOldValue("Counter"));
var curCounter;
$('field1').change(function(){
var newVal= $(this).val();
if(oldVal.val() == newVal.val()){
curCounter = oldCounter +1;
setField("Counter", parseInt(curCounter));
}
});
});
Your if statement is incorrect. It fires when the value has changed (.change()), yet you are checking if the value is the same through if(oldVal.val() == newVal.val())
Also, .val() is a method of the jQuery object, so unless the function getOldValue() returns a jQuery object, your if statement is probably not going to do what you're expecting it to do.
What I'd do is store the oldValues of the form fields inside a data attribute of the formfield, so you can easily access it from within the .change() event, something like:
$(document).ready(function(){
var oldCounter = parseInt(getOldValue("Counter"), 10); // use the second argument '10' here or you might get strange results
var curCounter = oldCounter;
$('.field').each(function() {
// store the old value
$(this).data("oldValue", getOldValue($(this).attr("id")));
})
.change(function(){
// compare values, increase counter if it is different than the original value
if($(this).data("oldValue") != $(this).val()) {
curCounter++;
setField("Counter", curCounter);
}
});
});
Untested code but you get the gist, hope this helps
3 things i've noticed
*. you are checking the newVal's value twice, it should be something like
var newVal = $(this).val();
if (oldVal == newVal).....
*. for the oldValue variable you can just do var oldVal=$('#filed1_id').val(); this will be much simpler and will get you the value needed and not the object, this is simpler to handle.
*. you say you need to check for change on submission but you're checking on change, change it to which means you'll be checking more often when you need to.
and again, it will be nice to know what's getOldValue does.
good luck
I assume you want to know whether the user modified any fields when the form is submitted. It would be easiest to use .data() to keep track of which fields have changed from their original value. As other posters have mentioned your code calls .val() redundantly, incorrectly uses == instead of !=, and might not be using jQuery objects correctly.
This fiddle should address your issues: http://jsfiddle.net/EYjxP/
Related
I am working on a module, which should select the only possible value of a Multi- or Single selection field, if there is only one valid value and a empty one available.
So far its working fine, until I use ACLs to disable selection values.
For example, I got a single selection field with 3 possible values. Then I disable 2 of them (ACL - if there is a special Queue selected) so theres only one value (+ an empty one) left.
My module wont pick the last value at first, but when I change anything else on the same page (second onchange call) it will pick the last possible value.
The first if condition checks if the Field has only one possible value in it. When I log the 'Change' array it always got the disbaled values still in there even when the 'change' that called the whole function was the ACL disabling those values.
Im still kinda new to javascript and havent found a solution yet.
I would realy appreciate any help.
$('.TableLike').on("change", function () {
var Change = [];
$('.Row').each( function() {
$(this).children().next().children().next().children().each( function(index) {
Change[index] = $(this).text()
} )
if ( (!Change[2] || /.*Field needed.*/i.test(Change[2])) && Change[0] === "-") {
SoleOption = Change[1];
$(this).children().next().children().next().children().each(function() {
if ($(this).text() === "-") {
$(this).removeAttr("selected");
}
if ($(this).text() === SoleOption) {
$(this).attr("selected", "selected");
}
} )
$(this).children().next().children().children().children().val(SoleOption)
}
SoleOption = "";
Change = [];
} )
} )
I managed to fix the issue with the setTimeout() Method.
So the DOM updated before the ACL did the changes.
I opened up the setTimeout Method after the onChange method and inserted all the code thats supposed to run after the change into the setTimeout method.
I hope this will be helpfull for others in the future.
I have a project where a form is required for inputs for a week, so for efficiency elsewhere an array of inputs is used (i.e. start[0] etc) this seems to have exacerbated the issue.
The problem is when validating a form where some inputs are given initial values (its an update) jQuery only returns those initial values instead of changed ones unless use of 'this' is feasible. I found to resolve that I had to use:
$(".weekdays").change(function(){
var newval = $(this).attr('value');
$(this).attr('value', newval);
});
Which seems a crazy thing to have to do! Its here I found using $(this).val(newval); always fails except when setting initial values, though its the common given solution?
In the same vein setting check-boxes seems also problematical, using:
var id = $(this).attr('pid');
$("#choice["+id+"]").prop('checked', false);
$("#choiceLabel["+id+"]").css('background-image','url("images/Open.png")');
Always fails, yet reverting to javascript with:
var id = $(this).attr('pid');
document.getElementById("choice["+id+"]").checked = false;
document.getElementById("choiceLabel["+id+"]").style.backgroundImage = 'url("images/Open.png")';
Works fine!
So does jQuery not like inputs with id's in array form? or am I getting things wrong somewhere?
When attempting to select an element with an id that contains special characters, such as [], you have to remember to escape them for jQuery. For instance..
var id = 12;
console.log(
$('#choice\\['+ id +'\\]').get()
);
console.log(
$('#choice[data-something]').get()
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="choice[12]">weee</div>
<div id="choice" data-something>dang!</div>
Otherwise, jQuery will treat them as special characters, in this case, assuming you are trying to find an element that has an id and has an attribute matching your variable value.
Please I have my Jquery code that I want to do few things since. I have a form with a bunch of textboxes. I want to validate each textbox to allow numbers only. To also display error where not number.
var validateForm = function(frm){
var isValid = true;
resetError();
$(":text").each(function(variable){
console.log("The variable is" , variable);
if(!isNormalInteger(variable.val))
{
$("#error"+variable.id).text("Please enter an integer value");
isValid = false;
}
});
if(!isValid)
return false;
};
The above fails. When I print the variable on my console I was getting numbers 0 - 9. My textboxes where empty yet, it returns numbers. I tried variable.val() still fails and return numbers. I modified my select to
$("input[type=text]", frm).each();
Where my form is my form selected by id. It also failed. Below is the example of my html label and textbox. I have about ten of them
<div class="grid-grid-8">
<input class=" text" id="id" name="name" type="text">
<br>
<p class="hint">Once this limit is reached, you may no longer deposit.</p>
<p class="errorfield" id="errorMAXCASHBAL"></p>
Please how do I select them properly? Moreover, my reset function above also returns incrementing integers for value. The p property is of class errorField and I want to set the text property. Please how do I achieve this? Previously I tried the class name only $(.errorField). It also failed. Any help would be appreciated.
var resetError = function(){
//reset error to empty
$("p errorfield").each(function(value){
console.log("the val", value);
//value.text() = '';
});
};
//filter non integer/numbers
function isNormalInteger(str) {
return /^\+?\d+$/.test(str);
}
The main problem is your selectors in javascript. And as laszlokiss88 stated wrong usage of .each() function.
Here is a working example of your code: jsFiddle in this example all .each() functions use $(this) selector inside instead of index and value
You are using .each wrong because the first parameter is the index and the second is the element. Check the documentation.
Moreover, the correct selector for the resetError is: p.errorfield
So, you should modify your code to look something like this:
var resetError = function(){
$("p.errorfield").each(function (idx, element) {
$(element).text("");
});
};
With this, I believe you can fix the upper function as well. ;)
I'm unsure of the syntax here, but the code I have so far is this... (Note: I am passing the id's of three textboxes in the form '#begmile','#endmile','#totmile', and I want to set the value of the 'totmile' checkbox to endmile-bigmile)
function subtract(begmile, endmile, totmile){
y=$(begmile).attr('value');
z=$(endmile).attr('value');
y=z-y;
$(totmile).setAttr('value',???);
}
I'm not sure if my syntax here so far is correct, but assuming it is (that y is properly set to endmile-begmile, how do I use setAttr to set the value of totmile to the value of y?
This is the correct syntax:
var href = 'http://cnn.com';
$(selector).attr('href', href);
your last line isn't calling the right method:
$(totmile).setAttr('value',???);
should be:
$(totmile).attr('value',???);
e.g.
$(totmile).attr('value', y);//set the value to the variable "y"
you can also call .val(); instead to easily get the value of a field, or .val(newValue); to set the value.
also note that if your values for "y" and "z" are not actually representing numbers you'll get a weird result.
The value attribute refers to the default value for the textbox, not the current one. The current one is stored in the value property.
function subtract(begmile, endmile, totmile) {
document.getElementById(totmile).value =
document.getElementById(endmile).value - document.getElementById(begmile).value;
}
This also removes the need for jQuery, since the JavaScript Sledgehammer is far too excessive for this job. To make sure it works, just remove the # when you pass IDs to the function.
EDIT:
Ok so I'm updating this question, to show what I've built as I've still not been able to fix this issue. Here is an image of what I've got. So as you can see,
When the user enters a value, the calculation (they are just percentage and total calculations are done "onkeyup". As you can see because of this they return "NaN". Is there a way for me to stop the field displaying a NaN and then subsequently only showing the total values?
I have thought about this and I could just get all the fields to calculate as soon as something is input into the final field? What do you think. Apologies to all those that had perviously answered my question, I am still trying to figure out the best approach, I'm just not as good with JavaScript as I am with HTML/CSS!!
You should try writing a checkNumber function that takes the entered value as its argument (rather than referring directly to each field inside the function). Something like this:
var checkNumber = function (testval) {
if ( isNaN(testval) ) {
alert('Bad!');
// clean up field? highlight in red? etc.
} else {
// call your calculation function
}
}
Then bind that function to the keyup event of each form field. There are a number of ways to do this. Look into addEventListener(), or the binding features of a framework like jQuery (.delegate() or .keyup(), e.g.).
Note that if you do bind the function to the event, you won't have to explicitly pass in the value argument. You should be able to work with a field's value within the function via this.value. So you'd have something like this:
var checkNumber = function () {
if ( isNaN( this.value ) ) {
alert('Bad!');
// clean up field? highlight in red? etc.
} else {
// call your calculation function
}
}
And then (with a naive binding approach by ID):
document.getElementById('id_of_a_field').addEventListener('keyup', checkNumber, true);
Can't you just initialize the text box with a default value, say 0?
Why don't you use 3 different functions or an argument to identify which of the inputs the user is pressing? If each of the inputs calls checkNumber(1), checkNumber(2) and checkNumber(3) you can only validate the input that the user is using instead of validating all 3 at the same time.
Alternatively you can use input validation and instead of an alert just return false to prevent the user from inputing invalid chars
How about use short-circuit evaluation with jsFiddle example
EDIT for parseFloat:
function checkNumber()
{
var sInput = parseFloat(document.getElementById('sInput').value || 0);
var dInput = parseFloat(document.getElementById('dInput').value || 0);
var pInput = parseFloat(document.getElementById('pInput').value || 0);
if (isNaN(sInput) || isNaN(dInput) || isNaN(pInput)) {
alert("You entered an invalid character. Please press 'Reset' and enter a number.");
}
}
So if pInput is undefined just use 0, but if the input has value then use that value.
SIDE NOTE: white space is actually a number, +' '; // 0