Reputation: 19
I have the following DOM structure and I need to get the text inside my h1 or h2 tag (but always first-child) and add that text value as as data-attribute to the second-child.
<div class="my-item">
<div class="mac">
<h1>test123</h1>
<div>p1</div>
</div>
</div>
<div class="my-item">
<div class="mac">
<h2>test456</h2>
<div>p2</div>
</div>
</div>
So my DOM after JS should look like this:
<div class="my-item">
<div class="mac">
<h1>test123</h1>
<div data-head="test123">p1</div>
</div>
</div>
<div class="my-item">
<div class="mac">
<h2>test456</h2>
<div data-head="test456">p2</div>
</div>
</div>
I attempted to do this by getting the list of all selectors and iterating over the list, but it wouldn't add the data-attributes and I don't see any console error. I believe the way I'm doing it is unable to find the elements:
var items = document.querySelectorAll("div.my-item");
for (var i=0, max=items.length; i < max; i++) {
var itemH = $( "div.body:first-child" ).find(items[i]);
var itemP = $( "div.body:nth-child(2)" ).find(items[i]);
itemP.setAttribute('data-head', itemH.text());
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="my-item">
<div class="mac">
<h1>test123</h1>
<div>p1</div>
</div>
</div>
<div class="my-item">
<div class="mac">
<h2>test456</h2>
<div>p2</div>
</div>
</div>
Upvotes: 0
Views: 1238
Reputation: 11416
You can directly target the <h1>
and and <h2>
elements inside the div with class .my-class
like this:
$(".my-item h1, .my-item h2").each(function() {
$(this).next("div").attr("data-head", $(this).text());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="my-item">
<div class="mac">
<h1>test123</h1>
<div>p1</div>
</div>
</div>
<div class="my-item">
<div class="mac">
<h2>test456</h2>
<div>p2</div>
</div>
</div>
Update: As mentioned in the comments, the header tags could not only be h1 and h2, but everything up to h6. To target all header tags, it's possible to use :header
:
$(".my-item :header").each(function() {
$(this).next("div").attr("data-head", $(this).text());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="my-item">
<div class="mac">
<h1>test123</h1>
<div>p1</div>
</div>
</div>
<div class="my-item">
<div class="mac">
<h2>test456</h2>
<div>p2</div>
</div>
</div>
Upvotes: 1
Reputation: 65808
When you use JQuery selectors, they return a JQuery wrapped set object, which is not a native object in JavaScript, so when you try to call setAttribute()
on that JQuery object, you will get an error message in your developer's console.
Really, JQuery is overkill for this problem. If you just locate each second child of the respective groups and loop over them, you can update its data-head
attribute to include that div
s previous sibling element's text using the dataset
API.
// Get all the second child elements within the my-item groups
var items = document.querySelectorAll("div.my-item > div.mac > :nth-child(2)");
// Loop over the returned node list with the Array.forEach() API
// which is simpler than for loops because there's no index you
// have to manage.
items.forEach(function(item){
// Set data-* attribute using the dataSet API
item.dataset.head = item.previousElementSibling.textContent;
console.log(item);
});
<div class="my-item">
<div class="mac">
<h1>test123</h1>
<div>p1</div>
</div>
</div>
<div class="my-item">
<div class="mac">
<h2>test456</h2>
<div>p2</div>
</div>
</div>
Upvotes: 2