title: JavaScript: drag selection markers, so the current selection can be extended or shrunk
body: <p>I have the following working code: <a href="http://jsfiddle.net/henrichro/Z75wS/" rel="nofollow noreferrer">http://jsfiddle.net/henrichro/Z75wS/</a></p>
  
  <p>When the user is selecting some text, left and right markers will appear, just like on iPhones for example. Selection is possible also backwards. The code was mainly built on the solution found here <a href="https://stackoverflow.com/a/15369695/621639">https://stackoverflow.com/a/15369695/621639</a> , of course changed a little bit, converted the jQuery into JS, as my main goal is to write everything in JavaScript, instead of using any library.</p>
  
  <p>What I need, is to make the markers draggable, so I can extend or shrink the selection.</p>
  
  <p><strong>Current JavaScript code:</strong></p>
  
  <pre><code>function applySelectionMarkers() {
  
      if( !window.getSelection().isCollapsed ) {
  
          var sel = window.getSelection();
          var range = document.createRange();
          range.setStart( sel.anchorNode, sel.anchorOffset );
          range.setEnd( sel.focusNode, sel.focusOffset );
          var backwards = range.collapsed;
          range.detach();
  
          var rects = sel.getRangeAt(0).getClientRects();
          var n = rects.length - 1;
  
          //console.log(rects);
  
          var lineHeight = getLineHeight( edit );
  
          var markerRight = document.getElementById( "markerRight" );
          var markerRightWidth = markerRight.offsetWidth;
  
          var markerLeft = document.getElementById( "markerLeft" );
          var markerLeftWidth = markerLeft.offsetWidth;
  
  
          if ( markerRightWidth == 0 ) {
              markerRightWidth = 10;
          }
  
          if ( markerLeftWidth == 0 ) {
              markerLeftWidth = 10;
          }
  
          if ( lastCharRTL( getSelectionHtml() ) ) {
  
              markerLeft.style.top = ( rects[0].top + lineHeight ) + "px";
              markerLeft.style.left = ( rects[0].left - markerLeftWidth ) + "px";
              markerLeft.style.display = "block";
  
              markerRight.style.top = ( rects[n].top + lineHeight ) + "px";
              markerRight.style.left = ( rects[n].left - markerRightWidth ) + "px";
              markerRight.style.display = "block";
  
              //alert( "one" + markerLeftWidth );
  
          } else if ( backwards ) {
  
              markerLeft.style.top = ( rects[n].top + lineHeight ) + "px";
              markerLeft.style.left = rects[n].right + "px";
              markerLeft.style.display = "block";
  
              markerRight.style.top = ( rects[0].top + lineHeight ) + "px";
              markerRight.style.left = ( rects[0].left - markerRightWidth ) + "px";
              markerRight.style.display = "block";
  
              //alert( "two" + markerRightWidth );
  
          } else {
  
              markerLeft.style.top = ( rects[0].top + lineHeight ) + "px";
              markerLeft.style.left = ( rects[0].left - markerLeftWidth ) + "px";
              markerLeft.style.display = "block";
  
              markerRight.style.top = ( rects[n].top + lineHeight ) + "px";
              markerRight.style.left = rects[n].right + "px";
              markerRight.style.display = "block";
  
              //alert( "three" + markerLeftWidth );
          }
      } else {
          markerLeft.style.display = "none";
          markerRight.style.display = "none";
      }
  }
  
  function getSelectionHtml() {
      var html = "";
      if ( typeof window.getSelection != "undefined" ) {
          var sel = window.getSelection();
          if ( sel.rangeCount ) {
              var container = document.createElement( "div" );
              for ( var i = 0, len = sel.rangeCount; i &lt; len; ++i ) {
                  container.appendChild( sel.getRangeAt(i).cloneContents() );
              }
              html = container.innerHTML;
          }
      } else if ( typeof document.selection != "undefined" ) {
          if ( document.selection.type == "Text" ) {
              html = document.selection.createRange().htmlText;
          }
      }
      return html;
  }
  
  function lastCharRTL( txt ) {
      return /[\u0591-\u07FF\uFB1D-\uFDFD\uFE70-\uFEFC]$/.test(txt);
  }
  
  // line height in selectie ca putem adauga la markerLeft top attribute
  function getLineHeight( element ){
      var temp = document.createElement( element.nodeName );
      temp.setAttribute( "style","margin:0px;padding:0px;font-family:"+element.style.fontFamily+";font-size:"+element.style.fontSize );
      temp.innerHTML = "test";
      temp = element.parentNode.appendChild( temp );
      var ret = temp.clientHeight;
      temp.parentNode.removeChild( temp );
      return ret;
  }
  
  document.onmouseup = function() {
      applySelectionMarkers();
  }
  
  function KeyPress(e) {
      var evtobj = window.event ? event : e;
      if ( evtobj.keyCode == 65 &amp;&amp; evtobj.ctrlKey ) {
          console.log(evtobj.keyCode);
          applySelectionMarkers();
      }
  }
  
  document.onkeydown = KeyPress;
  </code></pre>
  
  <p><strong>Further credits:</strong></p>
  
  <p><a href="https://stackoverflow.com/a/5222955/621639">https://stackoverflow.com/a/5222955/621639</a>,
  <a href="https://stackoverflow.com/a/4515470/621639">https://stackoverflow.com/a/4515470/621639</a></p>
  
  <p><strong>Update</strong>: Playing while dragging one of the markers:</p>
  
  <pre><code>window.onload = function() {
      draggable( 'markerLeft' );
  }
  
  var dragObj = null;
  
  function draggable( id ) {
      var obj = document.getElementById( id );
      obj.style.position = "absolute";
      obj.onmousedown = function() {
          dragObj = obj;
      }
  }
  
  document.onmouseup = function(e) {
      dragObj = null;
  }
  
  document.onmousemove = function(e) {
      var x = e.pageX;
      var y = e.pageY;
      if( dragObj == null )
          return;
      dragObj.style.left = x + "px";
      dragObj.style.top = y + "px";
  }
  </code></pre>
  
  <p>But when I drag the left marker (red), the whole selection disappears.</p>