I have a line of jQuery code which I don't understand.
var layerid = $('ul.layerstack li.selected').data('layerid');
I understand that $(ul.layerstack) is to select ul elements with layerstack class, and similarly for li.selected. But I don't understand the syntax for juxtaposing the two with a space in between.
Can someone please help explain this syntax and give a reference for this? (The DOM structure is listed below for reference).
Thanks,
It is called as the descendant selector... it is a part of css selector spec.
It is used to select all elements which satisfies the second selector which are inside the first part
Descendant selectors
A space means "any descendant of": direct children and children of those children would be selected.
Related
Hello this is my first question and I'm an amateur developer so forgive me in advance. I'm trying to grab this specific instance of the value class. The website I am working on has hundreds of different values associated with the value class.
<li class = "vin">
<strong class = "title">VIN:</strong>
<span class="value">121212121212121212</span>
</li>
Below is what I've been doing and it hasn't been working.
var vinNum = document.getElementsByClassName('li.vin','span.value');
console.log(vinNum.innerText);
Thank you
Although the existing answers cover the "modern" way to do this already - you can use most of the getElementsBy... (all, I think - was gonna say except getElementById, but that is named in singular for a reason, and because of the meaning of an id special) methods on all elements.
https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByClassName:
The Element.getElementsByClassName() method returns a live HTMLCollection containing all child elements which have all of the given class names. When called on the document object, the complete document is searched, including the root node.
So you can use that twice, to first select an element with one specific class, and then another with a different class "within it", among the descendants of the former. (Not "child elements", as the quoted MDN reference wrongly puts it.)
var vinNumContainer = document.getElementsByClassName('vin')[0],
vinNumElement = vinNumContainer.getElementsByClassName('value')[0];
(Necessary checks for whether elements exist before accessing them, what to do if more than one element (of either one) exists, etc., left out for brevity ;-)
But a simple call to querySelector is of course a quicker way to do it.
Try
var vinNum = document.querySelector('li.vin span.value');
console.log(vinNum.innerText);
This works because rather than selecting by class you're selecting the li.vin element which has a span.value as a child. vinNumber is now a node element. When you call vinNum.innerText you should get the correct number. When you console.log(vinNum) in uour example you will most likely see undefined or the incorrect element.
You can use the document.querySelector function in order to search elements on your page based on class, ID, or anything else that can be selected using a CSS selector.
Using Mozilla's CSS Selector reference, we can see that the CSS selector syntax to select an element which is a direct child of some other element is A > B, where A is a selector matching the parent, and B is a selector matching the child.
So one way to do this is to use:
var vinNum = document.querySelector('li.vin > span.value')
The one-liner above will match the first span element of class value which is a child of a li element of class vin.
However, if you have multiple examples of this structure (a li of class vin with a span of class value within it), using this selector won't work. In fact, if you want to have access to each specific span of class value individually, perhaps the best way would be to add a unique id attribute to each of them.
If your structure looked like this:
<li class = "vin">
<strong class = "title">VIN:</strong>
<span class="value" id="v25">121212121212121212</span>
</li>
You could then use the following:
var vinNum = document.querySelector('#v25')
One last alternative for when you have a list of nested HTML elements all with the same structure is to use document.querySelectorAll, which will return all DOM nodes which match your query and allow you to use JavaScript to run through them and select the values you want.
I'd like to select a set of elements and their children from the DOM.
Then, I would like to run a set of selections on the DOM that excludes those elements, as if they were removed.
.not() seems to match both parent elements and child elements and doesn't properly exclude.
.find(':not(.myclass)') returns a list of about a bajillion elements and doesn't properly exclude.
What's my trouble? This seems simple but the functions I expect to do this don't behave as I expect.
I thought about cloning the DOM, removing the elements, and then running my selection matches on the cloned DOM... but that seems bad. Like, a major performance hit.
What's the best way to do this?
Here's the code I have:
jQuery('html').not(".page-node,.quote").find(selector).each(function(){
//do stuff here to returned elements
.page-node is a body class and should return the body element on nearly all pages and exclude the selector from being matched on those pages.
Edit: I have created a jsFiddle to demonstrate what I'm talking about: http://jsfiddle.net/glassdimly/H4tJe/4/
Not() will work with an appropriate descendant selector. A * following any selector will match all descendants (children, grandchildren etc). By applying it in a not, you can ask that all descendants be excluded from the match. As you also want to exclude the parent, include that in the not as well:
e.g.
$(selector).not(".page-node,.page-node *,.quote,.quote *")
Which equates to:
"Not has class page-node OR and child/descendant of page-node" or "Not has class quote OR any child/descendant of quote"
Updated JSFiddle: http://jsfiddle.net/TrueBlueAussie/H4tJe/7/
jQuery(document).find('.list').not('.exclude,.exclude *').each(function(){
this.remove();
});
Which equates to "Find all items has class list, but exclude any that also have class exclude and also exclude any descendants of any element that has class exclude"
Actual case is much more complicated but please play along. I am trying to select siblings of element that has class 'sss', by using
$('.sss').parent().parent().find(">div.childCollapsible>div[data-onthemovecollapsible=true]")
I can only use CSS selectors (this is part of Selenium thest). I expected to get only siblings of 'sss' however I am getting all the children of sub elements too.
How could I restrict it only to siblings?
or any other workaround that can get me from any element in the tree siblings only of any
data-onthemovecollapsible="true"
attribute holder.
EDIT: Firstly I would like apologise for failing to express myself clearly. The structure that I am working with is 'infinite tree structure' that has unknown amount of nodes on each layer, mechanism I am looking for is ability to get siblings on the same level that I am starting search from is and only children of his parent (his brothers + himself). All levels of tree have identical HTML syntax, so looking at them relatively from element one starts from, each layer is identical, hence the CSS selector should be identical too. I cannot use any other Jquery method but 'find', and only can use CSS selectors, as mechanism is part of selenium test so only By.CssSelector("...") can be used. I can traverse up the elements by using element.FindElements(By.XPath("..")) that gets me parent as I know how many levels up parent is, but from parent position I need to get all siblings without children (that have identical html syntax) in one go, so i would assume selector with only certain layer should do (like one in jsfiddle below), however it selects all the children nodes too - does not respect '>' for some reason. This would do nicely if I could use all JQuery functions.
$('.sss').parent().parent().children().children()
what I need is same result but with CSS selector.
http://jsfiddle.net/2a46U/
I think this will work for you:
.find("body>div>div>div>div.childCollapsible>div[data-onthemovecollapsible=true]")
If I'm understanding this correctly, you have two different restrictions here. One is that you only want siblings of an .sss element. The other is that the parent of the element is div.childCollapsible. I don't believe you will be able to do this with a single selector/find. You would need something like this:
// get the siblings of .sss with appropriate data attribute
var $els = $('.sss').siblings("div[data-onthemovecollapsible=true]");
// filter the collection to only those with appropriate parent
$els = $els.filter(function(){
return $(this).parent().is("div.childCollapsible");
});
http://jsfiddle.net/2a46U/4/
I've updated your jsfiddle with two options (check the console please):
Get all the siblings:
$('.sss').siblings();
Get specific siblings:
$('.sss').siblings("div.AppletBase")
If you need to set styles you can use the siblings selector in CSS3:
.sss ~ div.AppletBase {/* Your styles in here */}
Anything please leave a comment and I will review it again if is needed
I have a table with some radiobuttons in it. When i click on a radiobutton, i want to update two of the sorrounding containers ID attribute (a div and a table). The problem is, i need to go 4 and 6 levels up, and the only way i know how to do this is parent().parent().parent().parent() etc.
I am looking for a better solution, and was hoping someone could point me in the right direction. You can see an image of how the "parent-child" tree is here:
http://imageshack.us/photo/my-images/834/imgkz.png/
I already have a clickhandler etc set up.
Basicly i need to check if the table's id attribute is "answeredTable", if not i need to change it. Also i need to check if the div two levels up from the table is "answered", if not, i need to change that too.
Thanks
You can use .closest('#answeredTable') or .parents('#answeredTable').
Using .parent() only selects the first parent element upon the DOM tree, selecting .closest() will allow you to walk up to DOM tree and match until it finds the element, while .parents() will return the whole parentset of the DOM and match the element in the whole parentset.
You need to use .parents() that go through multiple level of the DOM
For instance, in your example, you could get the surrounding div with this code:
$("#Q_18_2015").parents("div#answered")
By the way, id should be unique, or else, your code might probably not work. You should use classes instead.
<div class="answered">
Thus, the code would become:
$("#Q_18_2015").parents("div.answered")
provided that Q_18_2015 is really a unique id
I think what you want to use is closest http://api.jquery.com/closest/
you can use .parents
$("element").parent(".parentClass")
parents will go up the DOM until finds the parent with class parentClass
I'm trying to fill an array with all direct child elements of a div.
example:
<div>
<span></span>
<a></a>
</div>
should result in an array containing span and a
How Would I achieve this?
I tried var elements = $('.thediv').children(); but that doesn't seem to work.
Also how Would I then use that information for this kind of function?:
$("element1","element2","element3") depending on the result of the array?
Really thank you for your help! I am kind of lost with this thing
Note: I'm using zepto.js which has a similar syntax to jquery but misses a lot of functions so that might be a problem but I am also happy with solutions using jquery syntax because it should work pretty well :) https://github.com/madrobby/zepto
To get the tags into the array, you could easily use, with jQuery (though I'm unfamiliar with zepto):
var elementsArray = [];
$('div').children().each(
function(i){
elementsArray.push(this.tagName.toLowerCase());
});
JS Fiddle demo.
And to use them, you can try:
for(i=0;i<elementsArray.length;i++){
$('div').find(elementsArray[i]).css('color','red');
}
JS Fiddle demo.
Although this simply uses the tagName of each element, so if there is more than one a within the relevant element all elements matching the selector, effectively $('div').find('a') in this case, will be targeted by the selector.
The above caution seems to be discounted through use of a more complicated selector, and behaviour, and allows for each element to be iterated over one at a time, though I can't help but feel it's a little more complex than it needs to be:
var elementsArray = [];
$('div').children().each(
function(i){
elementsArray.push(this.tagName.toLowerCase());
});
for(i=0;i<elementsArray.length;i++){
$('div')
.find(elementsArray[i])
.not('.edited')
.eq(0).css('color','red')
.addClass('edited');
}
JS Fiddle demo.
Sigh, I'm an idiot. The final iteration of this is below, which reduces the complexity somewhat, and allows for proper iteration over each element according to their position in the array:
var elementsArray = [];
$('div').children().each(
function(i){
elementsArray.push(this.tagName.toLowerCase());
});
for(i=0;i<elementsArray.length;i++){
$('div')
.children()
.eq(i)
.css('color','red');
}
JS Fiddle demo.
Having said the above, though, if you want to "target all elements within," why not simply target those elements with:
$('div').children();
Which will select, and target, each direct child of the div element without first holding them in, or having to hold them in, a user-created array variable.
$("div").children().toArray();
http://api.jquery.com/toArray/
$("element1","element2","element3")
Does this mean you want to use the array as a jQuery selector? Or you really want the tag names?
Each DOM node has a childNodes attribute, which is a NodeList containing all the direct descendants of the node in question.