I wrote some code using jQuery to convert <input> field values from one unit system to another (English <-> Metric). All was going well until I have realized that I am using a class selector, so instead of each value doing its conversion individually, all values (with same class) get converted to the same identical value (equal to the first occurrence of class).
An obvious solution is to assign an id to each value, which I suppose will work, but I am here to ask if there is a better way. I have a lot of values (which is why I tried using class), and would like to avoid using id, if possible. But, all I am looking for is "convert each value individually (using my conversion function)". How can this be done?
jQuery
function convertValues() {
if ($('#unit_system').val() == "English") //if changed to English
{
$('.value_gpm').val( //do converstion from Metric to English
convert($('.value_gpm').val(), "m3h", "gpm")
);
}
else if ($('#unit_system').val() == "Metric") //if changed to Metric
{
$('.value_gpm').val( //do conversion from English to Metric
convert($('.value_gpm').val(), "gpm", "m3h")
);
}
}
Calling Function
//below code is for select box (HTML for it is not shown)
$("#unit_system").change(function(){ //select box change detected
convertValues(); //function is called
});
HTML at first (before Select box change)
<input type="text" class="value_gpm" name="design_a" value="444" />
<input type="text" class="value_gpm" name="design_b" value="555" />
<input type="text" class="value_gpm" name="design_c" value="666" />
<input type="text" class="value_gpm" name="design_d" value="777" />
<input type="text" class="value_gpm" name="design_e" value="888" />
HTML after (after Select box is changed)
<input type="text" class="value_gpm" name="design_a" value="1954.87" />
<input type="text" class="value_gpm" name="design_b" value="1954.87" />
<input type="text" class="value_gpm" name="design_c" value="1954.87" />
<input type="text" class="value_gpm" name="design_d" value="1954.87" />
<input type="text" class="value_gpm" name="design_e" value="1954.87" />
Expected behavior: conversion produces different value per row
Actual behavior: same value produced for each row
Just loop through them, something like this.
var inputs = $('.value_gpm');
for(i=0;i < inputs.length; i++){
var input = inputs[i];
input.val( convert(input.val(), "m3h", "gpm") );
}
Best bet - using $.each and $(this).
$(document).ready(function(){
var valueEls = $('.value_gpm');
$("#unit_system").change(function(){
var unit = $(this).val();
switch(unit){
case "English":
valueEls.each(function(){
$(this).val(convert($(this).val(), "m3h", "gpm");
});
break;
case "Metric":
valueEls.each(function(){
$(this).val(convert($(this).val(), "gpm", "m3h");
});
break;
}
});
});
Use each()
$("value_gpm").each(function () {
convert(this.val(), ...etc
The less lines of codes I figure out for this is this:
var unit_system = $('#unit_system').val();
$('.value_gpm').each(function(){
convert($(this).val(), unit_system == "English" ? "m3h" : "gpm", unit_system == "English" ? "gpm" : "m3h");
});
You can use jQuery each:
$("#unit_system").change(function(){
var fromUnit = "m3h";
var toUnit = "gpm";
if ($(this).val() == "Metric"){
fromUnit = "gpm";
toUnit = "m3h";
}
$('.value_gpm').each(function(){
$(this).val(convert($(this).val(), fromUnit, toUnit));
});
});
Related
I have the following input field and a checkbox:-
<input id="ClientManagerApproval_e565da24-d454-4537-b902-771a37689e9d_MultiChoiceOption_0" type="checkbox">
<input type="text" value="" id="ProjectManHoursUsed_becead30-410d-42de-872e-c12ad4c322b2_$NumberField" title="Man Hours Used" size="11" class="ms-input" style="ime-mode : inactive">
now what i am trying to do inside jQuery, if that if the checkbox is checked then the user must enter a value inside the input field, i tried this but it did not work (the alert will never show!)
if ($("[id^=ProjectManHoursUsed_]").value === "" && $("[id^=ClientManagerApproval_]").is(':checked'))
{
alert("Please enter Man Hour Used before setting the stage to Closure approval");
result = false;
}
JQuery has its own function for getting values. Replace
$("[id^=ProjectManHoursUsed_]").value
by
$("[id^=ProjectManHoursUsed_]").val()
See here:
$("button").on("click", function(){
if ($("[id^=ProjectManHoursUsed_]").val() === "" && $("[id^=ClientManagerApproval_]").is(':checked')){
alert("Please enter Man Hour Used before setting the stage to Closure approval");
result = false;
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="ClientManagerApproval_e565da24-d454-4537-b902-771a37689e9d_MultiChoiceOption_0" type="checkbox">
<input type="text" value="" id="ProjectManHoursUsed_becead30-410d-42de-872e-c12ad4c322b2_$NumberField" title="Man Hours Used" size="11" class="ms-input" style="ime-mode : inactive">
<button>submit</button>
You can achieve the result you're looking by using the following code snippet without needing any jQuery at all:
if (document.querySelector('.chkbx').checked) { // I'd recommend using class instead of id, here chkbx if the class attr of the checkbox input -> class="chkbx"
alert("Please enter Man Hour Used before setting the stage to Closure approval");
result = false;
}
You are trying to check if value is empty when value is undefined. If you want to make sure if there's any value, you can use ! operator. You should use === to make sure for empty string over null.
I just changed your code from $("[id^=ProjectManHoursUsed_]").value === "" to !$("[id^=ProjectManHoursUsed_]").value and it's working fine.
function testMe() {
let result = true
if (!$("[id^=ProjectManHoursUsed_]").val() && $("[id^=ClientManagerApproval_]").is(':checked'))
{
alert("Please enter Man Hour Used before setting the stage to Closure approval");
result = false;
}
return result
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form onSubmit="return testMe();">
<input id="ClientManagerApproval_e565da24-d454-4537-b902-771a37689e9d_MultiChoiceOption_0" type="checkbox"/>
<input type="text" value="" id="ProjectManHoursUsed_becead30-410d-42de-872e-c12ad4c322b2_$NumberField" title="Man Hours Used" size="11" class="ms-input" style="ime-mode : inactive"/>
<input type='submit' value="Click"/>
</form>
Im trying to write a validation for 2 groups of fields. I have 6 inputs, 3 for text name and 3 more for id number... the validation should do this "if input name="RE_SignedByID" has an input type name="RE_SignedByName", then other inputs name="RE_SignedByID", should NOT contain the same name="RE_SignedByName" More easy explanation... one ID number should have only one Person Name (Id number is unique for one person name). What can I use for that? Should I map() all the inputs?
Those are my inputs:
<div id="signedBy" class="clearfix">
<label>Signer, person ID & name</label>
<span id="signedByID" class="ids half">
<input type="text" name="RE_SignedByID" placeholder="personID, person1" data-validate="" tabindex="101" required>
<input type="text" name="RE_SignedByID" placeholder="personID, person2" data-validate="" tabindex="103">
<input type="text" name="RE_SignedByID" placeholder="personID, person3" data-validate="" tabindex="105">
</span>
<span class="names half">
<input type="text" name="RE_SignedByName" placeholder="name, person1" tabindex="102" required>
<input type="text" name="RE_SignedByName" placeholder="name, person2" tabindex="104">
<input type="text" name="RE_SignedByName" placeholder="name, person3" tabindex="106">
</span>
</div>
I guess it should also be an "on change" function? or can I make the validation on click? Some ideas...? Im actually compleatley lost here...
Thanks in advance!!!
Maybe use different class names for all 3 of them to make them unique?
<input class="name1">
<input class="name2">
<input class="name3">
I'm not sure what you mean but if you want to make the input types unique and not call them all when you write class="names half", then you should give them all unique class names.
So from my understanding you don't want multiple fields to have the same value.
My approach would be this:
let inputTimeout = null; //set an empty timeout object
let vars = [null, null, null, null]; // create an array containing as many nulls as you have inputs
$('.nameInput').on('keyup', function(){
let self = $(this);
clearTimeout(inputTimeout); //clear the timeout
inputTimeout = setTimeout(function(){ //set a timeout to check whether there is a dupe after the user has stopped typing
if (vars.indexOf(self.val()) == -1){ //check if the vals array contains the newly entered string
vars[self.attr('data-inputnum')] = self.val(); //insert the value into the array
}else{
//handle duplicates here
}
}, 500); //500ms is a sensible value for end of user input, change it if users complain that your app is too fast/slow
});
You then just have to edit your HTML a bit so that all name inputs have a class in common (i used .nameInput) and have a data-inputnum attr.
This would look something like this:
<input type="text" name="RE_SignedByName" placeholder="name, person1" tabindex="102" class='nameInput' data-whichinput='0'/>
<input type="text" name="RE_SignedByName" placeholder="name, person2" tabindex="103" class='nameInput' data-whichinput='1'/>
<!--and so on-->
Of course, never rely on JavaScript verification alone, always also check inside your backend. However this would be out of scope for this answer.
Hi Thanks all for the help, made me realize a couple of things till I got the answer. This is my working code:
var valSignedID = $("[name=SignedByID]").map(function() {
return this.value.trim();
}).get();
var valOwnersID = $("[name=OwnersID]").map(function() {
return this.value.trim();
}).get();
valSignedID.sort();
valOwnersID.sort();
for (var i = 0; i < valSignedID.length - 1; i++) {
if (valSignedID[i] == valSignedID[i + 1] && valSignedID[i] != "") {
alert(" You can not have duplicated signers ID's");
return false;
// break;
}
}
for (var i = 0; i < valSingedName.length; i++) {
if (valSingedName[i] == valSingedName[i + 1] && valSingedName[i] != "") {
alert(valSingedName[i] + " should not have different ID");
//return false;
}
}
I am trying to update two input fields in a form when clicking one button. I actually had all the code right when using document.getElementById, but the form that I'm using strips the ID's I set away, so I can't use getbyid. If I know the form field name, how could I change my function to do the same thing? Please note that my form has more than two fields, including a submit button, so I don't want to update those.
This is what I used before (with the ID selector)
Html:
<input type="text" name="field-1" id="info1">
<input type="text" name="field" id="info2">
Populate
JS:
function addTxt(val, id,no)
{
var id = id;
for(var i=1;i<=no;i++){
document.getElementById(id+i).value = val[i-1];
}
}
Fiddle:
http://jsfiddle.net/qwz47phx/3/
Edited with a much simpler and readable approach
function addVal(obj) {
event.preventDefault(); // Prevent page scrolltop on anchor click
$.each(obj, function(k, v) {
$("input[name='"+ k +"']").val( v );
})
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" name="foo">
<input type="text" name="bar">
<a href="#" onclick='addVal({foo:"Hello", "bar-baz":"World"})'>Populate</a>
Or with native JS (ES5+):
function addVal(obj) {
Object.keys(obj).forEach(function(name) {
document.querySelector('input[name="' + name + '"]').value = obj[name];
});
}
<input type="text" name="foo">
<input type="text" name="bar">
<input type="text" name="name-with-dashes">
<a href="#" onclick='addVal({foo:"Hello", bar:"World", "name-with-dashes": "Works !"})'>Populate</a>
If you have problems with IDs you can use querySelector to select inputs by name like this:
JS:
function addTxt(val, id, no) {
for (var i = 1; i <= no; i++) {
document.querySelector('input[name="' + id + i + '"]').value = val[i - 1];
}
}
HTML:
<input type="text" name="info1" id="info1">
<input type="text" name="info2" id="info2">
Populate
Demo: http://jsfiddle.net/iRbouh/qwz47phx/6/
I hope this will help you.
You can use a jQuery attribute= selector to grab by name instead of ID.
function addTxt(val, id,no)
{
for(var i=1;i<=no;i++){
var name = id+i;
$("input[name='"+name+"']").val(val[i-1]);
}
}
Please note that this function will be looking for names of info1, info2, info3, etc, just as your original script did. However, in the HTML, you have names of info and info-1. Either the names will have to be changed to fit the function, or the function can be slightly more intricate.
Fiddle: http://jsfiddle.net/qwz47phx/8/
Ok, I've checked a lot of other answers but the solutions posted there are beyond the scope of the class I am taking. IE we haven't discussed how to do it that way.
Anyways, I'm simply trying to get the value from a radio button here is my html code and my javascript.
<script type="text/javascript">
function bookTrip()
{
var arrivalcity;
arrivalcity = document.reservations.radCity.value;
alert(arrivalcity);
}
</script>
and the actual button looks like this in my html code.
Milwaukee: ($20) <input type="radio" name="radCity" value="20" />
When I alert(arrivalcity); all I get is NaN. I don't understand why, shouldn't it return the string 20??
Allow me to clarify. I have 3 different city choices. I have edited it to show exactly what I have when I begin my form.
<form name="reservations">
<p>First Name: <input type="text" name="txtFirstName" />
Last Name: <input type="text" name="txtLastName" /></p>
<span style="font-weight:bold;">Arrival City:</span><br />
Milwaukee: ($20) <input type="radio" name="radCity" value="20" /><br />
Detriot: ($35) <input type="radio" name="radCity" value="35" /><br />
St. Louis: ($40) <input type="radio" name="radCity" value="40" />
I need to get the value from whatever one is selected. I can't hardcode it into my script.
This function will do what you want, through the querySelector method:
function selectedRadio(){
var selValue = document.querySelector('input[name="radCity"]:checked').value;
alert(selValue);
}
JSFiddle
Reference
Do you have a form named reservation in your body?
It will work like this:
<form name="reservations">
<input type="radio" name="radCity" value="20" />
</form>
function bookTrip()
{
var arrivalcity;
arrivalcity = document.reservations.radCity.value;
alert(arrivalcity);
}
See it running here: http://jsfiddle.net/eBhEm/
However, I would prefer this instead:
<input type="radio" id="radCity" value="20" />
And then use getElementById
function bookTrip()
{
var arrivalcity;
arrivalcity = document.getElementById("radCity").value;
alert(arrivalcity);
}
See this running on jsfiddle.
function bookTrip() {
var arrivalcity= document.reservations.radCity;
for (var i = 0, iLen = arrivalcity.length; i < iLen; i++) {
if (arrivalcity[i].checked) {
alert(arrivalcity[i].value);
}
}
}
i believe this should help.
see it working here
http://jsfiddle.net/eBhEm/24/
You can use querySelector in browsers that support it, but not all browsers in use do. The old fashioned (reliable, robust, works every where) method is to loop over the collection to find the one that is checked:
function getValue() {
var buttonGroup = document.forms['reservations'].elements['radCity'];
// or
// var buttonGroup = document.reservations.radCity;
// Check for single element or collection, collections don't have
// a tagName property
if (typeof buttonGroup.tagName == 'string' && buttonGroup.checked) {
return buttonGroup.value;
} else {
// Otherwise, it's a collection
for (var i=0, iLen=buttonGroup.length; i<iLen; i++) {
if (buttonGroup[i].checked) {
return buttonGroup[i].value;
}
}
}
}
Note that the test between an HTMLCollection and DOM element uses a property that DOM elements must have but an HTMLCollection should not have, unless a member of the collection has a name of "tagName".
I am trying to attach a calendar field to a dynamically added html code.
Initially, the code shows 3 input fields (as shown in the "p_scents" div).
When the "Add Another Employer" is clicked, it should generate another 3 inputs( as the ones above).
It is working fine for me to generate the first 2 fields (without the calendar field), but when I add the calendar field, it is not working.
<body>
<h2>Add Another Employer</h2>
<div id="p_scents">
<p>
<label>Employer Name</label><input class="dynamic" type="text" name="employern" id="employern" />
<label>Job Title</label><input class="dynamic" type="text" name="jtitle" id="jtitle" />
<label>Start Date </label>
<input type="text" name="startd" class="textfield" />
<script language="JavaScript">
new tcal ({
// form name
'formname': 'form',
// input name
'controlname': 'startd'
});
</script>
</p>
</div>
<script type="text/javascript">
$(function() {
var scntDiv = $('#p_scents');
var i = $('#p_scents p').size() + 1;
$('#addScnt').live('click', function() {
if( i <= 10 ) {
$('<p><label>Employer Name</label><input class="dynamic" type="text" name="employern' + i +'" id="employern" /><label>Job Title</label><input class="dynamic" type="text" name="jtitle' + i +'" id="jtitle" /><label>Start Date </label>
<input type="text" name="startd' + i +'" class="textfield" />
<script language="JavaScript">
new tcal ({'formname': 'form','controlname': 'startd' + i +''});</script>Remove</p>').appendTo(scntDiv);
i++;
return false;}
else{
alert('Maximum Reached!');
}
});
$('#remScnt').live('click', function() {
if( i > 2 ) {
$(this).parents('p').remove();
i--;
}
return false;
});
});
</script>
</body>
Sorry, but there is lot of stuff wrong/not good in your code. I'm trying to give some suggestions how to improve this, but first, what's wrong:
IDs have to be unique. In your code, you give multiple elements the same ID. Especially the remove link will not work.
Strings cannot span multiple lines in JavaScript.
Don't add such a bunch of HTML as string. You have a quotation error in this string.
Don't add <script> tags this way (at least here it is not necessary).
My suggestions:
Remove the script tag from the HTML, you don't need it and remove the IDs of the input elements
<h2>Add Another Employer</h2>
<div id="p_scents">
<p>
<label>Employer Name</label><input class="dynamic" type="text" name="employern" />
<label>Job Title</label><input class="dynamic" type="text" name="jtitle" />
<label>Start Date </label>
<input type="text" name="startd" class="textfield" />
</p>
</div>
You also don't need to use live [docs] for the click event handler on #addScnt. Just use click [docs]:
$('#addScnt').click(...
You only need live for elements you add dynamically.
Now the most important thing: How you add new fields.
You can do this very easily, by cloning the existing p element. The only thing you have to remember is to change the name of input fields (add the i) and call the tcal function:
$('#addScnt').click(function() {
if (i <= 10) {
$('#p_scents p:first').clone() // clone
.find('input').attr('name', function(index, value) { // change name
return value + i;
}).end()
.append('Remove') // add remove link
.appendTo(scntDiv);
// init calender
new tcal({
formname: 'form',
controlname: 'startd'+i
});
i++;
return false;
}
else {
alert('Maximum Reached!');
}
});
Reference: clone [docs], attr [docs]
Note that the remove link has a class, not an id. For this link it is better to use delegate [docs]:
$('#p_scents').delegate('.remScnt', 'click', function() {
if (i > 2) {
$(this).closest('p').remove();
i--;
}
return false;
});
Also note that I use closest [docs] here, which only gives the closest p element. If you use parents, you will remove all ancestor p elements and that might result in removing a lot more than you intended.
Last but not least, you also have to make a call to
new tcal ({
// form name
'formname': 'form',
// input name
'controlname': 'startd'
});
because we removed the script tag.
Here is a working demo of all that: http://jsfiddle.net/fkling/ygSn9/ (with empty tcal function).