Ian Lloyd
Ian Lloyd

Reputation: 31

Identifying an HTML element that has *no* attributes of any kind with JavaScript?

I have a tool that is used for cleaning up crappy HTML in order to make sense of the underlying structure. Having stripped class, style attributes and various Angular attributes, often the resulting markup is a series of nested <div> or <span> elements that have no attributes. What I would like to do is provide option to do a second pass where a <div> or <span> with no attributes can be removed, to flatten the structure more.

Is there a way in JavaScript to confirm that an HTML element has no attributes of any kind?

And if that is possible, how might I approach this stripping of an element?

For example, assuming I have this:

<div>
 <div>
  <div id="blah">
   <div>
    <div>
     <span dir="auto">
      <span>Joe Bloggs</span>
     </span>
    </div>
   </div>
  </div>
 </div>
</div>

That should end up as:

  <div id="blah">
     <span dir="auto">
      Joe Bloggs
     </span>
  </div>

Which I would then format to:

<div id="blah">
 <span dir="auto">
  Joe Bloggs
 </span>
</div>

So I'd need a function that can walk the DOM and remove a div (or span) that has no attributes while leaving the inner contents intact (unless of course any of those inner elements can also be stripped for same reason).

Any pointers before I go ahead and construct a shoddy (but working) script would be appreciated!

Upvotes: 2

Views: 733

Answers (3)

TechySharnav
TechySharnav

Reputation: 5084

Updated Code

Here you go.

document.querySelectorAll("div").forEach((ele) => {
  if (ele.attributes.length === 0) {
    var fragment = document.createDocumentFragment();
    while (ele.firstChild) {
      fragment.appendChild(ele.firstChild);
    }
    ele.parentNode.replaceChild(fragment, ele);
  }
});
<div>
 <div>
  <div id="blah">
   <div>
    <div>
     <span dir="auto">
      <span>Joe Bloggs</span>
     </span>
    </div>
   </div>
  </div>
 </div>
</div>
So final output would be

<div id="blah">
  <span dir="auto">
    <span>Joe Bloggs</span>
  </span>
</div>

Upvotes: 0

a.mola
a.mola

Reputation: 4011

Here's how I did it.

I created a demo element, to get the elements, then I checked the number of elements, I checked if the element should be stripped.

I replaced the element with its children, and if it didn't have any, I used its text

function strip(startElement, toStrip) {
  const test = document.createElement('div');
  test.innerHTML = startElement.outerHTML;
  
  [...test.querySelectorAll('*')].forEach(elem => {
    if (!elem.attributes.length && toStrip.includes(elem.tagName.toLowerCase())) {
      if (elem.children.length) elem.replaceWith(...elem.children);
      else elem.replaceWith(elem.innerText);
    } ;
  });
  
  return test.innerHTML;
}

console.log(strip(document.querySelector('div'), ['span', 'div']));
<div>
 <div>
  <div id="blah">
   <div>
    <div>
     <span dir="auto">
      <span>Joe Bloggs</span>
     </span>
    </div>
   </div>
  </div>
 </div>
</div>

Upvotes: 0

Quentin
Quentin

Reputation: 943537

The attributes property will tell you how many attributes an element has.

const countAttributes = element => console.log({
  count: element.attributes.length,
  list: [...element.attributes].map(attribute => attribute.name)
});

const divs = document.querySelectorAll('div');
divs.forEach(countAttributes);
<div></div>

<div class="one attribute"></div>

<div class="two attributes" id="second attribute"></div>

Do note that an element without attributes might still be used for something (e.g. a stylesheet might reference it in relation to other elements).

Upvotes: 1

Related Questions