Table cells in columns accountDTO.state and accountDTO.accountDTO should change background color, depending on the text value of accountDTO.state.
I've tried this:
Thymeleaf - How to apply two (or more) styles based on mutually exclusive conditions
and I've searched some more solutions, but everyone uses conditionals for two possible values, or in URL above there is multiple conditions. I have only one condition, but I have 9 possible values on that field. User selects a value for that field in a different web page. On this page, a list from database is shown.
Now I've tried with th:switch statement inside td tag but then I need to add span or div inside td, but in this case it doesn't work, cells are not colored.
I've searched for something like if/else/if structure or elif, but there is none it seems. And I can't repeat th:if in a single tag. I hope I can use th:switch but, why it doesn't work?
Below is just a shorter version switch, just some of the cases for this example, but I'll need nine cases in total.
<tbody>
<tr th:each = "accountDTO : ${listOfAccounts}">
<td th:text = "${accountDTO.accountDTO}"></td>
<td th:text = "${accountDTO.startBalance}"></td>
<td th:text = "${accountDTO.currentBalance}"></td>
<td th:text = "${accountDTO.state}" th:switch = "${accountDTO.state}"
><span th:case = "${accountDTO.state} == 'OUT_OF_USE'" th:appendstyle = "'background: red'"></span>
<span th:case = "${accountDTO.state} == 'DEVICE'" th:appendstyle = "'background: green'"></span>
<span th:case = "${accountDTO.state} == 'LOCKED'" th:appendstyle = "'background: blue'"></span>
</td>
<td th:text = "${accountDTO.employee.employeeName}"></td>
<td><a th:href = "#{/editAccount/{id}(id=${accountDTO.idAccount})}" class="btn btn-primary btn-lg" id = "eBtn" th:data = "${accountDTO.idAccount}">Edit</a></td>
</tr>
</tbody>
Consider using the variable as class to simplify the Thymeleaf and HTML. Then you can set the format consistently with your CSS. Your HTML would look something like this:
<tbody>
<tr th:each = "accountDTO : ${listOfAccounts}">
<td th:text = "${accountDTO.accountDTO}"></td>
<td th:text = "${accountDTO.startBalance}"></td>
<td th:text = "${accountDTO.currentBalance}"></td>
<td th:text = "${accountDTO.state}" th:classappend = "${accountDTO.state}"></td>
<td th:text = "${accountDTO.employee.employeeName}"></td>
<td><a th:href = "#{/editAccount/{id}(id=${accountDTO.idAccount})}" class="btn btn-primary btn-lg" id = "eBtn" th:data = "${accountDTO.idAccount}">Edit</a></td>
<tr>
</tbody>
Then look at something like this in your CSS:
td.OUT_OF_USE {
background: red;
}
td.DEVICE {
background: green;
}
td.LOCKED {
background: blue;
}
Possibly useful for making similar output consistent on seperate pages.
Related
I am trying to pull data from WSJ and yahoofiance using google sheet app script.
I was able to pull some data through following code with HTML of current price from following page ie <span id="quote_val">(.+?)<\/span>....please note that it containing Id .
Now i am trying to pull target price with HTML of <span class="data_data"><sup>$</sup>50.80</span> . This will not give me desired result . please note that it contains Class not id..
When we choose url as lets say https://www.wsj.com/market-data/quotes/PCT/research-ratings
function SAMPLE(url) {
const html = UrlFetchApp.fetch(url).getContentText();
const res = html.match(/<span id="quote_val">(.+?)<\/span>/);
if (!res) throw new Error("Value cannot be retrieved.")
return isNaN(res[1]) ? res[1] : Number(res[1]);
}
Is there a simple solution?
I would tackle this in two steps:
Use a regular expression to extract the subsection of the web page that you are interested in - specifically the "Stock Price Target" table.
Parse that <table>...</table> string into an HTML document and then iterate over the nodes in that document to extract each relevant item from the table.
function scrapeDemo() {
var url = 'https://www.wsj.com/market-data/quotes/PCT/research-ratings';
var html = UrlFetchApp.fetch(url).getContentText();
var res = html.match(/<div class="cr_data rr_stockprice module">.+?(<table .+?<\/table>)/);
var document = XmlService.parse(res[1]);
var root = document.getRootElement();
var trNodes = root.getChild('tbody').getChildren();
trNodes.forEach((trNode) => {
var tdNodes = trNode.getChildren();
var fieldName;
var fieldValue;
tdNodes.forEach((tdNode, idx) => {
if (idx % 2 === 0) {
fieldName = tdNode.getValue().trim();
} else {
fieldValue = tdNode.getValue().trim();
console.log( fieldName + " : " + fieldValue );
}
} );
} );
}
The regular expression uses this as its starting point:
<div class="cr_data rr_stockprice module">
This is because we need a reliably unique element which is a parent of the table we want (the table itself does not contain anything which uniquely identifies it).
This gives us the table in the res[1] captured group. Here is that HTML:
<table class="cr_dataTable">
<tbody>
<tr>
<td>
<span class="data_lbl">High</span>
</td>
<td>
<span class="data_data">
<sup>$</sup>48.00</span>
</td>
</tr>
<tr>
<td>
<span class="data_lbl">Median</span>
</td>
<td>
<span class="data_data">
<sup>$</sup>37.50</span>
</td>
</tr>
<tr>
<td>
<span class="data_lbl">Low</span>
</td>
<td>
<span class="data_data">
<sup>$</sup>24.00</span>
</td>
</tr>
<tr class="highlight">
<td>
<span class="data_lbl">Average</span>
</td>
<td>
<span class="data_data">
<sup>$</sup>36.75</span>
</td>
</tr>
<tr>
<td>
<span class="data_lbl">Current Price</span>
</td>
<td>
<span class="data_data">
<sup>$</sup>24.18</span>
</td>
</tr>
</tbody>
</table>
Now we perform step 2 using XmlService.parse() to create a mini-XML document containing our HTML.
Then we iterate over the elements of that document, by drilling down into each level's child nodes.
Each field's value is written to the console, so for this table...
...we get this data:
High : $48.00
Median : $37.50
Low : $24.00
Average : $36.75
Current Price : $24.18
In my experience, doing this type of scraping can be difficult. Any unexpected changes in web page structure, from one page to another, can cause the regular expression to fail, or cause the drill-down into the table to fail. In other words, this type of approach should work, but it may also break unexpectedly.
I am taking in an input from a text box in one HTML page and saving it to local storage using this function.
function writeMail(emailInput){
console.log(emailInput);
localStorage.setItem('emailInput',emailInput);
let theEmail = localStorage.getItem('emailInput');
console.log(theEmail);
}
This works fine and I can check the inputs are correct through my console logs.
Yet when I try and get this from local storage to store in my table in my emailList html file, it seems to not work at all.
<body>
email = localstorage["emailInput"];
<table>
<caption> Email list
</caption>
<tr>
<th> Name </th>
<th> Email </th>
</tr>
<tr>
<td>email </td>
</tr>
</table>
</body>
For you to be able to manipulate the contents of HTML, you need to modify the DOM node specifically. In this specific case you should have an id attribute on the <td>and then use the innerHTML property of that node to set the desired value.
i.e.:
<td id="xpto"></td>
then on the code:
let theEmail = localStorage.getItem('emailInput');
document.getElementById("xpto").innerHTML = theEmail;
You should also set that code inside of a function that is called once the document has finished loading, so something like:
JAVASCRIPT:
function go(){
let theEmail = localStorage.getItem('emailInput');
document.getElementById("xpto").innerHTML = theEmail;
}
HTML:
<body onload="go()">
I am working on an HTML web page where I have a table with some data in it and I am trying to control CSS for an entire column in the table based on the values in another column and same row
For example, In the following screenshot I have my data
In the above picture, I have Volume, Price and Type. Now, I want to control the color of Price column based on the corresponding value in Type Column. Like for Price=10 I have Type as Sell, so I want to make the value 10 to red color and similarly if type is Buy then Price value should be in Yellow.
I am trying to do that using following script
<td data-bind="text: Volume"></td>
<td data-bind="text: (typeof Price() === 'number') ? Price().toFixed(2) : '',css:{cclientType:Type=='Sell'}"></td>
<td data-bind="text: Type"></td>
But, that doesn't seem to be working.
Provided, the data is coming from a Knockout View model which in turn is pulling from SQL Server.
Is there a better way I could achieve this?
You could add a ko.computed function to each of your data items to help you determine the css:
self.volume = ko.observable(volume);
self.price = ko.observable(price);
self.type = ko.observable(type);
self.priceCss = ko.computed(function() {
if (self.type() == 'buy') {
return 'buy-class';
} else if (self.type() == 'sell') {
return 'sell-class';
} else return '';
});
This can then be added to your markup:
<tr>
<td data-bind="text:volume"></td>
<td data-bind="text:price, css: priceCss"></td>
<td data-bind="text:type"></td>
</tr>
A plunker demonstrating this can be seen here
Dev.
Please, try this! Works.
<td data-bind="text: volume"></td>
<td data-bind="text: (typeof price() === 'number') ? price().toFixed(2) : '',css:{ cclientType: type() == 'sell'}"></td>
<td data-bind="text: type"></td>
I would set styles on the <tr> based on the contents of type column (or any other column) and handle everything you need in CSS.
Eg.
<tr class="sell">
<td>100</td>
<td>10.00</td>
<td>Sell</td>
</tr>
tr.sell td:nth-of-type(2) {
color: red;
}
If you don't like using the nth-of-type selector, you can set a class on the <td> and then your CSS selector would be:
tr.sell td.price {
color: red;
}
I am trying to dynamically change the values inside my HTML markup depending on certain conditions in the code-behind.
In my code-behind in the Page_Load(), I have the following:
If Not myCheck = 1 Then
mySuffix = "_gr"
myColor = "#cccccc"
Else
mySuffix = ""
myColor = "#bdd1ec"
End If
This is used for my HTML markup to change the way the page looks on certain conditions.
<table>
...
<tr>
<td style="background-color: <%=myColor%>" colSpan="6"><IMG height="5" src="/images/corner-inner-blue-topLeft<%=mySuffix%>.gif" width="5"></td>
<td style="background-color: <%=myColor%>; text-align:right"><IMG height="5" src="/images/corner-inner-blue-topRight<%=mySuffix%>.gif" width="5"></td>
</tr>
...
</table>
Now my problem is this. It works on the suffix but not on the color.
When I run my site, navigate to the page, and I do an inspect element, I get this.
<table>
...
<tr>
<td style="background-color: <%=myColor%>" colspan="6"><img src="/images/myImg_gr.gif" height="5" width="5"></td>
<td style="background-color: <%=myColor%>; text-align:right"><img src="/images/myImg_gr.gif" height="5" width="5"></td>
</tr>
...
</table>
It's reading the <%=mySuffix%> variable from my code-behind but not the <%=myColor%>.
I tried debugging just to be sure that it does pass something to the variable and it does.
Can someone help me point out which I am doing wrong? Or is there any other better way to achieve this?
Thanks a lot!
If not using the table is an option, you might consider using a span or div element, and give it an id, instead of using a <td> element. Then you can reference the span control inside the code-behind to set the style properties. Like this:
ASPX:
<span id="spnSample" runat="server">Hello</span>
.VB:
If Not myCheck = 1 Then
mySuffix = "_gr"
spnSample.Style.Add("background-color", "#cccccc")
Else
mySuffix = ""
spnSample.Style.Add("background-color", "#bdd1ec")
End If
I am trying to create a javascript function within my html document that essentially takes the value of each <td> and places it in the textbox. Any help is very appreciated.
<html>
<head>
<script type="text/javascript">
function typeThis(){
document.getElementById('box_1').value = document.getElementById('typewriter');
}
</script>
<style type="text/css">
td{
border:1px solid black;
padding:10px 10px 10px 10px;
font-family:"Helvetica Neue";
font-size:20px;
}
table{
margin-top:50px;
}
</style>
</head>
<body>
<table id = "typewriter">
<td value="k" onclick="typeThis();">k</td>
<td value="c" onclick="typeThis();">c</td>
<td value="y" onclick="typeThis();">y</td>
<td value="s" onclick="typeThis();">s</td>
<td value="p" onclick="typeThis();">p</td>
<input type="text" id="box_1">
</table>
</body>
</html>
value is a custom property for a td,
so you can access it using this method
function typeThis(){
document.getElementById('box_1').value = this.getAttribute("value");
}
Side Note:
this is how your table should look like
<table id = "typewriter">
<tr>
<td value="k" onclick="typeThis();">k</td>
<td value="c" onclick="typeThis();">c</td>
<td value="y" onclick="typeThis();">y</td>
<td value="s" onclick="typeThis();">s</td>
<td value="p" onclick="typeThis();">p</td>
</tr>
</table>
<input type="text" id="box_1">
Example 2:
function typeThis(letter){
document.getElementById('box_1').value = letter;
}
<table id = "typewriter">
<tr>
<td value="k" onclick="typeThis('k');">k</td>
<td value="c" onclick="typeThis('c');">c</td>
<td value="y" onclick="typeThis('y');">y</td>
<td value="s" onclick="typeThis('s');">s</td>
<td value="p" onclick="typeThis('p');">p</td>
</tr>
</table>
How about
var box = document.getElementById("box_1");
var tds = document.getElementsByTagName("td");
for (var i = 0; i < tds.length; i++) {
var valToAdd = tds[i].textContent ? tds[i].textContent :
(tds[i].innerText ? tds[i].innerText : tds[i].innerHTML);
box.value = box.value + valToAdd;
}
to avoid using innerHTML it checks for the newer textContent and uses it if present. If not, it falls back to innerText and, as a last resort, innerHTML.
Also, if you want to add custom attributes to your td tags, you may want to opt for the more standard data-value="k" format. And check your code for a closing table tag
The main problem is on this line:
document.getElementById('box_1').value = document.getElementById('typewriter');
You are assigning the value of the 'box_1' input equal to the table element itself, not to the value from the particular td that was clicked.
If you change your function to accept a parameter that is the clicked td you can then access the value property:
function typeThis(el){
document.getElementById('box_1').value = el.getAttribute('value');
}
// then change each TD to look like this:
<td value="k" onclick="typeThis(this);">k</td>
However, you can simplify your code somewhat if you use a single click handler on the table instead of putting one on every individual td. When a td is clicked that event "bubbles up" to the containing tr and then to the table, so you handle it there and check the event object to see which td was the actual target:
function typeThis(e) {
// allow for the way IE handles the event object
// compared to other browsers
e = e || window.event;
var el = e.srcElement || e.target;
if (el.tagName.toLowerCase() === "td")
document.getElementById('box_1').value = el.getAttribute('value');
}
document.getElementById('typewriter').onclick = typeThis;
Regarding your table html, some browsers may guess what you meant and display it OK, but you should have a closing </table> tag and your tds should be in a tr. Note that I've removed all of the onclick assignments because with the code above that assigns one for the table you don't need them:
<table id="typewriter">
<tr>
<td value="k">k</td>
<td value="c">c</td>
<td value="y">y</td>
<td value="s">s</td>
<td value="p">p</td>
</tr>
<table>
Note that at the moment each td's value is exactly the same as its innerHTML, so you could just remove all of the value properties from the markup and user .innerHTML in your function instead of getting the value of value:
document.getElementById('box_1').value = el.innerHTML;