Reputation: 490
I wanna be able to select a specific set of child in which an attribute is defined.
But how to select childs which are first child of the root selector that having the attribute data-role
first-of-type
selector doesn't work due to the type of the element.
<body>
<div data-role="ca:panel" title="foo">
<div data-role="ca:vbox" width="100%">
<div data-role="ca:form">
<div data-role="ca:formitem">
<div data-role="ca:hbox">
<input data-role="ca:textinput">
<div data-role="ca:menu"></div>
</div>
</div>
<div data-role="ca:formitem">
<input data-role="ca:passwordinput">
</div>
<div data-role="ca:formitem">
<select data-role="ca:combobox">
<option>[...]</option>
</select>
</div>
</div>
<table>
<tbody>
<tr>
<td>
<span data-role="ca:label"></span>
</td>
<td>
<button data-role="ca:button"></button>
</td>
<td>
<button data-role="ca:button"></button>
</td>
</tr>
</tbody>
</table>
</div>
</body>
<div data-role="ca:form">
<span data-role="ca:label"></span>
<button data-role="ca:button"></button>
<button data-role="ca:button"></button>
It should work in any case, meanings, it shouldn't be linked to a specific structure of the dom and must use data-role as 'selector'.
I'm not a relevant jQuery developer. I tried some selector such as $('[data-role]:first-of-type');
but it doesn't work.
Do you have an idea to select the right set of child.
Note: Finding the first parent is not a concern.
Upvotes: 2
Views: 156
Reputation: 93551
It is possible to do this generically using a filter, so long as you have a start node:
JSFilter: http://jsfiddle.net/TrueBlueAussie/2uppww9s/5/
var root = $('[data-role="ca:vbox"]');
var matches = root.find('[data-role]').filter(function(){
return $(this).parentsUntil(root, '[data-role]').length == 0;
});
alert(matches.length);
Upvotes: 1
Reputation: 22570
If you want first of all overall specifications, then you can simply use selector on all three tag types and filter them as so:
$('div, span, button').filter(function(i){
if (this.tagName == 'DIV' && $(this).data('role') == 'ca:form') return true;
if (this.tagName == 'SPAN' && $(this).data('role') == 'ca:label') return true;
if (this.tagName == 'BUTTON' && $(this).data('role') == 'ca:button') return true;
}).first();
Using .first
grabs the first of them.
Also, filter can be used in a million ways to get what you want and sounds like it may get you to what you need. Just set what you're filtering for in an if/for/switch statement and return true on items that match.
jsFiddle
However, if you wanted first of each you could do something like:
$('div[data-role="ca:form"]:first, span[data-role="ca:label"]:first, button[data-role="ca:button"]:first')
If variable driven in someway, just use string concatenation.
Upvotes: 0
Reputation: 3797
You can use the :first pseudonym to select the first occurance of a element like for example:
var elm = $('*[data-role="ca:form"]:first');
this will select * any type of DOM-element, with the data-role that matches "ca:form"
Since you want to return two buttons with the same data-role, we cant use ":first" for that. You would have to get the first child of a that matches in that case
var elm = $('td').children('button[data-role="ca:button"]:first');
This will look through the child elements of all TD-tags and find the first button with data-role matching "ca:button"
Upvotes: 0