I know, I suck because I am using a table and not div tags but I could not get the div tags to display properly and my deadline was some time last week...
I am trying to layout a bunch of devices along with their statuses and other simple options and yet I cannot get the ìf statements to work. Here is my code:
#if (CurrentSystem == null)
{
<p><em>Loading...</em></p>
}
else
{
#foreach (Device thisDevice in CurrentSystem.LocalDevices)
{
menuCounter++;
divCounter++;
if (divCounter == 1)
{
//Starting with the first column
<tr><td class=cardBox>
}
else
{
//Starting with the last column
<tr><td class=outSideColumns></td>
<td></td>
<td class=cardBox>
}
targetName = "target" + #menuCounter;
targetNameWithDot = "." + #targetName;
menuId = "contextMenu" + #menuCounter;
modalID = "modalWindow" + #menuCounter;
<table>
<tr>
<td></td>
<td>
<div class="targetName" style="text-align:right;justify-content:right;">
...
</div>
</td>
</tr>
<tr>
<td colspan="2" align="center">
<h3>
thisDevice.DeviceName
</h3>
<img src="#ReturnDeviceImage(thisDevice)" class=deviceImage />
#if (thisDevice.CurrentStatus == Device.DeviceStatus.Alert)
{
<h4 Class="cardAlert">Status: Alert</h4>
}
else if (thisDevice.CurrentStatus == Device.DeviceStatus.Inactive)
{
<h4 Class="cardInactive">Status: Inactive</h4>
}
else if (thisDevice.CurrentStatus == Device.DeviceStatus.Unknown)
{
<h4 Class="cardUnknown">Status: Unknown</h4>
}
else if (thisDevice.CurrentStatus == Device.DeviceStatus.Normal)
{
<h4 Class=cardNormal>Status: Normal</h4>
}
else if (thisDevice.CurrentStatus == Device.DeviceStatus.Updating)
{
<h4 Class=cardUpdating>Status: Normal</h4>
}
else
{
<h4>Status: thisDevice.CurrentStatus</h4>
}
<TelerikContextMenu IdField="#menuId" Selector="#targetNameWithDot" Data="#MenuItems" OnClick="#((ContextMenuItem item) => OnItemClick(item, #thisDevice.DeviceIDHash))">
</TelerikContextMenu>
</td>
</tr>
<tr>
<td class=nameDivs>
Device Type:
</td>
<td>
#thisDevice.DeviceType
</td>
</tr>
<tr>
<td class=nameDivs>
Hostname:
</td>
<td>
#thisDevice.DeviceHostname
</td>
</tr>
<tr>
<td class=nameDivs>
Communications:
</td>
#if (thisDevice.UsingEncryption)
{
<td class=cardNormal>Are Encrypted</td>
}
else
{
<td> class=cardAlert>Are Not Encrypted</td>
}
</tr>
<tr>
<td class=nameDivs>
Anomaly Response Level:
</td>
<td>
#thisDevice.AnomalyResponse
</td>
</tr>
</table>
if (divCounter == 1)
{
//Ending the first column
</td>
<td></td>
<td class=outSideColumns></td>
</tr>
}
else
{
//Ending the last column
</td></tr>
divCounter = 0;
}
}
</table>
}
The beginning if statement and the if statements that run the CurrentStatus and UsingEncryption seem to be working, however the last if statement is simply writing text to the screen.
If I add # signs to the first and/or last if statements, I get a ton
of errors about not having closing tags, objects not being defined,
etc...
If I remove the # signs from the CurrentStatus and UsingEncryption if
statements, those statements stop working.
If I remove the # from the foreach statement, nothing prints out.
What am I doing wrong?!?
To use tag helpers, your html structure must mirror your control flow. You can't just start a tag inside an if test without also closing it within that if test.
While you can escape unmatched html tags with #: (eg Razor doesn't understand unclosed html tags), with a little effort, you can eliminate your unmatched tags;
<tr>
#if(divCounter != 1)
{
//Starting with the last column
<td class=outSideColumns></td>
<td></td>
}
<td class=cardBox>
While Jeremy provided an excellent answer. I ended up running into issues where I absolutely needed open tags and, in fact, I had to re-write everything back into DIV tags to make things work.
That is when I discovered my new bestest friend - the MarkupString - that I can use to insert any HTML code I desire without blowing up the IDE!
Here is a link that explains how to use it - https://www.meziantou.net/rendering-raw-unescaped-html-in-blazor.htm
Related
I am populating a razor table with a decent amount of data, but it takes > 10 minutes to load.
I am using a lot of logic in my view, and i know this isnt the best way to do this but this is what ive come up, as im new to razor.
names contains about 800 items, contacts 700, urls 3600, servers 1200
I dont think this is a lot but the way i am making the table is what i assume is holding up the application since i traverse these lists multiple times while within other ones.
Ive applied DataTables to this table, i thought it would help as limiting the rows show on the screen should mean the entire lists arent being traversed? Unless datatables still loads the entire table and just displays the 25. Is there a way to only load 100 results initially then slowly load the rest in over time?
Whats the best way to stop my app from hanging when creating this table
<table class="table table-responsive" id="result" data-page-length='25'>
<thead>
<tr>
<th>Application</th>
<th>Ministry</th>
<th>Contacts</th>
<th>Server</th>
<th>URL</th>
</tr>
</thead>
<tbody>
#foreach(var l in Model.names)
{
<tr>
<td style="width: 27%">
#Html.DisplayFor(modelItem => l.appName)
</td>
<td style="width:20%">
#Html.DisplayFor(modelItem => l.ministry)
</td>
<td style="width:20%">
#foreach (var k in Model.contacts)
{
if(k.appName == l.appName){#Html.Raw(k.contactName + " - " + k.contactRole + "<br>")}
}
</td>
<td colspan="2">
<table>
#foreach(var s in Model.servers)
{
<tr >
#if(s.appName == l.appName)
{
<td>
<p class="big">
#Html.Raw(s.server)
</p>
</td>
}
<td>
#foreach(var u in Model.filteredURls)
{
#if(u.appName == l.appName && u.server == s.server){#Html.Raw(u.url + "<br>")}
}
</td>
</tr>
}
</table>
</td>
</tr>
}
</tbody>
</table>
</div>
<script type="text/javascript" >
jQuery(document).ready(function () {
jQuery('#result').DataTable();
});
</script>
Im triyng to make some calculation on my View, but i cant show the result out of my #{} block
I have this table.
<!--Table to display registered products-->
<table class="table table-condensed table-hover">
<thead>
<tr>
<th>CODIGO</th>
<th>NOME</th>
<th>PRECO</th>
<th>QUANTIDADE</th>
<th></th>
</tr>
</thead>
<tbody>
#if (Model != null)
{
double sum = 0;
for (int i = 0; i < Model.Item2.Count; i++)
{
<tr>
#using (Html.BeginForm("AddProduct", "Sale", FormMethod.Post))
{
<td>
#Html.DisplayFor(modelItem => Model.Item2[i].idProduct)
</td>
<td>#Html.DisplayFor(model => Model.Item2[i].nameProduct)</td>
<td>
<p>R$#Html.DisplayFor(model => Model.Item2[i].pricesaleProduct)</p>
</td>
<td>#Html.DisplayFor(model => Model.Item2[i].quantityProduct)</td>
<td>
<input type="submit" class="btn btn-danger" value="Deletar">
</td>
sum += Model.Item2[i].pricesaleProduct * Model.Item2[i].quantityProduct;
}
</tr>
}
}
</tbody>
</table>
<!--I want display "sum" here-->
Total Value: #sum
I want to show "sum" out of my table, but trying several variations and a get error!
How can i make it?
You have declared sum inside if(){} block and hence you're not able to access it. Move it outside like this and it'll work
double sum = 0;
#if (Model != null)
{
............
............
}
I have the following HTML:
<tbody>
<tr>
<td class="metadata_name">Headquarters</td>
<td class="metadata_content">Princeton New Jersey, United States</td>
</tr>
<tr>
<td class="metadata_name">Industry</td>
<td class="metadata_content"><ul><li>Engineering Software</li><li>Software Development & Design</li><li>Software</li><li>Custom Software & Technical Consulting</li></ul></td>
</tr>
<tr>
<td class="metadata_name">Revenue</td>
<td class="metadata_content">$17.5 Million</td>
</tr>
<tr>
<td class="metadata_name">Employees</td>
<td class="metadata_content">201 to 500</td>
</tr>
<tr>
<td class="metadata_name">Links</td>
<td class="metadata_content"><ul><li>Company website</li></ul></td>
</tr>
</tbody>
I want to be able to load the metadata_content value (ex "$17.5 Million") in to a var where the metadata_name is = to a value (ex: "Revenue").
I have tried to use combinations of code like this for a few hours...
orgHtml.DocumentNode.SelectNodes("//td[#class='metadata_name']")[0].InnerHtml;
But I'm not getting the right combination down. If you have a helpful SelectNodes syntax - that will get me the solution I would appreciate it.
It seems what you're looking for is this:
var found = orgHtml.DocumentNode.SelectSingleNode(
"//tr[td[#class = 'metadata_name'] = 'Revenue']/td[#class = 'metadata_content']");
if (found != null)
{
string html = found.InnerHtml;
// use html
}
Note that to get the text of an element, you should use found.InnerText, not found.InnerHtml, unless you specifically need its HTML content.
I have created a web page used for spelling exercises.
I display everything from SQL like this:
public void FillPageSpelling()
{
ArrayList videoList1 = new ArrayList();
if (!IsPostBack)
{
videoList1 = ConnectionClass.GetSpelling(1);
}
else
{
int i = Convert.ToInt32(DropDownList1.SelectedValue);
videoList1 = ConnectionClass.GetSpelling(i);
}
StringBuilder sb = new StringBuilder();
foreach (Spelling sp in videoList1)
{
sb.Append(
string.Format(
#"<table class='VideoTable'>
<tr>
<td align='center'><font face='Verdana'> <font size='3'>Level:</font> <font size='2'>{3}</font></font></td>
</tr>
<tr>
<td align='center'><font face='Verdana'> <font size='3'>Sentence:</font> <font size='2'>{1}</font></font></td>
</tr>
<tr>
<td align='center'><font size='3'>Sound:<audio controls><source src=sound/{2}></audio>
<font face='Verdana'> <font size='2'> </font> </font></td>
</tr>
<tr>
<tr><td align='center'><font face='Verdana'> <font size='3'>Write the word here: <input type=text id=TextBox1></font></font> </td> </tr>
<td><input type=button value='Check' class='p-userButton' onClick='ButtonClick(document.getElementById(""TextBox1"").value, document.getElementById(""TextBox2"").value);'/></td>
<td><input type=button value='Cheat' class='p-userButton' onClick='Cheat(document.getElementById(""TextBox2"").value);' </td>
</tr>
<tr>
<td align='center'><font face='Verdana'><input type=text style=display:none id=TextBox2 value={4}></td>
</tr>
</br>
</table>", sp.SID, sp.Sentence, sp.Audio, sp.Level, sp.Word));
lblOutput.Text = sb.ToString();
}
This is how it looks like when I choose level 2 on the dropdown list:
This is the javascript function that checks whether the word is good or not:
<script type="text/javascript">
function ButtonClick(a, b)
{
if (a.toString() == b.toString())
{
alert("Correct!");
}
else
{
alert("Wrong!");
}
}
</script>
This is how I create the button and call the function:
<input type=button value='Check' class='p-userButton' onClick='ButtonClick(document.getElementById(""TextBox1"").value, document.getElementById(""TextBox2"").value);'/>
Now, this works great with the first sentence, but when I go to the second sentence underneath, and when I type in the word in the textbox, it checks only the first sentence, not the second.
Any ideas on how can I solve this?
Multiple page elements are not supposed to have the same 'id'. That is why you keep getting the first element when using the 'id' to grab the textbox because the 'id's on the textboxes are all the same. You can create an iterator that increments on each pass through the loop and use that to put a unique number on the end of each textbox id (in both the textbox itself and the generated javascript).
I need to grab a timesheets from a website. I want to store/add this timesheet to a data table in my C# Application.
The structure of the data table looks like this:
1. | Day | Time | Status |
2. ..1.......7:00.........IN
3. ..1.......9:45.......OUT
4. ..1......10:15........IN
5. ..1......15:45......OUT
6. ..1.......8:45.....TOTAL
7. ..2 .. ..
My C# code for the DataTable:
DataTable table = new DataTable("Worksheet");
table.Columns.Add("Day");
table.Columns.Add("Time");
table.Columns.Add("Status");
I tried different variants and I always mess up with all the data.
For testing purpose I made a new Winform with a "textbox" (for the sitepath) and "button"(to start the process)
Then I want HTMLAgilityPack to get all the data. one example:
public string[] GREYsource;
public Form1()
{
InitializeComponent();
}
private void btnSubmit_Click(object sender, EventArgs e)
{
var doc = new HtmlAgilityPack.HtmlDocument();
var fileName = txtPath.Text; // I downloaded the HTML-File
doc.Load(fileName);
string strGREYInner;
foreach (HtmlNode td in doc.DocumentNode.SelectNodes("//tr[#class=\"tblDataGreyNH\"]"))
{
strGREYInner = td.InnerText.Trim();
string shorted = strGREYInner.Replace("\t", ""); string shorted2 = shorted.Replace("\n\n\n\n", "\n\n\n"); string shorted3 = shorted2.Replace("\n\n\n", "\n\n"); string shorted4 = shorted3.Replace("\n\n", "\n");
GREYsource = shorted4.Split(new Char[] { '\n', });
}
foreach (string str in GREYsource)
{
...
}
}
Problem: the result contains a lot of tabs(/t) and newlines(/n) I need to trim.
Problem: This isn't a good way to do it, IMO. And this would just grab the Totaltimes.
It can be done better.
This is just a example I tried (other codes just went a pile of junk)
I attached the HTML-structure below:
Overview(picture):
A bit more in depth:
<html>
<head>
</head>
<style type="text/css">
</style>
<body id="body" onload="handleMenuOverlapLogo();onload_column_expand();;firstElementFocus();">
<.. some (java)scripts> /* has to be ignoered. not necessary */
<.. some other divs> /* has to be ignoered. not necessary */
<div id="rowContent"> /* This <div> contains the content i need */
<div id="titleTab"> /* Title is not necessary */
</div>
<div id="rowContentInner"> /* Here the content starts */
<table class="tblList">
<tbody>
<tr> /* not necessary */
<tr class="tblHeader"> /* not necessary */
<tr class="tblHeader"> /* not necessary */
<tr class="tblDataWhiteNH"> /* IN : */
<td class="tblHeader" style="font-weight: bold; text-align: right"> In </td>
<td nowrap=""> /* "tblDataWhiteNH" always contains 7 "td nowrap"
<td nowrap="">
<td nowrap=""> /* Example: if it contains a value */
<table width="100%" border="0" align="center">
<tbody>
<tr>
<td width="25%" align="left"> </td>
<td nowrap="" width="50%" align="center"> 7:53 </td> /* value = 7:53 (THIS!) */
<td width="25%" align="right"> </td>
</tr>
</tbody>
</table>
</td>
<td nowrap="">
<td nowrap=""> /* Example: if it contains no value */
<table width="100%" border="0" align="center">
<tbody>
<tr>
<td width="25%" align="left"> </td>
<td nowrap="" width="50%" align="center"> /* no value = 0:00 (THIS!) */
<td width="25%" align="right"> </td>
</tr>
</tbody>
</table>
</td>
<td nowrap="">
<td nowrap="">
<tr class="tblDataWhiteNH"> /* OUT : */
<td class="tblHeader" style="font-weight: bold; text-align: right"> Out </td>
<td nowrap=""> /* "tblDataWhiteNH" always contains 7 "td nowrap".
<td nowrap="">
<td nowrap=""> /* Example: if it contains a value */
<table width="100%" border="0" align="center">
<tbody>
<tr>
<td width="25%" align="left"> </td>
<td nowrap="" width="50%" align="center"> 7:53 </td> /* value = 7:53 (THIS!) */
<td width="25%" align="right"> </td>
</tr>
</tbody>
</table>
</td>
<td nowrap="">
<td nowrap=""> /* Example: if it contains no value */
<table width="100%" border="0" align="center">
<tbody>
<tr>
<td width="25%" align="left"> </td>
<td nowrap="" width="50%" align="center"> /* no value = 0:00 (THIS!) */
<td width="25%" align="right"> </td>
</tr>
</tbody>
</table>
</td>
<td nowrap="">
<td nowrap="">
<tr class="tblDataGreyNH"> /* IN : */
<tr class="tblDataGreyNH"> /* OUT : */
... /* "tblDataGreyNH" is built up the same way like "tblDataWhiteNH".
... /* sometimes there could be more "tblDataWhiteNH" and "tblDataGreyNH". */
... /* Usally there are just the "tblDataWhiteNH"(IN/OUT) */
<tr class="tblHeader"> /* not necessary */
/* It continues f.egs. with "tblDataWhite" if the last above header was a "tblDatagrey" */
/* and versa vice ("grey" if there was a "white" before.) */
<tr class="tblDataWhiteNH"> /* Worked : */
<td class="tblHeader" style="font-weight: bold; text-align: right"> Total Time </td>
<td> 07:47 </td> /* value = 7:47 (THIS!) */
<td> 04:48 </td>
<td> 00:00 </td> /* no value = 0:00 (THIS!) */
<td> 00:00 </td>
<td> 07:42 </td>
<td> 00:00 </td>
<td> 00:00 </td>
</tr>
<tr class="tblDataGreyNH"> /* Total : */
<td class="tblHeader" style="font-weight: bold; text-align: right"> Regular Time </td>
<td> 07:47 </td> /* value = 7:47 (THIS!) */
<td> 04:48 </td>
<td> </td> /* no value = 0:00 (THIS!) */
<td> </td>
<td> 07:42 </td>
<td> </td>
<td> </td>
</tr>
<tr class="tblHeader"> /* not necessary */
<tr valign="top"> /* not necessary */
</tbody>
</table>
</div>
</div>
</body>
</html>
a copy of the original HTML: http://time.wnb.dk/123/
I Hope anyone could help me get this to work.
Okay let me explain it with a picture. https://www.abload.de/img/eeeqnuwu.png
On the Picture you see the website + a table below, how the result should look like.
Declaring the Datatable isnt the problem.
The main problem is I can't get htmlagility to spit out right results and if it did, its almost buggy.
Some of the selectnodes I tried got the output messed up after a while. As yet I wasn't able to get "all" data from the table on the website, just some values, but often buggy.
So I'm actually searching for someone who could take a look on this and maybe help me to find the right selectnodes.
Not sure I fully understand what you want to do but here is a sample code that should help you get started. I strongly suggest you have a look at XPATH to understand it.
HtmlDocument doc = new HtmlDocument();
doc.Load(yourFile);
// get all TR with a specific class name, starting from root (/), and recursively (//)
foreach (HtmlNode node in doc.DocumentNode.SelectNodes("//tr[#class='tblDataGreyNH' or #class='tblDataWhiteNH']"))
{
// get all TD below the current node with a specific class name
HtmlNode inOrOut = node.SelectSingleNode("td[#class='tblHeader']");
if (inOrOut != null)
{
string io = inOrOut.InnerText.Trim();
Console.WriteLine(io.ToUpper());
if (io.Contains("Time"))
{
// normalize-space gets rid or whitespaces (\r,\n, etc.)
// text() gets the node's inner text
foreach (HtmlNode td in node.SelectNodes("td[normalize-space(#class)='' and normalize-space(text())!='' and normalize-space(text())!='00:00']"))
{
Console.WriteLine("value:" + td.InnerText.Trim());
}
}
}
// gets all TD below the current node that define the NOWRAP attribute
HtmlNodeCollection tdNoWraps = node.SelectNodes("td[#nowrap]");
if (tdNoWraps != null)
{
foreach (HtmlNode tdNoWrap in tdNoWraps)
{
string value = tdNoWrap.InnerText.Trim();
if (value == string.Empty)
continue;
Console.WriteLine("value:" + value);
}
}
}
It will output this from your sample page:
IN
value:7:47
value:7:46
value:7:45
value:7:51
OUT
value:15:35
value:15:33
value:12:38
value:8:59
IN
value:12:38
value:8:59
OUT
value:15:35
TOTAL TIME
value:07:48
value:07:47
value:07:50
value:01:08
REGULAR TIME
value:07:48
value:07:47
value:07:50
value:01:08