I have a web page that populates a table via jQuery.
Since I only want to change classes of a particular <td> element I used replaceWith. This worked well on the first search, but I realized that I could not asynchronously perform another search without first refreshing my page. I then tried html instead of replaceWith. This worked well, but crammed all the new <td> into one <td> that has the specified id.
How can I achieve this without refreshing the page so that I can get the <td> elements well distributed?
Before updating:
<table>
<tr>
<td>first row</td>
<td>measure1</td>
<td>measure2</td>
<td>measure3</td>
<td>measure4</td>
<td> </td>
</tr>
<tr>
<td>First row</td>
<td id="no_rec" colspan="4"> No record to display!</td>
<td>More+</td>
</tr>
</table>
After updating I expect to have a table of the format:
<table>
<tr>
<td>first row</td>
<td>measure1</td>
<td>measure2</td>
<td>measure3</td>
<td>measure4</td>
<td> </td>
</tr>
<tr>
<td>First row</td>
<td class="new"></td>
<td class="new"></td>
<td class="new"></td>
<td class="new"></td>
<td>More+</td>
</tr>
</table>
My JavaScript:
$('#mybutton').click(function()
{
$.post
(
'search.php',
{
regNo: $("#regNo").val(),
datepicker: $(".datepicker").text()
},
function(data)
{
$.each(data, function(i)
{
var tm = data.time;
add_html='';
for (i=0; i<4; i++)
(i === 0 || i === 2)
? add_html += '<td class="new"></td>'
: add_html += '<td></td>';
$('#no_rec').replaceWith(add_html);
});
},
'json'
);
});
My JsFiddle Attempts
What I did was add id=results to the tr so that I could find and store all td tags and then manipulate them accordingly.
See working jsFiddle demo
All notes are left in the comments of the jQuery, but one that I should mention here is that I added a simulateData() function that basically allows you to click the Update button as many times as you want to see how the code will handle different data that's returned.
HTML
<table border="1">
<tr>
<td>first row/measures</td>
<td>measure1</td>
<td>measure2</td>
<td>measure3</td>
<td>measure4</td>
<td>measure5</td>
</tr>
<tr id="results">
<td>First row</td>
<td colspan="4">No record to display!</td>
<td>More+</td>
</tr>
</table>
<button>Update</button>
jQuery
var noRecord = "<td colspan=\"4\">No record to display!</td>",
currentTime = 0;
$( "button" ).click( function ()
{
var $results = $( "#results" ), // Get the TR.
$tds = $( "#results" ).find( "td" ), // Get the TDs within the TR.
data = simulateData(); // Simulate data.
// Check to see if data was returned.
if ( data === undefined )
{
// Data was not returned.
if ( $results.html().indexOf( noRecord ) === -1 )
{
// Results TR has previous values that need to be removed.
for ( i = 1; i < 5; i++ )
$( $tds[i] ).remove();
// Add back the [No record to display!] TD.
$( noRecord ).insertAfter( $tds[0] );
}
}
else
{
// Data was returned.
$.each( data, function ( i )
{
// Store the current data.
var tm = parseInt( data.time );
// Check to see if the Results TR has previous values or not.
if ( $results.html().indexOf( noRecord ) > -1 )
{
// Results TR does not have previous values.
var html = "";
// Generate new TDs.
for ( i = 1; i < 5; i++ )
html += "<td class=\"new\">" + tm + "</td>";
// Remove [No record to display!] TD and replace with new TDs.
$( $tds[1] ).replaceWith( html );
}
else
{
// Results TR has previous values so we need to loop
// through each existing TD replacing its class and value.
for ( i = 1; i < 5; i++ )
{
if ( i != tm )
{
// Change class to "new" and add stored data value.
$( $tds[i] )
.removeClass( "rr" )
.addClass( "new" )
.text( tm );
}
else
{
// Change class to "rr" and add "ee" value.
$( $tds[i] )
.removeClass( "new" )
.addClass( "rr" )
.text( "ee" );
}
}
}
});
}
});
// This simulates the async calls to search.php to generate
// different times on each click of the Update button.
function simulateData()
{
// Increment our simulated time.
currentTime++;
if ( currentTime > 4 )
{
// Start over by resetting our incrementer.
currentTime = 0;
// Simulate a call that doesn't return data.
return undefined;
}
else
{
return { "time": currentTime }
}
}
Since I only wants to change classes of perticular element I used replaceWith
replaceWith() method entirely replaces all matching elements with the new content.
for simply changing the css class you can use
.addClass()
adds the specified class to matched elements
.removeClass()
removes the specified class from matched elements
.toggleClass()
adds the class if it's not applied, removes it if it's already applied
Related
I was looking for a method to sort my very complex table, and found this approach which is working perfectly:
( completed code is here: http://jsfiddle.net/sg552sg552/Lsw6mnh4/15/
)
my html code is:
<table>
<thead>
<tr>
<th>string</th>
</tr>
</thead>
<tbody>
<tr>
<td>C</td>
</tr>
<tr>
<td>B</td>
</tr>
<tr>
<td>A</td>
</tr>
</tbody>
</table>
and my js code is:
$('th').click(function() {
var table = $(this).parents('table').eq(0);
var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()));
for (var i = 0; i < rows.length; i++) {
console.info("== before append, rows count: " + $(table).find('tr').size() )
// WHY doesn't this "append" increase the total tr size ?
table.append(rows[i]);
console.info("== after append, rows count: " + $(table).find('tr').size() )
}
})
function comparer(index) {
return function(a, b) {
var valA = getCellValue(a, index),
valB = getCellValue(b, index);
return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.localeCompare(valB) ;
}
}
function getCellValue(row, index) {
return $(row).children('td').eq(index).html();
}
The function( sorting the table) works perfectly, but I just wonder, why the "append()" function doesn't increase the "tr" count while there's no place to "remove" any "tr" ?
Thanks a lot.
From the jQuery append docs:
You can also select an element on the page and insert it into another:
$( ".container" ).append( $( "h2" ) );
If an element selected this way is inserted into a single location elsewhere in the DOM, it will be moved into the target (not cloned)
So the elements are really just being shuffled, not created/destroyed
Because you're not actually appending a 'tr', you're just finding the ones that already exist, putting them into an array, and sorting them. You're not actually telling your code to append any 'tr's to the table.
I'am making a small personal app for creating html tables with jquery. I have this script (which i borrowed from somewhere around here and tweaked it a bit) that would, at the click of a button, add a new column at the end of my table.
function addJSONKey(){
var first = true;
$('#jsonTable').find('tr').each(function(){
$(this).find('th').eq(-1).after(
'<th contentEditable>New Key</th>'
);
if(first === true){
first = false;
// the function does not execute this statement
// even though the debugger breaks here.
$(this).find('td').eq(-1).after(
'<td>Frist</td>'
);
} else {
$(this).find('td').eq(-1).after(
'<td contentEditable>Not First</td>'
);
}
});
}
What i'd like the script to do is, for the first row to be different than the others, but if i run the script it gives back Not First rows everywhere.
You overcomplicated it a little. You can distinguish rows by their indexes and append new th or td accordingly:
function addJSONKey() {
$('#jsonTable').find('tr').each(function(i) {
// Header row
if (i === 0) {
$(this).find('th').eq(-1).after('<th contentEditable>New Key</th>');
}
// First data row
else if (i === 1) {
$(this).append('<td>Frist</td>');
}
// Not header and not the first row
else {
$(this).append('<td contentEditable>Not First</td>');
}
});
}
$('button').click(addJSONKey);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>Add</button>
<table id="jsonTable">
<tr>
<th>One</th>
</tr>
<tr>
<td>Data</td>
</tr>
<tr>
<td>Data</td>
</tr>
</table>
replace your method with
function addJSONKey()
{
$( '#jsonTable' ).find( 'tr' ).each(function(){
$(this).find('th').eq(-1).after(
'<th contentEditable>New Key</th>'
);
});
$( '#jsonTable' ).find( 'tr' ).each(function(){
if($(this).find('td').length == 0 )
{
$(this).append('<td>Frist</td>');
}
else
{
$(this).append('<td contentEditable>Not First</td>');
}
});
}
basically your boolean first will only be true for first column of first row.
In your code you counted the 1st row that was the header as first, you want to add to the 1st non-header row, that is the 2nd row, that is index 1, because it's 0 based :)
function addJSONKey(){
$('#jsonTable').find('tr').each(function(row){
$(this).find('th').eq(-1).after('<th contentEditable>New Key</th>');
if(row == 1){
// the function does not execute this statement
// even though the debugger breaks here.
$(this).find('td').eq(-1).after('<td>Frist</td>');
} else {
$(this).find('td').eq(-1).after(
'<td contentEditable>Not First</td>'
);
}
});
}
//addJSONKey();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table id="jsonTable">
<tr><th>a</th><th>b</th></tr>
<tr><td>10</td><td>11</td></tr>
<tr><td>20</td><td>21</td></tr>
</table>
<button onclick="addJSONKey()">go</button>
I am trying to show child nodes(If option selected is 'Yes') based on the indent value. indent0-> parent node , indent1 - child node.
Sort-order is the order in which nodes are placed in DB.
$( "body" ).on( "click", ".js-show-aspects", function(event) {
var displayLabel = $(this).data('meta-value');
var sort_order = $('.js-data-selector.active:first').data('sort-order');
var indent = $('.js-data-selector.active:first').data('indent');
var rowCount = $('#show_aspects td').length;
for (var i=0;i<rowCount;i++)
{
var hasindent0 =$(this).next().hasClass("indent0");
if((displayLabel=='Yes') && (hasindent0== false)) {
child1 = $("table tr td").filter(function() {
return $(this).prop("class").match(/indent/)});
child = child1.addClass(function (index){ return "sort-order"+(sort_order+1)});
}
}
});
HTML
In the below html, $aspects gets all the nodes from DB,
<tbody>
<? foreach($aspects as $a) { ?>
<tr id="show_aspects" class="js-data-selector
<?=($a['active'] == 0) ? "text-warning" :""; ?> "
data-sort-order="<?= $a['sort_order'] ?>"
data-indent="<?= $a['indent']?>" align="left"
data-taxonomy-id="<?=$a['taxonomy_id']?>">
<td class="indent<?=$a['indent']?>
sort-order<?=$a['sort_order']?>"
data-indent="<?= $a['indent']?>">
<? if($a['active'] == 0) {
echo '<strong class="pull-right text-warning">Inactive</strong>';
} ?>
<?=$a['aspect_label']?> :
<span class="aspect-data" data-taxonomy-id="<?=$a['taxonomy_id']?>"></span>
</td>
</tr>
<?}?>
</tbody>
But I am unable to get the child nodes displayed. Any idea how to sort this out?
Edited the question with the HTML content..
It is difficult to understand exactly what you are trying to do with the question in its current form, but if you want to hide or show child nodes with jQuery, it can be done with $("#id").children().hide(); and $("#id").children().show();.
(Where "#id" is the ID of the parent DOM node.)
children() also takes a selector as an argument in case you only want specific children hidden/shown: http://api.jquery.com/children/
(If you clear up your question a bit, it would be possible to give a more appropriate answer)
<body>
<input type="text" id="search"/>
<table id="boxdata">
<tr>
<td class="namebox1">jQuery</td>
</tr>
<tr>
<td class="namebox2">javascript</td>
</tr>
<tr>
<td class="namebox3">php</td>
</tr>
<tr>
<td class="namebox4">sql</td>
</tr>
<tr>
<td class="namebox5">XML</td>
</tr>
<tr>
<td class="namebox6">ASP</td>
</tr>
</table>
</body>
<script>
$(document).ready(function(){
$('#search').keyup(function(){
searchBox($(this).val());
});
});
function searchBox(inputVal) {
$('#boxdata').find('tr').each(function(index, row){
var names = $(row).find('td');
var found = false;
if(names.length > 0) {
names.each(function(index, td) {
var regExp = new RegExp(inputVal, 'i');
if(regExp.test($(td).text()) & inputVal != ''){
found = true;
return false;
}
});
if(found == true)
$(row).addClass("red");
else
$(row).removeClass("red");
}
});
}
</script>
there's a textfield for searching words and there are 6 words in the each 6 boxes below textfield.(I omitted css codes. but, it wouldnt matter to solve the problem.). if i type a letter 's' then the words that including letter 's' like 'javascript', 'sql', 'ASP' these font-color will be changed black to red. And i made it by using table elements in html but i'd like to change all elements into div style to put some data fluidly later. i have difficulty to fix especially jquery. how can i fix it?
You can simplify this a little bit.
function searchBox(inputVal) {
var regExp = new RegExp(inputVal, 'i');
$('#boxdata').find('tr').removeClass('red').filter(function() {
return $(this).find('td').filter(function() {
return regExp.test( $(this).text() );
}).length && $.trim(inputVal).length;
}).addClass('red');
}
So remove the red class from all <tr>'s first, then filter them, test the text of each <td>, if it matches, return the <tr> and then add the class red again.
Here's a fiddle
As for changing from a table to div, the jQuery would depend on how you structure your markup, but the principle would remain the same.
Here's another fiddle
You can make javascript code HTML agnostic by using css classes instead of element names. Demo.
function searchBox(inputVal) {
var regExp = new RegExp(inputVal = $.trim(inputVal), 'i'),
highlight = 'red';
$('#wrapper').find('.word') //instead of tr/td/div
.removeClass(highlight)
.each(function(){
var $this = $(this);
inputVal && regExp.test($this.text()) &&
$this.addClass(highlight);
});
}
I am new to javascript.
Can anyone help me to implement an onclick event on click of a HTML table row created through javascript?
Kindly note that I am inserting the data in table cells using innerHTML.
Below is the code snippet of what i have tried.?
Java Script function:
function addRow(msg)
{
var table = document.getElementById("NotesFinancialSummary");
var finSumArr1 = msg.split("^");
var length = finSumArr1.length-1;
alert("length"+ length);
for(var i=1; i<finSumArr1.length; i++)
{
var row = table.insertRow(-1);
var rowValues1 = finSumArr1[i].split("|");
for(var k=0;k<=10;k++)
{
var cell1 = row.insertCell(k);
var element1 = rowValues1[k];
cell1.innerHTML = element1;
}
}
for(var i=1; i<rowCount; i++)
{
for(var k=0;k<=10;k++)
{
document.getElementById("NotesFinancialSummary").rows[i].cells[k].addEventListener("click", function(){enableProfileDiv()}, false);
}
}
}
HTML table code in jsp :
<TABLE id="NotesFinancialSummary" width="800px" border="1" align="left" >
<tr >
<th>Symbol</th>
<th>Claimant</th>
<th>MJC</th>
<th>S</th>
<th>Type</th>
<th>Indemnity Resv</th>
<th>Indemnity Paid</th>
<th>Medical Resv</th>
<th>Medical Paid</th>
<th>Legal Resv</th>
<th>Legal Paid</th>
</tr>
<tr>
<td>
</td>
<TD> </TD>
<TD> </TD>
<TD> </TD>
<TD> </TD>
<TD> </TD>
<TD> </TD>
<TD> </TD>
<TD> </TD>
<TD> </TD>
<TD> </TD>
</tr>
</table>
<table id="table"></table>
$("#table").append("<tr><td>Hi there</td></tr>");
$("#table").on( "click", "tr", function(){
// do something
alert( $(this).children("td:first").text() );
});
Any time the click event bubbles up to <table id="table">, this function will be called (no matter if the <tr>s are inserted dynamically, or hard coded).
This will require the jQuery library
http://jquery.com/
http://api.jquery.com/on/
One way to do it would be using document.createElement
Instead of doing:
yourParentElement.innerHTML = "<tr>Something</tr>";
You can do
var tr = document.createElement("tr");
tr.innerHTML = "Something";
tr.onclick = function() {
//code to be executed onclick
};
yourParentElement.appendChild(tr);
Another way, would be to use an id (only if you're doing this once, you don't want duplicated ids):
yourParentElement.innerHTML = "<tr id='someId'>Something</tr>";
document.getElementById("someId").onclick = function() { //fetch the element and set the event
}
You can read more about events here, but just so you have an idea onclick will only let you set one function.
If you want a better solution you can use something like addEventListener, but it's not crossbrowser so you may want to read up on it.
Lastly, if you want to set up an event on every tr you can use:
var trs = document.getElementByTagName("tr"); //this returns an array of trs
//loop through the tr array and set the event
after you insert your <tr> using innerHTML, create a click event listener for it.
document.getElementById("the new id of your tr").addEventListener("click", function() {
what you want to do on click;
});
Something like this: http://jsfiddle.net/gnBtr/
var startEl = document.getElementById('start');
var containerEl = document.getElementById('container');
var inner = '<div id="content" style = "background: pink; padding:20px;" > click on me </div>'
// Function to change the content of containerEl
function modifyContents() {
containerEl.innerHTML = inner;
var contentEl = document.getElementById('content');
contentEl.addEventListener("click", handleClickOnContents, false);
}
// listenting to clikc on element created via innerHTML
function handleClickOnContents() {
alert("you clicked on a div that was dynamically created");
}
// add event listeners
startEl.addEventListener("click", modifyContents, false);
Check it out:
$('#your_table_id tbody').on('click', 'tr', function (e) {
$('td', this).css('background-color', 'yellow');
} );
css:
tr:hover td{
background-color: lightsteelblue !important;
}
It works fine for me, specially when I'm using jquery dataTable pagination.