Add a class to an element's first child with javascript - javascript

New to js and trying to add a class to every section's first child automatically. I'm thinking something like:
<script>
var element = document.getElementsByTagName('section p:first-child');
element.classList.add('firstp');
</script>
but it's not producing any effect in the document. Any help?

getElementsByTagName returns a collection, not an element, so you'd have to iterate over it
To use a string, enclose the string in string delimiters, like '
To use a selector string to select elements, use querySelectorAll. getElementsByTagName only accepts tag names (like p, or span - it's not flexible at all):
var allFirstPs = document.querySelectorAll('section p:first-child');
allFirstPs.forEach((p) => {
p.classList.add('firstp');
});
To support older browsers (since NodeList.prototype.forEach is a somewhat new method), use Array.prototype.forEach instead:
var allFirstPs = document.querySelectorAll('section p:first-child');
Array.prototype.forEach.call(
allFirstPs,
function(p) {
p.classList.add('firstp');
}
);

You could use querySelectorAll (to get the paragraphs) and forEach (to iterate over each paragraph) to accomplish this:
var elements = document.querySelectorAll('section p:first-child');
elements.forEach((e) => {
e.classList.add('firstp');
});
.firstp {
color: red;
}
<section>
<p>1st</p>
<p>2nd</p>
<p>3rd</p>
</section>
<section>
<p>1st</p>
<p>2nd</p>
<p>3rd</p>
</section>
<section>
<p>1st</p>
<p>2nd</p>
<p>3rd</p>
</section>

use querySelectorAll:
var elements = document.querySelectorAll('section p:first-child');
and iterate over result:
[...elements].forEach((element) => element.classList.add('firstp'));

Related

Add Class to div that Contains innerHTML String

I am trying to add a CSS class to each div on a page that contains the string Subject:
I tried
var elList = document.querySelectorAll("div");
elList.forEach(function(el) {
if (el.innerHTML.indexOf("Subject") !== -1) {
console.log(el);
el.setAttribute('class', "newClass");
}
});
but it didn't return any nodes. And also
var headings = document.evaluate("//*[contains(normalize-space(text()), 'Subject:')]", document, null, XPathResult.ANY_TYPE, null );
while(thisHeading = headings.iterateNext()){
thisHeading.setAttribute('class', "newClass");
console.log(thisHeading);
}
which returned an XPathResult that didn't seem to have any nodes as part of the object.
This is what the HTML looks like, although it is deeply nested inside the document body.
<div class="note-stream-header">Subject: Please Reply to This</div>
How can I select all nodes that contain a string and add a class to them with JS?
Your approach is fine, but since you are interested in the content of an element, use .textContent instead of innerHTML.
See additional comments inline.
// .forEach is not supported in all browsers on node lists
// Convert them to arrays first to be safe:
var elList = Array.prototype.slice.call(
document.querySelectorAll("div"));
elList.forEach(function(el) {
// Use .textContent when you aren't interested in HTML
if (el.textContent.indexOf("Subject") > -1) {
console.log(el);
el.classList.add("newClass"); // Use the .classList API (easier)
}
});
.newClass { background-color:#ff0; }
<div>The subject of this discussion is JavaScript</div>
<div>The topic of this discussion is JavaScript</div>
<div>The queen's royal subjects weren't amused.</div>
<div>Subject: textContent DOM property</div>

Get an element's value without an id

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);

Why does jQuery, outputs same rel each time?

so basically here is my script:
http://jsfiddle.net/JJFap/42/
Code -
jQuery(document).ready(function() {
var rel = new Array();
var count = 0;
jQuery(".setting").each(function() {
rel[count] = [];
if(jQuery("span").attr("rel")) {
rel[count].push(jQuery("span").attr("rel"));
}
console.log(count);
count++;
});
jQuery("body").text(rel);
console.log(rel);
});​
and
<div class="setting">
<span rel="Variable">Variable</span>
<span rel="Item">Item</span>
<span rel="Something">Something</span>
</div>
<div>
<span rel="Smth">Smth</span>
<span>Sec</span>
</div>
<div class="setting">
<span>Second</span>
<span rel="first">First</span>
<span rel="Third">Third</span>
</div>
​my question, is why does it display Variable, variable?
I would like it to display Variable, First, but I'm not able to do.
Basically what I would like to achieve is create new array, in which insert each div.setting span elements with rel attribute array.
So basically in this example it should output -
Array (
Array[0] => "Variable","Item","Something";
Array[1] => "first","Third";
)
Hope you understood what I meant :)
EDIT:
In my other example I tried to add jQuery("span").each(function() ... inside first each function, but it outputted two full arrays of all span elements with rel. I can't have different classes / ids for each div element, since all will have same class.
jQuery('span') is going to find ALL spans in your page, and then pull out the rel attribute of the first one. Since you don't provide a context for that span search, you'll always get the same #1 span in the document.
You should be using this:
jQuery('span',this).each(function() {
rel[count] = [];
if (jQuery(this).attr("rel")) {
rel[count].push(jQuery(this).attr("rel"));
}
console.log(count);
count++;
})
instead of this:
rel[count] = [];
if(jQuery("span").attr("rel")) {
rel[count].push(jQuery("span").attr("rel"));
}
console.log(count);
count++;
http://jsfiddle.net/mblase75/JJFap/52/
The trick is to use a second .each to loop over all the span tags inside each <div class="setting"> -- your original code was using jQuery("span"), which would just grab the first span tag in the document every time.
In addition to what has been said, you can also get rid of the count and one push() when using jQuery.fn.map() as well as getting rid of the if when adding [rel] to the selector:
jQuery(document).ready(function() {
var rel = [];
jQuery(".setting").each(function() {
rel.push(jQuery(this).find('span[rel]').map(function() {
return this.getAttribute('rel');
}).get());
});
jQuery("body").text(rel);
console.log(rel);
});
Within the .each() method, you have this code a couple times: jQuery("span").attr("rel"). That code simply looks for ALL span tags on the page. When you stick it inside the .push() method, it's just going to push the value for the rel attribute of the first jQuery object in the collection. Instead, you want to do something like $(this).find('span'). This will cause it to look for any span tags that are descendants of the current .setting element that the .each() method is iterating over.

How to search the children of a HTMLDivElement?

I have an HTMLDivElement, and my goal is to find a div nested beneath this.
Ideally I'd want something like getElementById, but that function doesn't work for HTMLDivElement.
Do I need to manually traverse the graph, or is there an easier way?
Demo: http://jsfiddle.net/ThinkingStiff/y9K9Y/
If the <div> you're searching for has a class, you can use getElementsByClassName():
document.getElementById( 'parentDiv' ).getElementsByClassName( 'childDiv' )[0];
If it doesn't have a class you can use getElementsByTagName():
document.getElementById( 'parentDiv' ).getElementsByTagName( 'div' )[0];
And if it has an id you can, of course, just use getElementById() to find it no matter where it is in the DOM:
document.getElementById( 'childDiv' );
//For immediate children
var children = document.getElementById('id').childNodes;
//or for all descendants
var children = document.getElementById('id').getElementsByTagName('*');
var div = ...
var divChildren = div.getElementsByTagName("div");
var divYouWant = [].filter.call(divChildren, function (el) {
return matchesSomeCondition(el);
});
Ideally, I'd want something like getElementById
And you can use getElementById just do document.getElementById(id) and since ids are unique that will find that single div item you wanted.
You can also use elem.getElementsByClassName to select a descendant of elem by class
You can use .querySelector(). The functions getElementById() and getElementByClassName() work perfectly fine on document, but they do not work on the child records returned by these functions. If you need many children elements, then consider .querySelectorAll()
Full Working Demo:
const topdiv = document.getElementById('top-div');
const seconddiv = topdiv.querySelector('#second-div');
seconddiv.innerHTML = '456';
<div id="top-div">
123
<div id="second-div">
abc
</div>
</div>
Demonstration of getElementById() Failing:
const topdiv = document.getElementById('top-div');
const seconddiv = topdiv.getElementById('second-div');
seconddiv.innerHTML = '456';
<div id="top-div">
123
<div id="second-div">
abc
</div>
</div>
Concise and readable:
document.getElementById('parentDiv').children[0];
Using .childNodes returns lots of extra children, whereas .children returns a smaller array.

Find an element in DOM based on an attribute value

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.

Categories