I wrote the below code for finding the records in a table grid.
$(function () {
grid = $('#tblsearchresult');
// handle search fields key up event
$('#search-term').keyup(function (e) {
text = $(this).val(); // grab search term
if (text.length > 1) {
// iterate through all grid rows
grid.find('tr').each(function (i) {
if ($(this).find('td:eq(1)').text().toUpperCase().match(text.toUpperCase()))
$(this).css({ background: "#A4D3EE" });
});
}
else {
grid.find('tr:has(td)').css({ background: "" });
grid.find('tr').show();
} // if no matching name is found, show all rows
});
});
<table id="tblsearchresult" class="tablesorter"">
<thead>
<tr>
<th>ApplicationName</th>
</tr>
</thead>
<tbody>
<% foreach (var request in Model.ApplicationRoles)
{ %>
<tr>
<td>
<span id="appName_<%: request.Id%>">
<%: request.Application.Name%></span>
</td>
</tr>
</tbody>
</table>
EDIT Table Data
applicationame role
application1 appadministrator
app developer
application2 tester
if i given 'app'as search text need to highlight secondrow only .highlightling firstrow also because 'app' is there in role of firstrow..exact match should be highlight on every rows.please tell me.
Your code is behaving correctly. Just that you need to clear all previously highlighted rows on "keyup" of input text first.
if (text.length > 1) {
grid.find('tr:has(td)').css({ background: "" });
grid.find('tr').show();
......rest of your code.......
You need to clear the highlight before you parse. Add this statement of yours:
grid.find('tr:has(td)').css({ background: "" });
before entering this loop:
// iterate through all grid rows
grid.find('tr').each(function (i) {
...
});
Check this fiddle: http://jsfiddle.net/F3jRj/1/
And this updated fiddle with 3 columns: http://jsfiddle.net/F3jRj/2/
Related
I have a SQL table that I'm using to populate a table, and I want to add 'Delete' and 'Edit' Buttons to the row.
I have an input textbox corresponding to a column in my sql table, "PartNo". I currently have two functions: BuildTable and GetData, both a called when a button is pushed. GetData() makes the connection with the sql database and queries for data with the user specified PartNo, and BuildTable uses a StringBuilder class to create an html table and populate it with the sql data. I want each row to have a delete and edit button for which can delete and edit that specific row.
protected void BuildTable(Datatable dt){
//Building an HTML string;
StringBuilder html = new StringBuilder();
html.Append("<h3><b>Parts Location Details</b></h3>");
//table start
html.Append("<table align='center' bgcolor='#dbdbdb'>");
//Building the Header row.
html.Append("<tr >");
foreach (DataColumn column in dt.Columns)
{
html.Append("<th style='color: white' bgcolor='darkblue'>");
html.Append(column.ColumnName);
html.Append("</th>");
}
html.Append("<th style ='color:white' bgcolor ='blue'>Edit</th>");
html.Append("<th style ='color:white' bgcolor ='blue'>Delete</th>");
html.Append("<th style ='color:white' bgcolor ='blue'>Print</th>");
html.Append("<tr>");
//building the data row
foreach (DataRow row in dt.Rows)
{
countRows++;
html.Append("<tr>");
foreach (DataColumn column in dt.Columns)
{
html.Append("<td>");
html.Append(row[column.ColumnName]);
html.Append("</td>");
}
html.Append("<td><input type='button' value='Edit'/></td>");
html.Append("<td><input type='button' value='Delete' runat='server' onclick='btndelete_Click'/></td>");
//html.Append("<td><asp:button ID='delete' runat='server' Text='Delete' OnClick='btndelete'/></td>");
html.Append("<td><input type='button' value='Print'/></td>");
html.Append("</tr>");
}
//table end
html.Append("</table>");
//append the HTML string to PlaceHolder with ID=spDetailsNew
spDetailsNew.Controls.Add(new Literal { Text = html.ToString() });
}
I have tried using a regular html input button and an asp:button object; the asp:button object doesn't show on the table, and the input button's 'onclick' function isn't called when it's clicked. I haven't coded the Delete onclick function yet; it's just supposed to give an alert that the Delete button has been pushed, and it's not doing that.
why you don't build your table with razor ?
- create a customObject to store your data
- create a view and pass your object
- on your cshtml
<table>
<tr>
#foreach (var item in items)
{
<td>#item.something</td>
}
</tr>
...
If you don't want use razor, you should write some javascript and attach to the onclick="javascriptFunction()".
And on the stringbuilder add the javascript :
<script> javascriptFunction() { /** code here */ } </script>
As Thomas said, it'll be easier to use an MVC approach. here's an example of how I use razor style markup (using "HTMLHelpers") for edit/details/delete links:
#foreach (var item in Model.BOMs)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.BOMItem.InternalPN)
</td>
// other cells....
<td nowrap="">
<a asp-page="./Edit" asp-route-id="#item.BOMItem.ID"
asp-route-limit="#Model.CurrentLimit"
asp-route-pageIndex="#Model.CurrentPageIndex"
asp-route-SortOrder="#Model.CurrentSort"
asp-route-SortDir="#Model.CurrentSortDir"
asp-route-ViewMode="#Model.CurrentViewMode">Edit</a> |
<a asp-page="./Details" asp-route-id="#item.BOMItem.ID"
asp-route-limit="#Model.CurrentLimit"
asp-route-pageIndex="#Model.CurrentPageIndex"
asp-route-SortOrder="#Model.CurrentSort"
asp-route-SortDir="#Model.CurrentSortDir"
asp-route-ViewMode="#Model.CurrentViewMode">Details</a> |
<a asp-page="./Delete" asp-route-id="#item.BOMItem.ID" asp-route-KitID="#Model.CurrentKitID"
asp-route-limit="#Model.CurrentLimit"
asp-route-pageIndex="#Model.CurrentPageIndex"
asp-route-SortOrder="#Model.CurrentSort"
asp-route-SortDir="#Model.CurrentSortDir"
asp-route-ViewMode="#Model.CurrentViewMode">Delete</a>
</td>
</tr>
}
The "asp-page" parts set which page the data is sent to. The "asp-route-" part defines variables which are bound to the controller (page_name.cs). You'll see the "asp-route-id" value is set to "#item.BOMItem.ID" which is a part of the viewmodel and corresponds to the datamodel's UID. The controller does the database lookup and creates the "BOMs" viewmodel. (Ignore the other "asp-route-" variables, those are just view variables for the page.) Here's a tutorial on Razor Pages: https://learn.microsoft.com/en-us/aspnet/core/tutorials/razor-pages/razor-pages-start?view=aspnetcore-2.2&tabs=visual-studio If needed. (It's just a sort of simplified framework for MVC... and is a good starting point for learning MVC.)
Let's say, I've this table:
+--------+----------+----
| Device | Serial # |
+--------+----------+----
| Cam1 | AB123 |
+--------+----------+----
Since I don't know in advance the columns that'll be displayed, I construct the table by sending just a pair of key/vale for each cell.
This is how I'm getting my data in C# code.
List<List<KeyValue>> myTable = deviceRepository.GetKeyValues(int facilityId);
Once set to the client side, data in the myTable will be of the following structure:
myTable = [
[ { key: "DeviceName", value: "Device"}, { key: "SerialNumber", value: "Serial #"}, ..],
[ { key: "DeviceName", value: "Cam1"}, { key: "SerialNumber", value: "AB123"}, ..],
...
]
In razor, I'd just have to loop through the list.
#foreach(var row in Model)
{
<tr>
#foreach(var cell in row)
{
<td>#cell.Value</td>
}
</tr>
}
In Angular, I don't see how to do that with directives.
<tr *ngFor="let myInnerList of myTable">
//I'd like to loop through the each inner list to build each table cell
</tr>
Thanks for helping
EDIT
Is it possible to get something like this? i.e if the column is the ID, display a checkbox so that the row can be selected.
#foreach(var cell in row)
{
if(cell.Key == "Id")
{
<td><input type="checkbox" id="row_#cell.Value" /></td>
}
else
{
<td>#cell.Value</td>
}
}
This way, the first cell for every row will display a checkbox.
I am not sure what you are trying to show, you write this but it is dependent on your arrays all being sorted the same within each array. If that is not the case you can either add code to make it so or create a filter.
This is the equivalent of the c# code you have in your question.
<tr *ngFor="let row of myTable">
<td *ngFor="let col of row">
{{col.value}}
</td>
</tr>
new to this type of work , need your help
in my view .cshtml ----
<table class>
<thead>
<tr>
<th >#Html.CheckBox("IsAllRowSelected")</th>
<th >
#Html.DropDownListFor(m => m._dropDownForcolumn2, new List<SelectListItem>
{ new SelectListItem{Text="option1", Value="option1"},
new SelectListItem{Text="option2", Value="option2"},
new SelectListItem{Text="option3", Value="option3"}
}, new {#id="dropDownForcolumn2" })
</th>
<th>#Html.Label(" column 3 ")</th>
<th>#Html.Label("column 4")</th>
<th>#Html.Label("column 5")</th>
</tr>
</thead>
<tbody>
#foreach (Models.MyModelClass item in Model._List)
{
<tr>
<td>#Html.CheckBox("IsEachRowSelected")</td>
<td>#item.Option1Values</td>
#*//#item.option2values;
#item.option3vlaues;*#
<td>#item.column3value</td>
<td>#item.column4value</td>
<td>#item.column5value</td>
</tr>
}
1 .cant post back to controller again to get only this column values . its just a small table in a huge page
2 i already have the other values in item
now only option1 values are coming in the column , the requirement is to bind 2nd colmn with header dropdown and 2nd option selected then this will show #item.option2values and 3rd option selected then #item.option3values will be shown
other columns will not be changed or touched .
somthing like this
<td>
if(dropdownvalue = option1)
#item.Option1Values
elseif(dropdownvalue == option2 )
#item.option2values
elseif(dropdownvalue == option2 )
#item.option3vlaues
</td>
ajax , jquery is allowed but whole page post or partial view post is not allowed
do it like this
put onload method in table tag
function load()
{
$('.MyProperty2').hide();
$('.MyProperty3').hide();
}
function Filldropdown(){
var value = $('#dropdownID :selected').text();
if (value == 'option1') {
$('.MyProperty1').show();
$('.MyProperty2').hide();
$('.MyProperty3').hide();
} else if (value == 'option2') {
$('.MyProperty2').show();
$('.MyProperty1').hide();
$('.MyProperty3').hide();
} else if (value == 'option3') {
$('.MyProperty3').show();
$('.MyProperty2').hide();
$('.MyProperty1').hide();
}
}
I have been trying to scrape some data off a website. The source has differentiated all the headers of tables to that of the actual contents by different class names. Because I want to scrape all the table information, I got all the headers into one array and contents into another array. But the problem is that when I am trying to write the array contents into a file, I can write a header but second array contains contents from all the table and I cannot mark where contents of first table ends.
Because htmlagilitypack scrapes all the tags of specified Nodes, I get all the contents. First let me show the code to make it clear:
<tr class=tableHeader>
<th width=16%>Caught</th>
<th width=16%><p>Normal Range</p></th>
</tr>
<TR class=content><TD><i>Bluegill</i></TD>
<TD>trap net</TD>
<TD align=CENTER>4.05</TD>
<TD align=CENTER> 7.9 - 37.7</TD>
<TD align=CENTER>0.26</TD>
<TD align=CENTER> 0.1 - 0.2</TD>
</TR>
<TR class=content><TD><i></i></TD>
<TD>Gill net</TD>
<TD align=CENTER>1.50</TD>
<TD align=CENTER>N/A</TD>
<TD align=CENTER>0.07</TD>
<TD align=CENTER>N/A</TD>
</TR>
<tr class=tableHeader>
<th>0-5</th>
<th>6-8</th>
<th>9-11</th>
<th>12-14</th>
<th>15-19</th>
<th>20-24</th>
<th>25-29</th>
<th>30+</th>
<th>Total</th>
</tr>
<TR class=content><TD><i>bluegill</i></TD>
<TD align=CENTER>19</TD>
<TD align=CENTER>65</TD>
<TD align=CENTER>0</TD>
<TD align=CENTER>0</TD>
<TD align=CENTER>0</TD>
<TD align=CENTER>0</TD>
<TD align=CENTER>0</TD>
<TD align=CENTER>0</TD>
<TD align=CENTER>84</TD>
</TR>
Below is my code to save the headers and contents into array and try to display it exactly like in the website.
int count =0;
foreach (var trTag4Pale in trTags4Pale)
{
string trText4Pale = trTag4Pale.InnerText;
paleLake[count] = trText4Pale;
if (trTags4Small != null)
{
int counter = 0;
foreach (var trTag4Small in trTags4Small)
{
string trText4Small = trTag4Small.InnerText;
smallText[counter] = trText4Small;
counter++;
}
}
File.AppendAllText(path,paleLake[count]+Environment.Newline+smallText[count]+Environment.Newline);
}
As you see, When I try to append the contents of the array to a file, it lines in the first header, and contents of all the table. But I only want contents of the first table and would repeat the process to get the content of the second table and so forth.
If I could get the contents between tr tag tableHeader, the arrays for the content would contain every contents for all the tables in different arrays. I don't know how to do this.
This might not be the best approach but I made it work somehow. It might be useful resource for somebody someday. So below is the code that worked for me. I append the data stored in the list into an excel sheet. As I have all the data I need for each tr tag with each class, I can manipulate the data I want:
var trTags4Header = document.DocumentNode.SelectNodes("//tr[#class='tableheader']");
if (trTags4Header != null)
{
//Create a list to store td values
List<string> tableList1 = new List<string>();
int row = 2;
foreach (var item in trTags4Header)
{
//Get only next siblings which matches the calss name as "content"
var found = item.SelectNodes("followin-sibling::*").TakeWhile(tag => tag.Name == "tr" && tag.Attributes["class"].Value == "content");
//store the nodes selected in an array (this is the selection of nodes I wanted which has td information I want.
HtmlNode[] nextItem = found.ToArray();
foreach (var node in nextItem)
{
//Gets individual td values within tr class='content' Notice .//td- this starts looking from the present node instead of the root nodes.
var tdValues = node.SelectNodes(".//td").TakeWhile(tdTag => tdTag.Name == "td");
int column = 1;
//Stores each td values into the list which is why I have control over the data to where I want to store, I am storing them in one excel worksheet.
foreach (var tdText in tdValues)
{
tableList1.Add(tdText.InnerText);
ws1.Cells[row, column] = tdText.InnerText;
column++;
}
row++;
}
}
//Display the content in a listbox
listBox1.DataSource = tableList1;
}
Please suggest a better solution if you come across this or leave your feedback. Thanks
I have a table with rows that is sorted based on the INT Priority in my database.
Every row has a <input type="hidden" /> with an ID reference to the database. It also have some up and down arrows (class .up and .down) with the following JavaScript to move the row.
$(document).ready(function(){
$(".up,.down").click(function(){
var row = $(this).parents("tr:first");
if ($(this).is(".up")) {
row.insertBefore(row.prev());
} else {
row.insertAfter(row.next());
}
});
});
Now my question is, how to I update the priority in the database? I need somehow to get the order of the ID's and update the priority column - is there a neat solution for this?
Use jQuery to get a list of the IDs after you have moved a row. Something like:
var inputs = $("#myTable").find("tr").find("input");
// store each rows id in an array - this will be in the correct order
var ids = [];
inputs.each(function(){
ids.push($(this).val());
});
Then pass this list to a PageMethod or WebService and loop through the list, setting the priority of each row in the database. Obviously you will also need to take into account paging or any filtering you have applied to the items too.
Update:
You might want to also look at jQueryUI Sortable to enable drag/drop sorting. You would update the db in the same way.
Update 2:
Here is a simple delay function.
var delay = (function () {
var timer = 0;
return function (callback, ms) {
clearTimeout(timer);
timer = setTimeout(callback, ms);
};
})();
Then use it as follows:
delay(function () {
MySortFunction();
}, 300);
This will delay the function for x milliseconds and cancel any previous calls if you call it again within the specified time.
well, if you also update the prioirty number (index?) when you reorder two rows (),
right in the handler for 'up' / 'down' next to the row.insertBefore(row.prev());
then you could simply loot through the rows on the server and generate a simple "update x set priority = #priority where id = #id"
This may be overkill but I wanted to randomly move a row more than one row up or down. Still have to submit back to the server and this snippet doesn't have the <form> tag, but it should be pretty easy to process the inputs into a sort order based on looping through the input name form.hdrSort* values.
<cfoutput>
<script type="text/javascript">
var maxHdr=#qX.recordCount#;
var curHdr=0;
$(document).ready(function(){
bindReorder();//set with function because when the table gets regenerated, the ordering functionality gets stripped and has to be rebound to the content
});
function bindReorder(ok2do){
if(ok2do==null) ok2do=true;
$("input[id^='hdr']").each(function(){
$(this).mask("?999").focus(function(){
curHdr=parseInt($(this).val());//original value held in global js var
}).blur(function(){
var tVal=parseInt($(this).val());//entered value
if(curHdr!=tVal){
var tId =parseInt($(this).attr("id").substr(3));//id of changed value - this is the new value we don't change'
if(tVal>#qX.recordCount# || tVal<1){//validate entered is in scope
alert("please enter a positive number less than or equal to #qX.recordCount#");
$(this).val(curHdr);
}else if(ok2do){
var lo=Math.min(tVal,curHdr);//lower of original and entered values
var hi=Math.max(tVal,curHdr);//higher of original and entered values
var upDn=1;//default that entered value is less than original value
var aryHdrTbls=new Array(#qX.recordCount#+1);//zero based
if(lo==curHdr) upDn=-1;
$("input[id^='hdr']").each(function(i){
var checkVal=parseInt($(this).val());
var thisId=parseInt($(this).attr("id").substr(3));
if(checkVal<=hi && checkVal>=lo){
if(thisId!==tId) $(this).attr("value",checkVal+upDn);
else $(this).attr("value",checkVal);
aryHdrTbls[$(this).val()]=$("##tbl"+thisId).parent().html();
}
});
for(var i=lo; i<=hi; i++){
$("##td"+i).html(aryHdrTbls[i]);
}
bindReorder(false);
}
}
});
});
}
</script>
<table width="80%">
<cfloop query="qX">
<tr>
<td id="td#qX.currentRow#">
<table style="width:100%;border:1px solid gray;" id="tbl#qX.currentRow#">
<tr>
<td colspan="2" style="background-color:##dddddd;">
<div style="float:right;"><input name="hdrSort#qX.currentRow#" id="hdr#qX.currentRow#" size="1" value="#qX.currentRow#"> <input type="button" width="3" value="go"></div></td>
</tr>
<tr>
<td>#qX.currentRow# #qX.nada#</td>
<td>#qX.nada# more your content original header #qX.currentRow#</td>
</tr>
</table>
</td>
</tr>
</cfloop>
</cfoutput>
</table>