1

I'm in no way a coder but I got an idea. I create websites with the tool webflow and when you set up a CMS collection with a rich-text-field the client can add headlines including h1, which I don't want them to. My idea is that with javascript replace every h1 with h2 within a class (so the page title doesn't get changed).

So far I manage to create this:

var e = document.getElementsByTagName('h1')[0];

var d = document.createElement('h2');
d.innerHTML = e.innerHTML;

e.parentNode.replaceChild(d, e);
<h1>Don't change this</h1>
<div class="the-class">
  <h1>Replace this with h2</h1>
</div>
InSync
  • 4,851
  • 4
  • 8
  • 30
Billy Berg
  • 49
  • 4
  • Provide the HTML code please. – MrAlbino Apr 17 '23 at 11:26
  • Do you need the HTML code? Here: `

    Heading

    some content

    `
    – Billy Berg Apr 17 '23 at 11:42
  • 3
    When we ask for the HTML (or CSS, JavaScript...), we're asking for it to be added to the question; code in comments isn't really readable, and those trying to help shouldn't have to read the comments (which are prone to deletion) to understand the question. On this occasion I've added the code for you, and converted it into a runnable snippet. – David Thomas Apr 17 '23 at 11:54
  • I don't know what approach Webflow uses, but changing the h1 element after the page has been rendered will probably have no effect. – Quentin Veron Apr 17 '23 at 12:01
  • Ah, so this might not be posable? – Billy Berg Apr 17 '23 at 12:03
  • Like Quentin, I don't know that client-side changes would be useful (or possible), but if it *is* a possibility, there's this approach: https://jsfiddle.net/davidThomas/yvgmbe24/ – David Thomas Apr 17 '23 at 12:16
  • Maybe https://stackoverflow.com/questions/13389751/change-tag-using-javascript is an option. – Reporter Apr 17 '23 at 12:21

3 Answers3

5

You can use querySelector and use a proper CSS selector to match only <h1> elements inside .the-class:

for (let header of document.querySelectorAll('.the-class h1')) {
    // I gave these variables real names, very good practice
    var new_header = document.createElement('h2');
    new_header.innerHTML = header.innerHTML;

    header.parentNode.replaceChild(new_header, header);
}
<h1>Don't change this</h1>
<div class="the-class">
  <h1>Replace this with h2</h1>
</div>

This will replace all h1 elements anywhere inside .the-class

mousetail
  • 7,009
  • 4
  • 25
  • 45
  • very elegant and clean :) before "header.parentNode.replaceChild(new_header, header);" one could also move classes and attributes from the old node to the new_header. – Kathara Apr 17 '23 at 12:25
0

[edit 2023/04/18] Here is a utility function to change the name of any tag, whilst maintaining the properties of the original. It replaces the tagname part of outerHTML.

Note: the browser automagically replaces the end tag.

See also.

/* 
   Simplified alternative: a generic function 
   to change the tag name of an element by 
   changing its outerHTML.
   This conserves attributes/classNames of the
   original element
*/
const replaceElem = (elem, nwTag) => 
  elem.outerHTML = elem.outerHTML
    .replace(RegExp(`^<${elem.tagName}`, `i`), `<${nwTag}`);

document.querySelectorAll(`.the-class h1`)
   .forEach(h1 => replaceElem(h1, `h2`));
document.querySelectorAll(`div`)
  .forEach(div => replaceElem(div, `span`));

/* 
original snippet
-----------------
document.querySelectorAll(`.the-class h1`)
  .forEach(h1 => h1.replaceWith( Object.assign(
    document.createElement(`h2`), {
      innerHTML: h1.innerHTML,
      className: [...(h1.classList || [])].join(` `)
    } ) ) );
*/
body {
  font: normal 12px/15px verdana, arial, sans-serif;
}
h1 { color: red; }
h2.italic { font-style: italic; }
h2.blue { color: blue; }
h2[data-header] { background-color: #eee; }
span.the-class { display: block; }
span.the-class::after {
  content: 'Once I was <div> ';
  font-size: 1.2rem;
  margin-left: 2rem;
}
<h1>Don't change this</h1>
<div class="the-class">
  <h1>Replace this with h2</h1>
</div>
<div class="the-class">
  <h1 class="blue" data-header="2">Replace this with h2 too</h1>
</div>
<div class="the-class">
  <h1 class="italic blue">He! I want to be replaced too!</h1>
</div>
KooiInc
  • 119,216
  • 31
  • 141
  • 177
0

querySelectorAll to select the h1s inside of a class, createElement to make the new h2, and replaceWith to swap.

document.querySelectorAll('.the-class h1').forEach(h1 => { 
  const h2 = document.createElement('h2');
  h2.innerHTML = h1.innerHTML;
  h1.replaceWith(h2);
});
h1 {
  color: red;
}

h2 {
  color: blue;
}
<h1>Don't change this</h1>
<div class="the-class">
  <h1>Replace this with h2</h1>
</div>
<div class="the-class">
  <h1>And Replace this with h2</h1>
</div>
epascarello
  • 204,599
  • 20
  • 195
  • 236