Zou Ales
Zou Ales

Reputation: 15

associate a number to each link html using javascript

I want to put a number to each link selected from the DOM, using js.
For that, i have made a function using a map method in order to associate all the links with a key

function mapLinks(){
    var links = document.querySelectorAll('a')
    var listLinks = new Array(links.length); 
    for(i = 0; i <links.length; i++){
        listLinks[i] = i; 
    }
    var mapLink = new Map([[listLinks, links]]) 
    return (mapLink)
}
var map = mapLinks(); 
now, what i want to do is to show the numbers (or the keys) on the web page, something like this:

the link with the key associate to it

I tried this code but it's not the best solution because in some case it distorts the structure of the web page

function linksNumber(){ 
    for(var [key, value] of map){
        for(var i = 0, j = 0; i < key.length, j < value.length; i++, j++){
            value[j].textContent = value[j].textContent + key[i]
        }
    }
}

Upvotes: 0

Views: 138

Answers (3)

dave
dave

Reputation: 64657

You could use the css ::before or ::after selector with content: attr(data-n) to keep the page structure basically the same.

function mapLinks(){
    var links = document.querySelectorAll('a')
    var listLinks = new Array(links.length); 
    for(i = 0; i <links.length; i++){
        links[i].setAttribute('data-n', i)
    }
    var mapLink = new Map([[listLinks, links]]) 
    return (mapLink)
}

mapLinks()
a::after {
  content: attr(data-n);
  width: 10px;
  height: 10px;
  background: yellow;
  display: inline;
  font-size: 10px;
  position: relative;
  top: -6px;
}
<a href="test">Test</a>
<a href="hi">Hi</a>

If you can't add a css file, you can use JS to add an inline <style> element:

var sheet = document.createElement('style');
sheet.innerHTML = `
  a::after {
    content: attr(data-n);
    width: 10px;
    height: 10px;
    background: yellow;
    display: inline;
    font-size: 10px;
    position: relative;
    top: -6px;
  }
`
(document.head || document.getElementsByTagName('head')[0]).appendChild(sheet);

Or, with no javascript except creating the stylesheet:

var sheet = document.createElement('style');
sheet.innerHTML = `
      body { counter-reset: number -1; }
      a::after {
        content: counter(number);
        counter-increment: number;
        width: 10px;
        height: 10px;
        background: yellow;
        display: inline;
        font-size: 10px;
        position: relative;
        top: -6px;
      }
    `;
(document.head || document.getElementsByTagName('head')[0]).appendChild(sheet);
<a href="hello">Hello</a>
<a href="world">World</a>

Upvotes: 2

Careful with this:

var links = document.querySelectorAll('a')

If you have more <a /> in the future, it will also take them. I recommend adding a class to the elements (<a/>) that you want to mark.

Lets say we add the class "anchorTooltip" to all that you need.

var links = document.querySelectorAll('a.anchorTooltip')

This will take all anchors with the class "anchorTooltip"

Now you can do:

Array.from(links).map((link, index)=>link.setAttribute("title", index))

querySelectorAll() returns a static (not live) NodeList representing a list of the document's elements that match the specified group of selectors. Use Array.from() to convert NodeList to array then iterate through Array.map().

Tests:

var links = document.querySelectorAll('a.anchorTooltip')

Array.from(links).map((link, index)=>link.setAttribute("title", index))
  <a class="anchorTooltip">test 1</a><br >
  <a class="anchorTooltip">test 2</a><br >
  <a class="anchorTooltip">test 3</a>

Without the Array.from():

document.querySelectorAll('a.anchorTooltip').forEach((link, index)=>link.setAttribute("title", index+40))

Test:

document.querySelectorAll('a.anchorTooltip').forEach((link, index)=>link.setAttribute("title", index+10))
  <a class="anchorTooltip">test 1</a><br >
  <a class="anchorTooltip">test 2</a><br >
  <a class="anchorTooltip">test 3</a>

Upvotes: 0

Scott Marcus
Scott Marcus

Reputation: 65796

The use of .map() is redundant here. .querySelectorAll() returns an array-like object which you can iterate using .forEach() and get the index from.

All you really need to do in the loop is just create a new element that will hold the "badge" value. Most of the work is actually in the CSS, not the JavaScript.

See inline comments:

// Just loop over the collection returned by .querySelectorAll()
// with .forEach, which has a callback funciton that can provide
// you with the index.
document.querySelectorAll('a').forEach(function(link, index){
  let badge = document.createElement("span");
  badge.classList.add("badge");
  // Just use the index of the item you are iterating over
  badge.textContent = index + 1;
  link.appendChild(badge);
});
/* Giving the new elements this class
   will allow them to "float" above the
   link element they correspond to. You 
   can tweak the top and left values for
   better positioning. */
.badge {
  position:absolute; /* puts in own layer */
  display:inline-block; /* let's us style as a block */
  border:1px solid #808080;
  padding:2px;
  background: #ff7;
  border-radius:3px;
  font-size:.7em;
  top:-.8em;  /* Moves the element relative to the parent <a> */
  left:-.8em; /* Moves the element relative to the parent <a> */
}

/* Basic styling for the links */
a {
  position:relative; /* doesn't move them, but puts them in their own layer */
  text-decoration:none; /* no underline */
  display:block;
  margin:1em;
  height:50px;
  width:50px;
  border:#e0e0e0;
  background-color:#99f;
  padding:5px;
}
<a href="#one">One</a>  
<a href="#two">Two</a>  
<a href="#three">Three</a>

Upvotes: 0

Related Questions