Parse info from slightly different html bodys - java

I am building an email scraper in JAVA which need to scrape information from specific mails. Those mails have been send through a couple of years. I am facing the problem that every year there is a little change in the html code my code works fine for a specific year but won't for the following or previous year. I am looking for a way to write smart code. NEEDED is the value I need, and VARIABLE can be different. SAME TITLE is always the same.
<span class="confirmationtitle">SAME TITLE 1</span></td></tr>
<tr>
<td><span class="confirmationleft">VARIABLE</span></td>
<td><span class="confirmationright">NEEDED1 </span></td>
</tr>
<tr>
<td><span class="confirmationleft">VARIABLE</span></td>
<td><span class="confirmationright">NEEDED2</span></td>
</tr>
<tr>
<td><span class="confirmationleft">VARIABLE</span></td>
<td><span class="confirmationright">NEEDED3</span></td>
</tr>
<tr>
<td><span class="confirmationleft">VARIABLE</span></td>
<td><span class="confirmationright">NEEDED4</span></td>
</tr>
<tr>
<td><span class="confirmationleft">VARIABLE</span></td>
<td><span class="confirmationright">NEEDED5</span></td>
</tr>
<tr>
<td><span class="confirmationleft">VARIABLE</span></td>
<td><span class="confirmationright">NEEDED6</span></td>
</tr>
Above the code from year x, below from year y. There are multiple table rows like this with different info.
<tr>
<div style="font-weight: bold; display: block; margin-top: 20px;">SAME TITLE 1</div>
</td>
</tr>
<tr>
<td><span style="width: 145px; display: inline-block; zoom:1; /* IE 7 Hack starts here*/ *display:inline; line-height: 18px; vertical-align: top;">VARIABLE</span></td>
<td><span style="display: inline-block; zoom:1; /* IE 7 Hack starts here*/ *display:inline; line-height: 18px; width: 488px; vertical-align: top;">NEEDED1 </span></td>
</tr>
<tr>
<td><span style="width: 145px; display: inline-block; zoom:1; /* IE 7 Hack starts here*/ *display:inline; line-height: 18px; vertical-align: top;">VARIABLE</span></td>
<td><span style="display: inline-block; zoom:1; /* IE 7 Hack starts here*/ *display:inline; line-height: 18px; width: 488px; vertical-align: top;">NEEDED2</span></td>
</tr>
<tr>
<td><span style="width: 145px; display: inline-block; zoom:1; /* IE 7 Hack starts here*/ *display:inline; line-height: 18px; vertical-align: top;">VARIABLE</span></td>
<td><span style="display: inline-block; zoom:1; /* IE 7 Hack starts here*/ *display:inline; line-height: 18px; width: 488px; vertical-align: top;">NEEDED3</span></td>
</tr>
<tr>
<td><span style="width: 145px; display: inline-block; zoom:1; /* IE 7 Hack starts here*/ *display:inline; line-height: 18px; vertical-align: top;">VARIABLE</span></td>
<td><span style="display: inline-block; zoom:1; /* IE 7 Hack starts here*/ *display:inline; line-height: 18px; width: 488px; vertical-align: top;">NEEDED4</span></td>
</tr>
<tr>
<td><span style="width: 145px; display: inline-block; zoom:1; /* IE 7 Hack starts here*/ *display:inline; line-height: 18px; vertical-align: top;">VARIABLE</span></td>
<td><span style="display: inline-block; zoom:1; /* IE 7 Hack starts here*/ *display:inline; line-height: 18px; width: 488px; vertical-align: top;">NEEDED5</span></td>
</tr>
<tr>
<td><span style="width: 145px; display: inline-block; zoom:1; /* IE 7 Hack starts here*/ *display:inline; line-height: 18px; vertical-align: top;">VARIABLE</span></td>
<td><span style="display: inline-block; zoom:1; /* IE 7 Hack starts here*/ *display:inline; line-height: 18px; width: 488px; vertical-align: top;">NEEDED6</span></td>
</tr>
<tr>
My code for this specific row in the table:
String[] SpecificInfo = new String[6];
String TravellerInfoGender = SpecificInfo[0] = headerInfo.split("</span></td>")[1].split("</span>")[0].split(">")[2];
String TravellerInfoFirstname = SpecificInfo[1] = headerInfo.split("</span></td>")[3].split("</span>")[0].split(">")[2];
String TravellerInfoMiddleName = SpecificInfo[2] = headerInfo.split("</span></td>")[5].split("</span>")[0].split(">")[2];
String TravellerInfoSurName = SpecificInfo[3] = headerInfo.split("</span></td>")[7].split("</span>")[0].split(">")[2];
String TravellerInfoDateOfBirth = SpecificInfo[4] = headerInfo.split("</span></td>")[9].split("</span>")[0].split(">")[2];
String TravellerInfoNationality = SpecificInfo[5] = headerInfo.split("</span></td>")[11].split("</span>")[0].split(">")[2];
for(int i = 0; i < TravellerInfo.length ; i++)
writeToFile(TravellerInfo[i]);
return TravellerInfo;
Where headerInfo contains the html snippet as in the first two code examples.
I hope there is a way I do not have to hard code every little change.
Thanks!

Related

On ButtonClick backgroundcolor of various Tablecells

I need a little help with Java here. How do I fill e.g. table cell 4,3, and 16 by clicking a Button ?
So If I click my Button I want the predefined tablecells to be red. Sorry but I'm a beginner.
Hope someone can help me :-)
cheers and stay healthy
table td {
border: 1px solid black;
padding: 30px;
}
.fill {
background-color: red;
}
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
</tr>
<tr>
<td>9</td>
<td>10</td>
<td>12</td>
<td>12</td>
</tr>
<tr>
<td>13</td>
<td>14</td>
<td>15</td>
<td>16</td>
</tr>
</table>
<button onclick="">CLICK</button>
Given your question, I am going to assume that it is related to Javascript and not Java. If not and you really needed a helping hand in Java, I'm sorry for the misunderstanding!
So, first I think you need to add some ids to your tablecells, so we can identify them later.
Then you call a small Javascript function when you click the button with just a parameter, an array of the tablecells' ids that you want to color.
That function, for each id that you provide, will add the class fill.
I hope that answers your question, sorry for my English and my technique, I'm a kind of beginner too!
function fill_cells($cells) {
$cells.forEach(e => document.getElementById(e).classList.add('fill'));
}
table td {
border: 1px solid black;
padding: 30px;
}
.fill {
background-color: red;
}
<table>
<tr>
<td id="1">1</td>
<td id="2">2</td>
<td id="3">3</td>
<td id="4">4</td>
</tr>
<tr>
<td id="5">5</td>
<td id="6">6</td>
<td id="7">7</td>
<td id="8">8</td>
</tr>
<tr>
<td id="9">9</td>
<td id="10">10</td>
<td id="11">12</td>
<td id="12">12</td>
</tr>
<tr>
<td id="13">13</td>
<td id="14">14</td>
<td id="15">15</td>
<td id="16">16</td>
</tr>
</table>
<button onclick="fill_cells([4, 3, 16])">CLICK</button>
I'm not an expert either on this, but you could use JQuery to change css, see https://api.jquery.com/css/
function makeRed() {
$(".selected").css("background-color", "red");
}
table td {
border: 1 px solid black;
padding: 30 px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
</tr>
<tr>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
</tr>
<tr>
<td class='selected'>9</td>
<td>10</td>
<td>12</td>
<td>12</td>
</tr>
<tr>
<td>13</td>
<td>14</td>
<td>15</td>
<td>16</td>
</tr>
</table>
<button onclick=makeRed()>CLICK</button>

Table body width relative to table head [duplicate]

How can I set for <table> 100% width and put only inside <tbody> vertical scroll for some height?
table {
width: 100%;
display:block;
}
thead {
display: inline-block;
width: 100%;
height: 20px;
}
tbody {
height: 200px;
display: inline-block;
width: 100%;
overflow: auto;
}
<table>
<thead>
<tr>
<th>Head 1</th>
<th>Head 2</th>
<th>Head 3</th>
<th>Head 4</th>
<th>Head 5</th>
</tr>
</thead>
<tbody>
<tr>
<td>Content 1</td>
<td>Content 2</td>
<td>Content 3</td>
<td>Content 4</td>
<td>Content 5</td>
</tr>
</tbody>
</table>
I want to avoid adding some additional div, all I want is simple table like this and when I trying to change display, table-layout, position and much more things in CSS table not working good with 100% width only with fixed width in px.
In order to make <tbody> element scrollable, we need to change the way it's displayed on the page i.e. using display: block; to display that as a block level element.
Since we change the display property of tbody, we should change that property for thead element as well to prevent from breaking the table layout.
So we have:
thead, tbody { display: block; }
tbody {
height: 100px; /* Just for the demo */
overflow-y: auto; /* Trigger vertical scroll */
overflow-x: hidden; /* Hide the horizontal scroll */
}
Web browsers display the thead and tbody elements as row-group (table-header-group and table-row-group) by default.
Once we change that, the inside tr elements doesn't fill the entire space of their container.
In order to fix that, we have to calculate the width of tbody columns and apply the corresponding value to the thead columns via JavaScript.
Auto Width Columns
Here is the jQuery version of above logic:
// Change the selector if needed
var $table = $('table'),
$bodyCells = $table.find('tbody tr:first').children(),
colWidth;
// Get the tbody columns width array
colWidth = $bodyCells.map(function() {
return $(this).width();
}).get();
// Set the width of thead columns
$table.find('thead tr').children().each(function(i, v) {
$(v).width(colWidth[i]);
});
And here is the output (on Windows 7 Chrome 32):
Working demo.
Full Width Table, Relative Width Columns
As the original poster needed, we could expand the table to 100% of width of its container, and then using a relative (Percentage) width for each columns of the table.
table {
width: 100%; /* Optional */
}
tbody td, thead th {
width: 20%; /* Optional */
}
Since the table has a (sort of) fluid layout, we should adjust the width of thead columns when the container resizes.
Hence we should set the columns' widths once the window is resized:
// Adjust the width of thead cells when *window* resizes
$(window).resize(function() {
/* Same as before */
}).resize(); // Trigger the resize handler once the script runs
The output would be:
Working demo.
Browser Support and Alternatives
I've tested the two above methods on Windows 7 via the new versions of major Web Browsers (including IE10+) and it worked.
However, it doesn't work properly on IE9 and below.
That's because in a table layout, all elements should follow the same structural properties.
By using display: block; for the <thead> and <tbody> elements, we've broken the table structure.
Redesign layout via JavaScript
One approach is to redesign the (entire) table layout. Using JavaScript to create a new layout on the fly and handle and/or adjust the widths/heights of the cells dynamically.
For instance, take a look at the following examples:
jQuery .floatThead() plugin (a floating/locked/sticky table header plugin)
jQuery Scrollable Table plugin. (source code on github)
jQuery .FixedHeaderTable() plugin (source code on github)
DataTables vertical scrolling example.
Nesting tables
This approach uses two nested tables with a containing div. The first table has only one cell which has a div, and the second table is placed inside that div element.
Check the Vertical scrolling tables at CSS Play.
This works on most of web browsers. We can also do the above logic dynamically via JavaScript.
Table with fixed header on scroll
Since the purpose of adding vertical scroll bar to the <tbody> is displaying the table header at the top of each row, we could position the thead element to stay fixed at the top of the screen instead.
Here is a Working Demo of this approach performed by Julien.
It has a promising web browser support.
And here a pure CSS implementation by Willem Van Bockstal.
The Pure CSS Solution
Here is the old answer. Of course I've added a new method and refined the CSS declarations.
Table with Fixed Width
In this case, the table should have a fixed width (including the sum of columns' widths and the width of vertical scroll-bar).
Each column should have a specific width and the last column of thead element needs a greater width which equals to the others' width + the width of vertical scroll-bar.
Therefore, the CSS would be:
table {
width: 716px; /* 140px * 5 column + 16px scrollbar width */
border-spacing: 0;
}
tbody, thead tr { display: block; }
tbody {
height: 100px;
overflow-y: auto;
overflow-x: hidden;
}
tbody td, thead th {
width: 140px;
}
thead th:last-child {
width: 156px; /* 140px + 16px scrollbar width */
}
Here is the output:
WORKING DEMO.
Table with 100% Width
In this approach, the table has a width of 100% and for each th and td, the value of width property should be less than 100% / number of cols.
Also, we need to reduce the width of thead as value of the width of vertical scroll-bar.
In order to do that, we need to use CSS3 calc() function, as follows:
table {
width: 100%;
border-spacing: 0;
}
thead, tbody, tr, th, td { display: block; }
thead tr {
/* fallback */
width: 97%;
/* minus scroll bar width */
width: -webkit-calc(100% - 16px);
width: -moz-calc(100% - 16px);
width: calc(100% - 16px);
}
tr:after { /* clearing float */
content: ' ';
display: block;
visibility: hidden;
clear: both;
}
tbody {
height: 100px;
overflow-y: auto;
overflow-x: hidden;
}
tbody td, thead th {
width: 19%; /* 19% is less than (100% / 5 cols) = 20% */
float: left;
}
Here is the Online Demo.
Note: This approach will fail if the content of each column breaks the line, i.e. the content of each cell should be short enough.
In the following, there are two simple example of pure CSS solution which I created at the time I answered this question.
Here is the jsFiddle Demo v2.
Old version: jsFiddle Demo v1
In following solution, table occupies 100% of the parent container, no absolute sizes required. It's pure CSS, flex layout is used.
Here is how it looks:
Possible disadvantages:
vertical scrollbar is always visible, regardless of whether it's required;
table layout is fixed - columns do not resize according to the content width (you still can set whatever column width you want explicitly);
there is one absolute size - the width of the scrollbar, which is about 0.9em for the browsers I was able to check.
HTML (shortened):
<div class="table-container">
<table>
<thead>
<tr>
<th>head1</th>
<th>head2</th>
<th>head3</th>
<th>head4</th>
</tr>
</thead>
<tbody>
<tr>
<td>content1</td>
<td>content2</td>
<td>content3</td>
<td>content4</td>
</tr>
<tr>
<td>content1</td>
<td>content2</td>
<td>content3</td>
<td>content4</td>
</tr>
...
</tbody>
</table>
</div>
CSS, with some decorations omitted for clarity:
.table-container {
height: 10em;
}
table {
display: flex;
flex-flow: column;
height: 100%;
width: 100%;
}
table thead {
/* head takes the height it requires,
and it's not scaled when table is resized */
flex: 0 0 auto;
width: calc(100% - 0.9em);
}
table tbody {
/* body takes all the remaining available space */
flex: 1 1 auto;
display: block;
overflow-y: scroll;
}
table tbody tr {
width: 100%;
}
table thead, table tbody tr {
display: table;
table-layout: fixed;
}
full code on jsfiddle
Same code in LESS so you can mix it in:
.table-scrollable() {
#scrollbar-width: 0.9em;
display: flex;
flex-flow: column;
thead,
tbody tr {
display: table;
table-layout: fixed;
}
thead {
flex: 0 0 auto;
width: ~"calc(100% - #{scrollbar-width})";
}
tbody {
display: block;
flex: 1 1 auto;
overflow-y: scroll;
tr {
width: 100%;
}
}
}
In modern browsers, you can simply use css:
th {
position: sticky;
top: 0;
z-index: 2;
}
CSS-only
for Chrome, Firefox, Edge (and other evergreen browsers)
Simply position: sticky; top: 0; your th elements:
/* Fix table head */
.tableFixHead { overflow: auto; height: 100px; }
.tableFixHead th { position: sticky; top: 0; }
/* Just common table stuff. */
table { border-collapse: collapse; width: 100%; }
th, td { padding: 8px 16px; }
th { background:#eee; }
<div class="tableFixHead">
<table>
<thead>
<tr><th>TH 1</th><th>TH 2</th></tr>
</thead>
<tbody>
<tr><td>A1</td><td>A2</td></tr>
<tr><td>B1</td><td>B2</td></tr>
<tr><td>C1</td><td>C2</td></tr>
<tr><td>D1</td><td>D2</td></tr>
<tr><td>E1</td><td>E2</td></tr>
</tbody>
</table>
</div>
PS: if you need borders for TH elements th {box-shadow: 1px 1px 0 #000; border-top: 0;} will help (since the default borders are not painted correctly on scroll).
For a variant of the above that uses just a bit of JS in order to accommodate for IE11 see this answer Table fixed header and scrollable body
I'm using display:block for thead and tbody.
Because of that the width of the thead columns is different from the width of the tbody columns.
table {
margin:0 auto;
border-collapse:collapse;
}
thead {
background:#CCCCCC;
display:block
}
tbody {
height:10em;overflow-y:scroll;
display:block
}
To fix this I use small jQuery code but it can be done in JavaScript only.
var colNumber=3 //number of table columns
for (var i=0; i<colNumber; i++) {
var thWidth=$("#myTable").find("th:eq("+i+")").width();
var tdWidth=$("#myTable").find("td:eq("+i+")").width();
if (thWidth<tdWidth)
$("#myTable").find("th:eq("+i+")").width(tdWidth);
else
$("#myTable").find("td:eq("+i+")").width(thWidth);
}
Here is my working demo:
http://jsfiddle.net/gavroche/N7LEF/
Does not work in IE 8
var colNumber=3 //number of table columns
for (var i=0; i<colNumber; i++)
{
var thWidth=$("#myTable").find("th:eq("+i+")").width();
var tdWidth=$("#myTable").find("td:eq("+i+")").width();
if (thWidth<tdWidth)
$("#myTable").find("th:eq("+i+")").width(tdWidth);
else
$("#myTable").find("td:eq("+i+")").width(thWidth);
}
table {margin:0 auto; border-collapse:separate;}
thead {background:#CCCCCC;display:block}
tbody {height:10em;overflow-y:scroll;display:block}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<table id="myTable" border="1">
<thead>
<tr>
<th>A really Very Long Header Text</th>
<th>Normal Header</th>
<th>Short</th>
</tr>
</thead>
<tbody>
<tr>
<td>
Text shorter than header
</td>
<td>
Text is longer than header
</td>
<td>
Exact
</td>
</tr>
<tr>
<td>
Text shorter than header
</td>
<td>
Text is longer than header
</td>
<td>
Exact
</td>
</tr>
<tr>
<td>
Text shorter than header
</td>
<td>
Text is longer than header
</td>
<td>
Exact
</td>
</tr>
<tr>
<td>
Text shorter than header
</td>
<td>
Text is longer than header
</td>
<td>
Exact
</td>
</tr>
<tr>
<td>
Text shorter than header
</td>
<td>
Text is longer than header
</td>
<td>
Exact
</td>
</tr>
<tr>
<td>
Text shorter than header
</td>
<td>
Text is longer than header
</td>
<td>
Exact
</td>
</tr>
<tr>
<td>
Text shorter than header
</td>
<td>
Text is longer than header
</td>
<td>
Exact
</td>
</tr>
<tr>
<td>
Text shorter than header
</td>
<td>
Text is longer than header
</td>
<td>
Exact
</td>
</tr>
<tr>
<td>
Text shorter than header
</td>
<td>
Text is longer than header
</td>
<td>
Exact
</td>
</tr>
<tr>
<td>
Text shorter than header
</td>
<td>
Text is longer than header
</td>
<td>
Exact
</td>
</tr>
<tr>
<td>
Text shorter than header
</td>
<td>
Text is longer than header
</td>
<td>
Exact
</td>
</tr>
</tbody>
</table>
Create two tables one after other, put second table in a div of fixed height and set the overflow property to auto. Also keep all the td's inside thead in second table empty.
<div>
<table>
<thead>
<tr>
<th>Head 1</th>
<th>Head 2</th>
<th>Head 3</th>
<th>Head 4</th>
<th>Head 5</th>
</tr>
</thead>
</table>
</div>
<div style="max-height:500px;overflow:auto;">
<table>
<thead>
<tr>
<th></th>
<th></th>
<th></th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td>Content 1</td>
<td>Content 2</td>
<td>Content 3</td>
<td>Content 4</td>
<td>Content 5</td>
</tr>
</tbody>
</table>
</div>
I got it finally right with pure CSS by following these instructions:
http://tjvantoll.com/2012/11/10/creating-cross-browser-scrollable-tbody/
The first step is to set the <tbody> to display: block so an overflow and height can be applied. From there the rows in the <thead> need to be set to position: relative and display: block so that they’ll sit on top of the now scrollable <tbody>.
tbody, thead { display: block; overflow-y: auto; }
Because the <thead> is relatively positioned each table cell needs an explicit width
td:nth-child(1), th:nth-child(1) { width: 100px; }
td:nth-child(2), th:nth-child(2) { width: 100px; }
td:nth-child(3), th:nth-child(3) { width: 100px; }
But unfortunately that is not enough. When a scrollbar is present browsers allocate space for it, therefore, the <tbody> ends up having less space available than the <thead>. Notice the slight misalignment this creates...
The only workaround I could come up with was to set a min-width on all columns except the last one.
td:nth-child(1), th:nth-child(1) { min-width: 100px; }
td:nth-child(2), th:nth-child(2) { min-width: 100px; }
td:nth-child(3), th:nth-child(3) { width: 100px; }
Whole codepen example below:
CSS:
.fixed_headers {
width: 750px;
table-layout: fixed;
border-collapse: collapse;
}
.fixed_headers th {
text-decoration: underline;
}
.fixed_headers th,
.fixed_headers td {
padding: 5px;
text-align: left;
}
.fixed_headers td:nth-child(1),
.fixed_headers th:nth-child(1) {
min-width: 200px;
}
.fixed_headers td:nth-child(2),
.fixed_headers th:nth-child(2) {
min-width: 200px;
}
.fixed_headers td:nth-child(3),
.fixed_headers th:nth-child(3) {
width: 350px;
}
.fixed_headers thead {
background-color: #333333;
color: #fdfdfd;
}
.fixed_headers thead tr {
display: block;
position: relative;
}
.fixed_headers tbody {
display: block;
overflow: auto;
width: 100%;
height: 300px;
}
.fixed_headers tbody tr:nth-child(even) {
background-color: #dddddd;
}
.old_ie_wrapper {
height: 300px;
width: 750px;
overflow-x: hidden;
overflow-y: auto;
}
.old_ie_wrapper tbody {
height: auto;
}
Html:
<!-- IE < 10 does not like giving a tbody a height. The workaround here applies the scrolling to a wrapped <div>. -->
<!--[if lte IE 9]>
<div class="old_ie_wrapper">
<!--<![endif]-->
<table class="fixed_headers">
<thead>
<tr>
<th>Name</th>
<th>Color</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>Apple</td>
<td>Red</td>
<td>These are red.</td>
</tr>
<tr>
<td>Pear</td>
<td>Green</td>
<td>These are green.</td>
</tr>
<tr>
<td>Grape</td>
<td>Purple / Green</td>
<td>These are purple and green.</td>
</tr>
<tr>
<td>Orange</td>
<td>Orange</td>
<td>These are orange.</td>
</tr>
<tr>
<td>Banana</td>
<td>Yellow</td>
<td>These are yellow.</td>
</tr>
<tr>
<td>Kiwi</td>
<td>Green</td>
<td>These are green.</td>
</tr>
<tr>
<td>Plum</td>
<td>Purple</td>
<td>These are Purple</td>
</tr>
<tr>
<td>Watermelon</td>
<td>Red</td>
<td>These are red.</td>
</tr>
<tr>
<td>Tomato</td>
<td>Red</td>
<td>These are red.</td>
</tr>
<tr>
<td>Cherry</td>
<td>Red</td>
<td>These are red.</td>
</tr>
<tr>
<td>Cantelope</td>
<td>Orange</td>
<td>These are orange inside.</td>
</tr>
<tr>
<td>Honeydew</td>
<td>Green</td>
<td>These are green inside.</td>
</tr>
<tr>
<td>Papaya</td>
<td>Green</td>
<td>These are green.</td>
</tr>
<tr>
<td>Raspberry</td>
<td>Red</td>
<td>These are red.</td>
</tr>
<tr>
<td>Blueberry</td>
<td>Blue</td>
<td>These are blue.</td>
</tr>
<tr>
<td>Mango</td>
<td>Orange</td>
<td>These are orange.</td>
</tr>
<tr>
<td>Passion Fruit</td>
<td>Green</td>
<td>These are green.</td>
</tr>
</tbody>
</table>
<!--[if lte IE 9]>
</div>
<!--<![endif]-->
EDIT: Alternative solution for table width 100% (above actually is for fixed width and didn't answer the question):
HTML:
<table>
<thead>
<tr>
<th>Name</th>
<th>Color</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td>Apple</td>
<td>Red</td>
<td>These are red.</td>
</tr>
<tr>
<td>Pear</td>
<td>Green</td>
<td>These are green.</td>
</tr>
<tr>
<td>Grape</td>
<td>Purple / Green</td>
<td>These are purple and green.</td>
</tr>
<tr>
<td>Orange</td>
<td>Orange</td>
<td>These are orange.</td>
</tr>
<tr>
<td>Banana</td>
<td>Yellow</td>
<td>These are yellow.</td>
</tr>
<tr>
<td>Kiwi</td>
<td>Green</td>
<td>These are green.</td>
</tr>
</tbody>
</table>
CSS:
table {
width: 100%;
text-align: left;
min-width: 610px;
}
tr {
height: 30px;
padding-top: 10px
}
tbody {
height: 150px;
overflow-y: auto;
overflow-x: hidden;
}
th,td,tr,thead,tbody { display: block; }
td,th { float: left; }
td:nth-child(1),
th:nth-child(1) {
width: 20%;
}
td:nth-child(2),
th:nth-child(2) {
width: 20%;
float: left;
}
td:nth-child(3),
th:nth-child(3) {
width: 59%;
float: left;
}
/* some colors */
thead {
background-color: #333333;
color: #fdfdfd;
}
table tbody tr:nth-child(even) {
background-color: #dddddd;
}
Demo: http://codepen.io/anon/pen/bNJeLO
Adding a fixed width to td,th after making tbody & thead display block works perfectly and also we can use slimscroll plugin to make the scroll bar beautiful.
<!DOCTYPE html>
<html>
<head>
<title> Scrollable table </title>
<style>
body {
font-family: sans-serif;
font-size: 0.9em;
}
table {
border-collapse: collapse;
border-bottom: 1px solid #ddd;
}
thead {
background-color: #333;
color: #fff;
}
thead,tbody {
display: block;
}
th,td {
padding: 8px 10px;
border: 1px solid #ddd;
width: 117px;
box-sizing: border-box;
}
tbody {
height: 160px;
overflow-y: scroll
}
</style>
</head>
<body>
<table class="example-table">
<thead>
<tr>
<th> Header 1 </th>
<th> Header 2 </th>
<th> Header 3 </th>
<th> Header 4 </th>
</tr>
</thead>
<tbody>
<tr>
<td> Row 1- Col 1 </td>
<td> Row 1- Col 2 </td>
<td> Row 1- Col 3 </td>
<td> Row 1- Col 4 </td>
</tr>
<tr>
<td> Row 2- Col 1 </td>
<td> Row 2- Col 2 </td>
<td> Row 2- Col 3 </td>
<td> Row 2- Col 4 </td>
</tr>
<tr>
<td> Row 3- Col 1 </td>
<td> Row 3- Col 2 </td>
<td> Row 3- Col 3 </td>
<td> Row 3- Col 4 </td>
</tr>
<tr>
<td> Row 4- Col 1 </td>
<td> Row 4- Col 2 </td>
<td> Row 4- Col 3 </td>
<td> Row 4- Col 4 </td>
</tr>
<tr>
<td> Row 5- Col 1 </td>
<td> Row 5- Col 2 </td>
<td> Row 5- Col 3 </td>
<td> Row 5- Col 4 </td>
</tr>
<tr>
<td> Row 6- Col 1 </td>
<td> Row 6- Col 2 </td>
<td> Row 6- Col 3 </td>
<td> Row 6- Col 4 </td>
</tr>
<tr>
<td> Row 7- Col 1 </td>
<td> Row 7- Col 2 </td>
<td> Row 7- Col 3 </td>
<td> Row 7- Col 4 </td>
</tr>
<tr>
<td> Row 8- Col 1 </td>
<td> Row 8- Col 2 </td>
<td> Row 8- Col 3 </td>
<td> Row 8- Col 4 </td>
</tr>
<tr>
<td> Row 9- Col 1 </td>
<td> Row 9- Col 2 </td>
<td> Row 9- Col 3 </td>
<td> Row 9- Col 4 </td>
</tr>
<tr>
<td> Row 10- Col 1 </td>
<td> Row 10- Col 2 </td>
<td> Row 10- Col 3 </td>
<td> Row 10- Col 4 </td>
</tr>
<tr>
<td> Row 11- Col 1 </td>
<td> Row 11- Col 2 </td>
<td> Row 11- Col 3 </td>
<td> Row 11- Col 4 </td>
</tr>
<tr>
<td> Row 12- Col 1 </td>
<td> Row 12- Col 2 </td>
<td> Row 12- Col 3 </td>
<td> Row 12- Col 4 </td>
</tr>
<tr>
<td> Row 13- Col 1 </td>
<td> Row 13- Col 2 </td>
<td> Row 13- Col 3 </td>
<td> Row 13- Col 4 </td>
</tr>
<tr>
<td> Row 14- Col 1 </td>
<td> Row 14- Col 2 </td>
<td> Row 14- Col 3 </td>
<td> Row 14- Col 4 </td>
</tr>
<tr>
<td> Row 15- Col 1 </td>
<td> Row 15- Col 2 </td>
<td> Row 15- Col 3 </td>
<td> Row 15- Col 4 </td>
</tr>
<tr>
<td> Row 16- Col 1 </td>
<td> Row 16- Col 2 </td>
<td> Row 16- Col 3 </td>
<td> Row 16- Col 4 </td>
</tr>
</tbody>
</table>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jQuery-slimScroll/1.3.8/jquery.slimscroll.min.js"></script>
<script>
$('.example-table tbody').slimscroll({
height: '160px',
alwaysVisible: true,
color: '#333'
})
</script>
</body>
</html>
Css workaround for forcing columns to display correctly with a 'block' tbody
This solution still requires the th widths to be calculated and set by jQuery
table.scroll tbody,
table.scroll thead { display: block; }
table.scroll tbody {
overflow-y: auto;
overflow-x: hidden;
max-height: 300px;
}
table.scroll tr {
display: flex;
}
table.scroll tr > td {
flex-grow: 1;
flex-basis: 0;
}
And the Jquery / Javascript
var $table = $('#the_table_element'),
$bodyCells = $table.find('tbody tr:first').children(),
colWidth;
$table.addClass('scroll');
// Adjust the width of thead cells when window resizes
$(window).resize(function () {
// Get the tbody columns width array
colWidth = $bodyCells.map(function () {
return $(this).width();
}).get();
// Set the width of thead columns
$table.find('thead tr').children().each(function (i, v) {
$(v).width(colWidth[i]);
});
}).resize(); // Trigger resize handler
try below approach, very simple easy to implement
Below is the jsfiddle link
http://jsfiddle.net/v2t2k8ke/2/
HTML:
<table border='1' id='tbl_cnt'>
<thead><tr></tr></thead><tbody></tbody>
CSS:
#tbl_cnt{
border-collapse: collapse; width: 100%;word-break:break-all;
}
#tbl_cnt thead, #tbl_cnt tbody{
display: block;
}
#tbl_cnt thead tr{
background-color: #8C8787; text-align: center;width:100%;display:block;
}
#tbl_cnt tbody {
height: 100px;overflow-y: auto;overflow-x: hidden;
}
Jquery:
var data = [
{
"status":"moving","vehno":"tr544","loc":"bng","dri":"ttt"
}, {
"status":"stop","vehno":"tr54","loc":"che", "dri":"ttt"
},{ "status":"idle","vehno":"yy5499999999999994","loc":"bng","dri":"ttt"
},{
"status":"moving","vehno":"tr544","loc":"bng", "dri":"ttt"
}, {
"status":"stop","vehno":"tr54","loc":"che","dri":"ttt"
},{
"status":"idle","vehno":"yy544","loc":"bng","dri":"ttt"
}
];
var sth = '';
$.each(data[0], function (key, value) {
sth += '<td>' + key + '</td>';
});
var stb = '';
$.each(data, function (key, value) {
stb += '<tr>';
$.each(value, function (key, value) {
stb += '<td>' + value + '</td>';
});
stb += '</tr>';
});
$('#tbl_cnt thead tr').append(sth);
$('#tbl_cnt tbody').append(stb);
setTimeout(function () {
var col_cnt=0
$.each(data[0], function (key, value) {col_cnt++;});
$('#tbl_cnt thead tr').css('width', ($("#tbl_cnt tbody") [0].scrollWidth)+ 'px');
$('#tbl_cnt thead tr td,#tbl_cnt tbody tr td').css('width', ($('#tbl_cnt thead tr ').width()/Number(col_cnt)) + 'px');}, 100)
Try this jsfiddle. This is using jQuery and made from Hashem Qolami's answer. At first, make a regular table then make it scrollable.
const makeScrollableTable = function (tableSelector, tbodyHeight) {
let $table = $(tableSelector);
let $bodyCells = $table.find('tbody tr:first').children();
let $headCells = $table.find('thead tr:first').children();
let headColWidth = 0;
let bodyColWidth = 0;
headColWidth = $headCells.map(function () {
return $(this).outerWidth();
}).get();
bodyColWidth = $bodyCells.map(function () {
return $(this).outerWidth();
}).get();
$table.find('thead tr').children().each(function (i, v) {
$(v).css("width", headColWidth[i]+"px");
$(v).css("min-width", headColWidth[i]+"px");
$(v).css("max-width", headColWidth[i]+"px");
});
$table.find('tbody tr').children().each(function (i, v) {
$(v).css("width", bodyColWidth[i]+"px");
$(v).css("min-width", bodyColWidth[i]+"px");
$(v).css("max-width", bodyColWidth[i]+"px");
});
$table.find('thead').css("display", "block");
$table.find('tbody').css("display", "block");
$table.find('tbody').css("height", tbodyHeight+"px");
$table.find('tbody').css("overflow-y", "auto");
$table.find('tbody').css("overflow-x", "hidden");
};
Then you can use this function as follows:
makeScrollableTable('#test-table', 250);
This is the code that works for me to create a sticky thead on a table with a scrollable tbody:
table ,tr td{
border:1px solid red
}
tbody {
display:block;
height:50px;
overflow:auto;
}
thead, tbody tr {
display:table;
width:100%;
table-layout:fixed;/* even columns width , fix width of table too*/
}
thead {
width: calc( 100% - 1em )/* scrollbar is average 1em/16px width, remove it from thead width */
}
table {
width:400px;
}
For using "overflow: scroll" you must set "display:block" on thead and tbody. And that messes up column widths between them. But then you can clone the thead row with Javascript and paste it in the tbody as a hidden row to keep the exact col widths.
$('.myTable thead > tr')
.clone()
.appendTo('.myTable tbody')
.addClass('hidden-to-set-col-widths')
;
http://jsfiddle.net/Julesezaar/mup0c5hk/
<table class="myTable">
<thead>
<tr>
<td>Problem</td>
<td>Solution</td>
<td>blah</td>
<td>derp</td>
</tr>
</thead>
<tbody></tbody>
</table>
<p>
Some text to here
</p>
The css:
table {
background-color: #aaa;
width: 100%;
}
thead,
tbody {
display: block; // Necessary to use overflow: scroll
}
tbody {
background-color: #ddd;
height: 150px;
overflow-y: scroll;
}
tbody tr.hidden-to-set-col-widths,
tbody tr.hidden-to-set-col-widths td {
visibility: hidden;
height: 0;
line-height: 0;
padding-top: 0;
padding-bottom: 0;
}
td {
padding: 3px 10px;
}

How to add values from checkbox to array?

I need your help.
I'm working on a jsp application.
The thing is that I have a form within a "select-option" then depending on the item I select from the "select option" I get a list with checkboxes, and I can get the checkboxes values in my servlet, but now what I try to do is to get does values and add them to an array. How can I do that?
JSP code:
//Select-option
<table>
<tr>
<td width="50%" style="text-align: left;">
<select class="selectSmall" id="a_selectCta" name="a_selectCta"
style="margin-bottom: 5px; width: 310px;">
<option value="">Seleccione un Cuentahabiente</option>
<%
for (Ctahabiente habiente : CtahabienteDAO.getCtahabientes()) {
if (ctahabiente != null && habiente.getIdCtahabiente().equalsIgnoreCase(ctahabiente.getIdCtahabiente())) {
%>
<option selected="selected" value="<%=ctahabiente.getIdCtahabiente()%>">
<%=ctahabiente.getIdCtahabiente() + " - " + ctahabiente.getDesCtahabiente()%></option>
<%
} else {
%>
<option value="<%=habiente.getIdCtahabiente()%>">
<%=habiente.getIdCtahabiente() + " - " + habiente.getDesCtahabiente()%></option>
<% } }
%>
</select>
</td>
</tr>
</table>
//List with checkboxes from select-option
<%
if (request.getAttribute("a_accion") != null) {
%>
<%
ctahabiente = null;
List<Directorio> listaDirectorio = (List<Directorio>)request.getAttribute("a_listaDirectorio");
ctahabiente =(Ctahabiente)request.getAttribute("a_ctahabiente");
%>
<table class="tableDirectorio" style="text-align: left;">
<tr>
<th width="5px">CheckBox</th>
<th width="5px">ID dir</th>
<th width="5px">ID cta</th>
</tr>
<%
if(listaDirectorio.size()>0){
itDirectorio = listaDirectorio.iterator();
boolean renglon=true; // renglon par
while(itDirectorio.hasNext()){
directorio = (Directorio) itDirectorio.next();
if(renglon){
%>
<tr>
<td style="background-color: #fff; text-align: center;"><input type="checkbox" id="checkCta" name="checkCta" value="<%=directorio.getIdDirectorio()%>" /></td>
<td style="background-color: #fff; text-align: center;"><%=directorio.getIdDirectorio()!= 0? directorio.getIdDirectorio():""%></td>
<td style="background-color: #fff; text-align: center;"><%=directorio.getIdCtahabiente()!= null? directorio.getIdCtahabiente():""%></td>
</tr>
<%
renglon=false;
}else{
%>
<tr>
<td style="background-color: #fff; text-align: center;"><input type="checkbox" id="checkCta" name="checkCta" value="<%=directorio.getIdDirectorio()%>" /></td>
<td style="background-color: #fff; text-align: center;"><%=directorio.getIdDirectorio()!= 0? directorio.getIdDirectorio():""%></td>
<td style="background-color: #fff; text-align: center;"><%=directorio.getIdCtahabiente()!= null? directorio.getIdCtahabiente():""%></td>
</tr>
<%
renglon=true;
}
}
%>
</table>
<%}%>

Relative Xpath from list of WebElements

Is it possible to use a relative xpath after I've gathered a list of WebElements? If so what's the best way to do it?
This is what I have:
List <WebElement> rows = driver.findElements(By.xpath(rowsXpath));
int j = 1;
boolean foundCollector = false;
for(WebElement e : rows) {
String c = e.findElement(By.xpath("(//tbody)[" + j + "]//u[text()=\"" + collector + "\"])")).getText();
if(c.equals(collector)) {
foundCollector = true;
break;
}
++j;
}
the list rows contains individual rows with multiple columns and I'm trying to find the row which contains a particular name in a column. Within my for loop I was trying to use a relative xpath to look for an element, is this even possible? Or do I need to provide the whole xpath I used to find the rows with the additional xpath for the individual divs?
I'm not guaranteed the order of the columns which is why I have to do it this way.
This is the xpath I used to obtain the rows:
String rowsXpath = "//div[#id=\"QosDashpardPanelBottom\"]//div[#id=\"CollectorQoSPerformanceMetricsgrid\"]//div[contains(#class, \"x-grid3-row x-unselectable-single\")]";
Here's the HTML:
<body class=" ext-gecko ext-windows" onload="processLoaders();">
<script type="text/javascript">
<div id="topNavDiv" style="height: 90px">
<div id="bodyContentOuter" style="width: 1280px; height: 587px;">
<div id="bodyContentInner">
<script src="RLT/RLT.nocache.js" language="javascript" type="text/javascript">
<script defer="defer">
<script language="javascript" type="text/javascript">
<div id="rtcpMain" class=" x-component x-border-layout-ct" style="width: 1280px; height: 587px;">
<div id="rtcpMainWest" class=" x-panel x-component x-border-panel" style="left: 5px; top: 5px; width: 225px;">
<div id="x-auto-2" class=" x-tab-panel x-component x-border-panel" tabindex="0" hidefocus="true" style="left: 235px; top: 5px; width: 1040px;">
<div class="x-tab-panel-header x-unselectable" style="width: 1038px;" unselectable="on">
<div class="tone-rtcp-tabbed-content-panel" style="width: 1040px; height: 550px;">
<div id="x-auto-10" class=" x-component" style="overflow: auto; width: 1040px; height: 550px;">
<div id="QosDashboardPanel0" class=" x-panel x-component" style="width: 1040px;">
<div id="x-auto-13" class=" x-small-editor x-panel-header x-component x-hide-display" role="presentation">
<div id="rtcpDPBWrap" class="x-panel-bwrap" role="presentation" style="overflow: visible;">
<div class="x-panel-tbar x-panel-tbar-noheader" role="presentation" style="width: 1040px;">
<div id="rtcpDPBody" class="x-panel-body x-panel-body-noheader x-border-layout-ct" role="presentation" style="width: 1038px; height: 700px;">
<div id="QosDashboardPanelTop" class=" x-component x-border-panel x-border-layout-ct" style="left: 0px; top: 0px; width: 1038px; height: 400px;">
<div id="QosDashpardPanelBottom" class=" x-component x-border-panel x-border-layout-ct" style="left: 1px; top: 401px; width: 1036px; height: 298px;">
<div id="QosDashpardPanel_pqosChartsLC" class=" x-component x-border-panel x-border-layout-ct x-hide-display" style="left: 0px; top: 0px; width: 1036px; height: 400px;">
<div id="QosDashpardPanel_metricsTablesLC" class=" x-component x-border-panel x-border-layout-ct" style="left: 1px; top: 1px; width: 1034px; height: 296px;">
<div id="CollectorMetrics_toneletWrapper" class=" x-panel x-component x-border-panel" style="left: 1px; top: 1px; width: 330px;">
<div id="x-auto-99" class=" x-small-editor x-panel-header x-component x-hide-display" role="presentation">
<div class="x-panel-bwrap" role="presentation">
<div class="x-panel-body x-panel-body-noheader" role="presentation" style="width: 328px; height: 292px;">
<div id="CollectorMetrics" class=" x-panel x-component" style="width: 328px;">
<div id="x-auto-109" class=" x-small-editor x-panel-header x-component x-unselectable" role="presentation" unselectable="on">
<div class="x-panel-bwrap" role="presentation">
<div class="x-panel-body" role="presentation" style="width: 326px; height: 265px;">
<div id="CollectorQoSPerformanceMetricsgrid" class=" x-grid-panel x-component" style="position: relative; width: 326px; height: 265px;" tabindex="0" hidefocus="true" unselectable="">
<div class="x-grid3" role="presentation" style="width: 326px; height: 265px;">
<div class="x-grid3-viewport" role="presentation">
<div class="x-grid3-header" role="presentation">
<div class="x-grid3-scroller" role="presentation" style="width: 326px; height: 243px;">
<div class="x-grid3-body" role="presentation">
<div id="CollectorQoSPerformanceMetricsgrid_x-auto-633" class="x-grid3-row x-unselectable-single x-grid3-row-selected x-grid3-highlightrow " style="width:510px;">
<table class="x-grid3-row-table" cellspacing="0" cellpadding="0" border="0" style="width:510px;" role="presentation">
<tbody role="presentation">
<tr role="presentation">
<td id="x-auto-634" class="x-grid3-col x-grid3-cell x-grid3-td-name x-grid-cell-first " style="width:148px;" role="gridcell">
<div class="x-grid3-cell-inner x-grid3-col-name" unselectable="on">
<u>Lync</u>
</div>
</td>
<td id="x-auto-635" class="x-grid3-col x-grid3-cell x-grid3-td-badCalls " style="width:53px;" role="gridcell">
<div class="x-grid3-cell-inner x-grid3-col-badCalls" unselectable="on">36</div>
</td>
<td id="x-auto-636" class="x-grid3-col x-grid3-cell x-grid3-td-totalCalls " style="width:58px;" role="gridcell">
<div class="x-grid3-cell-inner x-grid3-col-totalCalls" unselectable="on">120</div>
</td>
<td id="x-auto-637" class="x-grid3-col x-grid3-cell x-grid3-td-avgLatency " style="width:73px;" role="gridcell">
<div class="x-grid3-cell-inner x-grid3-col-avgLatency" unselectable="on">223</div>
</td>
<td id="x-auto-638" class="x-grid3-col x-grid3-cell x-grid3-td-avgLoss " style="width:53px;" role="gridcell">
<div class="x-grid3-cell-inner x-grid3-col-avgLoss" unselectable="on">0.80</div>
</td>
<td id="x-auto-639" class="x-grid3-col x-grid3-cell x-grid3-td-avgJitter " style="width:58px;" role="gridcell">
<div class="x-grid3-cell-inner x-grid3-col-avgJitter" unselectable="on">29</div>
</td>
<td id="x-auto-640" class="x-grid3-col x-grid3-cell x-grid3-td-avgMOS x-grid3-cell-last " style="width:53px;" role="gridcell">
<div class="x-grid3-cell-inner x-grid3-col-avgMOS" unselectable="on">3.86</div>
</td>
</tr>
</tbody>
</table>
</div>
<div id="CollectorQoSPerformanceMetricsgrid_x-auto-641" class="x-grid3-row x-unselectable-single " style="width:510px;">
<table class="x-grid3-row-table" cellspacing="0" cellpadding="0" border="0" style="width:510px;" role="presentation">
<tbody role="presentation">
<tr role="presentation">
<td id="x-auto-642" class="x-grid3-col x-grid3-cell x-grid3-td-name x-grid-cell-first " style="width:148px;" role="gridcell">
<div class="x-grid3-cell-inner x-grid3-col-name" unselectable="on">
<u>CUCM-Publisher</u>
</div>
</td>
<td id="x-auto-643" class="x-grid3-col x-grid3-cell x-grid3-td-badCalls " style="width:53px;" role="gridcell">
<div class="x-grid3-cell-inner x-grid3-col-badCalls" unselectable="on">3</div>
</td>
<td id="x-auto-644" class="x-grid3-col x-grid3-cell x-grid3-td-totalCalls " style="width:58px;" role="gridcell">
<div class="x-grid3-cell-inner x-grid3-col-totalCalls" unselectable="on">52</div>
</td>
<td id="x-auto-645" class="x-grid3-col x-grid3-cell x-grid3-td-avgLatency " style="width:73px;" role="gridcell">
<div class="x-grid3-cell-inner x-grid3-col-avgLatency" unselectable="on">190</div>
</td>
<td id="x-auto-646" class="x-grid3-col x-grid3-cell x-grid3-td-avgLoss " style="width:53px;" role="gridcell">
<div class="x-grid3-cell-inner x-grid3-col-avgLoss" unselectable="on">0.79</div>
</td>
<td id="x-auto-647" class="x-grid3-col x-grid3-cell x-grid3-td-avgJitter " style="width:58px;" role="gridcell">
<div class="x-grid3-cell-inner x-grid3-col-avgJitter" unselectable="on">31</div>
</td>
<td id="x-auto-648" class="x-grid3-col x-grid3-cell x-grid3-td-avgMOS x-grid3-cell-last " style="width:53px;" role="gridcell">
<div class="x-grid3-cell-inner x-grid3-col-avgMOS" unselectable="on">3.98</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>
Yes, this is definitely possible. See this:
// Find the outer element.
WebElement outer = driver.findElement(By.anything("whatever"));
// This doesn't work, it searches the whole page for the XPath expression.
WebElement inner = outer.findElement(By.xpath("//some/nasty/xpath"));
// This works! It takes the outer element as root.
WebElement inner = outer.findElement(By.xpath(".//some/nasty/xpath"));
Therefore, if I understood your need well, your XPath expression needs to look like this:
By.xpath("(.//tbody)[" + j + "]//div[text()=\"" + collector + "\"])")
EDIT (Holy cow, that's a lot of HTML and only a small amount of it is actually needed :).)
Now that I caught what you're after, I think you don't need this approach at all. Try this instead:
WebElement row = driver.findElement(By.xpath("id('CollectorQoSPerformanceMetricsgrid')//div[contains(#class,'x-grid3-row x-unselectable-single') and .//u[text()='" + collector + "']]"));
Only the XPath expression:
id('CollectorQoSPerformanceMetricsgrid')
//div[contains(#class,'x-grid3-row x-unselectable-single')
and .//u[text()='" + collector + "'] ]
Taken apart:
FIND ELEM WITH ID = 'CollectorQoSPerformanceMetricsgrid'
id('CollectorQoSPerformanceMetricsgrid')
FIND ALL DIV ELEMS THAT CONTAIN 'x-grid3-row x-unselectable-single' IN #CLASS
//div[contains(#class,'x-grid3-row x-unselectable-single')
AND HAVE AN <U> DESCENDANT WITH TEXT EQUAL TO collector VARIABLE
and .//u[text()='" + collector + "'] ]
This finds you only the single row you need with a single command.
If you rather want to stick with your current solution, try:
String rowsXpath = "id('CollectorQoSPerformanceMetricsgrid')//div[contains(#class, 'x-grid3-row x-unselectable-single')]";
List<WebElement> rows = driver.findElements(By.xpath(rowsXpath));
boolean foundCollector = false;
for(WebElement row : rows) {
if(!row.findElements(By.xpath(".//u[text()='" + collector + "']")).isEmpty()) {
foundCollector = true;
break;
}
}
Nowhere I found row (tr tag) in this xpath then how it will get rows count.
String rowsXpath = "//div[#id=\"QosDashpardPanelBottom\"]//div[#id=\"CollectorQoSPerformanceMetricsgrid\"]//div[contains(#class, \"x-grid3-row x-unselectable-single\")]";
You need to construct xpath something like below to get row count in particular table
int rowCount=driver.findElements(By.xpath("//table[#class='x-grid3-row-table']/tbody/tr"))
Or else if you want to find all columns in that table with particular name
construct xpath like below
int columnCount=driver.findElements(By.xpath("//table[#class='x-grid3-row-table']/tbody//tr//td[#name='RequiredName']"))

Velocity and $foreach.count

I am using velocity 1.7 and within a foreach loop I want to print the count. In the template I have the following string in a #foreach/#end section:
Count: $foreach.count
and was expecting to see in the rendered result something like
Count: 1
...
Count: 2
...
but all I see is:
Count: $foreach.count
...
Count: $foreach.count
...
Any ideas what am I doing wrong?
Neither $foreach.count nor $counter worked for me.
This answer suggests using $velocityCount, and it worked for me.
Your code is partial, we don't see the foreach directive.
Else, I know that the foreach loop has a built-in variable called $counter, though in the guide they do refer to $foreach.count
I tried with $counter & $foreach.count but neither of these worked for me.
However, the $velocityCount tag worked and below is the example.
Input code:
#foreach($entry in $entries)
<p>In for Loop count is : $velocityCount</p>
#end
Output:
In for Loop count is : 1
In for Loop count is : 2
In for Loop count is : 3
I do not know why the foreach loop built-in variable called $count is not working as guide refer. But $velocityCount is worked for me.
There is property called directive.foreach.counter.name is velocityCount in velocity.properties file, so default $count variable may not be working.
k.honsalis answer is deprecated.
At this point you can only use $velocityCount, even though the documentation will refer to deprecated methods.
#foreach($item in $items)
counter 0: $foreach.index
counter 1: $foreach.count
counter 2: $counter
counter 3: $velocityCount
#end
Output:
$foreach.index
$foreach.count
$counter
1
The default variable is velocityCount, but you can change the variable name and initial value (only in prior 2.0 versions) if you want.
VelocityEngine engine = new VelocityEngine();
engine.setProperty("directive.foreach.counter.name", "velocityCount");
engine.setProperty("directive.foreach.counter.initial.value", 1);
http://people.apache.org/~henning/velocity/htmlsingle/VelocityUsersGuide.html
$velocityCount is works for me and i'm using velocity 1.5 $foreach.count & $counter
I am currently formatting my email_html.vm like so.
Note, I am using
#set( $count = 1 )
and
#set( $count = $count + 1 )
<html>
<body>
<table style="border: 1px solid black; border-collapse: collapse">
#set( $count = 1 )
#foreach( $film in $filmList )
<tr>
<td colspan=2 style="background: bisque; text-align: center"><b>Movie $count</b></td>
</tr>
<tr>
<th style="border: 1px solid black; border-collapse: collapse; padding: 5px; text-align: left">Title</th>
<td style="border: 1px solid black; border-collapse: collapse; padding: 5px; text-align: left"> $film.getTitle() </td>
</tr>
<tr>
<th style="border: 1px solid black; border-collapse: collapse; padding: 5px; text-align: left">Synopsis</th>
<td style="border: 1px solid black; border-collapse: collapse; padding: 5px; text-align: left"> $film.getSynopsis() </td>
</tr>
<tr>
<th style="border: 1px solid black; border-collapse: collapse; padding: 5px; text-align: left">Trailer</th>
<td style="border: 1px solid black; border-collapse: collapse; padding: 5px; text-align: left"> $film.getTrailerLink() </td>
</tr>
<tr>
<th style="border: 1px solid black; border-collapse: collapse; padding: 5px; text-align: left">More Information</th>
<td style="border: 1px solid black; border-collapse: collapse; padding: 5px; text-align: left">
https://www.landmarktheatres.com/$film.getMoreInfoLink() </td>
</tr>
#set( $count = $count + 1 )
#end
</table>
</body>
</html>
Output
$foreach.count (starts with 1) and $foreach.index (starts with 0) worked for me with Velocity 2.3.
More available loop variables are mentioned in the docs.

Categories

Resources