Get position of characters in textnode using Range

In this example below you will see how to do a Get position of characters in textnode using Range with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by rosefalk, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright rosefalk ©
  • HTML
  • CSS
  • JavaScript
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>Get position of characters in textnode using Range</title>
  
  
  
      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>

  <div id="application">
  <h1 id="after-text">Overlay without wrapping</h1>
  <div id="characters-wrapper">
    <div id="characters">Some characters1!</div>
  </div>
  <button id="chars">Characters</button><button id="words">Words</button>
  <p id="description">*does not refresh automatically on resize :)</p>
</div>
  
  

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




</body>

</html>

/*Downloaded from https://www.codeseek.co/rosefalk/get-position-of-characters-in-textnode-using-range-yzgEEv */
/* if you want the CSS you can safely ignore everything from here */
html,body {
  height: 100%;
  background: #b33;
  color: #333;
}

body {
  display: flex;
  justify-content: center;
  align-items: center;
}

#application {
  text-align: center;
  padding: 25px;
  background: #fff;
  box-shadow: 0 0 20px #000;
  border-radius: 3px;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  
  grid-template-rows: auto;
  
  grid-template-areas: 
    "after-text after-text"
    "characters characters"
    "button-chars button-words"
    "description description";
}

#characters-wrapper {
  margin: 25px;
  font-size: 24px;
  grid-area: characters;
}

#characters {  
  position: relative;
}

button {
  margin: 5px;
  padding: 5px;
  text-transform: uppercase;
  font-size: 12px;
  font-weight: bold;
  background: #ececec;
  border: 1px solid #bbb;
}

#chars {
  grid-area: button-chars;  
}
#words {
  grid-area: button-words;  
}

#after-text {
  grid-area: after-text;
  font-size: 20px;
  text-transform: uppercase;
}

#description {
  grid-area: description;
  font-style: italic;
}
/*to here*/

.marker {
  position: absolute;
  box-sizing: border-box;
  height: 4px;
  border: 1px solid #abc;
}

/*Downloaded from https://www.codeseek.co/rosefalk/get-position-of-characters-in-textnode-using-range-yzgEEv */
function getCharacterPositions(target,word) {
  var range = document.createRange(),
      parentEl = document.getElementById(target).childNodes[0],
      chars = parentEl.textContent.split( (word)?' ':'' ),
      arrayPositions = new Array();

  var start = 0,
      end = 0;
  
  for (var i = 0; i < chars.length; i++) {
    var char = chars[i],
        start = (word)?start:i,
        end = (word)?(start+char.length):i+1;
    range.setStart(parentEl, start);
    range.setEnd(parentEl, end);
    arrayPositions.push(range.getClientRects());
    
    if(word) {
      start = end+1;
    }
  }
  
  return arrayPositions;
}

function visualize(arrayOfPositions) {
  //remove old markers
  var elements = document.getElementsByClassName('marker');
  while(elements.length > 0){
    elements[0].parentNode.removeChild(elements[0]);
  }      
  
  //make new markers
  for (var i = 0; i < arrayOfPositions.length; i++) {
    var data = arrayOfPositions[i];
    
    var marker = document.createElement('div')
        marker.className = 'marker';
        marker.style.width = data[0].width+'px';
        marker.style.height = data[0].height+'px';
        marker.style.left = data[0].left+'px';
        marker.style.top = data[0].top+'px';
    
    document.getElementById('characters-wrapper').appendChild(marker);
  }
}

document.getElementById("chars").addEventListener("click", function( event ) {
  visualize(getCharacterPositions("characters"))
}, false);

document.getElementById("words").addEventListener("click", function( event ) {
  visualize(getCharacterPositions("characters",true))
}, false);

Comments