Editable content

by mingjian sun

HTML

<div style="width: 50px;border: 1px solid #ccc;overflow:hidden">
  <div id="editor" contenteditable="false" style="display:inline-block;height:1.2em; white-space: nowrap;">Some editable text. Double click to edit</div>
</div>

JavaScript

function getMouseEventCaretRange(evt) {
  var range, x = evt.clientX,
    y = evt.clientY;

  // Try the simple IE way first
  if (document.body.createTextRange) {
    range = document.body.createTextRange();
    range.moveToPoint(x, y);
  } else if (typeof document.createRange != "undefined") {
    // Try Mozilla's rangeOffset and rangeParent properties, which are exactly what we want

    if (typeof evt.rangeParent != "undefined") {
      range = document.createRange();
      range.setStart(evt.rangeParent, evt.rangeOffset);
      range.collapse(true);
    }

    // Try the standards-based way next
    else if (document.caretPositionFromPoint) {
      var pos = document.caretPositionFromPoint(x, y);
      range = document.createRange();
      range.setStart(pos.offsetNode, pos.offset);
      range.collapse(true);
    }

    // Next, the WebKit way
    else if (document.caretRangeFromPoint) {
      range = document.caretRangeFromPoint(x, y);
    }
  }

  return range;
}

function selectRange(range) {
  if (range) {
    if (typeof range.select != "undefined") {
      range.select();
    } else if (typeof window.getSelection != "undefined") {
      var sel = window.getSelection();
      sel.removeAllRanges();
      sel.addRange(range);
    }
  }
}

document.getElementById("editor").ondblclick = function(evt) {
  evt = evt || window.event;
  this.contentEditable = true;
  this.focus();
  var caretRange = getMouseEventCaretRange(evt);

  // Set a timer to allow the selection to happen and the dust settle first
  window.setTimeout(function() {
    selectRange(caretRange);
  }, 10);
  return false;
};

document.getElementById('editor').addEventListener("blur", function(event) {
  var parent = event.target.parentElement || event.target.parentNode || null;
  event.target.contentEditable = false;
  parent.scrollLeft = 0;
}, true);