I've a list of objects (question-items), each with a property named category and title.
(The list of objects is ordered by its category property)
With this Fluid Template I want to iterate over the question items:
<f:for each="{questions}" as="question">
<!-- every time category changes, display it as a new headline ??? -->
<!-- if (question.category != previousQuestion.category) ?.....? -->
<span>{question.title}</span>
</f:for>
How can I check, if the category property has changed in the for?
The output should be something like this:
Category-A
Question
Question
Category-B
Question
Category-C
Question
Question
Question
...
You are looking for the f:groupedFor viewhelper: http://docs.typo3.org/typo3cms/ExtbaseGuide/Fluid/ViewHelper/GroupedFor.html
<f:groupedFor each="{questions}" as="categoryQuestion" groupBy="category" groupKey="category">
<h2>{category}</h2>
<f:for each="{categoryQuestion}" as="question">
<span>{question.title}</span>
</f:for>
</f:groupedFor>
Your approach with the <f:if> viewhelper won't work, because there are no real template-variables in fluid, just xml-scoped "constants", so even if you define previousQuestion via the <f:alias> viewhelper, you wouldn't be able to compare it to the current value.
Related
Given I have the following HTML structure:
<button aria-labelledby="ref-1" id="foo" onclick="convey(event)">action 2</button>
<div class="anotherElement">foobar</div>
<div id="ref-1" hidden>target 2</div>
I would like to fetch button by its aria-labelledby attribute. I tried the following options:
//*[#aria-labelledby=string(/div[#id="ref-1"]/#id)]
//*[#aria-labelledby = string(.//*[normalize-space() = "target 2"]/#id)]
//*[#aria-labelledby = .//*[normalize-space() = "target 2"]/#id]
But wasn't able to fetch the element. Anyone has an idea what the right xPath could be?
Edit: simply put: how do I fetch the button element if my only information is "target 2", and if both elements can be randomly located?
//button[#aria-labelledby='ref-1']
or
//button[#aria-labelledby=(//*/#id)]
or
//button[#aria-labelledby=(//*[contains(.,'target 2')]/#id)]
or
//button[#aria-labelledby=(//*[contains(text(),'target 2')]/#id)]
?
Since button and div are the same level siblings here you can use preceding-sibling XPath expression like this:
//div[text()='target 2']//preceding-sibling::button
pay attention with with your actual XML this will match 2 button elements.
To make more precise math I think we will need to be based on more details, not only the target 2 text
I am scraping through real estate listings from a certain site that contains multiple pages.
Here, I have summarized a structure nested deep in the DOM. I want to select all list items, based on the descendants that do not have a certain attribute name like <div id="nav-ad-container">
<ul class="photo-cards photo-cards_wow photo-cards_short photo-cards_extra-attribution">
<li>..</li>
<li>..</li>
<li>
<div id="nav-ad-container" class="zsg-aspect-ratio"></div>
</li>
<li>..</li>
<li>..</li>
<li>..</li>
</ul>
However, given that the attribute and the attribute's name change in the DOM for each page.
For example:
#id = 'nav-ad-container' or #class = 'nav-ad-empty'
In general, I want to retrieve the list items that do not contain the name pattern 'nav-ad'.
Things that I've tried with no success (still selects every list item)
xpath + //li[not(contains(#class, 'nav-ad'))]
xpath + //li[not((contains(#class,'nav-ad')) or contains(#id,'nav-ad'))]
Can anyone guide me toward a solution? I feel like I'm pretty close but missing something.
filter by classname of list items or descendants:
//li[not(contains(descendant-or-self::node()/#class,'nav-ad'))]
(not tested)
Try
//li[not(descendant-or-self::node()/#class[contains(.,'nav-ad')])]
I am in the process of refactoring a model (let's call it Parent), which stores a number of Many2one fields that reference records of the same model (Child). The Parent form view contains a notebook and each page displays details for a specific Child, currently described within the page in a repetitive fashion and with lots of related fields. I'm trying to avoid the repetition in the view, and get rid of the need for the related fields.
class Child(models.Model):
_name = "child"
# ...
class Parent(models.Model):
_name = "parent"
child_1 = fields.Many2one('child', 'Child 1')
child_1_age = fields.Float(related='child_1.age', string='Child Age')
# ...
child_2 = fields.Many2one('child', 'Child 2')
child_2_age = fields.Float(related='child_2.age', string='Child Age')
# ...
<!-- ... -->
<field name="model">parent</field>
<field name="type">form</field>
<field name="arch" type="xml">
<notebook colspan="8" col="8">
<page>
<!-- buttons, a bunch of related Child fields, etc -->
</page>
<page>
<!-- buttons, a bunch of related Child fields, etc -->
</page>
</notebook>
</field>
I have a special form view defined for the Child, but I don't know how to insert it in the notebook pages of the Parent view. Since it is possible to insert tree views in forms (like for One2many fields for example), I guess there has to be a way to do it with forms as well. An example how to achieve this effect would be greatly appreciated.
Please ignore any syntax errors, the above is just a simple visual representation to help better describe my case.
You can use the widget attribute in order to assign a widget to your relational field, for example
<field name="my_field" widget="my_widget"/>
To see an example as to how a widget works and is created take a look at the following example:
Go to addons/account/project/wizard/account_analytic_journal_report_view.xml and see the line that defines a many2many_tags widget.
This form widget is assigned on addons/web/static/src/js/view_form.js at around line 6396 that comments Registry of form fields ...
The many2many_tags string that we used is assigned a actual widget, that widget has a template, and that template is rendered in place of your field.
TL;DR Give a widget element to your field, define that widget, assign that widget to work on a template and create the template that contains your view.
suppose I have this structure:
<div class="a" attribute="foo">
<div class="b">
<span>Text Example</span>
</div>
</div>
In xpath, I would like to retrieve the value of the attribute "attribute" given I have the text inside: Text Example
If I use this xpath:
.//*[#class='a']//*[text()='Text Example']
It returns the element span, but I need the div.a, because I need to get the value of the attribute through Selenium WebDriver
Hey there are lot of ways by which you can figure it out.
So lets say Text Example is given, you can identify it using this text:-
//span[text()='Text Example']/../.. --> If you know its 2 level up
OR
//span[text()='Text Example']/ancestor::div[#class='a'] --> If you don't know how many level up this `div` is
Above 2 xpaths can be used if you only want to identify the element using Text Example, if you don't want to iterate through this text. There are simple ways to identify it directly:-
//div[#class='a']
From your question itself you have mentioned the answer for it
but I need the div.a,
try this
driver.findElement(By.cssSelector("div.a")).getAttribute("attribute");
use cssSelector for best result.
or else try the following xpath
//div[contains(#class, 'a')]
If you want attribute of div.a with it's descendant span which contains text something, try as below :-
driver.findElement(By.xpath("//div[#class = 'a' and descendant::span[text() = 'Text Example']]")).getAttribute("attribute");
Hope it helps..:)
This question already has answers here:
In which direction do selector engines read, exactly?
(2 answers)
Closed 6 years ago.
So I came across a couple of articles on CSS optimization:
http://csswizardry.com/2011/09/writing-efficient-css-selectors/
https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Writing_efficient_CSS
Apparently CSS is read from right to left. That means that div table a is read like: first all a elements on the page are retrieved, then all table elements that have an a in them (right?), then all div elements with both of those in them (right?).
My question, which I couldn't find an answer to anywhere, is: how is a CSS rule like div#div_id parsed? Do first all elements with the id "div_id" get parsed, and is a filter then applied to fetch from that bunch of #div_id elements all div elements? Or are first all div elements parsed, and is a filter then applied to fetch everything with the id "div_id"?
The first article I mentioned says that the recommended order of efficiency in CSS is: #id > > .class > tag > rest. But what about tag#id?
To clarify: I like to type div#div_id just to have it clear for myself that #div_id applies to a div element without having to look up the HTML to find out which element's styling I'm looking at, but I wouldn't want to use it that way if it costs me much of my website's performance .What would be the recommended way of writing the rule then? Should I drop the tags in my selectors? Is it really that expensive?
The answer
The answer would be, as jbutler483 says: leaving the tag name out is faster. If you want to have clarification on what element you're styling, don't use div#my_id but #div_my_id. If you don't care that much about performance, you could still go with the div#my_id, but it will be a bit slower (but you can ask yourself if it will really impact your application that much).
Ok, I think you've gotten a little confused.
In your example, you use:
div table a
So i'll use that.
Pretty much, that could look like this in your html
<div>
<table>
<a>
//styling applied here
</a>
</table>
</div>
or something else like
<div>
<div></div>
<table>
<tr>
<th>hi there</th>
<th>
<a>i'm an a tag!</a>
So, looking at that:
div table a
will be
div table a
^ ^ ^
| | |
| | a child
| |
| parent
|
grandparent
This means that you'll be styling any 'a' element that is a child/descendant of a table, which, in turn, is a descendant of a div element
so, in your other example:
div#div_id
you would be styling all id's of div_id in which have a div as a parent.
BTW looking at your example, I would like to point out that (in case you didn't know):
the id attribute should be unique
an <a> attribute shouldn't be used directly within a <table> element (instead nest it within a th or td tag)
If you wish to style multiple elements (of varying types), it would be more efficient to create a class, and use that instead
Answer after Clarification:
Your
div#div_id
In HTML, since the id is meant to be unique, it will look up 'all id's' with the specified id.
It will then check if it is a div element.
This seems to be a bad example, as obviously some (older) browsers will only look for the first id, and return it instead of checking the whole webpage for any 'duplicate' id's.
With your id's being unique, you could then drop your tag as it will be left redundant/ no use
Summary
So, an example of this extended conversation in the comments:
if I wanted to style a single div (and still know it was a div that i was adding styling to), i would use the naming convention of:
<div id="my-div-to-style">
^
|
[the word 'div' here could be anything]
in my css i would write:
_ this word must match the
/ id i used above
|
#my-div-to-style{
//styling...
}
If i wanted to add the same styling to multiple div elements (with the scope to add it to others), i would instead use a class:
<div class="myDivStyle">
and then use:
.myDivStyle{
//styling...
}
in this last example, I would not be restricted to just styling divs, so i wouldn't include this in my naming:
<div class="myStyle">
<a class="myStyle">
<table class="myStyle">
.myStyle{
//styling for any element I want
}
As you say, rules are parsed right to left, the same applies here.
Although duplicate id values are not valid, it is up to the browser to decide whether to accept and parse them, the below (in Chrome) for example, renders the first and last elements with red text.
Demo Fiddle
div#test {
color:red;
}
<div id='test'>text</div>
<span id='test'>
text
</span>
<div id='test'>text</div>
In modern browsers you may want to be less mindful of selector resolution performance and instead look to obtain valid CSS adhering to best practices, keeping selectors as short and concise as possible.
What about tag#id? The second link you mention contains the answer.
Don’t qualify ID rules with tag names or classes
If a rule has an ID selector as its key selector, don’t add the tag
name to the rule. Since IDs are unique, adding a tag name would slow
down the matching process needlessly.
Don’t qualify class rules with tag names
The previous concept also applies here. Though classes can be used
many times on the same page, they are still more unique than a tag.
You may learn more about your question here: css-tricks => efficiently rendering html
There are four kinds of key selectors: ID, class, tag, and universal. It is that same order in how efficient they are.
#main-navigation { } /* ID (Fastest) */
body.home #page-wrap { } /* ID */
.main-navigation { } /* Class */
ul li a.current { } /* Class *
ul { } /* Tag */
ul li a { } /* Tag */
* { } /* Universal (Slowest) */
#content [title='home'] /* Universal */
When we combine this right-to-left idea, and the key selector idea, we can see that this selector isn't very efficient:
#main-nav > li { } /* Slower than it might seem */
Even though that feels weirdly counter-intuitive... Since ID's are so efficient we would think the browser could just find that ID quickly and then find the li children quickly. But in reality, the relatively slow li tag selector is run first.