How to reference a data attribute of another element? - javascript

I am trying to create a responsive table, that collapses from a horizontal to a vertical layout. For that I use a :before pseudo-element, that gets its value from a data attribute. Consider the following dom-structure:
td:before {
content: attr(data-th);
}
<table>
<thead>
<tr>
<th>First</th>
<th>Second</th>
<th>Third</th>
<th>Fourth</th>
</tr>
</thead>
<tbody>
<tr>
<td data-th="First">Alpha</td>
<td data-th="Second">Beta</td>
<td data-th="Third">Gamma</td>
<td data-th="Fourth">AnotherGreekLetter</td>
</tr>
</tbody>
</table>
This works fine and well, until you realize, that you have to write every single data-attribute by hand, since every new row of data requires the data-attribute.
Ideally I would like to have something like this:
td:before:nth-of-type(4n+1) {
content: attr(data-th:nth-of-type(4n+1));
}
td:before:nth-of-type(4n+2) {
content: attr(data-th:nth-of-type(4n+2));
}
<table>
<thead>
<tr>
<th data-th="First">First</th>
<th data-th="Second">Second</th>
<th data-th="Third">Third</th>
<th data-th="Fourth">Fourth</th>
</tr>
</thead>
<tbody>
<tr>
<td>Alpha</td>
<td>Beta</td>
<td>Gamma</td>
<td>AnotherGreekLetter</td>
</tr>
</tbody>
</table>
where I am referencing the data-attribute of the th-nodes.
Now, as far as I know, there is no way of walking the dom-tree with just css, so I assume this would only be possible with javascript. Yet, I have never made use of the data-attribute, so I am hoping that I am wrong about that.
Can I make this work with (in descending order of preference): only css, php, javascript?

Don't think you can do this via CSS, you could probably use a slightly different approach if using jQuery too as you could use an ID to locate the values from the header and write it out to the body e.g.
<table>
<thead>
<tr data-id="1">
<th>A</th>
<th>B</th>
<th>C</th>
<th>D</th>
</tr>
</thead>
<tbody>
<tr data-id="1"></tr>
</tbody>
</table>
And the jQuery:
$(document).ready(function() {
$("thead tr th").each(function( index ) {
$("tbody tr[data-id='" + $(this).parent().attr('data-id') + "']").append('<td>' + $(this).text() + '</td>');
});
});
http://codepen.io/anon/pen/kXdkyY
Hopefully this gives you an alternative idea of how you could loop through and grab data in a different way.

Related

Adding element to dom doesn't work

When I try to add elements to my dom, they're not added, but when I console.log them, I do get a value <th class="text-right" rowspan="1" colspan="1"></th>
for(c=0; c<2; c++) {
console.log(document.getElementById('achats_table').tFoot.children[0].appendChild(document.createElement('th')));
document.getElementById('achats_table').tFoot.children[0].appendChild(document.createElement('th'));
}
Table HTML :
<table>
<thead>
<tr>
</tr>
</thead>
<tbody>
</tbody>
<tfoot>
<tr>
</tr>
</tfoot>
</table>
what am I doing wrong? how can I debug this? I get no console errors.
It looks like you want to add th elements to a currently blank tfoot? You could try this:
for(c=0; c<2; c++) {
document.querySelector('#achats_table tfoot').appendChild(document.createElement('th'));
}

Add column sorting feature on treegrid html

I have a treegrid that is build like this:
<table>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Number</th>
</tr>
</thead>
<tbody>
<tr class="treegrid-0">
<th>name2</th>
<th>type2</th>
<th>Number2</th>
</tr>
<tr class="treegrid-1">
<th>name1</th>
<th>type1</th>
<th>Number1</th>
</tr>
<tr class="treegrid-2 treegrid-parent-1" style="display:none;">
<th>name1-A</th>
<th>type1-A</th>
<th>Number1-A</th>
</tr>
<tr class="treegrid-3 treegrid-parent-1" style="display:none;">
<th>name1-B</th>
<th>type1-B</th>
<th>Number1-B</th>
</tr>
<tr class="treegrid-4">
<th>name0</th>
<th>type0</th>
<th>Number0</th>
</tr>
</tbody>
</table>
I would like to add the sorting option when i click on a column.
The sorting option has to be done only on the top parent.
It's a treegrid, so the expected behaviour is that the child nodes has to be moved also with the parent if the parent has to move.
How can i do that with JS ?
instead of doing all the hard work yourself, you can use the awesome js/jQuery library: datatables: https://datatables.net/
Just after defining your table, give it an ID
<table id = "myTable">..</table>
and then add the following snippet which will transform your table into an awesome table.
$(document).ready(function(){
$('#myTable').DataTable();
});
Cheers!

find child table selector from parent table - jQuery

I have a table structure like this. Fairly simple one.
<table id="myTable" class="table">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Doe</td>
<td>john#example.com</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
</tbody>
</table>
At runtime I am binding a new row to this table for a particular rowclick. This new row contains a new table.
Now on clicking the row again, I want to be able to remove the newly added row(the new table).
I am using bootstrap table.
Here is what I have tried so far.
$('#myTable').on('click-row.bs.table', function (e, row, $element) {
//if ($element.has('#newlyAddedTable').length) { ....// did not work
if ($('#myTable').has('#newlyAddedTable').length) { // this removes the table on any row click. Not what I intend to do
{
$("#newlyAddedTable").remove();
} else {
// some operation...
}
}
I want to be able to remove the newly added table on the row it was created.
Just more explanation based on the Answers below:
<tr> ----------> if i click this
<td>
<table id="newlyAddedTable"> ---------> this is added
</table>
</td>
</tr>
<tr> ----------> if i again click this or maybe any other row in the table
<td>
<table id="newlyAddedTable"> ---------> this is removed
</table>
</td>
</tr>
Update: from OP's comment below it sounds like the best way to implement the new table is to use a class selector and not an id selector. The code below has been updated accordingly. ***Where previously there was an id for newTable there is a class ---> #newTable ===> .newTable:
Just change:
$('#myTable').has('#newlyAddedTable').length
To:
$('.newlyAddedTable', $element).length //element === clicked row -- see demo
vvvvv DEMO vvvvv
$('#myTable').bootstrapTable().on('click-row.bs.table', function(e, row, $element) {
if( $('.newTable', $element).length ) {
$('.newTable', $element).remove();
} else {
$('td:first', $element)
.append( '<table class="newTable"><tr><td>NEW TABLE</td></tr></table>' );
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.7.0/bootstrap-table.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-table/1.7.0/bootstrap-table.min.css" rel="stylesheet"/>
<table id="myTable" class="table">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr>
<td>John</td>
<td>Doe</td>
<td>john#example.com</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
</tbody>
</table>
Try replacing your remove code with this:
$(document).on("click", "#newlyAddedTable", function(){
$(this).remove();
});
The code above registers a click listener on the document. The second parameter filters those events for those with the target #newlyAddedTable. This way you don't have to register a new click handler every time you insert a row (as in #VimalanJayaGanesh's solution).
P.S. If you are adding HTML that looks like this:
<tr>
<td>
<table id="newlyAddedTable">
</table>
</td>
</tr>
Then you are probably actually wanting to remove the parent tr (not the table with the id). There are two ways to fix this.
You can change the selector that filters click events and so have the tr handle the click rather than the table element in my example code:
$(document).on("click", "tr:has(#newlyAddedTable)", function(){
You can leave the selector as is but grab the parent tr from the table and remove that changing the remove line above to:
$(this).parents("tr").first().remove()
or
$(this).parent().parent().remove()
As I don't have your complete code / fiddler, here is a possible solution.
Are you looking for something like this?
$('#add').on('click', function()
{
var newRow = '<tr CLASS="newrow"><td colspan="3"><table><tr><td>Test</td><td>User</td><td>test#example.com</td></table></td></tr>'
$('#myTableBody').append(newRow);
Remove()
});
function Remove()
{
$('.newrow').off('click').on('click', function()
{
$(this).remove();
});
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id="myTable" class="table">
<thead>
<tr>
<th>Firstname</th>
<th>Lastname</th>
<th>Email</th>
</tr>
</thead>
<tbody id="myTableBody">
<tr>
<td>John</td>
<td>Doe</td>
<td>john#example.com</td>
</tr>
<tr>
<td>Mary</td>
<td>Moe</td>
<td>mary#example.com</td>
</tr>
<tr>
<td>July</td>
<td>Dooley</td>
<td>july#example.com</td>
</tr>
</tbody>
</table>
<button type='button' id='add'>Add</button>
Note:
The following line indicates that,
$('.newrow').off('click').on('click', function()
the click event will be binded to the new row only once.
The reason for adding 'off('click') is, when you are dynamically adding rows (with common class 'newrow') to the table, the events will be binded several times. To avoid that, remove the previously binded click event and add a new one.

delete all datatables using jQuery

so, I am using datatables along with jQuery, and am a bit stumped as to why this is not working. My HTML looks like this:
<table id="surnamePrimaryPartitionTable" border=1 class="display partitionDisplay">
<caption>Partitions</caption>
<thead>
<tr style="background-color: #afeeee;">
<th>Partition</th>
<th>CPU %</th>
<th>Search Count</th>
<th>Person Count</th>
<th>Disk Space</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
I have several tables, each of which follows a similar format, and each of which uses the partitionDisplay class (really just a class that I use so that I can select all the tables later using jQuery).
So, the problem arises when I try to destroy the datatables. Here is what I have:
function DeletePartitionInformation(data) {
jQuery(".partitionDisplay").each(function(){
jQuery(this).dataTable().fnDestroy();
});
jQuery("table tbody").each(function() {
jQuery(this).html("");
})
}
This code seems to work correctly for the first table, but throws an exception and doesn't work on any subsequent tables. The javascript error message I am getting is the following:
Uncaught TypeError: Cannot read property 'asSorting' of undefined
A quick Google search on this error says that it generally arises from having elements nested in a tag. This does not appear to be the problem, however. I will post the code for the other three tables to demonstrate this:
<table id="surnamePrimarySubpartitionTable" border=1 class="display partitionDisplay">
<caption>SubPartitions</caption>
<thead>
<tr style="background-color: #afeeee;">
<th>Partition</th>
<th>SubPartition</th>
<th>CPU %</th>
<th>Search Count</th>
<th>Person Count</th>
<th>Disk Space</th>
<th>Begin</th>
<th>End</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<table id="givenNullSurnamePartitionTable" border=1 class="display partitionDisplay">
<caption>Partitions</caption>
<thead>
<tr style="background-color: #98fb98;">
<th>Partition</th>
<th>CPU %</th>
<th>Search Count</th>
<th>Person Count</th>
<th>Disk Space</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<table id="givenNullSurnameSubpartitionTable" border=1 class="display partitionDisplay">
<caption>SubPartitions</caption>
<thead>
<tr style="background-color: #98fb98;">
<th>Partition</th>
<th>SubPartition</th>
<th>CPU %</th>
<th>Search Count</th>
<th>Person Count</th>
<th>Disk Space</th>
<th>Begin</th>
<th>End</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
One final note: I am actually able to get the behavior I want if I use the below code. Obviously I would prefer not to, however, since I'd really like to loop over the elements rather than hard-code the element id's in.
function DeletePartitionInformation(data) {
jQuery("#surnamePrimarySubpartitionTable").dataTable().fnDestroy();
jQuery("#surnamePrimaryPartitionTable").dataTable().fnDestroy();
jQuery("#givenNullSurnameSubpartitionTable").dataTable().fnDestroy();
jQuery("#givenNullSurnamePartitionTable").dataTable().fnDestroy();
jQuery("table tbody").each(function() {
jQuery(this).html("");
})
}
Uncaught TypeError: Cannot read property 'asSorting' of undefined
This seems to suggest it may be trying to destroy dataTables that weren't created.
The static fnTables should give you an Array of only the <table> elements with a dataTable:
var tables = $.fn.dataTable.fnTables(true);
$(tables).each(function () {
$(this).dataTable().fnDestroy();
});

Manipulating <td>'s within different <tr>'s

I'm wondering if the following can be done.
I have a list of 'expenses' that I'm displaying in a table. 4 columns - amount, date, where, and what.
I was thinking I'd like to make each clickable via jQuery which would expand that particular expense, inline, to show a more detailed description.
What I'm trying to do is, on click, replace the contents of the 'tr' with a single 'td' that would contain the extended info. Problem is that 'td' only expands to about a quarter of the table. Is there any way of making it extend to the whole row, while maintaining the widths of the other 'td's in the other rows?
Here's what I would do. Working Demo.
<table id="expenses">
<thead>
<tr>
<td>Amount</td>
<td>Date</td>
<td>Where</td>
<td>What</td>
</tr>
</thead>
<tbody>
<tr class='expense' id='expense-1'>
<td>$5.99</td>
<td>4/2/2009</td>
<td>Taco Bell</td>
<td>Chalupa</td>
</tr>
<tr class='details' id='details-1'>
<td colspan='4'>
It was yummy and delicious
</td>
</tr>
<tr class='expense' id='expense-2'>
<td>$4.99</td>
<td>4/3/2009</td>
<td>Burger King</td>
<td>Whopper</td>
</tr>
<tr class='details' id='details-2'>
<td colspan='4'>
The king of burgers, indeed!
</td>
</tr>
<tr class='expense' id='expense-3'>
<td>$25.99</td>
<td>4/6/2009</td>
<td>Olive Garden</td>
<td>Chicken Alfredo</td>
</tr>
<tr class='details' id='details-3'>
<td colspan='4'>
I love me some italian food!
</td>
</tr>
</tbody>
</table>
With styles like these:
#expenses tr.expense {
cursor: pointer;
}
#expenses tr.details {
display: none;
}
And then have Javascript that looks like this:
$(function() {
$('tr.expense', '#expenses').click(function() {
var id = $(this).attr('id').split('-').pop();
var details = $('#details-'+id);
if(details.is(':visible')) {
details.hide();
} else {
details.show();
}
});
});
That should do it.
<td colspan="4"> ?

Categories

Resources