Ranges and Character Clicked

by blueseal

HTML

<div class="parent">
    <div class="child" style="white-space: pre-wrap;">Bacon     ipsum dolor amet meatball bresaola t-bone tri-tip brisket. Jowl pig picanha cupim landjaeger, frankfurter spare ribs chicken. Porchetta jowl pancetta drumstick shankle cow spare ribs jerky tail kevin biltong capicola brisket venison bresaola. Flank sirloin jowl andouille meatball venison salami ground round rump boudin turkey capicola t-bone. Sirloin filet mignon tenderloin beef, biltong doner bresaola brisket shoulder pork loin shankle turducken shank cow. Bacon ball tip sirloin ham.</div>
  
</div>  <div id="info">Click somewhere in the paragraph above</div>

JavaScript

function isClickInRects(rects,x,y) {
        for (var i = 0; i < rects.length; ++i) {
            var r = rects[i]
            if (r.left<x && r.right>x && r.top<y && r.bottom>y) {            
                return r;
            }
        }
        return false;
    }

function findBetween(elem,x,y,start,stop){
	console.log(start,stop)
	if(start==stop || start == stop-1){
  	return start
  }
  var half = Math.round((stop-start)/2)+start
 	var range = document.createRange();
  range.setStart(elem, start);
  range.setEnd(elem, half);
   // not getBoundingClientRect as word could wrap
  var rects = range.getClientRects();
  if(isClickInRects(rects,x,y)){
  	// click is in first half
  	return findBetween(elem,x,y,start,half)
  } else {
  return findBetween(elem,x,y,half,stop)
  }
}


function onClick(e) {
    var info = document.getElementById('info');
    info.innerHTML = 'Nothing Clicked';
    
    var elem = e.target.childNodes[0]    
    if (elem.nodeName !== '#text') {
        return
    }    
  	var s = elem.textContent    
  	var clicked = findBetween(elem,e.clientX,e.clientY,0,s.length)     
    if (clicked !== null) {        
        info.innerHTML = 'character clicked:'+clicked
    }
}

document.addEventListener('click', onClick);