views:

361

answers:

1

Does anyone have any suggestions on how to edit an link in a contentEditable div? It would be ideal once the link is either clicked with mouse, or the cursor hits the link, that the a small prompt would pop up and allow the user to change the href property of the link. The prompt isn't the issue, but how is it possible to detect the link has been either clicked or that the cursor has arrived at the link? onfocus doesn't seem to work in a contentEditable div on Firefox & Safari. Any ideas?

+2  A: 

I'm pretty sure this is what you were looking for, however I used jQuery just to make the concept a little easier to mock. jsbin preview available, so go look at it. If anyone is able to convert this to pure JS for the sake of the answer, I have made it a community wiki.

It works by binding to the keyup/click events on the editable div, then checking for the node that the users caret is being placed at using window.getSelection() for the Standards, or document.selection for those IE people. The rest of the code handles popping/handling the edits.

jQuery methods:

function getSelectionStartNode(){
  var node,selection;
  if (window.getSelection) { // FF3.6, Safari4, Chrome5 (DOM Standards)
    selection = getSelection();
    node = selection.anchorNode;
  }
  if (!node && document.selection) { // IE
    selection = document.selection
    var range = selection.getRangeAt ? selection.getRangeAt(0) : selection.createRange();
    node = range.commonAncestorContainer ? range.commonAncestorContainer :
           range.parentElement ? range.parentElement() : range.item(0);
  }
  if (node) {
    return (node.nodeName == "#text" ? node.parentNode : node);
  }
}

$(function() {
    $("#editLink").hide();
    $("#myEditable").bind('keyup click', function(e) {
        var $node = $(getSelectionStartNode());
        if ($node.is('a')) {
          $("#editLink").css({
            top: $node.offset().top - $('#editLink').height() - 5,
            left: $node.offset().left
          }).show().data('node', $node);
          $("#linktext").val($node.text());
          $("#linkhref").val($node.attr('href'));
          $("#linkpreview").attr('href', $node.attr('href'));
        } else {
          $("#editLink").hide();
        }
    });
    $("#linktext").bind('keyup change', function() {
      var $node = $("#editLink").data('node');
      $node.text($(this).val());
    });
    $("#linkhref").bind('keyup change', function() {
      var $node = $("#editLink").data('node');
      $node.and('#linkpreview').attr('href',$(this).val());
    });
});
gnarf
Very cool, thanks a lot!!!
Travis D