Skip to main content

DHTMLX RichText. Text statistics example

Live example

RichText gives you the plain text of the document, so you can compute your own statistics. This demo shows a live word, sentence, and character count below the editor. The numbers recompute as you type.

let stats = { words: 0, sentences: 0, chars: 0, charsNoSpace: 0 };

function collectStats() {
    let spaceCount = 0;

    const text = widget.getValue(richtext.text.toText);
    const lines = text.split(/[\r\n]/g).filter(l => l.length > 0);
    const words = lines.map(l =>
        l.split(/\s/).filter(w => {
            if (!w.length) spaceCount++;
            return w.length > 0;
        })
    );
    const sentences = lines
        .filter(l => l.trim().length > 0)
        .map(l => l.split(/[.!?]+\s/));
    const wordCount = words.reduce((a, b) => a + b.length, 0);
    const charCount = words.reduce((a, b) => a + b.join("").length, 0);
    const sentenceCount = sentences.reduce((a, b) => a + b.length, 0);
    spaceCount += words.reduce((a, b) => a + (b.length - 1), 0);

    stats = {
        words: wordCount || 0,
        sentences: sentenceCount || 0,
        chars: charCount + spaceCount || 0,
        charsNoSpace: charCount || 0,
    };
}

function displayStats() {
    for (const key in stats) {
        document.getElementById(key).innerText = stats[key];
    }
}

const widget = new richtext.Richtext("#richtext", {
    value,
    imageUploadUrl,
    layoutMode: "document",
    menubar: true
});

widget.api.on("change", () => {
    collectStats();
    displayStats();
});

collectStats();
displayStats();
<!-- auxiliary controls for interacting with the sample -->
<link rel="stylesheet" href="https://snippet.dhtmlx.com/codebase/assets/css/auxiliary_controls.css">

<div class="richtext-demo">
    <div class="richtext-container">
        <div id="richtext" style="height:100%;"></div>
    </div>

    <section class="dhx_sample-controls bottombar">
        <div class="text-stats">
            <div>Words: <span id="words">0</span></div>
            <div>Sentences: <span id="sentences">0</span></div>
            <div>Characters: <span id="chars">0</span></div>
            <div>Characters (excluding spaces): <span id="charsNoSpace">0</span></div>
        </div>
    </section>
</div>

<style>
.richtext-demo {
        display: flex;
        flex-direction: column;
        height: 100%;
    }

    .richtext-container {
        height: 100%;
        width: 100%;
        padding: 0;
        box-sizing: border-box;
        overflow: hidden;
    }

    .dhx_sample-controls.bottombar {
        display: flex;
        flex-wrap: wrap;
      	flex-shrink: 0;
        height: auto;
        min-height: 34px;
        justify-content: flex-end;
        padding: 6px 12px;
        border-top: 1px solid #ccc;
        border-bottom: 1px solid #ccc;
    }

    .text-stats {
		display: flex;
		flex-direction: row;
        flex-wrap: wrap;
		align-items: center;
    }

    .text-stats > div {
		padding: 0 20px 0;
	}
</style>

<script>
const value = `
        <h2>Meet DHTMLX Rich Text Editor!</h2>
        <p>Create and edit text with ease! DHTMLX RichText is a powerful editor that allows you to:</p>
        <ul>
            <li>Format text: make it <b>bold</b>, <i>italic</i>, <u>underlined</u>, or <s>strikethrough</s>, choose fonts (e.g., Arial), <span style="font-size:16px;">text size</span>, <span style="color:#0066CC;">font color,</span> and <span style="color:#FFFFFF;background:#0066CC;">background color.</span></li>
            <li>Add headings of different levels (from H1 to H6) or use the Paragraph style, align text to the left, center, right, or justify, and create numbered or bulleted lists for structured content.</li>
            <li>Insert hyperlinks for navigation to external resources, add images for visual enhancement, insert horizontal lines for separation, and use subscripts (e.g., x₂) or superscripts (e.g., x²) for scientific or mathematical notation.</li>
            <li>Read and write editor content as HTML, plain text, or Markdown for flexible integration.</li>
            <li>Clear formatting from selected content with a single click.</li>
            <li>Customize the toolbar to suit your needs, adding or removing features as desired.</li>
            <li>Enjoy an adaptive design that works seamlessly on any device, including mobile.</li>
            <li>Use Undo and Redo functions to easily revert or reapply changes as needed.</li>
        </ul>
        <p><b>To learn more, read our <a href="https://docs.dhtmlx.com/richtext/">documentation</a> and check the <a href="https://snippet.dhtmlx.com/q8j4qqq9?tag=richtext">samples</a></b>.</p>
        <hr>
        <blockquote>It is very easy to get things up and running.</blockquote>
        <p><img src="https://docs.dhtmlx.com/richtext-backend/images/3490994099/i.png" style="width:415px;height:276px;"></p>
    `;

    const baseURL = "https://docs.dhtmlx.com/richtext-backend";
    const imageUploadUrl = `${baseURL}/images`;
</script>

Use case

Use it when writers need feedback on length, like a post editor with a word target, a comment box with a limit, or a document tool that shows a live count. Use the text encoder to read the editor's plain text, then count whatever you need: words, sentences, or characters with or without spaces. Recompute whenever the content changes so the numbers stay current. To adapt it, read the text with widget.getValue(richtext.text.toText) and run your own counting in the change handler.

How to do this in your app

  • Read the plain text: call widget.getValue(richtext.text.toText) to get the document as text.
  • Count what you need: split the text into lines and words to tally words, sentences, and characters.
  • Recompute on change: subscribe with widget.api.on("change", ...) so the stats update as the user types.
  • Run it once at start: compute the stats immediately after init so the display is right before any edits.

Good to know

  • There is no built-in stats method: RichText does not return counts for you, so the demo computes them from the plain text.
  • Counting rules are yours: what a "word" or "sentence" is depends on your split logic, so tune it to your needs.
  • Read text, not HTML, for counting: the text encoder strips tags, so the counts reflect visible content rather than markup.

API reference

Additional resources