Search code examples
javascriptdomfilteringnodelist

Selecting a childnode by inner text from a NodeList


First part [solved]

Given this HTML

    <div id="search_filters">
     <section class="facet clearfix"><p>something</p><ul>...</ul></section>
     <section class="facet clearfix"><p>something1</p><ul>...</ul></section>
     <section class="facet clearfix"><p>something2</p><ul>...</ul></section>
     <section class="facet clearfix"><p>something3</p><ul>...</ul></section>
     <section class="facet clearfix"><p>something4</p><ul>...</ul></section>
    </div>

I can select all the section with

const select = document.querySelectorAll('section[class^="facet clearfix"]');

The result is a nodelist with 5 children.

What I'm trying to accomplish is to select only the section containing the "something3" string.

This is my first attempt:

`const xpathResult = document.evaluate( //section[p[contains(.,'something3')]],
        select,  null, XPathResult.ANY_TYPE, null );

How can I filter the selection to select only the node I need?

Second part:

Sorry for keeping update the question but it seems this is a problem out of my actual skill.. Now that i get the Node i need to work in what i've to do it's to set a custom order of the li in the sections:

<ul id="" class="collapse">
  <li>
   <label>
    <span>
     <input>
      <span>
       <a> TEXT
       </a>
      </span>
     </input>
    </span>
   </label>
  </li>
<li>..</li>

Assuming there are n

  • with n different texts and i've a custom orders to follow i think the best way to go it would be look at the innertex and matching with an array where i set the correct order.

    var sorOrder = ['text2','text1','text4','text3']
    

  • Solution

  • I think this approach should lead you to the solution. Giving your HTML

    <div id="search_filters">
     <section class="facet clearfix"><p>something</p><ul>...</ul></section>
     <section class="facet clearfix"><p>something1</p><ul>...</ul></section>
     <section class="facet clearfix"><p>something2</p><ul>...</ul></section>
     <section class="facet clearfix"><p>something3</p><ul>...</ul></section>
     <section class="facet clearfix"><p>something4</p><ul>...</ul></section>
    </div>
    

    I would write this js

    const needle = "something3";
    const selection = document.querySelectorAll('section.facet.clearfix');
    let i = -1;
    
    console.info("SELECTION", selection);
    let targetIndex;
    while(++i < selection.length){
      if(selection[i].innerHTML.indexOf(needle) > -1){
        targetIndex = i;
      }
    }
    console.info("targetIndex", targetIndex);
    console.info("TARGET", selection[targetIndex]);
    

    Then you can play and swap elements around without removing them from the DOM.

    PS. Since you know the CSS classes for the elements you don't need to use the ^* (start with) selector. I also improved that.

    PART 2: ordering children li based on content

    const ul = selection[targetIndex].querySelector("ul"); // Find the <ul>
    const lis = ul.querySelectorAll("li"); // Find all the <li>
    const sortOrder = ['text2', 'text1', 'text4', 'text3'];
    i = -1; // We already declared this above
    while(++i < sortOrder.length){
        const li = [...lis].find((li) => li.innerHTML.indexOf(sortOrder[i]) > -1);
        !!li && ul.appendChild(li);
    }
    

    This will move the elements you want (only the one listed in sortOrder) in the order you need, based on the content and the position in sortOrder.

    Codepen Here