Create a bookmark system on an HTML page by utilizing the existing heading tags and implementing Javascript

Looking to implement a bookmark system using the headings within my HTML document, based on heading hierarchy. Unfortunately, my attempts have not been successful so far. https://i.stack.imgur.com/CdXjw.png

I envision my bookmarks looking something like this with corresponding links:

https://i.stack.imgur.com/7vBUb.png

Here's the snippet of my HTML code:

    <style>
    #bookMark {
      border: 1px solid black;
      margin-bottom: 10px;
    }
    </style>

    <div id="bookMark">
    <b>Book Mark: </b>
    </div>

    <h1> This is 1st main Heading1 </h1>
      <h2> This is h2 under h1 </h2>
          <h3> This is h3 under h1 and h2 </h3>

      <h2> This is h2 </h2>
         <h3> This is h3</h3> 

    <h1> This is 2nd main Heading1 </h1>
      <h2> This is h2 under h1 </h2> 

    <script src="dom.js"> </script>

This is how my script code looks:

    var heading1 = document.getElementsByTagName('h1');
    var heading2 = document.getElementsByTagName('h2');

    for(var i = 0; i < heading1.length; i++){
     var para = document.createElement("p");
     para.innerHTML = document.getElementsByTagName('h1')[i].innerHTML;
     document.getElementById("bookMark").appendChild(para);

      for(var j = 0; j < heading2 .length; j++){
        var para = document.createElement("p");
        para.innerHTML = "&nbsp;"+ document.getElementsByTagName('h2')[j].innerHTML;
        document.getElementById("bookMark").appendChild(para);
      }

    }

The current output does not maintain the hierarchy correctly: https://i.stack.imgur.com/Zc1Gf.png

Answer №1

To efficiently create a dynamic linked contents list for your document, you can start by mapping out the headings:

const allHeadings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');

Next, iterate through the map to generate the contents list:

Example in Action:

// GRAB ALL HEADINGS
const allHeadings = document.querySelectorAll('h1, h2, h3, h4, h5, h6');

// CREATE MAP OF HEADINGS
let headingsMap = []

allHeadings.forEach((heading) => {
  
  headingLevel = heading.nodeName.replace('H', '');
  headingsMap.push(headingLevel);
});

// BUILD CONTENTS LIST
let contentsList = '';
contentsList += '<div class="contents-list">';
contentsList += '<ul>';

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

  allHeadings[i].id = '10' + i;

  contentsList += '<li>';
  contentsList += '<a href="#10' + i;
  contentsList += '">' + allHeadings[i].textContent + '</a>';
  
  switch (true) {
  
    case (i === (headingsMap.length - 1)) :
      for (j = 0; j < headingsMap[i]; j++) {
        contentsList += '</li></ul>';
      }
    break;
  
    case (headingsMap[(i + 1)] > headingsMap[i]) :
      contentsList += '<ul>';
      break;
      
    case (headingsMap[(i + 1)] < headingsMap[i]) :
      let difference = (headingsMap[i] - headingsMap[(i + 1)]);
      for (j = 0; j < difference; j++) {
        contentsList += '</li></ul>';
      }
      break;
  }
}

contentsList += '</div>';

//  ADD CONTENTS LIST TO PAGE
let contentsListTemplate = document.createElement('template');
contentsListTemplate.innerHTML = contentsList;
document.body.insertBefore(contentsListTemplate.content, document.body.querySelector('*'));
.contents-list {
color: rgb(127, 0, 0);
font-size: 14px;
line-height: 28px;
text-transform: uppercase;
background-color: rgb(255, 255, 191);
border: 1px solid rgb(127, 0, 0);
}

.contents-list a {
  text-decoration: none;
}

.contents-list a:hover {
  text-decoration: underline;
}
<h1> This is 1st main Heading1 </h1>
<h2> This is h2 under h1 </h2>
<h3> This is h3 under h1 and h2 </h3>

<h2> This is h2 </h2>
<h3> This is h3</h3> 

<h1> This is 2nd main Heading1 </h1>
<h2> This is h2 under h1 </h2>
<h2> This is another h2 under h1 </h2>
<h3> This is h3 </h3>
<h4> This is h4 </h4>
<h2> This is h2 </h2>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Combining MySQL tables for main menu and subcategories

Working on a new project and seeking help with a certain situation. I have a SQL database featuring two tables: menu and submenu. The table structure is as follows: Menu: id | title | order Submenu: id | title | parentId Currently, I'm using two si ...

What sets $emit and $dispatch apart in Vue.js?

Vue 2.0 has deprecated the use of $dispatch and $broadcast. I have noticed that $dispatch is similar to $emit. What are the key differences between them? Can we safely replace $dispatch with $emit during migration? ...

problem arises when I attempt to use the code individually, as well as when I incorporate it into my existing

<!doctype html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width"> <title>App Title</title> <!-- Framework's CSS Fil ...

Ways to guarantee that a task is completed only after another task has finished

Attempting to avoid duplication as I find myself in the midst of a significant issue. Currently working on a JavaScript codebase consisting of thousands of lines. The specific problem at hand involves: methodA being invoked from within its own class. met ...

The children's className attribute can impact the parent element

As I work on creating a card object, I envision it with the className .card that is styled in CSS as follows: .card img{position:absolute; width:150px; height:160px} I want only the images inside my div to overlap each other while not affecting the divs ...

Strategies for redirecting search queries when adding a new path

Issue I am facing a challenge with pushing a new path to the URI while maintaining existing search queries. For example: Current URL: https://example.com/foo?bar=123&foobar=123 When I use history.push('newPath'), I end up with https://exa ...

Tips for designing a responsive element with a repeating border

Desired Design: Create a dotted border on top of each li-element Adjust the size of the dots and spacing between them using CSS or image/SVG manipulation Make the width of the ul responsive for varying border widths Ensure that dots are not partially dis ...

WARNING: Alert raised due to the discovery of two offspring sharing identical keys, `${item}-${index}`

I have been facing the issue of receiving an error message 'ERROR Warning: Encountered two children with the same key, ${item}-${index}' and I am not sure what is causing it. Can someone please guide me on how to resolve this problem? Any help w ...

"Optimizing Background Images with IE 8 Stretch Cover in Bootstrap

Page Broken I've searched all over Stack Overflow for a solution to resolve this background image issue. I'm using Bootstrap for the boxes and removed any margins. The problem arises when setting the background as cover; in IE8, it doesn't ...

Managing key presses with functions in VueJs

Within my component, I am utilizing VueStrap's modal in the following manner: <template> <modal-window v-model="show" v-on:keyup="keyHandler($event)" @ok="submit()" @cancel="cancel()" @closed=" ...

I'm looking to create a JavaScript function that will extract each element from a div and then apply a corresponding CSS block to activate it

My goal was to create this function using Flask, but it seems that only JavaScript is capable of achieving it. This is my first attempt at coding it. Here's the code snippet: const navSlide2 = () => { const burger = document.querySelector(&apos ...

Find the nearest element with a specific class using jQuery

I am currently using jQuery version 1.12.4 for the purpose of retrieving the value from the closest element with a specific class selector. Unfortunately, I am encountering difficulty in selecting the closest element as desired. $(function() { $("[cla ...

@page Css not displaying properly on the Mozilla Firefox browser

In order to fulfill my requirement, I need to ensure that there is a consistent 10cm margin on all pages when printing. Printing on my web page involves utilizing the window.print() function. However, due to the dynamic nature of the content, the number o ...

Include @url.action with a parameter on a cell within a table using AJAX

I am new to this and I want to add an action method on a table cell. The challenge is that the table is generated using JavaScript (AJAX). Here's the code: $.ajax({ url: "GetData", contentType: "application/json; charset=utf-8 ...

Combining a form and table on a single webpage, I am curious how to utilize the form to update the table effectively using Express and Node.js

Seeking guidance in website development as I face a particular challenge. I aim to create a dynamic search page for a website. The form should allow users to select a location or category, with the same page updating with relevant results. Despite succes ...

jQuery tipsy not triggering click event in Internet Explorer

Hey there! I've been using the jquery tipsy plugin for displaying colour names above colour swatch images. One thing I'm trying to do is trigger a checkbox to be checked/unchecked when a user clicks on the image. $(document).ready(function(){ ...

Reading JSON documents in JavaScript through multiline strings

Having a JSON document with multiline string data is causing issues for me. I have attempted multiple options, but none of them have successfully solved the problem. For example: [ { "someString" : "A rather long string of English text, an error m ...

A script page in Wordpress generates a numerical value in the URL

I created a script named search.php which utilizes various search engines APIs to display search results. From this file, I have developed a Page template and incorporated the simplePagination plugin The issue arises when I click on a page within the pag ...

Animate the service item with jQuery using slide toggle effect

Currently, I am working on a jQuery slide toggle functionality that involves clicking an item in one ul to toggle down the corresponding item in another ul. However, I am encountering difficulties in linking the click event to the correct id and toggling t ...

I'm having trouble displaying the Facebook page plugin on my HTML website

I encountered a minor issue. I attempted to add the "Facebook page plugin" on a test website. I copied the code from the official Facebook plugin page: <!-- 1. Include the JavaScript SDK on your page once, ideally right after the opening <body> t ...