how to get data element by title index with capybara "find"? - html

I have html page:
<html>
<body>
<th>a</th>
<th>b</th>
<th>c</th>
<th>d</th>
<th>e</th>
<th>f</th>
<th>g</th>
<th>h</th>
<th>i</th>
<td>1</td>
<td>2</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>6</td>
<td>7</td>
<td>8</td>
<td>9</td>
</body>
</html>
I need to get data (td tag) by choosing title (th tag).
I'm trying:
page.find(:xpath, "//body/td[count(//body/th[contains(.,'a')]/preceding-sibling::th)-1]")
and I'm expecting to get "1" as returning value, but it returns "8".
It seems to me, that "count" doesn't work right. So, what am I doing wrong?

The logic should've counted preceding-sibling th plus 1, to find the correct position index of the th :
//body/td[count(//body/th[contains(.,'a')]/preceding-sibling::th)+1]
xpathtester demo
output :
<td>1</td>

Related

XPath find element by position of different element

Example html:
<table>
<thead>
<tr>
<td class="foo"></td>
<td class="bar"></td>
<td class="buzz"></td>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>5</td>
<td>6</td>
</tr>
</tbody>
</table>
Problem
I have row position (//tbody/tr[X]) and header class (//thead//td[#class="XXX"])
I want to find table data cell using row and column
For example <td>5</td> can be located by //tbody/tr[2] and //thead//td[#class="bar"]
Pseudo-xpath:
//tbody/tr[2]/td[position() = //thead//td[#class="bar"]::position()]
I was tweaking with ancestor:: axis but it was dead end.
Any ideas how to write it properly?
Try to use this XPath to select required node:
//tbody/tr[2]/td[position() = count(//thead/tr/td[#class="bar"]/preceding-sibling::*) + 1]
Instead of position we're checking the count of preceding siblings + 1

jQuery UI sortable dynamic target not working

I have two tables in my html. The first is loaded on page load, the second is generated on button click.
My sortable function does not apply to the generated table.
Can you explain why?
Here is my Javascript some.js:
// sort all kinds of tables
$(function(){
$('table').sortable();
});
// generate new table
$(document).on('click','#test',function(){
let str = "<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>"
let content = $.parseHTML(str)
$('#main').html(content);
})
And here the actual html file index.html:
<!DOCTYPE html>
<html>
<head>
<script defer src="jquery/3.5.1/jquery-3.5.1.min.js"></script>
<script defer src="jquery/jquery-ui-1.13.1.js"></script>
<script defer src="some.js"></script>
</head>
<body>
<div id="main">
<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>
<input type="button" id="test" value="Generate Table" onclick="">
</div>
</body>
</html>
The generated table does not exist in the DOM in the ready event when you call $('table').sortable(); The table is added to the DOM later as response to the click event. You should call $('table').sortable(); after you add the table to the dom
This should work:
$(document).on('click','#test',function(){
let str = "<table>
<tr>
<td>1</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>4</td>
</tr>
</table>"
let content = $.parseHTML(str)
$('#main').html(content);
$('#main table').sortable();
})

Using this text method with html symbols in jQuery to find td with symbol inside

I am trying to highlight a table row if it has a tick (check mark) in one of the td’s. I am using the jQuery code below, but it will not find a td with a html symbol such as a tick (check mark). It makes no difference if I use .text() or .html(). The code works as expected if I use any other criteria such as text or numbers, but not with html symbols. Is there away round this?
$('#farm td').filter(
function(t) {
if ($(this).text() == "✓") {
$(this).closest('tr').css('background-color', 'Yellow');
return;
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="farm" border="1">
<tr>
<th>One</th>
<th>Two</th>
</tr>
<tr>
<td>Cat</td>
<td>Duck</td>
</tr>
<tr>
<td>Pig</td>
<td>✕</td>
</tr>
<tr>
<td>✓</td>
<td>Bull</td>
</tr>
<tr>
<td>8</td>
<td>10</td>
</tr>
</table>
You just need to check for the actual character (✓). jQuery acts on rendered HTML, not markup. I determined this by setting a breakpoint on the line with text() in it and looking at the values that came through.
Also:
.each() makes more sense to me here
no need to return anything in the function
no need to pass in anything (t)
console logs are far nicer than alerts for debugging
$('#farm td').each(function() {
if ($(this).text() == "✓") {
$(this).closest('tr').css('background-color', 'Yellow');
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<table id="farm" border="1">
<tr>
<th>One</th>
<th>Two</th>
</tr>
<tr>
<td>Cat</td>
<td>Duck</td>
</tr>
<tr>
<td>Pig</td>
<td>✕</td>
</tr>
<tr>
<td>✓</td>
<td>Bull</td>
</tr>
<tr>
<td>8</td>
<td>10</td>
</tr>
</table>
Mohamed-Yousef suggested a great refinement using an internal selector:
$('#farm td:contains("✓")').closest('tr').css('background-color', 'Yellow');
It's a slightly different selector as it would also match ✓ blah, for example, but maybe it's useful in your case.
https://api.jquery.com/contains-selector/

How to xpath values in a dynamic table?

Could please someone help me to xpath values in a dynamic table.
I have the following HTML code and I need to select the values of the cells, as for example:
if a tr-cell contains the text "Values1" then select the first value (0) in td / third value (1) in td of this cell
I would be very thankful.
<table class="DynamicTable">
<tbody>
<tr>
<th>Details</th>
</tr>
<tr>
<td>0</td>
<td>Values1</td>
<td>1</td>
</tr>
<tr>
<td>4</td>
<td>Values2</td>
<td>2</td>
</tr>
<tr>
<td>1</td>
<td>Values6</td>
<td>0</td>
</tr>
</tbody>
</table>

More than 12 columns DataTable/Bootstrap

I have a question.
I'm doing a DataTable and I want to style it with Bootstrap grid system for make it responsive.
So, my Table has more than 12 cols and when I try to use the grid system, some info does backspace or dates goes truncated:
14-06-
2017
My table is something like this:
<table>
<thead>
<tr>
<th>ID</th>
<th>Descripción</th>
<th>Responsable</th>
<th>Estado</th>
<th style="display:none">Pos.</th>
<th >Inicio</th>
<th>Finalización</th>
<th style="display:none">F. estim.</th>
<th>Tiempo</th>
<th >Puesto de Trabajo</th>
<th>Responsable proceso</th>
<th>Nº Oportunidad</th>
<th>Archivo</th>
</tr>
</thead>
<tbody>
<tr>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td hidden>...</td>
<td>...</td>
<td>...</td>
<td hidden>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
<td>...</td>
</tr>
</tbody>
</table>
First of all, it doesn't work well if I put class="col-*-*" (where -- are device and size) on <th> doesn't work, and if I put in <td> doesn't fit.
Also, headers lose alignment because of the sort arrows. Any help will be appreciated. Thank you.
You need css's white-space property:
https://www.w3schools.com/cssref/pr_text_white-space.asp
t.e. 6th td on each row should be:
<td style="white-space: nowrap;">...</td>
If you are using bootstrap, then it could be better to use class text-nowrap:
https://getbootstrap.com/docs/4.0/utilities/text/#text-wrapping-and-overflow
t.e. 6t td on each row should be:
<td class="text-nowrap">...</td>
But after you are using bootstarp with DataTable i recommend to use DataTable's property columnDefs:
https://datatables.net/reference/option/columnDefs
t.e.:
$('#example').dataTable( {
"columnDefs": [ {
"targets": 6,
"className": "text-nowrap"
} ]
} );