How to show HTML comments with JavaScript

Habdul Hazeez - Feb 5 '20 - - Dev Community

Comments are recommended practice in programming and software development in general, they can state a reason why a coding decision was taken or explain what needs to be done to improve the code you are working on.

HTML might not be considered as a programming language but it sure has comments. In HTML comments are mostly used to indicate segments of code like the header, sidebar or custom components.

Comments don't show up in your HTML (as in any language that has comments) but, you can display them on the page for debugging purposes.

Let's find out how we can actually pull this off.


HTML tags (including HTML comments) are represented as nodes in the DOM tree and each node has nodeType property which is a numerical value that identifies the type of node.

In order to get the numerical value, the format is node.nodeType where node is an HTML element. The numerical value is a value greater than 1.

The table below lists the possible return values.

Value Meaning
1 ELEMENT_NODE
2 ATTRIBUTE_NODE
3 TEXT_NODE
4 CDATA_SECTION_NODE
5 ENTITY_REFERENCE_NODE
6 ENTITY_NODE
7 PROCESSING_INSTRUCTION_NODE
8 COMMENT_NODE
9 DOCUMENT_NODE
10 DOCUMENT_TYPE_NODE
11 DOCUMENT_FRAGMENT_NODE
12 NOTATION_NODE

From the table above its evident that HTML comments have a numerical value of 8, this is the crucial requirement to actually get the comment and then show it on any part of the page.

The other requirement is the data value. The data as the name implies is the content of the node.

node data in JavaScript
A sample node data

Here is the HTML code:

<noscript style="color: red; text-align: center; text-decoration: underline;">
        <p>The core functionality of this app requires
JavaScript to work. Please enable JavaScript</p>
    </noscript>

    <div class="container">

        <!-- Information -->
        <div class="show" id="comments_section">

            <button class="btn remove-paragraph" id="remove-paragraph" title="Close"></button>

            <p id="number_of_comments"></p>

            <button id ="view_comments" class="btn success">Yes</button>
            <button id ="dont_view_comments" class="btn">No</button>

            <button class="btn success" id="show_comments">Show Comments</button>
            <button class="btn" id="hide_comments">Hide Comments</button>

            <div id="commentsInCode">
                <h2 style="display: none;" id="comment_subheading">Comments in your code</h2>
            </div>
        </div>

        <!-- A dummy text -->
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
        tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
        quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
        consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
        cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
        proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

    </div>

    <script>
        // JS code here
    </script>
Enter fullscreen mode Exit fullscreen mode

And the CSS:

p {
    font-weight: bold;
    line-height: 1.618;
    font: 18px Georgia;
}

pre {
    font-weight: bold;
    text-decoration: underline;
    font-family: Georgia;
}

.container {
    width: 70%;
    margin: 0 auto;
}

.form__label {
    display: block;
    margin-bottom: 0.6em;
}

.btn {
    border: none;
    padding: 1.2em;
    background-color: #cd5b45;
    color: #ffffff;
}

.btn.success {
    background-color: green;
}

.btn:hover {
    cursor: pointer;
}

.hidden {
    display: none;
}

.show {
   display: block;
}

#comments_section {
    border: 2px solid #1560bd;
    box-shadow: -3px 3px #1560bd;
    padding: 1.2em;
    position: relative;
}

.remove-paragraph {
    padding: 0.8em;
    position: absolute;
    top: 0em;
    right: 0em;
    border: 50%;
}

.remove-paragraph:hover {
    cursor: pointer;
    font-weight: bold;
}

.remove-paragraph::before {
    content: 'x';
}

#commentsInCode {
    background-color: #cccccc;
}

#commentsInCode pre {
    padding: 1em;
}

#commentsInCode h2 {
    text-align: center;
}

.hidden {
    display: none;
}

.show {
   display: block;
}
Enter fullscreen mode Exit fullscreen mode

Taking a look at the HTML, you'll notice we use id's. The first thing we'll do in our script is to create variables. Among the variables is an accumulator that'll keep track of the comments found in the code segment.

/**
  * querySelector. jQuery style
  * Inspiration from Todd Motto
  * https://ultimatecourses.com/blog/attaching-event-handlers-to-dynamically-created-javascript-elements
  */

let $ = function (selector) {
    return document.querySelector(selector);
};

// variables
let container = $('.container');
let comments_section = $('#comments_section');
let dont_view_comments = $('#dont_view_comments');
let view_comments = $('#view_comments');
let number_of_comments = $('#number_of_comments');
let hide_comments = $('#hide_comments');
let show_comments = $('#show_comments');
let remove_paragraph = $('#remove-paragraph');
let commentsInCode = $('#commentsInCode');
let comment_subheading = $('#comment_subheading');
let accumulator = 0;
Enter fullscreen mode Exit fullscreen mode

We need to know the number of comments, therefore, we loop through the childNodes and when we encounter a nodeType with a value of 8 we increment the accumulator.

for (let i = 0; i < container.childNodes.length; i++) {

    // save the childnode in a variable for
    // easy referencing
    let e = container.childNodes[i];

    if (e.nodeType === 8) { // we found a comment!

        // increment the accumulator
        accumulator += 1;

        // show the comments section
        comments_section.style.display = "block";

    }

}
Enter fullscreen mode Exit fullscreen mode

We gladly tell the user the number of comments.

// Tell the user the number of comments found
number_of_comments.innerHTML =
"<p>We found " + accumulator + " comment(s) in the selected
section of code, will you like to see them?";
Enter fullscreen mode Exit fullscreen mode

On initial page load we hide three HTML buttons:

  • show_comments
  • hide_comments
  • remove_paragraph
/**
  * On initial page load, hide the "show",
  * hide" remove paragraph buttons
  */
show_comments.classList.toggle('hidden');
hide_comments.classList.toggle('hidden')
remove_paragraph.classList.toggle('hidden');
Enter fullscreen mode Exit fullscreen mode

We attach an event listener to the view comments button. Inside the event listener we loop through the childNodes to find the comments then we create div and pre tag that will contain the data. The pre tag is then attached to the div tag which in turn is attached to the page via the appendChild() method and the comment subheading is shown.

The view_comments and dont_view_comments are hidden then we show the hide_comments and remove_paragraph buttons.

view_comments.addEventListener('click', function() {

    // loop through the childnodes
    for (let i = 0; i < container.childNodes.length; i++) {

        // save the childNodes in a variable
        // for easy referencing 
        let e = container.childNodes[i];

        if (e.nodeType === 8) { // we found a comment

            /**
              * create a text node with the "data", 
              * after which we create a div and pre
              * elements.
              *
              * The data is attached to the pre tag
              * and the pre tag to the created div
              * which in turn is attached to a section
              * on the page
              */
            let text = document.createTextNode(e.data);
            let div = document.createElement('div');
            let pre = document.createElement('pre');
            pre.appendChild(text);
            div.appendChild(pre);
            commentsInCode.appendChild(div);
            comment_subheading.style.display = "block";
        }
    }

    /**
      * We are using four buttons to make things simple
      * after the user click yes to view the comments
      * we hide the "yes" and "no"buttons. Afterward,
      * we show the "hide" and "remove" paragraph
      * buttons
      */
    view_comments.classList.toggle("hidden");
    dont_view_comments.classList.toggle("hidden");
    hide_comments.classList.toggle("show");
    remove_paragraph.classList.toggle("show");
});
Enter fullscreen mode Exit fullscreen mode

If the user prefers not to view the comments we close the comments section entirely:

// a button to close the comments section on initial
// page load
dont_view_comments.addEventListener('click', function() {
    comments_section.style.display = 'none'; 
});
Enter fullscreen mode Exit fullscreen mode

Once the user decides to see the comments, we toggle two buttons on and off when clicked by the user — the hide comments and show comments.

/**
  * Add an event listener to the hide, show,
  * dont view comments and view comments buttons
  */ 
hide_comments.addEventListener("click", function() {
    commentsInCode.style.display = "none";
    hide_comments.style.display = "none";
    show_comments.style.display = "block";
});

show_comments.addEventListener("click", function() {
    hide_comments.style.display = "block";
    commentsInCode.style.display = "block";
    show_comments.style.display = "none";
});
Enter fullscreen mode Exit fullscreen mode

Finally, we provide an alternative for the user to close the entire comments section.

// a button to close the entire comments section
remove_paragraph.addEventListener("click", function()  {
    comments_section.style.display = "none";
});
Enter fullscreen mode Exit fullscreen mode

The image below is an example of this code in action:

An image with text
An example showing two comments was found by the script

Limitations

This approach does not take comments in a child element into consideration. For example:

<div>
  <!-- comment -->
   <div class="child element">
      <!-- This approach won't see this comment -->
   </div>
</div>
Enter fullscreen mode Exit fullscreen mode

Conclusion

This is useful for debugging purposes. The code is hacky but it works. It's up to you to improve the code or better still, turn it into a function that accepts a selector as an argument.

Reference

Have fun!

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .