I’m working on what I thought would be a simple project but is something I’m struggling with. I’m wondering if someone could review what I’m trying to do and give me some pointers on how to proceed.
The concept here is fairly simple...I thought - identify each table in an html file based on the "table" element, count the number of rows in each table and if the table has more than 10 rows, dynamically create a unique id for the table.
I know how to do all this (for the most part) but it doesn’t respond how I anticipate.
Here’s my initial javascript code attempt to dynamically create and insert the unique table id’s:
/* This function dynamically sets a unique id to each table found in the html page: */
function set_table_id(){
var num_tables = document.getElementsByTagName("table"); //determine the number of “table” nodes in the html
//alert("set_table_id function: The total number of table elements are: " + num_tables.length);
if (num_tables) { //if one or more table nodes are found…
var id_name = "dataTbl_"; // create the prepend string for table id value
var n = 1;
var i;
//for each table node found…
for (i=0; i < num_tables.length; i++) {
var id_name_new = id_name + n; //create the next unique table id from the prepend string
n++;
num_tables[i].id = id_name_new; //apply the latest table id to the current table
//this will be the call to the function to apply the datatables javascript to each table that has more than 10 rows:
//num_tables[i].dataTable();
}
}
}
When I run the above js code there are no errors when I review the Inspect Element Console, but the unique id’s never get inserted into the table elements.
This should run through the html code, identify each table and dynamically apply (insert) a unique id to each table but it's not.
Any help is greatly appreciated.
This jQuery selector will find all tables that have 10 or more <tr> children and apply the ID and DataTables to each.
$(document).ready(function() {
$("table > tbody > tr:nth-child(10)").closest("table").each(function(index) {
var tableId = "dataTbl_" + (index + 1); //index is zero-based, so add 1
$(this).attr("id", tableId); //set the ID attribute
$(this).dataTable();
}
);
});
Heres is a JSFiddle, based on the on in your comment, which demonstrates it:
https://jsfiddle.net/5cgbdLzt/2/
Within that fiddle, I added a button that will alert the IDs to you, where you can see clearly that the ID of the table with fewer than 10 rows has an ID that is undefined.
Note: DataTables uses jQuery as a dependency, so it's assumed you can use jQuery selectors rather than strictly vanilla JS.
Related
We have used jQuery Datatables plugin to save update records in multiple rows.
Also validation is built for all the columns, once validation is failed.
We have the following line of code to focus on element for which validation is failed.
$(this).focus();
However this will not work if validation fails on some other page( $(this) is not on current).
As a workaround to this we thought we will click on the page number hyperlink
$(#identifier).trigger('click');
The problem is
"How to know if an element with id A ( $(#A)) is in which page of jQuery Table ?"
Once we know that problem will be solved.
Here, I've written a js function to move you to the page with a given row (row with class "selectedItem" in this case). It should be possible to rewrite the code to find any elements, not just rows, in case you need to.
function moveToPageWithSelectedItem() {
var numberOfRows = itemsTable.data().length;
var rowsOnOnePage = itemsTable.page.len();
if (rowsOnOnePage < numberOfRows) {
var selectedNode = itemsTable.row(".selectedItem").node();
var nodePosition = itemsTable.rows({order: 'current'}).nodes().indexOf(selectedNode);
var pageNumber = Math.floor(nodePosition / rowsOnOnePage);
itemsTable.page(pageNumber).draw(false); //move to page with the element
}
}
So I have an HTML table that populates based on a mysql query. It is contained within:
<div id="punchclock" class="timecard">
And I have the following jQuery script which calculates the totals of the times entered into the HTML table. However, it is repeating the "Total:" line of the script in the header (a separate div) and the table I want. Is there a way to ensure the code only outputs to the desired div?
$('table').each(function(){
var tr = {};
$(this).find('tr').each(function(){
var key = $(this).find('td.job_code').text();
var val1 = toSeconds($(this).find('td.hrs').text());
//var val = +$(this).find('td.hrs').text().split(':')[0];
if(tr[key]){
tr[key]+=val1;
}else{
tr[key]=val1;
}
});
$(this).append(function(){
var tfoot = $('<tfoot/>', {
html: addRows(tr)
});
return tfoot;
});
});
I believe the issue lies with the tfoot return statement as it is returning it to the header div and my table div. As always, any help is greatly appreciated. Thanks.
Select only the table in the div you have defined:
$('#punchclock table').each....
Your current code will run for every table on the page, and it sounds like you have multiple tables. By selecting #punchclock table, it only uses the tables inside #punchclock.
If you want to run this for only one table, it would be better to give that one table an id like <table id="schedule">, then get rid of your each loop, and select the table directly like $('table#schedule').
Also, this block looks suspect:
$(this).append(function(){
var tfoot = $('<tfoot/>', {
html: addRows(tr)
});
return tfoot;
});
I don't know what addRows does but it does not look necessary. Try this instead:
$(this).append($('<tfoot/>').append(tr));
I have a standard HTML formatted table, that dynamically generates the content, via Zend Framework. From which I have an issue altering the form internally PHP side. So I need to alter the tables appearance somehow. With that on the occasion I have an element show up in one of the rows and when this element shows up I want to break out of the table and then do something after it then start the table again.
Basically I want to inject the equivlant of
</tbody></table>/*other stuff*/<table><tbody> after the row containing the one element I seek which in this case is a label.
I tried $("label[for='theLable']").parents('tr').after('</tbody></table><br><table><tbody>') which appears to ignore the ending table parts add the br, and then does a complete open/close tag for table and tbody within the same table I am trying to break out of so inbetween tr tags basically it adds this new table
Whats the best way to approach this concept?
update with jsfiddle link
http://jsfiddle.net/cPWDh/
You can't really modify the HTML of the document the way you're thinking, since it's not a legitimate way to alter the DOM.
Instead, I would create a new table and .append the rows you want to move to it, which will automatically move them from their current location (instead of copying them):
$(document).ready(function() {
var $trow = $('label[for="specialLabel"]').closest('tr'),
$table = $trow.closest('table');
$('<table>').append( $trow.nextAll().andSelf() ).insertAfter($table);
});
http://jsfiddle.net/cPWDh/1/
this approach won't work in js. What you could do if the table has not too many rows is this:
var nextTable = $("table").after("/*other stuff*/<table id="nextTable"></table>");
//now you loop over the lines of your original table that you want to have after the "break", and move them to the nextTable:
var before = true;
$("table tr").each(function(){
if ($(this).has("[for='theLable']")) {
before = false;
}
if (!before) {
nextTable.append($(this));
}
});
In the JSFiddle, I am trying to generate divs dynamically using javascript. Those divs will contain tables where the last two rows can be incremented using the add button.
I have tried the code in the fiddle.
The ins_row() function is used to add rows in the table which are generated within the divs.
The addEvent() function is used to generate divs
When the Add product button is clicked a div containing a table with one row will get generated.
When the add button is clicked the last two rows should keep on getting added as per the clicks. If the remove button straight to the div is clicked the whole table and div should be deleted.
When the remove button straight to the generated rows is clicked, only that row should be deleted and not the whole div.
Problem
The problem here is the divs with table are getting generated but I couldn't figure out how to add the rows in the table.
See it in action here
Expected output
Note: I have just pasted the external JS file into the javascript column of the above fiddle as I don't have the resource link.
Present output
I hope I have presented the question understandable, if anything is not clear, Please let me know
I believe I have properly understood your requirement.
Try out this fiddle http://jsfiddle.net/Kucuk/14/
It uses jquery though - its just a sample sort of thing that you could probably base your own code off. Its all doable in plain old JavaScript, if that's what you prefer. The styling is a bit off, but that you can handle I hope.
Do let me know if this helps you in some manner.
Generally, I use jQuery's appendTo() function alongwith a dummy html structure. I store this in a variable & follow it up with further attribute manipulation.
To get an idea of what I am talking about, just check this fiddle: http://jsfiddle.net/GGS4N/
This is in answer to another question Smooth out this jQuery toggle animation?. Focus on the methodology as listed below:
To create a dummy HTML structure(generic in nature).
On your desired event, triggering of population and manipulation of the dynamic elements into the dom, with giving them an identifiers and manipulating other specific attributes, and as seen in the fiddle, even animating them.
If you prefer raw JS, as seen from your code, you can implement the same functionality in raw JS too! :)
Try this fiddle to see if it works for you.
In this example, when you click on add product, all 4 textboxes are created with an add more rows and remove div buttons.
When you click on add rows, last two textboxes are created with a remove row button.
Whenever the row count of a product is more than 1, the remove div button is hidden and is shown again when the row count is 1.
Is this more like what you expected?
http://jsfiddle.net/7AeDQ/81/
I achieved this by adding styles to widen the table and the cell containing the buttons. I also changed the buttons to input type="button".
Hope this works for you.
EDIT:
I have just noticed that I mixed up your expected output and present output. Working on expected output now.
Another pure js solution
<html>
<body>
<script>
var tblCount = 0
var tblIdStr = "productTbl";
function removeRow(id, rowNumber) {
var el = document.getElementById(id);
el.deleteRow(rowNumber);
}
function addTable() {
++tblCount;
tblId = tblIdStr + tblCount;
var args = "'" + tblId + "'";
var tblHtml = '<tr><td>Product name</td><td>Price</td><td>Competitor</td><td>Price</td></tr><tr><td><input type="text"></td><td><input type="text"><td><input type="text"></td><td><input type="text"></td><td><input type="button" value="Add" onclick="addRow(' + args + ')"></td><td></td></tr>'
var tbl = document.createElement("table");
tbl.setAttribute("id", tblId);
document.getElementById("container").appendChild(tbl)
document.getElementById(tblId).innerHTML = tblHtml;
}
function addRow(id) {
var el = document.getElementById(id)
var rowCount = el.rows.length;
var row = el.insertRow(rowCount);
//console.log(row)
var args = "'" + id + "'" + "," + rowCount;
var tblRowHtml = '<td colspan=2></td><td><input type="text"></td><td><input type="text"></td><td><input type="button" value="remove" onclick="removeRow(' + args + ')"></td>';
//el.rows[rowCount].setAttribute("id", rowId);
el.rows[rowCount].innerHTML = tblRowHtml
}
</script>
<input type="button" value="Add new product table" onclick="addTable()">
<div id="container">
</div>
</body>
</html>
I have a query building form built in PHP. The results of the query are returned and placed in two different tables one above the other. (table id's are results, and results2) Each record returned builds two tables to display its data. (Soon to be three)
I'm using the following code to change the class tags of my <tr>'s to provide alternate row coloring:
<script type="text/javascript">
function alternate(id){
if(document.getElementsByTagName){
var table = document.getElementById(id);
var rows = table.getElementsByTagName("tr");
for(i = 0; i < rows.length; i++){
if(i % 2 == 0){
rows[i].className = "row-one";
}else{
rows[i].className = "row-two";
}
}
}
}
</script>
Then I'm using a body onload like so:
<body onload="alternate('results'); alternate('results2');">
The problem is it only colors the first two instances of these tables, when depending on the amount of records returned there could be hundreds of them.
How can I get this function to apply to every table in the document with a id = results and results2 and soon to be a results3?
If you really want to do this with JavaScript, I would suggest the following code:
First, make your tables have a class of "results" instead of ID "results1", "results2", etc (because as my comment on the question says, IDs must be unique, and getElementById will only return one result and apply to only one real element):
<table class="results">...</table>
Next, use this JavaScript:
<script type="text/javascript">
function alternate(classNameMatch) {
var tables = document.getElementsByTagName("TABLE");
for (var i=0; i < tables.length; i++) {
var table = tables[i];
if (table.className.indexOf(classNameMatch) == -1)) continue;
for (var j=0; j < table.rows.length; j++) { // "TABLE" elements have a "rows" collection built-in
table.rows[j].className = j % 2 == 0 ? "row-one" : "row-two";
}
}
}
</script>
Then call alternate("results"); on page load.
But, I really suggest doing this in PHP. JavaScript will be very inefficient with large result sets. It will also not show up right away, making the style of the page visibily change after page load.
I would also just add a class to every other row, and then style all rows by default one way and the other class the other way:
<style type="text/css">
table.results tr { background-color:#f0f0f0; }
table.results tr.row2 { background-color:#f0f0ff; }
</style>
Of course each call to the method is only applying to one table - you are not looping over a number of tables, but set the table var at the top of the document and then colour the rows in that table. As others have pointed out, IDs are meant to be unique within a document anyway, which is why getElementByID only returns a single value.
Doing this on the server-side would be much better as well, because that's the canonical document sent to everyone so doesn't rely on them having JS enabled, and doesn't take a possibly non-negligible amount of processing time while the page gets striped.
If you must do this client-side, a better implementation would be to give your tables a particular class (instead of ID); refactor your solution slightly so that you split the core of your functionality into a method that stripes a single table that's passed in; then find all tables with the class "stripeme" (or whatever), and loop over that result, passing each table into your striping method.