Value not displaying in correct input - javascript

I have a 2 row table with input fields that does a calculation when I focusout on the first input. The problem I am experiencing is when I focusout on the second row, my new value is displayed in the first row corresponding input. I'm not sure why this is happening. I would greatly appreciate your help.
My expectation is when I enter a value in a row input (Cost) and focusout the new value should be set in the same row but in the input (New Cost).
function Calculate(element) {
var dollar = 216.98;
var id = element.id;
var oldcost = $(element).val();
var newcost = oldcost * dollar;
$("#" + id).closest("tr").find("td #new").val(newcost);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<th>Cost</th>
<th>New Cost</th>
</tr>
<tr>
<td><input type="number" id="old" onfocusout="Caluculate(this)" /></td>
<td><input type="number" new="new" /></td>
</tr>
<tr>
<td><input type="number" id="old" onfocusout="Caluculate(this)" /></td>
<td><input type="number" new="new" /></td>
</tr>
</table>

There's several issues here. Firstly you're repeating the same id attribute which is invalid; they must be unique. I'd suggest using a class instead. Secondly, there's is no new attribute. I presume that's a typo and should be an id, but again see my first point.
Next, the function you defined is named Calculate() yet the call is to Caluculate().
Then you should also be using unobtrusive event handlers as on* event attributes are very outdated and should be avoided where possible. As you've already included jQuery in the page you can use the on() method. The input event would seem to be more applicable to your usage as well, especially given it also catches the up/down arrow usage on the number control, although you can change this to blur if preferred.
Finally, it's a simply a matter of amending your DOM traversal logic to work with the new classes, like this:
var dollar = 216.98;
$('.old').on('input', function() {
var oldcost = $(this).val();
var newcost = oldcost * dollar;
$(this).closest("tr").find(".new").val(newcost);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<th>Cost</th>
<th>New Cost</th>
</tr>
<tr>
<td><input type="number" class="old" /></td>
<td><input type="number" class="new" /></td>
</tr>
<tr>
<td><input type="number" class="old" /></td>
<td><input type="number" class="new" /></td>
</tr>
</table>

Your use of id's is kind of messed up. First of all be sure to use an id once in the entire HTML file.
For your usecase better use classes.
Also be sure to type your function names correct ;)
function Calculate(element) {
var dollar = 216.98;
var parent = $(element).closest('tr');
var oldcost = $(element).val();
var newcost = oldcost * dollar;
parent.find(".new").val(newcost.toFixed(2));
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<th>Cost</th>
<th>New Cost</th>
</tr>
<tr>
<td><input type="number" class="old" onfocusout="Calculate(this)" /></td>
<td><input type="number" class="new" /></td>
</tr>
<tr>
<td><input type="number" class="old" onfocusout="Calculate(this)" /></td>
<td><input type="number" class="new" /></td>
</tr>
</table>

They have the same ID. You need to make the ID different

Firstly, there is a a typo.Change caluculate to calculate
There must not be the same id two elemnts have the same id.You could change the id of the first to old-1 or something different

Related

How to read input values based on checkbox checked?

How can I get the input value inside of the table that is associated with the next checkbox? I just need to get only those input values whose checkbox is checked. Display the value as an innerHTML of div comma separated.
I can get all the input value but I am not able to apply the logic for the checkbox
I tried for all the input box values.
let olist = [...document.querySelectorAll('table tbody tr')].map(row => {
const childs = row.querySelectorAll("input");
return {
oKey: parseInt(childs[1].value),
}
})
function checkboxChecked(event) {
let final = document.getElementById("final");
}
<table>
<thead>
<tr>
<td>Checbox</td>
<td>Key</td>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" onclick="checkboxChecked(event)"></td>
<td><input type="number" value=1></td>
</tr>
<tr>
<td><input type="checkbox" onclick="checkboxChecked(event)"></td>
<td><input type="number" value=2></td>
</tr>
<tr>
<td><input type="checkbox" onclick="checkboxChecked(event)"></td>
<td><input type="number" value=3></td>
</tr>
</tbody>
</table>
<div id="final"></div>
You are using the Array.prototype.map() function to create an array with transformed values. That's fine. But you want to include only values where the corresponding checkbox is checked. You can do that by adding a call to the Array.prototype.filter() function.
There are multiple ways to do this. One of the easiest solutions would be to first call map() to create an array with items containing the checkbox values and the corresponding number values, then use filter() to create an array with only the checked items, and then use map() again to get an array with the resulting number values. Something like this:
let olist =
[...document.querySelectorAll('table tbody tr')]
.map(row => {
const children = row.querySelectorAll('input');
return {
checked: children[0].checked,
value: parseInt(children[1].value)
}
})
.filter(item => item.checked)
.map(item => item.value)
document.getElementById('final').innerHTML = olist.join(', ')
Note that you can probably omit the parseInt call inside the first map callback function as well, because afterwards you are just concatenating those values into a string again.
Edit
An even shorter alternative would be something like this:
let olist =
[...document.querySelectorAll('table tbody tr')]
.filter(row => row.querySelector('input[type=checkbox]').checked)
.map(row => row.querySelector('input[type=number]').value)
document.getElementById('final').innerHTML = olist.join(', ')
function checkboxChecked(event) {
let checkBox=event.path[0]
let input=event.path[2].children[1].children[0]
console.log(`Box Checked: ${checkBox.checked}\nValue: ${input.value}`)
}
<table>
<thead>
<tr>
<td>Checbox</td>
<td>Key</td>
</tr>
</thead>
<tbody>
<tr>
<td><input type="checkbox" onclick="checkboxChecked(event)"></td>
<td><input type="number" value=1></td>
</tr>
<tr>
<td><input type="checkbox" onclick="checkboxChecked(event)"></td>
<td><input type="number" value=2></td>
</tr>
<tr>
<td><input type="checkbox" onclick="checkboxChecked(event)"></td>
<td><input type="number" value=3></td>
</tr>
</tbody>
</table>
<div id="final"></div>

Checkbox click event

I have a group of checkboxes inside a table where I want to change the value of a different column in the row when the checkbox is checked. I have researched for a solution but nothing I have found seems to solve my problem. I realize that my stumbling block is my unfamiliarity with jquery so any suggestions would help. Ultimately I wish to total the columns where the change has occurred to get a total. So if an answer included ideas about that as well I would not complain. Thanks as always, you are a great group.
HTML
<tr>
<td><input name="amputeeGolfer" type="checkbox" id="amputeeGolfer" value="amputee" onchange="changeFee"/>
<label for="amputeeGolfer">Amputee Golfer</label></td>
<td align="left"><label for="amputeeFee">$50.00</label></td>
<td></td>
<td><input name="amputeeFee" type="number" id="amputeeFee" class="tblRight" size="10" value="0.00"/></td>
</tr>
jquery
<script>
function changeFee(val) {
$('#amputeeFee').val(), "$50.00";
}
</script>
Fully functioning snippet. No jQuery required!
When the onchange event fires, it checks whether the checkbox was just checked or unchecked, and toggles the price accordingly. It can even be combined with all sorts of other checkboxes.
function togglePrice(element,price){
if(element.checked){
document.getElementById("amputeeFee").value = parseInt(document.getElementById("amputeeFee").value) + price;
}else{
document.getElementById("amputeeFee").value = parseInt(document.getElementById("amputeeFee").value) - price;
}
}
<tr>
<td><input name="amputeeGolfer" type="checkbox" id="amputeeGolfer" value="amputee" onchange="togglePrice(this,50);"/>
<label for="amputeeGolfer">Amputee Golfer</label></td>
<td align="left"><label for="amputeeFee">$50.00</label></td>
<td></td>
<td><input name="amputeeFee" type="number" id="amputeeFee" class="tblRight" size="10" value="0"/></td>
</tr>
It works perfectly and you can even set how much the checkbox adds to the cost!
You can get closest tr closest('tr') to assure input in same row with check box and find input with name find("input[name='amputeeFee']") and change value for it.
function changeFee(val) {
var amputeeFee = $(val).closest('tr').find("input[name='amputeeFee']");
if($(val).prop("checked")){
amputeeFee.val(50.00);
}
else{
amputeeFee.val(0);
}
}
function changeFee(val) {
var amputeeFee = $(val).closest('tr').find("input[name='amputeeFee']");
//console.log(amp.length);
if($(val).prop("checked")){
amputeeFee.val(50.00);
}
else{
amputeeFee.val(0);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td><input name="amputeeGolfer" type="checkbox" id="amputeeGolfer" value="amputee" onchange="changeFee(this)"/>
<label for="amputeeGolfer">Amputee Golfer</label></td>
<td align="left"><label for="amputeeFee">$50.00</label></td>
<td></td>
<td><input name="amputeeFee" type="number" id="amputeeFee" class="tblRight" size="10" value="0.00"/></td>
</tr>
</table>
To call a JavaScript function like changeFee(val) in an HTML's element event, the funciton has to be called as the same in the script. As all functions in an HTML' event: <element onclick="myFunction()">, and not <element onclick="myFunction"> beacuse it doesn't reconize it's a function in JavaScript.
Then the code will be:
<tr>
<td><input name="amputeeGolfer" type="checkbox" id="amputeeGolfer" value="amputee" onchange="changeFee(this.value)"/>
<label for="amputeeGolfer">Amputee Golfer</label></td>
<td align="left"><label for="amputeeFee">$50.00</label></td>
<td></td>
<td><input name="amputeeFee" type="number" id="amputeeFee" class="tblRight" size="10" value="0.00"/></td>

How to change the node when blur event occur?

Source HTML structure.
<table>
<tr>
<td>class</td>
<td><input type="text" id="data1"></td>
</tr>
<tr>
<td>name</td>
<td><input type="text" id="data2"></td>
</tr>
</table>
Event: The Source HTML struture turns into the Target HTML struture after typing test1 in input whose id is data1 and mouse focus go out of the input.
Target HTML structure.
<table>
<tr>
<td>class</td>
<td>test1</td>
</tr>
<tr>
<td>name</td>
<td><input type="text" id="data2"></td>
</tr>
</table>
Here is my JS.
function changeNode(event){
ob =document.activeElement;
_str = ob.value;
ob.parentNode.removeChild(ob);
ob.parentNode.innerText = _str;
}
document.addEventListener("blur",changeNode,true);
Why my JS can't achieve my expected target?
How to fix it?
You are selecting the active element while the event is that an object's focus is lost.
You should select event.target as ob and your code should work:
Also: you don't need to delete the object, your overriding all inner text so the object is automatically deleted.
function changeNode(event){
ob = event.target;
_str = ob.value;
ob.parentNode.innerText = _str;
}
document.addEventListener("blur",changeNode,true);
<table>
<tr>
<td>class</td>
<td><input type="text" id="data1"></td>
</tr>
<tr>
<td>name</td>
<td><input type="text" id="data2"></td>
</tr>
</table>
Several problems in your code:
You need to add the event listener to the input itself, not the document object. You can then simply use event.target instead of activeElement (input is no longer active after the blur event…)
You're trying to access ob.parentNode after removing ob. Try storing it in a variable first:
function changeNode(event) {
var ob = event.target;
var cell = ob.parentNode;
var _str = ob.value;
cell.removeChild(ob);
cell.innerText = _str;
}
document.querySelectorAll("input").forEach(function(input) {
input.addEventListener("blur", changeNode);
});
<table>
<tr>
<td>class</td>
<td><input type="text" id="data1"></td>
</tr>
<tr>
<td>name</td>
<td><input type="text" id="data2"></td>
</tr>
</table>
Note: querySelectorAll(…).forEach
might not be reliable in some old browsers, if you need to support them, see css-tricks.com: Loop Over querySelectorAll Matches
function changeNode(event){
var ob=event.target;
ob.parentNode.append(ob.value);
ob.parentNode.removeChild(ob);
}
document.getElementById("data1").addEventListener("blur",changeNode,true);
<table>
<tr>
<td>class</td>
<td><input type="text" id="data1"></td>
</tr>
<tr>
<td>name</td>
<td><input type="text" id="data2"></td>
</tr>
</table>
function changeNode(event) {
var ob = event.target;
var cell = ob.parentNode;
var _str = ob.value;
cell.removeChild(ob);
cell.innerText = _str;
}
document.addEventListener("blur",changeNode,true);

Applying AutoNumeric.js to an entire class

I would love if someone could help me with what i thought would be a simple application of AutoNumeric.js. I have the below code:
Fiddle link: https://jsfiddle.net/yu1s9nrv/8/
<table id="shareInput" class="table_standard">
<tr>
<th>Name</th>
<th>Quantity</th>
<th>Price</th>
<th>Growth</th>
<th>Yield</th>
</tr>
<tr>
<td><input type="text" class="input_field_large" id="shareName" value=""></td>
<td><input type="text" class="input_field_medium_num" id="shareQty" value=""></td>
<td><input type="text" class="input_field_medium_dollar" id="sharePrice" value=""></td>
<td><input type="text" class="input_field_medium_pct" id="shareGrowth" value=""></td>
<td><input type="text" class="input_field_medium_pct" id="shareYield" value=""></td>
</tr>
<tr>
<td><input type="text" class="input_field_large" id="shareName" value=""></td>
<td><input type="text" class="input_field_medium_num" id="shareQty" value=""></td>
<td><input type="text" class="input_field_medium_dollar" id="sharePrice" value=""></td>
<td><input type="text" class="input_field_medium_pct" id="shareGrowth" value=""></td>
<td><input type="text" class="input_field_medium_pct" id="shareYield" value=""></td>
</tr>
</table>
<script>
window.onload = function() {
const anElement = new AutoNumeric('.input_field_medium_pct', 0, {
suffixText: "%"
});
};
</script>
The output I expect is for all the fields with the class input_field_medium_pct to have the desired AutoNumeric formatting, however it only formats the first field with that class. The documentation reads:
// The AutoNumeric constructor class can also accept a string as a css
selector. Under the hood this use QuerySelector and limit itself to
only the first element it finds. anElement = new
AutoNumeric('.myCssClass > input'); anElement = new
AutoNumeric('.myCssClass > input', { options });
Taken from: https://github.com/autoNumeric/autoNumeric#initialize-one-autonumeric-object
I'm new to JS the and find the AutoNumeric documentation notes to be slightly confusing, has anyone run into this issue or able to shed some light on why this might be the case? Thanks in advance.
You need to use Autonumeric.multiple to apply it to multiple elements as once.
const anElement = AutoNumeric.multiple('.input_field_medium_pct', 0, {
suffixText: "%"
});
Check the working jsfiddle
Also, check the documentation https://github.com/autoNumeric/autoNumeric#initialize-multiple-autonumeric-objects-at-once

using js functions within js functions in html.erb

ok should be an easy one for everyone,...
i am calling a javascript function in the tag of a button using inclick. Im trying to get that function to have three different parameters. The function then submits three different times, which should end up being three different records in a ruby table.
But i cant see why this doesnt work...
<script>
function submiteffort( elem )
{
// Elem 1
$("#effort_hours").val( $( elem ).val() );
$("#task_id").val( elem.id );
$("#effort_form").submit();
return true;
}
function medium( leave, toil, sick)
{
var dave = submiteffort(document.getElementsByName(leave));
if(dave == true){
var dave2 = submiteffort(document.getElementsByName(toil));
}
if(dave2 == true){
submiteffort(document.getElementsByName(sick));
}
}
</script>
<div class="startleft">
<table>
<tr>
<td>Leave</td>
<td><input class="dayinput" type="text" name="Leave" placeholder="0" ></td>
</t>
<tr>
<td>TOIL</td>
<td><input class="dayinput" type="text" name="TOIL" placeholder="0"></td>
</tr>
<tr>
<td>Sick</td>
<td><input class="dayinput" type="text" name="Sick" placeholder="0"></td>
</tr>
<tr>
<td>Total</td>
<td><input id="total" class="total_low" type="text" value="0" disabled="" name="Dave">
</tr>
<tr>
<td></td>
<td><button onclick="medium('Leave','TOIL','Sick')">Commit</button></td>
</tr>
</table>
</div>
For some reason this only submits 1 record into the table and i cant figure out why.
Well if you submit the form, the page refreshes, and the other 2 function calls don't execute. You'd have to use AJAX to send data to the backend in 3 separate function calls.

Categories

Resources