css, nested, first column indented, collapsible, table - html

Straight to the point, Can you make something like this in pure css
This is a table with four columns, where:
certain rows can be collapsed (~ <details>)
the first column only is indented
some columns have a dynamic width ( ~ flex-grow , grid: 1fr )
some control over the dynamic width
the underlying html structure would look something like
<entry>
<A> example </A>
<B> example </B>
<C> example </C>
<D> example </D>
<sub-entries>
...
</sub-entries>
</entry>
using just css grids and <details> I can get requirements 1,3 and 4, but not 2.
As a side node, for my specific case the html structure can be generated from code.
EDIT
Example of requirements 1,3,4: https://codepen.io/samcoutteauhybrid/pen/XWYpEZe
the point isn't to make this example work, rather a way to display some data in a table ( not necessarily <table> ). So the starting point would be some json-esc object which needs to be converted to html.

using custom CSS property for depth was the right approach. here's how you could implement it
in your pen make this change to your CSS
.sub-entries {
padding-left: calc(1em * var(--depth,1));
}
here var() resolves to 1 if --depth is not defined. you may want to use 0 instead. that way there is no default indentation for subentries
to set the indent, the markup has to be updated to
<div class="sub-entries" style="--depth: 1">
<div class="entry">
<div class="name">indent me</div>
<div class="type">don't indent me</div>
<div class="sub-entries" style="--depth: 2">
<div class="entry">
<div class="name">indent me further</div>
</div>
</div>
</div>
</div>
PS: turns out cannot be done with <table> because only <tr> <th> <td> are valid children and the parser disposes everything else

Related

Difference between two types of CSS class declaration

So, I have been using my own CSS class named myclass and Bootstrap built-in class container. My question is while declaring a with both classes.
Should I use
<div class="myclass container">some code</div>
this format, or:
<div class="myclass">
<div class="container">
some code
</div>
</div>
Does both work in the same way? Or these two are different?
They are different, first one you have 2 classes for the same element, and you can select the element by using the following rules:
.container {}
.myclass{}
.myclass.container{} or .container.myclass{}
The second example you have a parent and a child elemtns
which you can use the following rule:
.myclass .container {}
Both are totally different.
<!-- Here you're declaring ONE div element with two values on class atribute -->
<div class="myclass container">some code</div> this format
<!-- Here you're declaring TWO elements with a different class each one -->
<div class="myclass">
<div class="container">
</div>
</div>
Why this is so different?
HTML tags/eelements have default properties with default values, plus the properties and values that you put in addition.
For example:
if you set globally:
div{padding:5px;}
On the first example, the content inside the div will be padded 5px.
On the second example, the content inside container will be padded 10px.
That can happen with default properties rendered by the browser or globally applied by frameworks as bootstrap.

XPath for getting nodes from HTML fragment based on element text content

I need an XPath expressions for the following HTML fragment (DOM structure)
<div class="content">
<div class="product-compare-row">
<div class="spec-title half-size">Model</div>
<div class="spec-values half-size">
<span class="spec-value">kast</span>
</div>
</div>
So I need the kast value if the spec-title div contains Model.
I've tried //div[preceding-sibling::div[contains(.,"Model)")]] but that doesn't work.
The XPath you are looking for is:
//div[contains(#class, "spec-title") and contains(text(), "Model")]/following-sibling::div/span/text()
It is a little bit tricky to follow, but in plain English:
Select all div elements who have a class spec-title and who have text that contains 'Model'.
Find any of this div's following siblings if they are a div.
Traverse to any of their children which are a span and return their text.

double slash for xpath. Selenium Java Webdriver

I am using Selenium WebDriver. I have a doubt about the xpath.
If I have the following code example:
<div>
<div>
<div>
<a>
<div>
</div>
</a>
</div>
</div>
</div>
And I want to locate the element which is in the last <div>. I think I have 2 options with the xpath.
First option is with single slash:
driver.findElement(By.xpath("/div/div/div/a/div")).click();
Second option is using double slash (and here is where I have the doubt).
driver.findElement(By.xpath("//a/div")).click();
Is it going to search in the <a> directly, but what happens if the html example code was just a part of a bigger code and in this bigger code are more "<a>"?. Where would this method look exactly?
What happens for example if I do it like this:
driver.findElement(By.xpath("//div")).click();
Would it looks if every <div> found in the html code?
First of all, avoiding // is usually the right thing to do - so, the first expression you show is perfect.
Would it looks if every <div> found in the html code?
Yes, exactly. An XPath expression like
//div
will select all div elements in the document, regardless of where they are.
what happens if the html example code was just a part of a bigger code and in this bigger code are more <a>?. Where would this method look exactly?
Then, let us make the HTML "bigger":
<div>
<a>
<p>C</p>
</a>
<div>
<div>
<a>
<div>A</div>
</a>
</div>
<a>
<div>B</div>
</a>
</div>
</div>
As you can see, I have added two more a elements - only one of them contains a div element. Assuming this new document as the input, there will now be a difference between
/div/div/div/a/div
which will select only <div>A</div> as the result, and
//a/div
which will select both <div>A</div> and <div>B</div> - because the exact position of a in the tree is now irrelevant. But none of them will select the first a element that contains p.

Using XPath 1.0 with HTML to match elements that aren't in a parent

Consider this HTML:
<div>
<table>
<tr>
<td>
<a class="cal-date">1</a>
<div class="checkin-time">6 AM | 8h 30m</div>
</td>
</tr>
</table>
</div>
I would like to use XPath 1.0 to return 6 AM | 8h 30m while matching the class (cal-date) and text contents (1) in <a class="cal-date">1</a>. The <a> isn't a parent or anything, so I'm a little lost.
How is this done?
XPath has the concept of axes (that’s plural of axis, not things for cutting down trees). The default axis is the child:: axis, so if you don’t specify it your query will be searching the children of the previous node. You can create more complex queries by using different axes.
In this case you probably want to use the following-sibling:: axis. First select a element as usual, then in the next location step of your query specify the following-sibling:: axis to search the siblings of the a node rather than its children:
//a[#class='cal-date' and . = '1']/following-sibling::div
If you need to you can be more specific with the div query, as with “normal” XPath, and can continue the query after the change of axis. For example if your HTML was more complex and looked like this:
<a class="cal-date">1</a>
<div>A decoy div</div>
<div>
<span>Not this</span>
<span class="checkin-time">6 AM | 8h 30m</span>
<span> Not this either</span>
</div>
you could get at the checkin-time span with an XPath expression like this:
//a[#class='cal-date' and . = '1']/following-sibling::div[2]/span[#class='checkin-time']
Note that when selecting the span element, after the following-sibling::div part, the axis isn’t specified so it uses the default of child::, because we are looking for children of the div.
There's no need to use following-sibling for this. Alternatively, search for <div/> elements contained by table cells which contain the link you're looking for.
//td[a[#class='cal-date' and . = '1']]/div

How to differentiate two HTML elements with same tagname and same text

I would like to know is there any method in Jsoup that tells me an element with same tag name, text and class (if any) is different from other element with same tag name, text and same class (if any). For clarification consider the following HTML snippet :
<html>
<body>
<div>Here I Am</div><div>First Time</div>
<div>Here I Am</div><div>Again</div>
</body>
</html>
Now in the above code how can I separate the two elements with div tag and text Here I am. Also note that here the two elements have no id.
The above example is very simple but actual scenario may be more complex. So if you kindly suggest me a generalized answer I will be really grateful. Thank you.
Give id for making it unique for the document. this can be done as
<div id="first">Here I Am</div>
<div id="second">Here I Am</div>
Under the concept of DOM and XPath, these nodes are the same EXCEPT its canonical order. If you want to access the n-th node of this pattern,
//div[text()='Here I Am'][n]
where n is 0-based.
Get all div elements and select what you want.
Example
Document doc = Jsoup.parse("<html>\n" +
"<body>\n" +
"<div>Here I Am</div><div>First Time</div>\n" +
"<div>Here I Am</div><div>Again</div>\n" +
"</body>\n" +
"</html>");
Element div = doc.select("div").first();
System.out.println(div.html());
Output
Here I Am
Other elements are accessible by index.
Example
Element div = doc.select("div").get(3);
Output:
Again
You could identify the divs. For example, you could do this:
<div class="div1"><h2>Here I Am</h2></div>
<div class="div2"><h2>First Time</h2></div>
<div class="div3"><h2>Here I Am</h2></div>
<div class="div4"><h2>Again</h2></div>