Search a table in jQuery after new rows have been added - javascript

I am very bad at Javascript/Jquery. Now that that's out of the way, I need some help with searching a dynamically built table. Here's the problem: on the pageload of my asp site, the repeater is bound, and the table is populated. I can use some sweet javascript function to filter the table, and that works very well. Unfortunately, I also rely on SignalR to get some realtime data into the table (it's a debug logger for another software project). Using SignalR and jQuery, I am able to prepend the new table row at the top and delete the last row so everything stays the same size. Once a new row is added to the table, though, my Javascript search breaks and is unable to search the newly added rows. I'm going to assume javascript does some sort of index on the table, but I'm not sure if that's right, and if it is, can I reindex? Yes, I have linked signalr and jquery up correctly. Thanks!
Below you'll find all the relevant code
HTML/ASP:
<HeaderTemplate>
<table id="debugTable" class="table table-bordered table-condensed">
<thead>
<tr >
<th >Time Stamp</th>
<th >Level</th>
<th >Logger</th>
<th >Message</th>
</tr>
</thead>
<tbody class="list">
</HeaderTemplate>
<ItemTemplate>
<tr >
<td class="timestamp"><%#Eval("Time_Stamp")%></td>
<td class="debuglevel" ><%#Eval("Level")%></td>
<td class="logger"><%#Eval("Logger")%></td>
<td class="message"><%#Eval("Message")%></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</asp:Repeater>
Javascript:
<script type="text/javascript">
$(function () {
var myChatHub = $.connection.myChatHub;
myChatHub.client.newMessageReceived = function (time, level, logger, text) {
$('#debugTable tr:first').after('<tr> <td>' + time + '</td><td class="debuglevel">' + level + '</td><td>' + logger + '</td><td>' + text + '</td> </tr>');
$('#debugTable tr:last').remove();
}
});
$('.search').keyup(function() {
$.each($(".list").find("tr"), function () {
if ($(this).text().toLowerCase().indexOf($('.search').val().toLowerCase()) == -1)
$(this).hide();
else
$(this).show();
});
});
</script>

you search function is this one right?
$('.search').keyup(function(){ . . . . })
evertime you add new ROWS in your TABLE the event needs to be called again, because the jQuery was loaded the old structure of HTML Elements.
So, to prevent a chain events in your page and solve the problem, you need to change your implementation to this:
function search(){
$('.search').unbind('keyup').bind('keyup', function(){ . . . });
}
search();
And call the function everytime you add new rows in your table:
search();
Cheers,

I found the problem!
It turns out every time I was adding a new row to the table, I was adding it to the thead. As a result, the search function was simply skipping those new rows. By simply changing my jquery selector to the following, I was able to add things to the tbody, and not the thead.
$('#debugTable tbody tr:first')
As opposed to
$('#debugTable tr:first')
A big shoutout to Cícero Feijó, who helped me with the search function and the event binding/unbinding. I have marked his response as the answer because that is the right way to do this, it was just a small oversight in my code that prevented his solution from working.

Related

jquery reload table (IE 7)

I have a HTML-code like this here:
<div id="overview" class="fadeable">
<table id="exportTable">
<tr>
<td style="width: 500px;"><strong>Col 1</strong></td>
<td style="width: 15px;" class="aligned_td"><strong>Col 2</strong></td>
</tr>
<% call getLocationPercentages(is_nll) %>
</table>
</div>
As you can see, I'm calling an asp-function after the first tr. The output it generates is correct (after reloading the site. However, I don't want to reload it.
For this scenario, I made a small JS-function, which works in Chrome, but not in IE (7).
Just a quick note: I can't just not support IE 7.
$(document).on("click", "#updateLocation", function() {
$.ajax({
url: "my-file.asp",
type: "GET",
scriptCharset: "utf-8",
cache: false,
contentType: "application/x-www-form-urlencoded; charset=UTF-8",
data: data
});
$('#exportTable').load(location.href + " #exportTable");
}
I read the documentation for load and as I said, it works in chrome. IE however just "hides" the output. After submitting (or pressing this button (which is in another div, if that is important)) the table just vanishes, but the dom is correct. There is no CSS rule or what so ever what could hide that table. It would affect the other browsers as well though.
The DOM after submitting also has the correct values (so it is "reloaded", but not displayed)
Ideas? Familiar with that problem?
Update
I figured out, that the Table isn't generated properly. My HTML results in something like this:
<table id="exportTable">
<table id="exportTable">
correct content here
</table>
</table>
When I move the inner table over the other, so it is alone again, the display is correct. For some reason, instead of re-generating the content, it adds another table.
I tried to "unwrap" the 2nd occurence with this, but that didn't do the trick:
var e = $('#exportTable:last');
e.prev().insertAfter(e);
The inner table isn't selected with that, it affects only the outer one
e.unwrap()
didn't do it either
I can't even reach it with each in a loop. It is simply left behind.
I don't know why, but "reloading" a table ends up in having 2 tables with the same classes + id's, where the 1st one is just a wrapper of the 2nd one.
I wrapped a <div> around the table, changed my JS to reload that div and now it is working.
HTML
<div id="tableWrap">
<table id="exportTable" class="exportTable">
<tr>
<td style="width: 500px;"><strong>col 1</strong></td>
<td style="width: 15px;" class="aligned_td"><strong>col 2</strong></td>
</tr>
<% call getLocationPercentages(is_nll) %>
</table>
</div>
JS
$('#tableWrap').load(location.href + " #exportTable");
I am not sure if your way of doing that is correct or what do you really want to achieve.
First of all - when you create HTML table you should create it like:
<table>
<thead>
<tr>
<!-- columns descriptions here -->
</tr>
</thead>
<tbody id="ContentId">
</tbody>
</table>
And only update tbody element.
Secondly, at first start of application you should render data with ASP.NET, but then (if you want to use AJAX with jQuery) the simplest (but not the best) way of updating that data would be:
JS
$("#UpdateTBody").on("click", function () {
$.ajax({
url : "script.asp",
...,
success: redrawTBody
});
// let's say success callback receives HTML in data argument
function redrawTBody (data) {
// disclaimer : this is simple, but not the best way
// drawing table
$("ContentId").html(data);
}
});
HTML returned by script.asp
<tr> <!-- row 1 --> </tr>
<!-- following rows -->
And when it comes to changing URL better way would be to use location.assign( location.href + '#ContentId' ) or location.hash="ContentId"

How to filter vertical html table with javascript

found many javascript scripts to filter html tables but they all seem to only work with horizontal tables. need to be able to filter whole records of vertical layout html table. any pointers?
Alternatively, is there a way to write a html vertical table without repeating field headers and thus make the structure more repeated record like? That should make it more amenable to filtering
Technically this is off-topic, as you're not supposed to ask for reviews or suggestions of external libraries - as it's bound to open more discussion than just a simple answer. "Product or service recommendations or comparisons" is listed under "Don't ask about" on the Tour page (https://stackoverflow.com/tour).
Seeing, however, as I've just written some code that could help you with this 'issue', I will post it here for you. Please remember for next time that SO is for assistance with scripts - where you've posted a minimal copy of your code so that the issue can be replicated by us. You should specify the issue you're having and what you've tried so far.
In any case; here's a small vertical table with some filters:
<div>
First Name:<input class='filter' row='1'>
Last Name:<input class='filter' row='2'>
</div>
<table border='1'>
<tr>
<th>First Name</th>
<td>Bill</td>
<td>Mark</td>
<td>Steve</td>
</tr>
<tr>
<th>Last Name</th>
<td>Gates</td>
<td>Zuckerberg</td>
<td>Wozniak</td>
</tr>
</table>
Here's a script to make it filter-able:
var filterTable = $('table');
$('.filter').keyup(function(){
var hide = [];
$('.filter').each(function(){
var val = $(this).val().toLowerCase();
var row = $(this).attr('row');
$('table tr:nth-child(' + row + ') td').each(function(){
if($.inArray($(this).index(), hide) == -1 && $(this).text().toLowerCase().indexOf(val) == -1)
hide.push($(this).index());
});
});
filterTable.find('tr td').each(function(){
if($.inArray($(this).index(), hide) != -1)
$(this).hide();
else
$(this).show();
});
});
And here's a link to a fiddle: https://jsfiddle.net/aacden58/

Pulling JS vars from Bootstrap table using Form without AJAX. Better way?

I wrapped a Bootstrap (BST) table with a Form element. The BST populates the table data with a json file automatically in Javascript on client side, and the table and form look like this:
<form id="info" role="form" action="#" method="post" accept-charset="utf-8">
<table data-toggle="table"
data-url="tables/sharedMem/jsonTickerList"
data-show-refresh="true"
data-show-toggle="true"
data-show-columns="true"
data-search="true"
data-select-item-name="toolbar1"
data-pagination="true"
data-sort-name="name"
data-sort-order="desc"
data-page-size="15"
data-single-select="true"
id="table">
<thead>
<tr>
<th data-field="state" data-radio="true" >Report ID</th>
<th data-field="cik" data-sortable="true">CIK</th>
<th data-field="ticker" data-sortable="true">Ticker</th>
<th data-field="company" data-sortable="true">Name</th>
</tr>
</thead>
</table>
<button type="submit" class="btn btn-small" name = "button">
Submit
</button>
</form>
As you can see, the BST DOES NOT define the table rows or TD's on the server side (because its client side JS enabled). So the only way to capture data that I can find to return row data with the click of a submit button in the form is:
$(function () {
$('#events-table').next().click(function () {
$(this).hide();
var $result = $('#result');
$('#table').bootstrapTable({})
.on('click-row.bs.table', function (e, row, $element) {
$result.text('Event: click-row.bs.table, data: ' + JSON.stringify(row));
var url = "confirm.php?cik=" + row.cik;
document.getElementById("info").setAttribute('action', url);
});
});
});
The two lines above work fantastic. They make it all work.
My problem is that the BST code has a message element needed. It looks like this:
<div class="alert alert-success" id="result" ></div>
When this alert is in the code, the table will not send events to the alert object unless I click the alert first, then click the row in the table. Without the alert in the code, I can't get anything to work. Once I do the preemptive click everything works great, but that is weird. I hope someone can see what is wrong. I'm just too lame with Javascript.. I would hope I could just load the page, click a row, and the JS updates the action attribute in the form element so that when I click the submit button then all is ok.
The BST is great! I can load 10000 records into the table from /dev/shm in about 100 milliseconds and its search feature just is screaming fast so I hope to just debug this last bit so it's a smoother customer experience.
I worked on the problem and found a solution. The correct javascript now is:
$(function () {
$('#events-table').click(function () {
$('#table').bootstrapTable({})
.on('click-row.bs.table', function (e, row, $element) {
var url = "confirm.php?cik=" + row.cik;
document.getElementById("info").setAttribute('action', url);
});
});
});
the HTML:
<div class="alert alert-success" id="result" > </div>
is completely deleted too. Net result is when the table loads, it is fully navigable via pages or search. clicking a row, (or radio button with a minor change) captures the row data so that when you click the Form Submit button, the form data created using client side javascript and json is passed into php's $_POST in the normal way.
I just tested the table with 1.1 million records (3 fields each). It loads in under a second and you can navigate to the last row in 1/2 second. While thats on a 1 Gb intranet, and the data file is 77MB on the test, I think it shows the BST is pretty cool, looks fantastic, and is pretty fast when you store the large json file on /dev/shm, too. All the Form and BST html mentioned previously is correct.
Key to this was removing the "next()" method in the JS since it was effectively ignoring the first click on the table row that I wanted to select. I just guessed that JS would accept ".click" instead...that turned out correct...after a fair number of trial and error mistakes.

Hiding specific rows in a table until an Ajax request completes

I have a specific rows in a HTML table that I do not want to be displayed when the page loads.
There will be an Ajax request made after the page loads that returns values that would populate the table rows.
So I would want to display these rows only after the Ajax returns with a response and until then I want to display a 'loading' message in place of these rows.
I tried adding these rows in a div and used jquery's show()/hide() appropriately but that didn't work.
I'm new to JS and jQuery, so any help is appreciated.
<html>
<body onload="my_ajax_func()">
<table>
.
. <!-- Other rows that will be displayed-->
.
<tr>
<th colspan=2 class="custHeader">High Value Flags</th>
</tr>
<tr>
<td align=right><div id="loading_msg"><b>Loading..</b></div></td>
</tr>
<tr>
<td id="val_header" class=caption>Value Tier: </td><td id="val"> </td>
</tr>
<tr>
<td id="hypo_val_header" class=caption>Hypo Value Tier: </td><td id="hypo_val"> </td>
</tr>
<tr>
<td id="service_type_header" class=caption>Service Type: </td><td id="service_type"></td>
</tr>
</table>
</body>
<script>
function my_ajax_func() {
//retrieves values for table rows
//on success calls another func, say display_data
}
function display_data() {
$("loading_msg").hide();
document.getElementById("val").innerHTML = <some_value>;
document.getElementById("hypo_val").innerHTML = <some_value>;
document.getElementById("service_type").innerHTML = <some_value>;
}
</script>
</html>
Basically, I want a div for 'loading' message which would be displayed by default. Once Ajax request completes successfully, that div must be hidden and another div (with these 2 table rows) must be displayed in it's place.
To hide your rows at page loading, just create two css classes like this:
.displayNone{
display:none;
}
.displayBlock{
display:block;
}
and use this class in your rows
<tr class="displayNone"></tr>
So when page loads, this rows will be hidden.
So, in ajax success put this js:
$(".displayNone").removeClass("displayNone").addClass("displayHidden");
Then, download some loading gif image like this:
http://thinkfuture.com/wp-content/uploads/2013/10/loading_spinner.gif
After that, wrap this img tag in a div with "displayNone" class too, and use inverse way of your rows:
Before your ajax call, remove "displayNone" class from it, and put "displayBlock".
Finally, in ajax success, remove "displayBlock" class from div, and put back "displayNone" to hide it again.
Hope it help.
Some doubts, please let me know.
Regards
You Can use .done() method
$.post( "example.php", function() {
alert( "success" );
})
.done(function() {
alert( "ajax request completed" );
})
If you only need to change text values in the rows, you might be able to get away with a class value of "display: none" in CSS for each complete row, until you are ready to update it. But you are going to have to have some unique ID for each, or way of counting children, in order to find that row again when you need to update it. Also, your table needs to be valid without those rows.
The other way to handle this would be to just add new rows dynamically. If you do this, remember the rows do not exist in DOM until you insert them there, and so you can't reference them before.
as mentioned above ajax has some methods like before and done where you have opportunity to show and hide your elements.
<table>
<thead>
<tr><th>header 1</th><th>header2</th><th>header3</th><tr>
<tr id="loadingrow"><th colspan=3>Loading Data...</th><tr>
</thead>
<tbody>....
$.ajax({
url: "http://fdafdas",
beforeSend: function( ) {
$('#loadingrow').show();
}
})
.done(function( data ) {
$('#loadingrow').hide();
//load your data
}
});

How to Copy and Insert Table Row using jQuery / JavaScript

I have a table with the following structure
<table id='table1'>
<tbody>
<tr id='rowa'>
<td><select>....</select></td>
<tr>
...
<tr id='rowx'>
<td>....</td>
</tr>
...
<tr id='rowz'>
</tr>
</tbody>
</table>
What I want to do is on clicking of a button, I want to copy the rowa and insert it before rowx.
What I am currently doing is
<script type='text/javascript'>
function copyRow() {
var row = $('#rowa').clone();
$('#rowx').before(row);
}
</script>
It seems to show the newly constructed row before the rowx but when I try to access that new row, it does not work. what I mean by does not work in that the select input item does not behave like a select item, it behaves like the static text.
elsewhere on the page I have
<a href='javascript:copyRow()'><img src='images/copyrow.png' title='Copy Row' /></a>
Sorry! I should have made it clear that the copyRow is being called when the user clicks on a link somewhere else on the page.
Check this http://jsbin.com/owivin/1/.
JS:
$(document).ready(function(){
$("#rowx").before($("#rowa").clone());
});
Your code's not working because you never call copyRow(). I put it in the document.ready() so that it would run as the document gets ready!

Categories

Resources