Imagine we have a lengthy list of entries sorted alphabetically by name. Our goal is to create a navigation bar with letters from A-through-Z. These letters represent links, and when clicked the view jumps to the respective entry in the list.
Imagine we have a lengthy list of entries sorted alphabetically by name. Let’s say each list entry displays an application with additional information. We could of course scroll along the list to find the application we are looking for. However, it would be more user-friendly to provide a navigation bar where the user clicks on a letter to directly jump to the category which holds the application starting with this letter.
The Roadmap
You will see how you access DOM elements from JavaScript, and how you create and append new elements. Furthermore, we will see how we create anchors to jump to specific positions in our website. You will see how to use the arrow function notation from ECMAScript 6. We will use jQuery, HTML, CSS and ECMAScript 6. Finally, you will learn how to execute JavaScript automatically when the webpage is loaded.
- Initially, we create a div which holds the navigation bar.
- We create an array with letters from A-through-Z.
- For each letter, we append a single entry to our character bar.
- We want to make all letters clickable with an onclick event where we have list entries with a matching initial letter.
- The onclick-Event calls a function jumpToAnchor which will place the application with the matching anchor at the top of the view.
- We do not want letters to be clickable if there are no matching entries.
Building the letter array
First, we create an array our letters. It displays a list of characters from A to Z. We could also create a div for each letter and copy-pasting it 26 times or create an array with all letters. In my oppinion, the following method is a much nicer solution.
let createArrayAtoZ = _ => { return Array .apply(null, {length: 26}) .map((x, i) => String.fromCharCode(65 + i)); }
In the following, I am using let and const instead of var to declare variables. Furthermore, I am using ES6 arrow functions. If you are interested, here is another post on arrow function expressions.
Then, we use this function to fill an array with letters from A-through-Z:
let abcChars = createArrayAtoZ();
Creating the navigation bar
We define the navigation bar with the following div. We assign an id to it so that we can easily access it from JavaScript.
<div id="nav" class="CharacterContainer"></div>
We add some styling to it (you can make it more colourful if you wan’t).
.CharacterContainer { text-align: center; font-size: 1.4em; line-height: 3em; background-color: #abcdef; color: white; cursor: pointer; }
Adding letters to the navigation bar
We access our navigation bar with $(‘#nav’) . For each letter from our abcChars array, we append one div to the navigation. Each div shows the respective letter and gets assigned some CSS class annotations and an onclick event. We will need the data-filter attribute later-on to find the respective div for a certain letter.
let createNavigationList = _ => { const abcChars = createArrayAtoZ(); const navigationEntries = abcChars.reduce(createDivForCharElement, ''); $('#nav').append(navigationEntries); } let createDivForCharElement = (block, charToAdd) => { return block + "<div id='CharacterElement' class='CharacterElement Inactive' data-filter='" + charToAdd + "'>" + charToAdd + "</div>"; }
My CSS class simply colours the letters grey and shows the default cursor if we hover over the letter. Additionally, we can set this to cursor:pointer for our active links with another CSS declaration.
.Inactive { color: grey; cursor: default; }
Make active letters clickable
Afterwards, we remove the Inactive class from all letters for which we have at least one application whose name starts with this letter. In general, we remove a CSS class from an element by element.removeClass(‘classname’). Also, we add an onclick event to the element, which then calls our jumptoAnchor method. Thereby, we can implement it in a way that only letters are clickable for which we have at least one entry in the list.
let changeItemState = character => { const characterElement = $('#nav').find('.characterElement[data-filter="' + character + '"]'); $(characterElement).on('click', function() { jumptoAnchor(character); }); characterElement.removeClass('Inactive'); }
When clicking on a letter, we want to jump to the matching position in our list. We achieve this with the following method.
let jumptoAnchor = anchor => { window.location.href="#"+anchor; }
However, you could also use
let jumptoAnchor = anchor => { document.getElementById("#"+anchor).scrollIntoView(); }
Adding some website content
Finally, we create a component which holds our application list. I leave it to you, to populate this list with entries.
<div id="AppComponent"></div>
For our short example, i will just append a div for each letter to AppComponent.
let addListEntries = letter => { $('#AppComponent').append("<div class='AppElement' id='" + letter + "'>" + letter + "</div>"); }
To execute a JavaScript function automatically when the website is loaded, we use the following method.
<body onload="createNavigationList()">
Again, there is more than one way. You could also the jQuery method $(document).ready() for the same purpose.
Summary
You made it! Finally, we have a alphabetical list navigation with letters from A-to-Z. If we click on a letter, the view jumps to the position where we placed the matching anchor link on our website.
<!DOCTYPE html> <html> <head> <title>Alphetical List Navigation</title> <script language="javascript" type="text/javascript"> let createArrayAtoZ = _ => { return Array .apply(null, {length: 26}) .map((x, i) => String.fromCharCode(65 + i)); } let jumptoAnchor = anchor => { window.location.href = "#" + anchor; } let createNavigationList = _ => { const abcChars = createArrayAtoZ(); const navigationEntries = abcChars.reduce(createDivForCharElement, ''); $('#nav').append(navigationEntries); const lettersActive = ['A', 'C', 'G', 'M', 'X']; lettersActive.forEach(letter => { changeItemState(letter); addListEntries(letter); }); } let changeItemState = character => { const characterElement = $('#nav').find('.CharacterElement[data-filter="' + character + '"]'); $(characterElement).click(() => jumptoAnchor(character)); characterElement.removeClass('Inactive'); } let createDivForCharElement = (block, charToAdd) => { return block + "<div id='CharacterElement' class='CharacterElement Inactive' data-filter='" + charToAdd + "'>" + charToAdd + "</div>"; } let addListEntries = letter => { $('#AppComponent').append("<div class='AppElement' id='" + letter + "'>" + letter + "</div>"); } </script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script> <style> .CharacterContainer { text-align: center; font-size: 1.4em; line-height: 3em; background-color: #abcdef; color: white; cursor: pointer; } .CharacterElement { margin-right: 10px; } .Inactive { color: grey; cursor: default; } .AppElement { font-size: 2em; border: 1px solid #000; text-align: center; line-height: 14em; background-color: #ffffdd; } </style> </head> <body onload="createNavigationList()"> <h1>Navigation List Example</h1> <div id="nav" class="CharacterContainer"></div> <div id="AppComponent"></div> </body> </html>