How to apply capitalization in paragraph text with specific classes directly in the page body?

Asked

Viewed 63 times

2

Basing myself in that question, I adapted a specific answer for my case, creating an array with the paragraphs of interest, where my intention is to capitalize the text present in these respective paragraphs (with some exceptions, such as abbreviations, prepositions and Roman numbers).

The code works perfectly, however I can’t get the capitalized results to replace the previous ones (before capitalization) in the HTML body. I’ve already removed the line console.log, replacing it with a capitalize(innerHTMLs); - that works when I see the result on the console, but I’m not able to make that mentioned replacement on the page itself.

One thing I found out is that using document.getElementsByClassName('h6').innerHTML = 'Novo valor' does not work unless I use an ID instead of class.

Any idea how I can replace paragraph text with classes h6 and professor their values capitalised in the function capitalize()? In other words:

<p class="h6">PREPOSIÇÃO DA SILVA</p>

transform into

<p class="h6">Preposição da Silva</p>

This is the code I’m using:

var innerHTMLs = Array.prototype.slice.call(document.querySelectorAll("[class='h6'], [class='professor']")).map(function(x){return x.innerHTML});

function abreviacao(s) {
    return /^([A-Z]\.)+$/.test(s);
}

function numeralRomano(s) {
    return /^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/.test(s);
}

function capitalize(texto) {
    let prepos = ["da", "do", "das", "dos", "e", "de", "à", "ao", "às", "aos", "tfc" ];
    return texto.split(' ') // quebra o texto em palavras
       .map((palavra) => { // para cada palavra
           if (abreviacao(palavra) || numeralRomano(palavra)) {
                return palavra;
           }

           palavra = palavra.toLowerCase();
           if (prepos.includes(palavra)) {
                return palavra;
           }
           return palavra.charAt(0).toUpperCase() + palavra.slice(1);
       })
       .join(' '); // junta as palavras novamente
}

innerHTMLs.forEach(t => console.log(capitalize(t)));
<p class="h6">PREPOSIÇÃO DA SILVA</p>
<p class="professor">ROMANOS IX</p>
<p class="h6">PREPOSIÇÃO DOS SANTOS</p>
<p class="professor">JOÃO PAULO II</p>
<p class="h6">INTRODUÇÃO À PRIMEIRA CARTA AOS CORÍNTIOS</p>
<p class="professor">REFERENTE AO PARÁGRAFO IV</p>

  • 1

    Its function capitalize only returns the text, does not change at any point, to exchange it is necessary to reference the element, but its variable innerHTMLs only contains "texts" (actually Htmls), not references to the elements, you need to change to save them. getElementsByClassName returns an array of elements, not an element, so the .innerHTML it won’t work, you’d have to iterate it to do something like elements[0].innerHTML = capitalize(innerHTMLs[0]), elements[1].innerHTML = capitalize(innerHTMLs[1]), ...

  • @First, thank you for the comment! I had already tried to do what you suggested to me, using innerHTMLs[0].innerHTML = capitalize(innerHTMLs[0]), but without success. In fact, there is capitalization in the element I refer to, but there is no substitution within the page.

  • Even I had created a bond for(var i = 0; i < innerHTMLs.length; i++){innerHTMLs[i].innerHTML = capitalize(innerHTMLs[i])}, but, as I said, unsuccessfully in replacing.

  • 1

    That’s because innerHTMLs[i] is not a reference to the HTML element, but HTML inside the element as a string. As I said, you need to adapt your variable innerHTMLs to store the element, not its contents (.innerHTML)

  • @Costamilam I get it. I will search how to do this (save the element - text - instead of content). Thank you!

1 answer

3


If you want to change the innerHTML of each of the elements, just use the result of querySelectorAll (that returns a list of the elements), travel around and change the innerHTML these in the capitalized version:

document.querySelectorAll("[class='h6'], [class='professor']")
    .forEach(e => e.innerHTML = capitalize(e.innerHTML));

Full example:

function abreviacao(s) {
    return /^([A-Z]\.)+$/.test(s);
}

function numeralRomano(s) {
    return /^M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$/.test(s);
}

function capitalize(texto) {
    let prepos = ["da", "do", "das", "dos", "e", "de", "à", "ao", "às", "aos", "tfc" ];
    return texto.split(' ') // quebra o texto em palavras
       .map((palavra) => { // para cada palavra
           if (abreviacao(palavra) || numeralRomano(palavra)) {
                return palavra;
           }

           palavra = palavra.toLowerCase();
           if (prepos.includes(palavra)) {
                return palavra;
           }
           return palavra.charAt(0).toUpperCase() + palavra.slice(1);
       })
       .join(' '); // junta as palavras novamente
}

function capitalizarTudo() {
    document.querySelectorAll("[class='h6'], [class='professor']")
        .forEach(e => e.innerHTML = capitalize(e.innerHTML));
}
<button onclick="capitalizarTudo()">Clique para capitalizar os parágrafos</button>
<p class="h6">PREPOSIÇÃO DA SILVA</p>
<p class="professor">ROMANOS IX</p>
<p class="h6">PREPOSIÇÃO DOS SANTOS</p>
<p class="professor">JOÃO PAULO II</p>
<p class="h6">INTRODUÇÃO À PRIMEIRA CARTA AOS CORÍNTIOS</p>
<p class="professor">REFERENTE AO PARÁGRAFO IV</p>

The way you did, you were just picking up the texts (yourself innerHTML), moving to function capitalize and printing the result on the console. That’s why the texts were not changed in the respective elements.


Note: here we are taking into account that within the elements there are no other tags (and in this case, it could even be used innerText instead of innerHTML that would make no difference). But if you have other tags inside the elements, then you would have to be careful not to replace the tags themselves, their attributes etc).

  • 1

    It worked perfectly, @hkotsubo! Regarding your remark, there are no other tags within paragraphs. Thank you so much for the instruction and the tips! Thanks!

Browser other questions tagged

You are not signed in. Login or sign up in order to post.