Search code examples
javascriptdocumentselectors-api

How to build an array larger than the nodeList, putting empty strings as placeholders for missing classes?


HTML

<div class="1"><div class="2">element1class2</div><div class="3">element1class3</div></div>
<div class="1"><div class="2">element2class2</div></div>

Javascript:

var class2List= document.querySelectorAll('div.class1 div.class2')
var class3List= document.querySelectorAll('div.class1 div.class3')
    
for (let i = 0; i < class2List.length; i++) {
            nodes[i] = {
              class2: class2List[i].innerText,
              class3: class3list[i].innerText,
            } 
          }

Hi, I'd like to know if it's possible to use querySelectors make an Array of HTML Elements in the following way:

i'd like an output array of of the the innerText, but when there is no class, to put an empty string.

[{class2: 'element1class2', class3: 'element1class3'},
 {class2: 'element2class2', class3: ''} ]

right now, if there is no div class="3" in the node, then the NodeList length is reduce by 1 for every element not carrying a class="3" div.

The current output is innerText is not defined for class3list for class3List because the length of class3list is shorter than class2List.


Solution

  • Use optional chaining so that the value is undefined if the element doesn't exist, then use ?? to alternate with the empty string in such a case:

    class3: class3list[i]?.innerText ?? '',
    

    If you can't use optional chaining, you can use the conditional operator:

    class3: class3list[i] ? class3list[i].innerText : '',
    

    If you need to handle "holes" in the middle, then use a different approach: map the <div class="2" elements to their next sibling:

    const nodes = [...document.querySelectorAll('[class="2"]')]
      .map(class2 => ({
        class2: class2.textContent,
        class3: class2.nextElementSibling?.textContent ?? ''
      }));
    console.log(nodes);
    <div class="1">
      <div class="2">element1class2</div>
      <div class="3">element1class3</div>
    </div>
    <div class="1">
      <div class="2">element2class2</div>
    </div>

    Note that you need to use the [class="2"] selector string, not .class2, because your elements are not class="class2", but class="2".

    You also need to fix the syntax of your HTML. The final

    </div>/div>
    

    should be

    </div></div>