1

We're using the below code as a typewriter effect for text. It worked fine previous and displayed the text set in the "_CONTENT" variable as text that then deleted and typed the next line but now we get "Uncaught TypeError: Cannot set property 'innerHTML' of null" in Console and no text appears.

Any ideas how we can fix this please?

<script>

// List of sentences
var _CONTENT = [ 
    "Domain Name", 
    "Website Hosting Plan", 
    "Virtual Private Server", 
    "WordPress Hosting Plan",
    "Web Design Package", 
    "Reseller Hosting Plan"
];

// Current sentence being processed
var _PART = 0;

// Character number of the current sentence being processed 
var _PART_INDEX = 0;

// Holds the handle returned from setInterval
var _INTERVAL_VAL;

// Element that holds the text
var _ELEMENT = document.querySelector("#text");

// Cursor element 
var _CURSOR = document.querySelector("#cursor");

// Implements typing effect
function Type() { 
    // Get substring with 1 characater added
    var text =  _CONTENT[_PART].substring(0, _PART_INDEX + 1);
    _ELEMENT.innerHTML = text;
    _PART_INDEX++;

    // If full sentence has been displayed then start to delete the sentence after some time
    if(text === _CONTENT[_PART]) {

        clearInterval(_INTERVAL_VAL);
        setTimeout(function() {
            _INTERVAL_VAL = setInterval(Delete, 50);
        }, 2000);
    }
}

// Implements deleting effect
function Delete() {
    // Get substring with 1 characater deleted
    var text =  _CONTENT[_PART].substring(0, _PART_INDEX - 1);
    _ELEMENT.innerHTML = text;
    _PART_INDEX--;


    // If sentence has been deleted then start to display the next sentence
    if(text === '') {
        clearInterval(_INTERVAL_VAL);

        // If current sentence was last then display the first one, else move to the next
        if(_PART == (_CONTENT.length - 1))
            _PART = 0;
        else
            _PART++;
        
        _PART_INDEX = 0;

        // Start to display the next sentence after some time
        setTimeout(function() {
            _CURSOR.style.display = 'inline-block';
            _INTERVAL_VAL = setInterval(Type, 100);
        }, 200);
    }
}

// Start the typing effect on load
_INTERVAL_VAL = setInterval(Type, 100);
</script>

<div id="container">
<div id="text"></div><div id="cursor"></div>
</div>

Thanks.

Reece
  • 13
  • 2
  • Does this answer your question? [Why does jQuery or a DOM method such as getElementById not find the element?](https://stackoverflow.com/questions/14028959/why-does-jquery-or-a-dom-method-such-as-getelementbyid-not-find-the-element) – VLAZ Jun 23 '20 at 12:28
  • 3
    Your script executes before the DOM is loaded in. You can move your script down to the bottom of the page (easiest solution), or otherwise you have to make sure it executes after the page is loaded. – VLAZ Jun 23 '20 at 12:29
  • Got it, moved to bottom of page and it works. Thanks all! – Reece Jun 23 '20 at 12:32

2 Answers2

0

add you code between document.addEventListener('DOMContentLoaded', function(){}) for execute javascript code after page load

document.addEventListener('DOMContentLoaded', function(){

// List of sentences
var _CONTENT = [ 
    "Domain Name", 
    "Website Hosting Plan", 
    "Virtual Private Server", 
    "WordPress Hosting Plan",
    "Web Design Package", 
    "Reseller Hosting Plan"
];

// Current sentence being processed
var _PART = 0;

// Character number of the current sentence being processed 
var _PART_INDEX = 0;

// Holds the handle returned from setInterval
var _INTERVAL_VAL;

// Element that holds the text
var _ELEMENT = document.querySelector("#text");

// Cursor element 
var _CURSOR = document.querySelector("#cursor");

// Implements typing effect
function Type() { 
    // Get substring with 1 characater added
    var text =  _CONTENT[_PART].substring(0, _PART_INDEX + 1);
    _ELEMENT.innerHTML = text;
    _PART_INDEX++;

    // If full sentence has been displayed then start to delete the sentence after some time
    if(text === _CONTENT[_PART]) {

        clearInterval(_INTERVAL_VAL);
        setTimeout(function() {
            _INTERVAL_VAL = setInterval(Delete, 50);
        }, 2000);
    }
}

// Implements deleting effect
function Delete() {
    // Get substring with 1 characater deleted
    var text =  _CONTENT[_PART].substring(0, _PART_INDEX - 1);
    _ELEMENT.innerHTML = text;
    _PART_INDEX--;


    // If sentence has been deleted then start to display the next sentence
    if(text === '') {
        clearInterval(_INTERVAL_VAL);

        // If current sentence was last then display the first one, else move to the next
        if(_PART == (_CONTENT.length - 1))
            _PART = 0;
        else
            _PART++;
        
        _PART_INDEX = 0;

        // Start to display the next sentence after some time
        setTimeout(function() {
            _CURSOR.style.display = 'inline-block';
            _INTERVAL_VAL = setInterval(Type, 100);
        }, 200);
    }
}

// Start the typing effect on load
_INTERVAL_VAL = setInterval(Type, 100);
})
<div id="container">
<div id="text"></div><div id="cursor"></div>
</div>
Hitesh Tripathi
  • 854
  • 10
  • 20
0

Here's a quick fix.

Fix Description:

  1. I have moved the global variables _ELEMENT and _CURSOR to the functions where they were actually being used.
  2. I have accessed both DOM Elements by using Vanilla JS document.getElementByID Is this the solution you're looking for?

Here's the code, hope it helps! :)

<script>
  // List of sentences
  var _CONTENT = [
    "Domain Name",
    "Website Hosting Plan",
    "Virtual Private Server",
    "WordPress Hosting Plan",
    "Web Design Package",
    "Reseller Hosting Plan",
  ];

  // Current sentence being processed
  var _PART = 0;

  // Character number of the current sentence being processed
  var _PART_INDEX = 0;

  // Holds the handle returned from setInterval
  var _INTERVAL_VAL;

  // Implements typing effect
  function Type() {
    // Element that holds the text
    var _ELEMENT = document.getElementById("text");

    // Get substring with 1 characater added
    var text = _CONTENT[_PART].substring(0, _PART_INDEX + 1);
    _ELEMENT.innerHTML = text;
    _PART_INDEX++;

    // If full sentence has been displayed then start to delete the sentence after some time
    if (text === _CONTENT[_PART]) {
      clearInterval(_INTERVAL_VAL);
      setTimeout(function () {
        _INTERVAL_VAL = setInterval(Delete, 50);
      }, 2000);
    }
  }

  // Implements deleting effect
  function Delete() {
    // Element that holds the text
    var _ELEMENT = document.getElementById("text");
    // Cursor element
    var _CURSOR = document.getElementById("cursor");

    // Get substring with 1 characater deleted
    var text = _CONTENT[_PART].substring(0, _PART_INDEX - 1);
    _ELEMENT.innerHTML = text;
    _PART_INDEX--;

    // If sentence has been deleted then start to display the next sentence
    if (text === "") {
      clearInterval(_INTERVAL_VAL);

      // If current sentence was last then display the first one, else move to the next
      if (_PART == _CONTENT.length - 1) _PART = 0;
      else _PART++;

      _PART_INDEX = 0;

      // Start to display the next sentence after some time
      setTimeout(function () {
        _CURSOR.style.display = "inline-block";
        _INTERVAL_VAL = setInterval(Type, 100);
      }, 200);
    }
  }

  // Start the typing effect on load
  _INTERVAL_VAL = setInterval(Type, 100);
</script>

<div id="container">
  <div id="text"></div>
  <div id="cursor"></div>
</div>