JS/jQuery: Count Number of Characters with Space with HTML tags

Massimo Scola
Massimo Scola used Ask the Experts™
on
I have to implement the ability to check the number of characters with spaces in a text. The text contains html tags and I need to remove them. I am allowed to use JavaScript as well as jQuery. While I have no problems removing regular tags, the biggest problem is removing <ul><li> tags. The way both plain JavaScript (with regex) and jQuery handles them is that it removes those tags, but leaves them empty ; that is: with space.

What is the best method to count the characters with space based on this example text:

  • Siguiendo el modelo de los libros educativos, El príncipe ofrece consejos prácticos para conquistar y garantizar un gobierno monárquico.
  • Contenido: un soberano debería hacer todo lo posible para garantizar su reinado, incluso si esto significa que debe usar la violencia. Puede mantenerse en el poder con crímenes o asegurarse la lealtad del pueblo con buenas acciones. Para un príncipe, es mejor ser temido que amado. Sin embargo, debe satisfacer a sus súbditos, promover el comercio y evitar por todos los medios que su pueblo lo aborrezca. El soberano nunca debe subestimar el arte de la guerra.
  • El famoso e infame libro de Maquiavelo fue escrito en 1513, pero solo se publicó después de su muerte.
  • La Italia del siglo XVI no contaba con un gobierno centralizado, por lo que se convirtió en el trofeo de fuerzas externas.
  • Maquiavelo dedicó su libro a Lorenzo de Medici, a quien exigió tomar el poder en Italia y defender el país de los bárbaros.
  • El príncipe se orienta a la realidad política y no a los ideales morales.
  • La forma de gobierno que fomenta la obra de Maquiavelo se corresponde parcialmente con el absolutismo ilustrado.
  • Ya para el siglo XVI se había acuñado el término “maquiavélico”, para describir un despotismo sin escrúpulos.
  • Aproximadamente 30 años después de la muerte de Maquiavelo (1527), sus escritos ingresaron a la lista de textos prohibidos.
  • Cita: “El odio puede surgir de malas o de buenas acciones. Es por eso que muchas veces un príncipe se ve obligado a no actuar bien cuando quiere lograr otra cosa.”

And this is the code which I have written so far. It only returns the plain text from which I will count the number of characters.

var plainText = "";
			
			try
			{
				if($(html).length==0) //it's plaintext already
				{
					plainText = html;
				}
				else
				{
					//replacing closing tags with a closing tag and a blank at the end to make sure that words are separated.
					html = html.replace(/<\/li>/g,"<\/li> "); //replaces all <\li>
					html = html.replace(/<\/p>/g,"<\/p> "); //replaces all <\p>
					html = html.replace(/<\/span>/g,"<\/span> "); //replaces all <\span>
					html = html.replace(/<\/blockquote>/g,"<\/blockquote> "); //replaces all <\blockquote>

					var $content = $("<div/>").html(html);
					var contFromJQuery = $("<div/>").html(html)
					cont = contFromJQuery.text();
					cont = cont.replace(/<[^>]*>/g,"");
					cont = cont.replace(/\r?\n|\r/gm,"");
					$content.find("citation").remove();
					$content.find("blockquote").remove();
					$content.find("comment").remove();

					textToCheck = $content.text().trim();
					console.log("Text with regex: ");
					console.log(cont.trim());
					console.log("cont length: " + cont.length);					


					plainText = $content.text() // html to text //to wrap everything in a paragraph is necessary for jquery.
				}
			}
			catch(e) // to catch "unrecognized expression" (syntax) error of jquery if it's not html
			{
				plainText = html;
			}
			
plainText = plainText.replace(/\r?\n|\r/gm," "); // remove line breaks 
			console.log("Text when regex is run on plainText/jquery result:");
			console.log(plainText);
			
			return plainText;
		},

Open in new window


What is the best approach to solve this problem?

I have created a jsFiddle - though I don't know how to display a console output.

Thanks for your help

Massimo
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
ste5anSenior Developer

Commented:
Trick or test question? It's the length of the innerText property. Create a new div assign your HTML source and return the value.
Massimo ScolaSoftware Engineer

Author

Commented:
I wish it was a test question ..This is for a project at work.
I'm in publishing and our writers have to adher to word and character counts.
This JavaScript snippet is part of a plugin for the ckEditor.

If it was a university assignment or question, I would have mentioned it.
ste5anSenior Developer

Commented:
In your case:

var getPlainText = function() 
{  
	return $("#exampleText").text().length;
}

Open in new window

But you need to handle line breaks.
Ensure you’re charging the right price for your IT

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden using our free interactive tool and use it to determine the right price for your IT services. Start calculating Now!

Massimo ScolaSoftware Engineer

Author

Commented:
and that doesn't return the correct length ... I have tried that already - see my jFiddle
https://jsfiddle.net/mscola75/8axc5dbp/57/?utm_source=website&utm_medium=embed&utm_campaign=8axc5dbp


The problem is that jQuery removes the tags, but keeps them empty... with space. And when I check the length, it counts these spaces.
I only need to count the spaces that were made by the authors/writers.

Maybe I have to loop through every single <li> and count the number of characters in it separately?
Senior Developer
Commented:
Nope. Your sample is not helpful. Run this locally in your browser:

<!DOCTYPE html>
<html>

<body>
    <div id="banner-message">
        <p>This text should contain 1524 characters with whitespace once the list/bullet points have been removed</p>
        <p> Number of characters in text: <input id="countOfChar">  </p>
    <button>Count number of characters</button>
    </div>
    <div id="exampleText">
        <ul>
            <li>Siguiendo el modelo de los libros educativos, <em>El príncipe</em> ofrece consejos prácticos para conquistar y garantizar un gobierno monárquico.</li>
            <li>Contenido: un soberano debería hacer todo lo posible para garantizar su reinado, incluso si esto significa que debe usar la violencia. Puede mantenerse en el poder con crímenes o asegurarse la lealtad del pueblo con buenas acciones. Para un príncipe, es mejor ser temido que amado. Sin embargo, debe satisfacer a sus súbditos, promover el comercio y evitar por todos los medios que su pueblo lo aborrezca. El soberano nunca debe subestimar el arte de la guerra.</li>
            <li>El famoso e infame libro de Maquiavelo fue escrito en 1513, pero solo se publicó después de su muerte.</li>
            <li>La Italia del siglo XVI no contaba con un gobierno centralizado, por lo que se convirtió en el trofeo de fuerzas externas.</li>
            <li>Maquiavelo dedicó su libro a Lorenzo de Medici, a quien exigió tomar el poder en Italia y defender el país de los bárbaros.</li>
            <li><em>El príncipe </em>se orienta a la realidad política y no a los ideales morales.</li>
            <li>La forma de gobierno que fomenta la obra de Maquiavelo se corresponde parcialmente con el absolutismo ilustrado.</li>
            <li>Ya para el siglo XVI se había acuñado el término “maquiavélico”, para describir un despotismo sin escrúpulos.</li>
            <li>Aproximadamente 30&nbsp;años después de la muerte de Maquiavelo (1527), sus escritos ingresaron a la lista de textos prohibidos.</li>
            <li>Cita: “El odio puede surgir de malas o de buenas acciones. Es por eso que muchas veces un príncipe se ve obligado a no actuar bien cuando quiere lograr otra cosa.”</li>
        </ul>
    </div>
    <hr>
    <div id="result">
    </div>
    <script>
        var text = document.getElementById("exampleText").innerText;
        document.getElementById("result").innerText = text;
        console.log(text.length);
    </script>
</body>

</html>

Open in new window

The difference are just the line breaks.
Massimo ScolaSoftware Engineer

Author

Commented:
Isn't .innerText the same as $content.text() in jQuery?
Massimo ScolaSoftware Engineer

Author

Commented:
After I run jQuery.text() this is what I get:

As you can see, where the <li> tags were, there is now space.

Annotation-2019-09-25-185354.png
Massimo ScolaSoftware Engineer

Author

Commented:
OK I found what the problem was in my code.
I ran a regex to remove all carriage returns .. and they were replaced with a space.
When I removed that, I was left with tabs that needed to be removed.

This code removes all carriage returns and tabs and then I get correct amount of characters

plainText = plainText.replace(/[\t\n\r]/gm,'')

thanks a lot for your help

Massimo

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial