onChange triggers only once in a while - javascript

i have the following problem:
I have a table with 2 input elements. If one of them bigger than the other, the whole row is supposed to be colored accordingly to the comparison. I trigger this with an onchange event and the first time while loading the site. The procedures work fine, but the onchange event only get triggered in 1 of 4 changes.
The table statement is the following:
<div class="grid">
<table id="table" class="tableRegion w100">
<thead style="text-align:left">
<tr>
<fmt:bundle basename="res/web/ec_resources">
<td class="tableHeader">
...
</td> ...
</fmt:bundle>
</tr>
</thead>
<tbody>
<c:set var="i" value="0"/>
<c:forEach var="participation" items="${someForm.list}">
<tr id="participationRow${i}">
And in here the code for the table > tr > td:
<td class="right bottom nowrap">
<div>
<c:out value="${someForm.event.currency.code}"/>
<fmt:formatNumber maxFractionDigits="2" minFractionDigits="2" var="ovFee" value="${overallFee}" />
<c:if test="${someForm.array[i].feeDebit != 0.0}">
<spring:input class="right debit" path="array[${i}].feeDebit" maxlength="7" size="6" onchange="isPaid(${i});" />
</c:if><c:if test="${someForm.array[i].feeDebit == 0.0}">
<spring:input class="right debit" path="array[${i}].feeDebit" maxlength="7" size="6" onchange="isPaid(${i});" value="${ovFee}"/>
</c:if>
</div>
</td>
<td class="right bottom nowrap">
<div class="padT5"><c:out value="${someForm.event.currency.code}"/> <spring:input class="right paid" path="array[${i}].feePaid" maxlength="7" size="6" onchange="isPaid(${i});"/></div>
</td>
The skript being called is the following:
$(document).ready(function(){
$('#table > tbody > tr').each(function(i) {
var paid = parseFloat($(this).find('input.paid').val());
var debit = parseFloat($(this).find('input.debit').val());
if (paid == debit)
$('#participationRow'+i).addClass("green");
else if (paid > debit)
$('#participationRow'+i).addClass("yellow");
}
);
});
function isPaid(i){
var paid = parseFloat($('#participationRow'+i).find('input.paid').val());
var debit = parseFloat($('#participationRow'+i).find('input.debit').val());
if (paid == debit)
$('#participationRow'+i).addClass("green");
else if (paid > debit)
$('#participationRow'+i).addClass("yellow");
}
What is the reason for the event being triggered just once in a while? I cross-checked with jQuery and onclick. They all get only triggered once in a while. No matter if I leave by clicking away or tabbing away.

Your code lacks any definition of a trigger when this is supposed to run.
The first part (the .each() block) is only executed on $(document).ready();, which means it is executed once per page load (right after the document has finished loading.)
The isPaid() function is nothing more than a function, I don't see where it is being called as it is not present in the current code snippet.
Your code seems OK by itself, but it just lacks any form of trigger.
You would expect something like:
$("input").change(function() {
var the_row = $(this).parent().parent(); //finds the <tr> it belongs to.
var i = the_row.attr("id").replace("participationRow","");
isPaid(i);
});
There are ways to improve on this, but this is the vital key you're missing in your code.

function highlightIfPaid(i){
var paid = parseFloat($('#participationRow'+i).find('input.paid').val());
var debit = parseFloat($('#participationRow'+i).find('input.debit').val());
if (paid == debit)
$('#participationRow'+i).addClass("green");
else if (paid > debit)
$('#participationRow'+i).addClass("yellow");
}
$(document).ready(function(){
//just use jquery for binding to change event,
//my guess is that Spring doesn't have a value for i at the point and jquery is not loaded by then so $ is undefined
$('input.debit').change(function(){
//you need to get the index i based on your table structure
//I assumed this is just the index of the row
//I get this method from this other post http://stackoverflow.com/questions/1620391/find-table-row-index-using-jquery
var i = $(this).closest('tr').prevAll().length;
highlightIfPaid(i);
});
//Dry: highlight your rows on first load
$('#table > tbody > tr').each(highlightIfPaid);
});

Okay... looking a while and with the help of #kabaros und #Flater I found the following which worked:
$(document).ready(function(){
$('input.paid').change(function(){
var i = $(this).closest('tr')[0].sectionRowIndex;
isPaid(i);
});
The solution was the $('input.paid') which got triggered, rather than $('input'). And counting the row was not that easy as well, but the above code counts the rows right. Unfortunately the onchange in the input-field only triggers once in a while!

Related

Struts2: checkbox stuck as selected

I am working on a website made with Struts2 and I am facing a problem with a checkbox.
I have a dropdown with a list of companies. If the user does not find his company in the list, he can click a checkbox to replace the dropdown with a text field. Here is the code:
Extract of the JSP:
<tr>
<td align="right" width="49%">
<table>
<sj:select id="company_select" name="company_select" list="company_list" .../>
</table>
</td>
<td colspan="2" align="left">
<table>
<s:hidden name="company_text" id="company_text" label="Company Type" disabled="true"/>
</table>
</td>
</tr>
<tr>
<td align=left>
<s:checkbox name="checkboxCompanyText" id="checkboxCompanyText" label="Company Not in the List"
fieldValue="false" onchange="showCompanyText()"/>
</td>
<td></td>
</tr>
The JS function:
function showCompanyText() {
if(document.querySelector('#checkboxCompanyText').checked = "true") {
document.getElementById('company_text').type = "visible";
document.getElementById('company_text').disabled = false;
document.getElementById('company_select').style.display = "none";
}else{
document.getElementById('company_text').type = "hidden";
document.getElementById('company_text').disabled = true;
document.getElementById('company_select').style.display = "block";
}
}
When the page loads, the checkbox is unchecked, the dropdown is here and the text input field is not visible. Good. When I check the checkbox, the dropdown goes away and the text field appears. Again: good. But when I try to uncheck the checkbox, it just remains checked, impossible to uncheck it.
If anyone has an idea of what's going on, you are welcome.
Sometimes, your error is so obvious that you don't see it. I sincerely spent several minutes looking at the code trying to figure out what was going on. Turns out the the solution was to transform if(document.querySelector('#checkboxCompanyText').checked = "true") into if(document.querySelector('#checkboxCompanyText').checked === true). Sometimes I hate myself.

How to set index variables in filters and selectors jquery

I have the following row structure that serves as a template to clone it and add it to a table each time a user presses an "Add" button, This template is hidden:
<tr class="plantilla">
<td>
<select class="cmb_arboles" id="cmb_arboles" name="arboles[]">
</select>
</td>
<td>
<input type="text" id="txttoneladas" name="txttoneladas[]"/>
</td>
<td>
<input type="text" id="txtprecio" name="txtprecio[]"/>
</td>
<td>
<select id="cmb_destino" name="destino[]">
</select>
</td>
<td class="eliminar_fila">
Eliminar
</td>
</tr>
When the "add" button is pressed, invokes:
$("#agregar").click(function()
{
nid++;
$("#plantilla tbody tr:eq(0)").clone().attr("id",nid).appendTo("#plantilla tbody");
$("#plantilla tbody tr:eq(nid)").find("td:eq(0)").find("select").attr("id","cmb_arboles_"+nid);
});
The first line, generates the sequence of the row number. The second line clones the entire template as a new row in the table and adds an id = nid to the .
The third line, accesses the row and looks for the select to add the nid sequential to the select id, but this does not work. When doing several tests, I conclude that the problem is that "tr: eq (nid)" does not accept the nid as variable, because when changing the nid by a specific integer, for example 1, it works, adding id to select. The question here is how to put the nid as a parameter in the: eq () so that it works correctly and do what I have explained ????
The same situation happens in the following line of code:
$(document).on('change', '.cmb_arboles', function () {
var $select = $(this);
var $row = $select.closest('tr');
var idd = $row.attr('id');
var valor=$("#tabla tbody tr[id=idd]").find("td:eq(0)").find("select").val();
});
Of lines 1 to 3, you get the number of the row in which you have selected in the select component.
The last line gets the value of the select that was selected, with the information of the row number where the selection was made, but this does not work. When doing several tests, I conclude that the problem is in "tr [id = idd]", which does not correctly process the variable "idd". I made the test of changing the idd by a specific integer, for example 1 and then I generate a new line in the table with id = 1 and the line of code works correctly, returning the option that was selected in the select element.
With these two examples, I want to check if someone can tell me how to place the parameters I mentioned in the two cases, so that the functionality is executed correctly and does what is expected.
I will be enormously grateful.
the issue is you have to give
("#plantilla tbody tr:eq(nid)" as (("#plantilla tbody tr:eq('"+nid+"')"
I have created a fiddle. check it out. I didn't use jquery for the same.
<style>
#template {
display: none;
}
</style>
<table><tbody id="template">
<tr class="plantilla">
<td>
<select class="cmb_arboles" id="cmb_arboles" name="arboles[]">
</select>
</td>
<td>
<input type="text" id="txttoneladas" name="txttoneladas[]" />
</td>
<td>
<input type="text" id="txtprecio" name="txtprecio[]" />
</td>
<td>
<select id="cmb_destino" name="destino[]">
</select>
</td>
<td class="eliminar_fila">Eliminar</td>
</tr></tbody>
</table>
<input type="button" id="agregar" value="Add">
<table>
<tbody id="plantilla"></tbody>
</table>
<script>
var nid = -1;
document.getElementById('agregar').onclick = function(){
var table = document.getElementById('plantilla');
var newRow = document.getElementById('template').innerHTML;
nid++;
newRow = newRow.replace('id="cmb_arboles"', 'id="cmb_arboles_'+nid+'"');
newRow.replace('id="cmb_arboles"', 'id="cmb_arboles_'+nid+'"');
table.innerHTML += newRow;
}
</script>
https://jsfiddle.net/nugee3s6/
You are hard coding the id value in $("#tabla tbody tr[id=idd]") not using the variable above it
If you wanted to use the variable it would be:
$("#tabla tbody tr[id=" +idd +"]")
But it makes no sense to use the ID to search again for the same row since you already have that row element as $row
So change to:
$(document).on('change', '.cmb_arboles', function () {
var $select = $(this);
var $row = $select.closest('tr');
var valor=$row.find("td:eq(0) select").val();
});
Then don't worry about using ID's, you don't need them

How to find next elements using jquery?

In my given example, i have two text boxes. when value in first text box changed i want to find the immediate next text box (note : without id) and change its value.
The example given contains only single text box group. actually it can be more than one text boxes. (group of from & to text boxes of Financial Data)
so, when value in from text box (txtFinancialYearFrom) changed, i want to find the to text box (txtFinancialYearTo) and change its value as well.
JsFiddle Link - Example
Thanks in advance for the help!!
<table class="fotm-table">
<tr>
<td class="text-right" width="120">
<span id="ContentPlaceHolder1_lblFinancialYear">Financial Data :</span>
</td>
<td>
<span>
<input type="text" id="txtFinancialYearFrom"
name="ctl00$ContentPlaceHolder1$txtFinancialYearFrom">
</span>
</td>
<td width="20" align="center">
<span style="align-content: center">to</span>
</td>
<td>
<span>
<input type="text" id="txtFinancialYearTo"
name="ctl00$ContentPlaceHolder1$txtFinancialYearTo">
</span>
</td>
</tr>
</table>
Using the given information, since you are going to have more blocks (that should be rows on your table), this solution should work:
var rows = $('.fotm-table tr');
$(rows).each(function(){
$('input:first', $(this)).on('change', function(){
var fromValue = $(this).val();
var row = $(this).closest('tr');
$('td:last input', row).val(parseInt(fromValue) + 1);
});
});
The code gets all the rows from your table and for each one of them, it will add a listener that when you change the first textbox (input), it will change the value of the next textbox (here it's adding 1 to it).
If I've understood correctly, you need something like this:
/* Loop through all table rows */
$('tr','table.fotm-table').each(function() {
var tr = this;
/* Cache all inputs a jquery object - you may want to specify which type of input you are targeting i.e. $('input[type="text"]') */
var inputs = $('input',tr);
/* Cache the slave (second in the example) input in a jquery object - you can do the same for multiple inputs, simply by modifying the eq() index parameter
*/
var slaveInput = inputs.eq(1);
/* Listen for changes on the master input */
var masterInput = inputs.eq(0).on('change',function() {
/* Do smt on the slave input - fill it with the next year in the example */
var year = $(this).val();
var followingYear = parseInt(year,10)+1
slaveInput.val(followingYear);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table class="fotm-table">
<tr>
<td class="text-right" width="120">
<span id="ContentPlaceHolder1_lblFinancialYear">Financial Year :</span>
</td>
<td>
<span>
<input type="text" id="txtFinancialYearFrom"
name="ctl00$ContentPlaceHolder1$txtFinancialYearFrom">
</span>
</td>
<td width="20" align="center">
<span style="align-content: center">to</span>
</td>
<td>
<span>
<input type="text" id="txtFinancialYearTo"
name="ctl00$ContentPlaceHolder1$txtFinancialYearTo">
</span>
</td>
</tr>
</table>
Here's an updated fork of the jsFiddle you provided:
https://jsfiddle.net/jkdaza/thonfzwu/5/
You can use this tricky solution from link:
$('#txtFinancialYearFrom').change(function(el) {
$(':input:eq(' + ($(':input').index(this) + 1) + ')').val('test');
});
https://jsfiddle.net/g34yqL0u/2/

Using object reference (this) in called function

I have rewritten this question as parts of the original were solved to a simpler solution:
I have a dynamically created table where there will potentially be over 100 table cells () that wont have ID's for them. When a table cell is clicked a onclick event fires and a conditional check is done to determine if it is the first click of a 2 click series or the second click. The conditional determines which value of 2 hidden form fields is set.
Now here is the simple part im trying to accomplish: onclick, IF it is the first click I want the background color of the object that triggered the function to be color1 else if it is the second click then it will be color2.
The code: (JSFiddle Here)
CSS
#test tr td {text-align:center; border: thin black solid;}
SCRIPT
<script>
var x = 0;
var click = 0;
function res(zz) {
if (click == 0) {document.getElementById('start').value=zz; click = 1;} else
{document.getElementById('end').value=zz; click = 0;}
}
</script>
HTML
<form action="" method="POST">
<input type="hidden" name="start" id="start" value="">
<input type="hidden" name="end" id="end" value="">
<input name="submit" type="submit" value="submit" />
</form>
<div id="starget"></div>
<div id="etarget"></div>
<table width="100%" id="test">
<thead>
<tr>
<th>Tech</th><th>0800</th><th>0900</th><th>1000</th><th>1100</th><th>1200</th>
</tr>
</thead>
<tr>
<td>Bill</td>
<td>XXX</td>
<td onclick="res(0900);"></td>
<td>XXX</td>
<td>XXX</td>
<td onclick="res(1200);"></td>
</tr>
</table>
This change works IF i want the background color between the first click and second click to be the same:
<td onclick="res(0900);this.style.backgroundColor='green';"></td>
This below however does not work, since the calling object () passes no reference of itself (this.style....) to the function, however this is in fact the way i need it to work because i need the conditional check to determine what color to set the background to:
function res(zz) {
if (click == 0) {document.getElementById('start').value=zz; click = 1;this.style.backgroundColor='green';} else {document.getElementById('end').value=zz; click = 0;this.style.backgroundColor='red';} }
You simply need to pass 'this' to the function res
Fiddle here:
http://jsfiddle.net/sifriday/r3jaapj5/2/
HTML:
<td onclick="res(0900, this);"></td>
Corresponding JS tweak:
function res(zz, el) {
if (click == 0) {document.getElementById('starget').innerHTML=zz; click = 1; el.style.backgroundColor='green';} else {document.getElementById('etarget').innerHTML=zz; click = 0;}
}

JQuery click event to add or remove table rows

I have a table that has plus or minus glyph-icons at the top that allow the user to add or subtract rows. The code I have works but if the user clicks the minus button too many times it will eat the whole table.
What I have tried is to add an unique ID tag to the rows I add and only delete the TRs with the ID but if 2 rows are added and the minus is pressed both rows will be deleted at once, I only want to delete one row at a time. Note: the code below does not reflect this attempt.
Glyphicons:
<div class="well" style="margin-bottom:0px;" id="addrow">
<span class="glyphicon glyphicon-plus" id="add"></span>
<span class="glyphicon glyphicon-minus" id="minus"></span>
Table:
<table class="table table-bordered table-striped" style="margin-bottom:0px;" id="myTable">
<tr>
<td>Customer Master #</td>
</tr>
<tr>
<td><input type="text" class="form-control" ></td>
</tr>
</table>
JS:
$(document).ready(function(){
$("#addrow").on("click", "span#add", function(){
var tablerow = '<tr><td><input type="text" class="form-control" ></td></tr>'
$("#myTable tr:last").after(tablerow);
})
$("#addrow").on("click", "span#minus", function(){
$('#myTable tr:last').remove();
} )
});
Not sure 100% you want changed with your code, but here is a fiddle which adds or removes - but will not remove the first row (won't eat the whole table).
http://jsfiddle.net/HR5se/
$('#myTable tr .form-control').size()
Will give you how many data (input) rows there are. In this fiddle, I check to see if there's greater than one data row, and if not, the remove doesn't happen.
Note: I turned your glyphs into "+" and "-" text so I could see them here.
See if changing the onclick event to mouseup has any effect. I had a similar problem a while back.
I added an if statement to only allow a row to be taken out if the table has 3 or more rows. This preserves the last two rows that I always want to be on the page.
if ($('#myTable tr').length > 2)
This seemed to solve the problem.
Full code:
$("#addrow").on("click", "span#minus", function(){
if ($('#myTable tr').length > 2) {
$('#myTable tr:last').remove();
};
} )

Categories

Resources