I have been trying to use Jeditable to make my html table editable. However upon much research I found that it is very difficult (if not impossible without a backend) to validate the input.
I really would prefer NOT to use any sort of plugin and simply write/use a bit of Javascript that would make cells editable and allow me to attach jQuery Validator to the input. The data will never get submitted to a backend (will return to default on page refresh) so the solution doesn't need to be complex...will only be using html and Javascript.
The problem with most code snippets I have found using Google is that they seem to get stuck when you click inside a cell and clicking outside the cell doesn't save/submit the change.
Does anyone have a snippet they have used successfully and/or experience using a snippet with Validator?
Well, according to information I got in your another question, you can change that function to:
function appendTable(id)
{
var tbody = document.getElementById(id).getElementsByTagName("tbody")[0];
var i = 0;
var rows = tbody.rows;
for (var r = 0; r < 4; r++) {
var row = rows[r];
for (var c = 0; c < 4; c++) {
var cell = row.cells[c];
cell.firstChild.value = subset[i++]; // the only part changed
}
}
}
when your html looks like:
<table id="alphabetTable" border="1">
<thead>
<tr>
<th>Header1</th>
<th>Header2</th>
<th>Header3</th>
<th>Header4</th>
</tr>
</thead>
<tbody>
<tr>
<td><input type = "text" size="1" /></td>
<td><input type = "text" size="1" /></td>
<td><input type = "text" size="1" /></td>
<td><input type = "text" size="1" /></td>
</tr>
<tr>
<td><input type = "text" size="1" /></td>
<td><input type = "text" size="1" /></td>
<td><input type = "text" size="1" /></td>
<td><input type = "text" size="1" /></td>
</tr>
<tr>
<td><input type = "text" size="1" /></td>
<td><input type = "text" size="1" /></td>
<td><input type = "text" size="1" /></td>
<td><input type = "text" size="1" /></td>
</tr>
</tbody>
</table>
As you could see, I rely on firstChild property, however it can be dangerous, e.g. when your html looks like:
<td> <input type = "text" size=1 /> </td>
then at least FF returns <TextNode textContent=" "> as firstChild. Not to depend on this issue you can go with:
cell.getElementsByTagName("input")[0].value = subset[i++];
PS. All I wrote was based on info I got from another question, if something wrong - comment and I will try to change ;)
Related
I'm new on coding, then any help will greatly appreciated.
I'm trying to make automatic multiplication from 2 value. Basically my table looks like this. Multiplication works perfectly on the first row. If I make another row by simply copying this code:
<tr>
<td><input id="box1" type="text" oninput="calculate()" /></td>
<td><input id="box2" type="text" oninput="calculate()" /></td>
<td><input id="result" /></td>
</tr>
then the second row won't work. This may happen because the id on second row exactly same with the first row. But if I change the id, the script won't work either. Would you please show me how to fix it?
EDIT: I use this scrip for multiplication purpose:
function calculate() {
var myBox1 = document.getElementById('box1').value;
var myBox2 = document.getElementById('box2').value;
var result = document.getElementById('result');
var myResult = myBox1 * myBox2;
result.value = myResult;
}
I would bind a single input event handler to the table, which will catch any input events on any of the table cells' input elements. Within the handler event.target will refer to the input element where the event originated, and you can use DOM navigation properties/methods to find the associated table cells in the same row.
Maybe a little something like this, using class instead of id:
document.getElementById("multiplier").addEventListener("input", function(e) {
var row = e.target.parentNode.parentNode
var val1 = row.querySelector(".valOne").value
var val2 = row.querySelector(".valTwo").value
row.querySelector(".result").value = val1 * val2
})
<table id="multiplier">
<tr>
<td><input class="valOne" type="text" /></td>
<td><input class="valTwo" type="text" /></td>
<td><input class="result" /></td>
</tr>
<tr>
<td><input class="valOne" type="text" /></td>
<td><input class="valTwo" type="text" /></td>
<td><input class="result" /></td>
</tr>
<tr>
<td><input class="valOne" type="text" /></td>
<td><input class="valTwo" type="text" /></td>
<td><input class="result" /></td>
</tr>
</table>
Further reading:
.addEventListener() method
.parentNode property
.querySelector() method
It would be better to use e.target.closest("tr") instead of e.target.parentNode.parentNode, but note that the .closest() method isn't supported in IE so you would need to use a polyfill.
Note that the JS that I've shown would need to be in a script element that is after the table (e.g., at the end of the body right before the closing </body> tag), or you'd need to wrap it in a document load or DOMContentLoaded handler.
I am using javascript cloneNode method to clone a table row which is actually hidden. But the row is being cloned with that hidden property. I dont want that. I want that when that row will be cloned it will have visibility on.
That particular table row is:
<tr style="visibility:hidden;">
<td><input size=25 type="text" id="latbox"/></td>
<td><input size=25 type="text" id="latbox"/></td>
<td><input size=25 type="text" id="latbox"/></td>
<td><input size=25 type="text" id="latbox"/></td>
<td><input size=25 type="text" id="latbox"/></td>
<td><img alt="Icon" src="/assets/add-icon.png" id="addmorePOIbutton" onclick="insRow()" /></td>
<td><img alt="Icon" src="/assets/minus-icon.png" id="delPOIbutton" onclick="deleteRow(this)"/></td>
</tr>
And the javascript code where I am cloning this row is:
var x=document.getElementById('POITable');
var new_row = x.rows[1].cloneNode(true);
x.appendChild( new_row );
So, how to set, rather control the style of the new cloned row?
Please give some hints.
Please give me javascript solutions only (no jquery). I need to develop the project using javascript.
First, use 0 instead 1 for the index.
next you can set style visibility to visible before adding the row to the table.
var x=document.getElementById('POITable');
var new_row = x.rows[0].cloneNode(true);
new_row.style.visibility = "visible";
x.appendChild( new_row )
Here is a fiddler
I have the following form that is created on the fly using Coldfusion. The different inputs all have different values when loaded, but share the same class.
I will have another input field with a unique identifier - #permup
The form is as follows (form tag stripped):
<table width="100%" border="0" cellpadding="0" cellspacing="0" id="county-table" style="margin-top: 15px;">
<tr>
<TD>Length</TD>
<TD align="center">PerM</TD>
</tr>
<tr bgcolor="#ffffff">
<TD>from 1-10m</TD>
<TD align="center"><input class="perm" type="text" name="PerM1" value="1.60" size="6" /></TD>
</tr>
<tr bgcolor="#efefef">
<TD>from 11-20m</TD>
<TD align="center"><input class="perm" type="text" name="PerM2" value="1.10" size="6" /></TD>
</tr>
<tr bgcolor="#ffffff">
<TD>from 21-50m</TD>
<TD align="center"><input class="perm" type="text" name="PerM3" value="1.50" size="6" /></TD>
</tr>
<tr bgcolor="#efefef">
<TD>from 51-80m</TD>
<TD align="center"><input class="perm" type="text" name="PerM4" value="1.55" size="6" /></TD>
</tr>
<tr bgcolor="#ffffff">
<TD>from 81-150m</TD>
<TD align="center"><input class="perm" type="text" name="PerM5" value="1.10" size="6" /></TD>
</tr>
<tr bgcolor="#efefef">
<TD>from 151-200m</TD>
<TD align="center"><input class="perm" type="text" name="PerM6" value="1.10" size="6" /></TD>
</tr>
<tr>
<td> </td>
<td><input id="permup" type="text" name="permup" value="0" size="6" /></td>
</tr>
</table>
What I need is that when someone types the base rate increase in the #permup field, the fields with the class .perm have all their values increased by that amount, and if someone then sets the #permup field to 0 (zero) the fields with .perm are set back to their original value.
This has to work with JQuery on the class name as the table rows could be any number. I have the following script:
<script language="JavaScript" type="text/javascript">
$('#permup').keyup( function() {
$('.perm').each(function(){
var defaultValue = $(this).val();
$(this).val( $('#permup').val() * defaultValue );
});
});
</script>
It kind of works, but sets every value the same in the .perm fields and also does weird stuff when the field #perm is clicked out of or set to zero.
I hope someone can help!!
Many thanks
JS
As others have said you need to make sure you are doing math with numbers and not the default "value" given by the .value property. Also it is not advisable to store values in your display as you run into issues on how to retrieve an old value once you modify it. Below is code that does what you want and keeps track of the original values.
<script language="JavaScript" type="text/javascript">
// Store default values
var perm_items = document.getElementsByClassName("perm");
var orig_perm_values = new Array(perm_items.length);
for (var i = perm_items.length - 1; i >= 0; i--)
{
orig_perm_values[i] = perm_items[i].value;
document.getElementById('out').innerHTML = orig_perm_values[i];
}
function updateValues(event)
{
for (var i = perm_items.length - 1; i >= 0; i--)
{
perm_items[i].value = (parseFloat(orig_perm_values[i]) + parseFloat(event.target.value)).toFixed(2);
}
}
</script>
Try using parseFloat() and use keyup and focus event as shown :-
$('#permup').on('keyup focus', function() {
$('.perm').each(function(){
var defaultval = $('#permup').val();
var myValue;
if(defaultval == "0"){
myValue = $(this).attr('value')
}
else{
myValue = parseFloat( parseFloat($(this).attr('value')) * parseFloat(defaultval) ) || $(this).attr('value')
}
$(this).val( myValue );
});
});
DEMO
Side Note :- Always try to use parseInt() or parseFloat() while dealing in numbers in javascript/jquery otherwise numbers are also treated as string.
I have a jquery / javascript function that totals the number of cubes in my order. this works 100% and is below.
function calculateTotalVolume() {
var grandTotalCubes = 0;
$("table.authors-list").find('input[name^="cubicvolume"]').each(function () {
grandTotalCubes += +$(this).val();
});
$("#grandtotalcubes").text(grandTotalCubes.toFixed(2));
}
as mentioned the above works great. I need a second function to total the same field but only if an checkbox named treated is checked. each row has the checkbox named treated but as the table is dynamically generated, a counter is appended to the name each time hence my use of name^="treated"
I am after something like below but this doesn't work:
function calculateTotalTreatedVolume() {
var grandTotaltreatedCubes = 0;
$("table.authors-list").find('input[name^="cubicvolume"]').each(function () {
if($("table.authors-list").find('checkbox[name^="treated"]').checked){
alert('10');
grandTotaltreatedCubes += +$(this).val();
}
});
$("#grandtotaltreatedcubes").text(grandTotaltreatedCubes.toFixed(2));
}
help appreciated as always.
UPDATE
Rendered HTML output [1 dynamic row added]: (Still in development so very rough, please excuse it)
<table class="authors-list" border=1>
<thead>
<tr>
<td></td><td>Product</td><td>Price/Cube</td><td>Qty</td><td>line total cost</td><td>Discount</td><td>Cubes per bundle</td><td>pcs per bundle</td><td>cubic vol</td><td>Bundles</td><td><input type="checkbox" class="checkall"> Treated</td>
</tr>
</thead>
<tbody>
<tr>
<td><a class="deleteRow"> <img src="http://devryan.tekwani.co.za/application/assets/images/delete2.png" /></a></td>
<td><input type="text" id="product" name="product" />
<input type="hidden" id="price" name="price" readonly="readonly"/></td>
<td><input type="text" id="adjustedprice" name="adjustedprice" /></td>
<td><input type="text" id="qty" name="qty" /></td>
<td><input type="text" id="linetotal" name="linetotal" readonly="readonly"/></td>
<td><input type="text" id="discount" name="discount" /></td>
<td>
<input type="text" id="cubesperbundle" name="cubesperbundle" >
</td>
<td>
<input type="text" id="pcsperbundle" name="pcsperbundle" >
</td>
<td>
<input type="text" id="cubicvolume" name="cubicvolume" size='5' disabled>
</td>
<td><input type="text" id="totalbundles" name="totalbundles" size='5' disabled ></td>
<td valign="top" ><input type="checkbox" id="treated" name="treated" ></td>
</tr>
</tbody>
<tfoot>
<tr>
<td colspan="15"><input type="button" id="addrow" value="Add Product" /></td>
</tr>
<tr>
<td colspan="3">Grand Total: R<span id="grandtotal"></span></td>
<td colspan="2">Ave Discount: <span id="avediscount"></span>%</td>
<td colspan="1">Total Cubes: <span id="grandtotalcubes"></span></td>
<td colspan="15">Treated Cubes: <span id="grandtotaltreatedcubes"></span></td>
</tr>
<tr>
<td colspan="15"><textarea rows="1" cols="50" placeholder="Specific Comments"></textarea><textarea rows="1" cols="20" placeholder="Customer Reference"></textarea>
</td>
</tr>
</tfoot>
</table>
First go the parent tr and then using find to find the checkbox in current row and also use checked with DOM object not jQuery object, you can use indexer to convert jQuery object to DOM object.
Change
if($("table.authors-list").find('checkbox[name^="treated"]').checked){
To
if($(this).closest('tr').find('checkbox[name^="treated"]')[0].checked){
checked is a property of the actual DOM element, and what you have is a jQuery element. You need to change this:
$("table.authors-list").find('checkbox[name^="treated"]').checked
To this:
$("table.authors-list").find('checkbox[name^="treated"]')[0].checked
-^- // get DOM element
Or more jQuery-ish:
$("table.authors-list").find('checkbox[name^="treated"]').is(':checked')
You can iterate through the "checked" checkboxes using $("table.authors-list").find('checkbox[name^="treated"]:checked') and use the value of the input nearest to it (assumed to be in the same row).
Assuming your table has many rows each having a checkbox and an input, you can use:
function calculateTotalTreatedVolume() {
var grandTotaltreatedCubes = 0;
// iterate through the "checked" checkboxes
$("table.authors-list").find('input[type="checkbox"][name^="treated"]:checked').each(function () {
// use the value of the input in the same row
grandTotaltreatedCubes += +$(this).closest('tr').find('input[name^="cubicvolume"]').val();
});
$("#grandtotaltreatedcubes").text(grandTotaltreatedCubes.toFixed(2));
}
Try this:
var grandTotaltreatedCubes = 0;
// Cache the table object here for faster processing of your code..
var $table = $("table.authors-list");
$table.find('input[name^="cubicvolume"]').each(function () {
// Check if checkbox is checked or not here using is(':checked')
if ($table.find('checkbox[name^="treated"]').is(':checked')) {
grandTotaltreatedCubes += $(this).val();
}
});
$("#grandtotaltreatedcubes").text(grandTotaltreatedCubes.toFixed(2));
Change the following line
if($("table.authors-list").find('input[name^="treated"]').checked){
To this
if($("table.authors-list").find('input[name^="treated"]').is(':checked')){
I have an html code like this -
<table border="0" cellspacing="2" cellpadding="2" width="99%" id="subAccTable">
<tr>
<h2>Sub Accounts</h2>
</tr>
<tr>
<th>action </th>
<th>account</th>
<th>homeDir</th>
<th>primaryGroup</th>
</tr>
<tr>
<td><input type="hidden" name="vtierId" value="" /></td>
<td><input type="text" name="subAcc"
value=""/></td>
<td><input type="text" name="subHomeDir"
value=""/></td>
<td><input type="text" name="subPriGroup"
value=""/></td>
</tr>
</table>
Now i want to fill the values of textboxes named subAcc, subHomeDir, subPriGroup using javascript. How can i do it ?
There are multiple ways to get the proper DOMElement; including:
Giving each element an id and getting it using document.getElementById
Using document.getElementsByName. This is not preferred since there can be multiple elements with the same name, however there can be only one with the same id.
Using the form directly. For example if your form's name is form1: form1.subAcc
Using document.getElementsByTagName('input') and then getting the proper index.
I'd recommend using the id to retrieve the proper element.
The easiest way would be to give these textboxes a unique id, then reference them like this:
<input type="text" id="subHomeDir" name="subHomeDir" value=""/>
var tb = document.getElementById("subHomeDir");
tb.value = "foo";
If you're stuck with the names only, then you can use document.getElementsByName, just remember, this will return a collection of elements (since names are not necessarily unique), which you'll have to index:
var tb = document.getElementsByName("subHomeDir")[0];
tb.value = "foo";