skip to Main Content

I’m building an HTML/CSS/JavaScript + jQuery web-application. I have a page that calls an API, which returns a string with HTML code. Here’s an example:

// Data returned by server

data = {
  text: "<b>Here is some example text<b> followed by line breaks<br><br><br><br><br"
}

I need to implement live typing animation to display the data. I’ve got that working (see code below), but when there’s an HTML tag such as <b> or <br>, the < characters briefly flash on the screen before the element is properly displayed. Is there some kind of decoding function I need to run before calling the function to display the text?

// The text we want to animate
let text =
  "Here is some example text followed by a line break<br><br>and another line break<br><br><b>as well as some bold text.<b>";

// The current position of the animation
let index = 0;

// Function to trigger the live typing animation
function typingAnimation(id) {
  setTimeout(() => {
    index++;
    updateText(id);
    if (index < text.length) {
      typingAnimation(id);
    }
  }, 50);
}

// Function to update the text 
function updateText(id) {
  // Get the element with our id
  const typing = document.getElementById(id);
  // Split our text into lines based on newline characters or <br> tags
  const lines = text.substring(0, index).split(/n|<br>/);

  // Check if our element exists before updating it
  if (typing == null) {
    return;
  }

  // Update the element with our new lines
  typing.innerHTML = lines
    .map((line, index) => {
      // Check if this is the last line in our text
      const isLastLine = index === lines.length - 1;

      // Add a line break if this isn't the last line of text
      const lineBreak = isLastLine ? "" : "<br>";

      // Return our line of text with or without a line break
      return `${line}${lineBreak}`;
    })
    .join("");
}

typingAnimation("typing-animation");
<div>
  <span id="typing-animation"></span>
</div>

2

Answers


  1. Your issue stems from the broken regex (which is not even necessary) & to be fair you shouldn’t parse HTML with regex anyway.

    While not the best approach you can get the number of opened and closed tags, and continue slicing up the string until you complete a tag.

    Here is some code I threw around in JSFiddle. Seems to be working right.

    // The text we want to animate
    let text =
      "<br>Here is some example text followed by a line break<br><br>and another line break<br><br><b>as well as some bold text.<b>";
    
    // The current position of the animation
    let index = 0;
    
    // Function to trigger the live typing animation
    function typingAnimation(id) {
      setTimeout(() => {
        index++;
        updateText(id);
        if (index < text.length) {
          typingAnimation(id);
        }
      }, 50);
    }
    
    // Function to update the text 
    function updateText(id) {
      // Get the element with our id
      const typing = document.getElementById(id);
      
      // Split our text into lines
      let lines = text.substring(0, index).split("");
      // Get the amount of opened tags
      let opcount = lines.filter(x => x === '<').length;
      // Get the amount of closed tags
      let endcount = lines.filter(x => x === '>').length;
      
      // Repeat until we have matching number of both open and closed tags
      do {
        index++;
        lines = text.substring(0, index).split("");
        opcount = lines.filter(x => x === '<').length;
        endcount = lines.filter(x => x === '>').length;
      } while(opcount !== endcount);
      
      // Check if our element exists before updating it
      if (typing == null) {
        return;
      }
    
      // Update the element with our new lines
      typing.innerHTML = lines.join("");
    }
    
    typingAnimation("typing-animation");
    
    Login or Signup to reply.
  2. I have created a function that checks if a letter is inside an HTML tag. If it is, the function doesn’t append it. Hope it works for you.

    function typeText(elementId, htmlContent, speed) {
        const element = document.getElementById(elementId);
        let index = 0;
        let tag = false;
        let temp = '';
    
        function typeCharacter() {
            let char = htmlContent.charAt(index);
    
            // Check if we're inside an HTML tag
            if (char === '<') tag = true;
            if (char === '>') tag = false;
    
            // Append character only if it's outside an HTML tag
            temp += char;
            element.innerHTML = temp;
    
            index++;
    
            if (index < htmlContent.length) {
                setTimeout(typeCharacter, tag ? 0 : speed);
            }
        }
    
        typeCharacter();
    }
    
    const textWithHtml = "<p><strong>Hello!</strong> This is a typing effect with <em>HTML</em> tags.</p>";
    
    typeText("typingArea", textWithHtml, 50);
    <div id="typingArea"></div>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search