Repeating an HTML snippet that contains elements with id attribute defined - html

I need to repeat an html snippet several times on a page but the problem is that the contained html elements have id defined that should be unique on page. So what is the proper way I could repeat this snippet without removing the id attribute from the elements ?
Could I use iframe as container for this snippet & let the duplicate ids exist on page?

You can use JavaScript to clone the snippet and at the same time change the IDs.
Example if your snippet is:
<div id="snippet">
<table id="list">
<tr id="0">
<td id="firstName0">John</td>
<td id="lastName0">Smith</td>
</tr>
<tr id="1">
<td id="firstName2">John</td>
<td id="lastName2">Doe</td>
</tr>
</table>
</div>
Using
$("#snippet").clone(false).find("*[id]").andSelf().each(function() { $(this).attr("id", $(this).attr("id") + "_1"); });
Will Produce
<div id="snippet_1">
<table id="list_1">
<tr id="0_1">
<td id="firstName0_1">John</td>
<td id="lastName0_1">Smith</td>
</tr>
<tr id="1_1">
<td id="firstName2_1">John</td>
<td id="lastName2_1">Doe</td>
</tr>
</table>
</div>
Which will solve the duplicate ID problem.

Related

Thymeleaf show button during even rows

I'm trying to display a button for each even row in my table ( Thymeleaf ) but I'm not sure how can I do it
<tr th:each="item, iter : ${flightlist}">
<td th:text="${item.flightNumber}"></td>
<td th:text="${item.airline}"></td>
<td th:text="${item.origin}"></td>
<td th:text="${item.destination}"></td>
<td th:text="${#dates.format(item.takeOffDate, 'MM-dd-yyyy')}"></td>
<td th:text="${item.takeOffTime}"></td>
<td th:text="${#dates.format(item.landingDate, 'MM-dd-yyyy')}"></td>
<td th:text="${item.landingTime}"></td>
<td th:text="${item.flightDuration}"></td>
<td th:text="${item.price}"></td>
// Display button code here if true for even
<td th:if="${iter.even == true ? '<a type="button" class="btn btn-primary"
href="/addUserFlight?id=${item.flightNumber}">Select</a> ' : ''}"></td>
</tr>
Edit: Iter worked!
You can use the Thymeleaf iterStat convention to get the value of even:
<tr th:each="item, iterStat : ${flightlist}">
<td th:text="${item.flightNumber}">[flight number]</td>
<td th:text="${item.airline}">[airline]</td>
<td th:text="${item.origin}">[origin]</td>
<td th:text="${item.destination}">[destination]</td>
<td th:text="${#dates.format(item.takeOffDate, 'MM-dd-yyyy')}">[takeOffDate]</td>
<td th:text="${item.takeOffTime}">[takeOffTime]</td>
<td th:text="${#dates.format(item.landingDate, 'MM-dd-yyyy')}">[takeOffTime]</td>
<td th:text="${item.landingTime}">[landingTime]</td>
<td th:text="${item.flightDuration}">[flight duration]</td>
<td th:text="${item.price}">[price]</td>
<td><a th:if="${iterStat.even}"
type="button"
class="btn btn-primary"
th:href="#{/addUserFlight(id=${item.flightNumber})}">Select</a></td>
</tr>
Note that you also want to put this th:if in your <a> tag because the column will otherwise not be included and it will break the design of your table.
You'll want to review the syntax for anchor tags too. You would need th: on the href because you will want Thymeleaf to dynamically evaluate your flight numbers.
Take a look at #numbers.formatCurrency() to format your price
You can include th:if=${!#lists.isEmpty(flightlist)} on the <table> to not show the table if there are no flights.
Lastly, include some default values between tags so that if you open up the page on a browser without a container, you can still what the design will look like. I usually just include the name of the property.

How to dynamically add HTML element/content - Angular

What would be the best way to dynamically add an HTML element, such as another column onto a basic HTML table?
I want to have a button below the table, and if the user were to click the button, the event would add the same amount of rows already in the table and add another column. I would want to support about 5 extra columns being added to the table.
Here's my HTML table as of right now:
<table>
<thead>
<tr>
<th id="row-tag"></th>
<th id="option-column">Option 1</th>
</tr>
</thead>
<tbody>
<tr>
<td id="row-tag">P</td>
<td id="option-column">{{ p }}</td>
</tr>
<tr id="row-tag">
<td>
<app-a-p (saveButtonClick)="toggleAP($event)"
[modModalValues]="modModalValues">
</app-a-p>
</td>
<td id="option-column">
<div class="input-group input-group-sm">
$<input
*ngIf="toggleAP==true"
type="text"
name="aP"
size="10"
disabled
value=""
/>
<input
*ngIf="toggleAP==false"
type="text"
name="aP"
size="10"
[ngModel]="con.pA"
(ngModelChange)="con.pA = $event" appFormatP
(blur)="checkAP($event.target.value);
inputTracker.addModifiedValue('Option 1', $event.target.value)"
/>
</div>
</td>
</tr>
<tr>
<td id="row-tag">L</td>
<td id="option-column">${{l}}</td>
</tr>
<tr>
<td id="row-tag">R</td>
<td id="option-column">${{r}}</td>
</tr>
</tbody>
</table>
I think in Angular, you define table based on your data. for example, you have fields array defining columns, and data array defines the what's actually in the table.
<table >
<thead>
<tr>
<th *ngFor='let key of this.fields'>{{key}}</th>
</tr>
</thead>
<tbody>
<tr *ngFor='let row of this.data ' >
<td scope="row" *ngFor='let key of this.fields'> {{row[key]}} </td>
</tr>
</tbody>
</table>
when you need a new column, just push a new field into fields. like
fields.push('newcolumn');
when you need a new row, just do:
data.push({col1: '', col2:'', newcolumn: ''});
Look into the insertRow() and insertCell() functions in JavaScript. This alongside an onClick function that you write will let you edit the table.
A good way of generating a table on UI when using angular would be to use 2D-array (row*column) use can have a button using which you can dynamically add values to this array and have another row/column to the table.

Unable to select only first occurrence of multiple attributes with same name?

Here is my html code:
<table id="laptop_detail" class="table">
<tbody>
<tr>
<td style="padding-left:18px" class="ha">Camera Pixels</td>
<td class="val">8 megapixel camera</td>
</tr>
<tr>
<td style="padding-left:36px" class="ha">Camera Pixels</td>
<td class="val">8 megapixel camera</td>
</tr>
</tbody>
and my xpath:
$x('//*[#id="laptop_detail"]//tr/td[contains(., "Camera Pixels")]/following-sibling::td[1]/text()')
My problem is I am unable to find any working way of selecting only one occurrence of attribute.
Enclose the part locating the "Camera Pixels" td element into parenthesis:
(//*[#id="laptop_detail"]//tr/td[contains(., "Camera Pixels")])[1]/following-sibling::td
Demo:
$ xmllint index.html --xpath '(//*[#id="laptop_detail"]//tr/td[contains(., "Camera Pixels")])[1]/following-sibling::td'
<td class="val">8 megapixel camera</td>

How to get line from table with Jsoup

I have table without any class or id (there are more tables on the page) with this structure:
<table cellpadding="2" cellspacing="2" width="100%">
...
<tr>
<td class="cell_c">...</td>
<td class="cell_c">...</td>
<td class="cell_c">...</td>
<td class="cell">SOME_ID</td>
<td class="cell_c">...</td>
</tr>
...
</table>
I want to get only one row, which contains <td class="cell">SOME_ID</td> and SOME_ID is an argument.
UPD.
Currently i am doing iy in this way:
doc = Jsoup.connect("http://www.bank.gov.ua/control/uk/curmetal/detail/currency?period=daily").get();
Elements rows = doc.select("table tr");
Pattern p = Pattern.compile("^.*(USD|EUR|RUB).*$");
for (Element trow : rows) {
Matcher m = p.matcher(trow.text());
if(m.find()){
System.out.println(m.group());
}
}
But why i need Jsoup if most of work is done by regexp ? To download HTML ?
If you have a generic HTML structure that always is the same, and you want a specific element which has no unique ID or identifier attribute that you can use, you can use the css selector syntax in Jsoup to specify where in the DOM-tree the element you are after is located.
Consider this HTML source:
<html>
<head></head>
<body>
<table cellpadding="2" cellspacing="2" width="100%">
<tbody>
<tr>
<td class="cell">I don't want this one...</td>
<td class="cell">Neither do I want this one...</td>
<td class="cell">Still not the right one..</td>
<td class="cell">BINGO!</td>
<td class="cell">Nothing further...</td>
</tr> ...
</tbody>
</table>
</body>
</html>
We want to select and parse the text from the fourth <td> element.
We specify that we want to select the <td> element that has the index 3 in the DOM-tree, by using td:eq(3). In the same way, we can select all <td> elements before index 3 by using td:lt(3). As you've probably figured out, this is equal and less than.
Without using first() you will get an Elements object, but we only want the first one so we specify that. We could use get(0) instead too.
So, the following code
Element e = doc.select("td:eq(3)").first();
System.out.println("Did I find it? " + e.text());
will output
Did I find it? BINGO!
Some good reading in the Jsoup cookbook!

Using ruby and nokogiri to parsing HTML using HTML comments as markers

How could I use ruby to extract information from a table consisting of these rows? Is it possible to detect the comments using nokogiri?
<!-- Begin Topic Entry 4134 -->
<tr>
<td align="center" class="row2"><image src='style_images/ip.boardpr/f_norm.gif' border='0' alt='New Posts' /></td>
<td align="center" width="3%" class="row1"> </td>
<td class="row2">
<table class='ipbtable' cellspacing="0">
<tr>
<td valign="middle"><alink href='http://www.xxx.com/index.php?showtopic=4134&view=getnewpost'><image src='style_images/ip.boardpr/newpost.gif' border='0' alt='Goto last unread' title='Goto last unread' hspace=2></a></td>
<td width="100%">
<div style='float:right'></div>
<div> <alink href="http://www.xxx.com/index.php?showtopic=4134&hl=">EXTRACT LINK 1</a> </div>
</td>
</tr>
</table>
<span class="desc">EXTRACT DESCRIPTION</span>
</td>
<td class="row2" width="15%"><span class="forumdesc"><alink href="http://www.xxx.com/index.php?showforum=19" title="Living">EXTRACT LINK 2</a></span></td>
<td align="center" class="row1" width='10%'><alink href='http://www.xxx.com/index.php?showuser=1642'>Mr P</a></td>
<td align="center" class="row2"><alink href="javascript:who_posted(4134);">1</a></td>
<td align="center" class="row1">46</td>
<td class="row1"><span class="desc">Today, 12:04 AM<br /><alink href="http://www.xxx.com/index.php?showtopic=4134&view=getlastpost">Last post by:</a> <b><alink href='http://www.xxx.com/index.php?showuser=1649'>underft</a></b></span></td>
</tr>
<!-- End Topic Entry 4134 -->
-->
Try to use xpath instead:
html_doc = Nokogiri::HTML("<html><body><!-- Begin Topic Entry 4134 --></body></html>")
html_doc.xpath('//comment()')
You could implement a Nokogiri SAX Parser. This is done faster than it might seem at first sight. You get events for Elements, Attributes and Comments.
Within your parser, your should rememeber the state, like #currently_interested = true to know which parts to rememeber and which not.