I've got following HTML:
<span class="testClass1" >
wanted Text
<a class="ctx" href="#"></a>
</span>
Now I want to get the text "wanted Text".
How can I achieve this?
I tried with:
document.getElementsByClassName("testClass1");
I also tried with document.getElementsByTagName() but I don't know how to use them properly.
You can use querySelectorAll
hence:
document.querySelectorAll('.testclass1 a')
will return all the <a> items children of a .testclass1
Snippet example:
var elements = document.querySelectorAll('.testClass1 a')
console.log(elements) // open the console to see this
console.log(elements[0].text) // this gets the first <a> text `wanted Text`
<span class="testClass1" >
wanted Text
<a class="ctx" href="#"></a>
</span>
The getElementsByClassName() function returns an array of matching elements, so if you need to access them, you could do so using a loop :
// Get each of the elements that have the class "testClass1"
var elements = document.getElementsByClassName("testClass1");
// Iterate through each element that was found
for(var e = 0; e < elements.length; e++){
// Get the inner content via the innerHTML property
var content = elements[e].innerHTML;
}
If you need to actually access the <a> tags directly below some of the elements as your edit indicates, then you could potentially search for those wihtin each of your existing elements using the getElementsbyTagName() function :
// Get each of the elements that have the class "testClass1"
var elements = document.getElementsByClassName("testClass1");
// Iterate through each element that was found
for(var e = 0; e < elements.length; e++){
// Find the <a> elements below this element
var aElements = elements[e].getElementsByTagName('a');
// Iterate through them
for(var a = 0; a < aElements.length; a++){
// Access your element content through aElements[a].innerHTML here
}
}
You can also use an approach like squint's comment or Fred's which take advantage of the querySelectorAll() function as the getElementsByClassName() and getElementsByTagName() are better served when accessing multiple elements instead of one specifically.
Try this:
document.getElementsByClassName("testClass1")[0].getElementsByTagName('a')[0].innerText
var testClass1 = document.getElementsByClassName("testClass1");
console.log(testClass1[0].innerHTML);
Related
I am trying to select one ore more elements that are NOT descendants of another specific element.
<html>
<body>
<div>
<p>
<b>
<i> don't select me </i>
</b>
</p>
</div>
<div>
<i>don't select me either </i>
</div>
<i> select me </i>
<b>
<i> select me too </i>
</b>
</body>
</html>
In the example above I want to select all 'i' elements, that are not inside div elements.
The other way around would be easy, with ('div i'), but using this in :not() is not possible.
How can I select all i elements outside of div elements?
Often it is suggested the use of jQuery, which would be like:
nondiv_i = all_i.not(all_div.find("i"))
I can't use jQuery, but could use jqLite - jqLite does not have a not()-function. A jqLite solution is welcome too!
Is it possible to do this without repeated iterations and comparisons?
Edit: To clarify, i don't want to have any div-ancestors for my i-elements, not only no direct div-parents.
A comparable XPath would look like this:
//i[not(ancestor::div)]
function isDescendant(parent, child) {
var all = parent.getElementsByTagName(child.tagName);
for (var i = -1, l = all.length; ++i < l;) {
if(all[i]==child){
return true;
}
}
return false;
}
for the specific case of yours;
is = document.getElementsByTagName("i");
divs = document.getElementsByTagName("div");
nondivs = [];
var contains;
for(i=0;i<is.length;i++){
contains = false;
for(j=0;j<divs.length;j++){
if(isDescendant(divs[j],is[i])){
contains = true;
j = divs.length;
}
}
if(!contains){
nondivs.push(is[i]);
}
}
Add a class to all of the <i> tags ("itag", for example). From there, you can fetch them by calling getElementsByClassName:
var r = document.getElementsByClassName("itag");
console.log("length" + r.length);
You can then get them by index:
console.log(r[0]);
console.log(r[1].innerHTML); // get text of i tag
There are some elements that are hidden in this web page. Now if I want to find the hidden elements:
var node = jQuery('body')[0];
$(node).find(":hidden").remove();
This removes the hidden elements from the main node (which further changes the layout of the page). What I want to do is to copy(clone) the elements which are not hidden. For which I am trying this:
var clone = node.cloneNode(true);
$(clone).find(":hidden").remove();
But this removes all the elements inside the clone and not just the hidden elements (as expected, since its not in the dom). What's the best possible way to remove hidden elements from the clone.
I assume the issue is that until your clone is re-inserted into the DOM, then all of it is being considered hidden.
Maybe you could mark the hidden elements for removal first, then clone and then remove the marked elements:
var $node = ... ; // jQuery object of node to be cloned
$node.find(':hidden').addClass('markedForRemoval');
var $clone = $node.clone();
$clone.find('.markedForRemoval').remove();
// tidy up:
$clone.find('.markedForRemoval').removeClass('markedForRemoval');
$node.find('.markedForRemoval').removeClass('markedForRemoval');
demo: http://jsfiddle.net/BYossarian/6ysq8/
Sometimes the :visible selector will not be enough, and you will also want a selector for styles with height:0px, since display:none; and height:0px; are not equivalent.
Before cloning, we need to mark the elements as visible or invisible, because once cloned, the clone is in a variable, but not on the page, so everything inside it will qualify as :hidden. (Bonus: Let's make this as efficient as possible, by not hijacking the class or id fields, and instead using a custom data-attribute.)
Identify truly hidden elements:
$(node).find(':hidden').attr('data-hidden', 'true');
$(node).find('
*[style*="height:0px"],
*[style*="height: 0px"]
').attr('data-hidden', 'true');
Deep clone the node:
var clone = node.clone(true, true);
Remove hidden elements:
clone.find('*[data-hidden="true"]').remove();
I would stick to jQuery clone. My method is kinda rough, but it works.
<div class="bla" >
<span class="hidden">hidden</span>
<span class="hidden">hidden</span>
<span class="hidden">hidden</span>
<span > visible </span>
</div>
So, first, clone the parent.
var a = $('.bla').clone()
Then clone the visible children.
var b = $('.bla > :visible').clone() ;
Then add them to each other.
a.html(b)
The whole thing will be like so:
var a = $('.bla').clone()
var b = $('.bla > :visible').clone() ;
a.html(b)
Here is an example : http://jsfiddle.net/4Dky9/1/
var clone = node.cloneNode(true);
var hiddenElements = clone.querySelectorAll('.hidden'); // if hidden elements are applied the css class hidden
for(var i = 0; i < hiddenElements.length; i++){
clone.removeChild(hiddenElements[i])
}
If there is no hidden class, iterate through all the child elements and check for the display property.
var children = clone.childNodes;
for(var i = 0; i < children.length; i++){
if(children[i].style && children[i].style.display == 'none'){
clone.removeChild(children[i]);
}
}
try using :
$(clone).children(':hidden').remove();
I have many spans with the same ID. how can assign their values to different variables in order of their occurance.
Ex
<span id="hello"> 18</span>
<span id="hello"> 12</span>
<span id="hello"> 21</span>
I want var1 = 18 var2= 12 var3= 21
See my comment regarding IDs. Now assuming you give that elements a class hello instead, this will work in all browsers:
var values = [],
spans = document.getElementsByTagName('span');
for(var i = 0, l = spans.length; i < l; i++) {
var span = spans[i];
if(span.className === 'hello') {
values.push(span.innerHTML);
}
}
DEMO
If you can't change the HTML, in this case you can compare the IDs:
if(span.id === 'hello')
This is ok, because we are iterating over all spans. But methods like getElementById won't work!
The id tag is supposed to be unique within a document. If you are trying to give them the same style, then you should use the class attribute instead of the id attribute. You can use the jQuery class selector to get all elements with a given class (assuming you change to using class instead of id).
I want open certain links in a new tab. Since I can't set it directly into the <a> tag, I want to put the link into <span> tags with a certain class name and set the target attribute via JavaScript.
I thought this would be easy, but I can't get it working:
addOnloadHook(function () {
document.getElementByClassName('newTab').getElementsByTagName('a').setAttribute('target', '_blank');
});
<span class="newTab">Link</span>
What am I doing wrong?
document.getElementByClassName does not exist, the correct function is document.getElementsByClassName (note the extra s). It returns an array of matching nodes, so you've to give an index:
addOnloadHook(function () {
document.getElementsByClassName('newTab')[0].getElementsByTagName('a')[0].setAttribute('target', '_blank');
});
but you might need to iterate through every span with the specified class ('newTab') on the page for it to work:
addOnLoadHook(function(){
var span = document.getElementsByClassName('newTab');
for(var i in span) {
span[i].getElementsByTagName('a')[0].setAttribute('target','_blank');
}
});
in case you'll have more than 1 anchor tag in a span you'd also
have to iterate through the anchor tags like this:
addOnLoadHook(function(){
var span = document.getElementsByClassName('newTab');
for(var i in span){
var a = span[i].getElementsByTagName('a');
for(var ii in a){
a[ii].setAttribute('target','_blank');
}
}
});
Can you please tell me if there is any DOM API which search for an element with given attribute name and attribute value:
Something like:
doc.findElementByAttribute("myAttribute", "aValue");
Modern browsers support native querySelectorAll so you can do:
document.querySelectorAll('[data-foo="value"]');
https://developer.mozilla.org/en-US/docs/Web/API/Document.querySelectorAll
Details about browser compatibility:
http://quirksmode.org/dom/core/#t14
http://caniuse.com/queryselector
You can use jQuery to support obsolete browsers (IE9 and older):
$('[data-foo="value"]');
Update: In the past few years the landscape has changed drastically. You can now reliably use querySelector and querySelectorAll, see Wojtek's answer for how to do this.
There's no need for a jQuery dependency now. If you're using jQuery, great...if you're not, you need not rely it on just for selecting elements by attributes anymore.
There's not a very short way to do this in vanilla javascript, but there are some solutions available.
You do something like this, looping through elements and checking the attribute
If a library like jQuery is an option, you can do it a bit easier, like this:
$("[myAttribute=value]")
If the value isn't a valid CSS identifier (it has spaces or punctuation in it, etc.), you need quotes around the value (they can be single or double):
$("[myAttribute='my value']")
You can also do start-with, ends-with, contains, etc...there are several options for the attribute selector.
We can use attribute selector in DOM by using document.querySelector() and document.querySelectorAll() methods.
for yours:
document.querySelector("[myAttribute='aValue']");
and by using querySelectorAll():
document.querySelectorAll("[myAttribute='aValue']");
In querySelector() and querySelectorAll() methods we can select objects as we select in "CSS".
More about "CSS" attribute selectors in https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors
FindByAttributeValue("Attribute-Name", "Attribute-Value");
p.s. if you know exact element-type, you add 3rd parameter (i.e.div, a, p ...etc...):
FindByAttributeValue("Attribute-Name", "Attribute-Value", "div");
but at first, define this function:
function FindByAttributeValue(attribute, value, element_type) {
element_type = element_type || "*";
var All = document.getElementsByTagName(element_type);
for (var i = 0; i < All.length; i++) {
if (All[i].getAttribute(attribute) == value) { return All[i]; }
}
}
p.s. updated per comments recommendations.
Use query selectors, examples:
document.querySelectorAll(' input[name], [id|=view], [class~=button] ')
input[name] Inputs elements with name property.
[id|=view] Elements with id that start with view-.
[class~=button] Elements with the button class.
Here's how you can select using querySelector:
document.querySelector("tagName[attributeName='attributeValue']")
Here is an example , How to search images in a document by src attribute :
document.querySelectorAll("img[src='https://pbs.twimg.com/profile_images/........jpg']");
you could use getAttribute:
var p = document.getElementById("p");
var alignP = p.getAttribute("align");
https://developer.mozilla.org/en-US/docs/Web/API/Element/getAttribute
Amendment for Daniel De León's Answer
It's possible to search with
^= - filters Elements where id (or any other attr) starts with view keyword
document.querySelectorAll("[id^='view']")
very simple, try this
<!DOCTYPE html>
<html>
<body>
<h1>The Document Object</h1>
<h2>The querySelector() Method</h2>
<h3>Add a background color to the first p element:</h3>
<p>This is a p element.</p>
<p data-vid="1">This is a p element.</p>
<p data-vid="2">This is a p element.</p>
<p data-vid="3">This is a p element.</p>
<script>
document.querySelector("p[data-vid='1']").style.backgroundColor = "red";
document.querySelector("p[data-vid='2']").style.backgroundColor = "pink";
document.querySelector("p[data-vid='3']").style.backgroundColor = "blue";
</script>
</body>
</html>
function optCount(tagId, tagName, attr, attrval) {
inputs = document.getElementById(tagId).getElementsByTagName(tagName);
if (inputs) {
var reqInputs = [];
inputsCount = inputs.length;
for (i = 0; i < inputsCount; i++) {
atts = inputs[i].attributes;
var attsCount = atts.length;
for (j = 0; j < attsCount; j++) {
if (atts[j].nodeName == attr && atts[j].nodeValue == attrval) {
reqInputs.push(atts[j].nodeName);
}
}
}
}
else {
alert("no such specified tags present");
}
return reqInputs.length;
}//optcount function closed
This is a function which is is used tu to select a particular tag with specific attribute value. The parameters to be passed are are the tag ID, then the tag name - inside that tag ID, and the attribute and fourth the attribute value.
This function will return the number of elements found with the specified attribute and its value.
You can modify it according to you.