0

That might sound a little confusing, but basically I have some html that looks like this (which is dynamically created)

<body>
<div class="component" id="465a496s5498">
  <div class="a-container">
   <div class="random-div">
    <div class="wantThis">
      <div class="wantThisHTML">Hello!<p>I'm another element!</p></div>
    </div>
   </div>
   <div class="random-div">
    <div class="random"></div>
   </div>
  </div>
</div>
<div class="component" id="683fg5865448">
  <div class="another-container">
   <div class="random-div">
    <div class="wantThis">
      <div class="wantThisHTML">Wow!</div>
    </div>
   </div>
   <div class="random-div6">
    <div class="random2"></div>
   </div>
 </div>
</div>
<div class="component" id="247487294js5">
  <div class="more-containers">
   <div class="random-div">
    <div class="wantThis">
      <div class="wantThisHTML">Haha!</div>
    </div>
   </div>
   <div class="random-div6">
    <div class="random5"></div>
   </div>
 </div>
</div>
</body>

And I want to create an array of objects which includes the unique id of the component and the raw HTML within the element with class name "wantThis" (it will always be called "wantThis"), so the array would look like

[{
 id: "465a496s5498",
 html: "<div class='wantThisHTML'>Hello!<p>I'm another element!</p></div>"
},{
 id: "683fg5865448",
 html: "<div class='wantThisHTML'>Wow!</div>"
},{
 id: "247487294js5",
 html: "<div class='wantThisHTML'>Haha!</div>"
}]

As for what i've tried, I split up the elements into an array using var elements = $(body).children, and I know to get the HTML within an element using $(.wantThis).html(), but how can I get the id and the HTML from each of the elements I obtain from the children?

Also, within the wantThis element there may me multiple elements, will $(.wantThis).html() get the raw HTML of ALL the children?

Hello Mellow
  • 169
  • 2
  • 15

4 Answers4

2

There you go.

var data = $('> .component', document.body).map(function(component) {
    return {
      id: this.id,
      html: $(this).find('.wantThisHTML').html()
    }
  })
  .toArray();

console.log(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="component" id="465a496s5498">
  <div class="a-container">
    <div class="random-div">
      <div class="wantThis">
        <div class="wantThisHTML">Hello!
          <p>I'm another element!</p>
        </div>
      </div>
    </div>
    <div class="random-div">
      <div class="random"></div>
    </div>
  </div>
</div>
<div class="component" id="683fg5865448">
  <div class="another-container">
    <div class="random-div">
      <div class="wantThis">
        <div class="wantThisHTML">Wow!</div>
      </div>
    </div>
    <div class="random-div6">
      <div class="random2"></div>
    </div>
  </div>
</div>
<div class="component" id="247487294js5">
  <div class="more-containers">
    <div class="random-div">
      <div class="wantThis">
        <div class="wantThisHTML">Haha!</div>
      </div>
    </div>
    <div class="random-div6">
      <div class="random5"></div>
    </div>
  </div>
</div>
Yom T.
  • 8,760
  • 2
  • 32
  • 49
  • What's the point of `$('> .component', document.body)`? Wouldn't just `$(".component")` be the same but simpler? Or at least `$(document.body).find(".component")` if you want to make the `body` an argument? – SergGr Jan 21 '19 at 02:32
  • `$('.component')` will work but it risks you from getting another possible elements with the same class, which may not come directly after the body element, whereas `$('> .component', document.body)` searches any element with this class directly under the body element. – Yom T. Jan 21 '19 at 02:35
  • I suspect that `.component` being a direct child is not really a requirement but an accident of the current layout but I get your point. – SergGr Jan 21 '19 at 02:37
  • In addition, what comes after the `$` (jQuery alias) is effectively a CSS selector, and in our case, we want all elements of class `component` that are children matched by the first selector (`document.body` serving as the [`context`](http://api.jquery.com/jquery/#jQuery-selector-context)), hence the [`>` child combinator](https://developer.mozilla.org/en-US/docs/Web/CSS/Child_combinator) character. – Yom T. Jan 21 '19 at 02:45
  • 1
    @nstanard, looking at the tags and at the question, the OP does use jQuery. I'm quite not sure that it is better to provide a non-jQuery answer in such a case. – SergGr Jan 21 '19 at 02:49
  • @nstanard jQuery helps you write less and do more, so why not? ;) BTW, I personally also do vanilla JS plus some other frameworks, so it really is a matter of choice. – Yom T. Jan 21 '19 at 02:50
  • @jom Thanks! This works perfectly with few lines. I'm just wondering, it comes up as a jQuery special object I assume as it has many other properties and fields than a normal array. Is there a way to turn this into a normal way/is it ok to send this to my back end and can I work with it like a normal array in there? – Hello Mellow Jan 21 '19 at 03:06
  • @HelloMellow Yes, you can convert them to normal array with [`.toArray()`](https://api.jquery.com/toArray/). Answer updated. – Yom T. Jan 21 '19 at 03:17
2

ONE approach to this is....

Select the Nodes (elements) using "querySelectorAll"

let nodeListOfComponentElements = document.querySelectorAll('.component')

This will get you a NodeList. NodeList

You can turn that into an array of Nodes by:

let nodeArray = [].slice.call(nodeListOfComponentElements) SO-Post

Then, using that array of nodes. You can 'map' it to the structure you want.

let result = nodeArray.map(function(item, index) {
  let targetElement = item.querySelector('.wantThisHTML')
  return {
    id: item.id,
    html: targetElement.innerHTML
  }
})

note: each "item" is an element/node and the method querySelector can be used to select children of that element. I'm targeting the class you mentioned. Then it's just a matter of returning an object for each iteration that the map function executes. You pick the keys and values that the map function returns. Here I'm setting the id key to the id of the element, and the html key to the "innerHTML" of the target child element within each main element.

The resulting structure is as follows:

(3) [{…}, {…}, {…}]
0: {id: "465a496s5498", html: "Hello!<p>I'm another element!</p>"}
1: {id: "683fg5865448", html: "Wow!"}
2: {id: "247487294js5", html: "Haha!"}
length: 3

CodePen: https://codepen.io/nstanard/pen/exOJLw

Don't forget to upvote and approve my answer it helps! Thanks

nstanard
  • 593
  • 3
  • 12
0

To make sure the .component has wanted '.wantThis' child.

var data = $('.wantThis').map(function() {
  return {
    id: $(this).parents('.component').attr('id'),
    html: $(this).html()
  }
});
console.log(data);

var data = $('.wantThis').map(function() {
  return {
    id: $(this).parents('.component').attr('id'),
    html: $(this).html()
  }
});
console.log(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="component" id="465a496s5498">
  <div class="a-container">
   <div class="random-div">
    <div class="wantThis">
      <div class="wantThisHTML">Hello!<p>I'm another element!</p></div>
    </div>
   </div>
   <div class="random-div">
    <div class="random"></div>
   </div>
  </div>
</div>
<div class="component" id="683fg5865448">
  <div class="another-container">
   <div class="random-div">
    <div class="wantThis">
      <div class="wantThisHTML">Wow!</div>
    </div>
   </div>
   <div class="random-div6">
    <div class="random2"></div>
   </div>
 </div>
</div>
<div class="component" id="247487294js5">
  <div class="more-containers">
   <div class="random-div">
    <div class="wantThis">
      <div class="wantThisHTML">Haha!</div>
    </div>
   </div>
   <div class="random-div6">
    <div class="random5"></div>
   </div>
 </div>
</div>
Cong Nguyen
  • 3,199
  • 1
  • 23
  • 22
-3
<div id="elem">
    <div id="elem-content">Element</div>
</div>

<script>
    alert(elem); // DOM-element with id="elem"
    alert(window.elem); // accessing global variable like this also works

    // for elem-content things are a bit more complex
    // that has a dash inside, so it can't be a variable name
    alert(window['elem-content']); // ...but accessible using square brackets [...]
</script>

reference: https://javascript.info/searching-elements-dom

  • 2
    Hello Clifford and welcome to Stack Overflow. It's good that you're learning JavaScript, but unfortunately this isn't an answer to the question asked. – traktor Jan 21 '19 at 02:48