Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Targeting an element by its content

How I can get DOM-element if I had and @media() ... in the content of this element? This is something like custom template engine that I made.

For case below, I need an <article> Node and <time> Node, because upper on every of these nodes exists @media tag (one or more).

    <div class="d-flex mt-20 vertical-around-flex">
        @media(1080) mmw-400 mmh-300
        @media(770) mmw-300
        <article class="card bubble mmw-500 mmh-400">
            @media(770) hide
            <time>14 June, 2023</time>
        </article>
    </div>

@media(1080) mmw-400 mmh-300 connected to <article>
@media(770) mmw-300 connected to <article>
@media(770) hide connected to <time>

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I need @media text and connected NODE element. Example structure:

{
    ARTICLE_NODE: {
        "media": "1080": {
            "classes": ["mmw-400", "mmh-300"]
        }
        "media": "770": {
            "classes": ["mmw-400", "mmh-300"]
        }
    },
    TIME_NODE: {
        "media": "770": {
            "classes": ["hide"]
        }    
    }

}

This is my code but it not working properly. This code return 6 Nodes, but I need 2 instead. Also, this code does not return me the @media text, only a HTML DomElement

        const REGEX_MEDIA = new RegExp('@media\\((\\d+)\\)\\s(.+)\\n', 'gm');
        const HTML = document.body.innerHTML;
        
        console.log(
            Array.prototype.slice.call(document.querySelectorAll('*')).filter(function(element) {
                const match = element.outerHTML.match(REGEX_MEDIA);

                if (match == null) {
                    return false;
                }
                if (match === void 0) {
                    return false;
                }

                return true;
            })
        )

>Solution :

No regexps needed. Just walk the node tree, look for text nodes that contain your @media tag and grab that value and the next sibling element (which is the "tagged" element).

Formatting the nodes from the example below to your object structure is left as a separate exercise.

const nodes = [];

function walkChildNodes(n) {
  for (let c of n.childNodes) {
    if (c.nodeType === 3) { // text node
      const val = c.nodeValue.trim();
      if (val.startsWith("@media")) {
        nodes.push([val, c.nextSibling]);
      }
    } else {
      if (c.hasChildNodes()) {
        walkChildNodes(c);
      }
    }
  }

}
walkChildNodes(document.body);
console.log(nodes);
<div class="d-flex mt-20 vertical-around-flex">
  @media(1080) mmw-400 mmh-300 @media(770) mmw-300
  <article class="card bubble mmw-500 mmh-400">
    @media(770) hide
    <time>14 June, 2023</time>
  </article>
</div>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading