title: JavaScript - Highlight an element on Hover
body: <p>I'm trying to write a JavaScript which will highlight an element in the DOM when the user hovers over it. This is supposed to be a cross-browser external plug-in. Ideally, i'm trying to mimic the behaviour of the browser inspector tools.</p>
  
  <p>I can't say I have no success, but I am stuck with two options, both with its own pros and cons.</p>
  
  <p><strong>Approach 1</strong></p>
  
  <p>I handle the <code>mouseover</code> event and simply add a border to the target element. When I hover on another element, I just reset the existing highlighted elements. The code for the same is below:</p>
  
  <pre><code>function addHighlight(target) {
      target.classList.add('highlighted');
  }
  
  function removeHighlight(target) {
      target.classList.remove('highlighted');
  }
  
  window.addEventListener('mouseover',function(e) {
      addHighlight(e.target);
  });
  
  window.addEventListener('mouseout',function(e) {
      removeHighlight(e.target);
  });
  </code></pre>
  
  <p><a href="http://jsbin.com/dakisad/1/edit?html,css,js,output" rel="noreferrer" title="Working example here">Working Example here</a></p>
  
  <p><strong>Pros with this Approach</strong></p>
  
  <p>It works absolutely fine.</p>
  
  <p><strong>Cons with this approach</strong></p>
  
  <p>As I'm adding a border to existing DOM elements, it sort of re-arranges the elements on the page, and you can observe a slight shuffling effect of the elements. Doesn't look great.</p>
  
  <p><strong>Approach 2</strong></p>
  
  <p>I wanted the highlighting to be seamless. That is, preserving the look of the page and simply overlaying a highlight mask on top of the element.</p>
  
  <p>TO do this, in the <code>mouseover</code> event, I dynamically created a mask element, whose <code>position</code> is set to <code>absolute</code> and its co-ordinates set to the exact co-ordinates of the target element. Below is my code:</p>
  
  <pre><code>window.addEventListener('mouseover',function(e) {
      applyMask(e.target);
  });
  
  function applyMask(target) {
      if(document.getElementsByClassName('highlight-wrap').length &gt; 0) {
          resizeMask(target);
      }else{
          createMask(target);
      }
  }
  
  function resizeMask(target) {
      var rect = target.getBoundingClientRect();
      var hObj = document.getElementsByClassName('highlight-wrap')[0];
      hObj.style.top=rect.top+"px";
      hObj.style.width=rect.width+"px";
      hObj.style.height=rect.height+"px";
      hObj.style.left=rect.left+"px";
     // hObj.style.WebkitTransition='top 0.2s';
  }
  
  function createMask(target) {
      var rect = target.getBoundingClientRect();
      var hObj = document.createElement("div");
      hObj.className = 'highlight-wrap';
      hObj.style.position='absolute';
      hObj.style.top=rect.top+"px";
      hObj.style.width=rect.width+"px";
      hObj.style.height=rect.height+"px";
      hObj.style.left=rect.left+"px";
      hObj.style.backgroundColor = '#205081';
      hObj.style.opacity='0.5';
      hObj.style.cursor='default';
      //hObj.style.WebkitTransition='top 0.2s';
      document.body.appendChild(hObj);
  }
  
  function clearMasks() {
      var hwrappersLength = document.getElementsByClassName("highlight-wrap").length;
      var hwrappers = document.getElementsByClassName("highlight-wrap");
      if(hwrappersLength &gt; 0) {
          for(var i=0; i&lt;hwrappersLength; i++) {
              console.log("Removing existing wrap");
              hwrappers[i].remove();
          }
      }
  }
  </code></pre>
  
  <p><a href="http://jsbin.com/rewahag/edit?html,css,js,output" rel="noreferrer">Working example here</a></p>
  
  <p><strong>Pros with this approach</strong>
  I feel this is more elegant, and doesn't disturb the page, just overlays a mask on top of elements.</p>
  
  <p><strong>Cons</strong></p>
  
  <p>When the user hovers over the top most container (<code>div</code>), it creates a mask for that element. After that, all the subsequent <code>mouseover</code> events are ignored, as they are registered on the <strong><em>mask</em></strong>, and not on the actual underlying elements. 
  I need to figure out a way around this.</p>
  
  <p>Can anyone help me better Approach 2? Or suggest another approach?</p>
  
  <p>Thanks,
  Sriram</p>