6

I'm building a simple WYSIWYG editor inside an iframe with designMode on , currently I can make the selected text bold, italic and underline and to link, and they work fine.

But I would like to know when the caret is inside the b, i, u, a, tags, so I can notify the user that the current selection is bold or whatever.

Examples:

Hello <b>Stackover|flow</b> is cool! = You are Inside the b tag

<i>Be|st place</i>! = You are Inside the i tag

Hello <a href="http://stackoverflow.com/">Go|od stuff!</a> = You are Inside the a tag

No libraries please I would like to learn this stuff :)

Adam Halasz
  • 57,421
  • 66
  • 149
  • 213
  • Possible duplicate of [this question](http://stackoverflow.com/questions/263743/how-to-get-cursor-position-in-textarea) – Tyler Holien Feb 06 '11 at 14:51
  • @Tyler Holien , I'm not talking about the caret position as a number, I would like to get it's Parent Node Name too, and the accepted answers solution works only on textareas. – Adam Halasz Feb 06 '11 at 14:53
  • True, sorry. Where is the caret, if not a textarea? – Tyler Holien Feb 06 '11 at 14:56
  • Nope :), I just edited my questions first line: I'm building a simple WYSIWYG editor inside an iframe with designMode on – Adam Halasz Feb 06 '11 at 14:58

1 Answers1

10

MSIE lte 8: TextRange.parentElement()

Others: DOMRange.commonAncestorContainer

<script type="text/javascript">
<!--
function fx()
{

  var target=null;
  if(window.getSelection)
  {
    target=window.getSelection().getRangeAt(0).commonAncestorContainer;
    return((target.nodeType===1)?target:target.parentNode);
  }
  else if(document.selection)
  {
    var target=document.selection.createRange().parentElement();
  }
  return target;
}
//-->
</script>
<input type="button" onclick="alert(fx().tagName)" value="click">
<div id="editor" contenteditable="true">
Hello <b>Stackoverflow</b> is cool! <i>Best place</i>
Hello <a href="http://stackoverflow.com/">Good stuff!</a>
</div>
Dr.Molle
  • 116,463
  • 16
  • 195
  • 201
  • Hi @Dr.Molle , I know about `commonAncestorContainer` , but +1 for `parentElement` :), My problem with `commonAncestorContainer.nodeName` is that gives me `#text` for every kind of text, sooo how should I get the real parent node name from it? :) – Adam Halasz Feb 06 '11 at 15:06
  • Choose `commonAncestorContainer.parentNode` if `commonAncestorContainer.nodeType` is not 1 – Dr.Molle Feb 06 '11 at 15:16
  • Hmm I get `#text` with Chrome(9.0.597.84), Safari(5.0.3) , and nothing with firefox and opera, IE untested :| – Adam Halasz Feb 06 '11 at 15:17
  • OMG!!! This works on Chrome and Safari, cooool!!, I'm trying to make it since a weeek. But doesn't works on Firefox and Opera yet but maybe I missed something :) – Adam Halasz Feb 06 '11 at 15:25
  • Hmm there is a problem with iframe.contentWindow.onkeyup in firefox and opera, but this is another question, in the parent window works cool in all browsers here, so thanks very very much, you made me really happy!! – Adam Halasz Feb 06 '11 at 15:31
  • 1
    +1, since this will work in the vast majority of cases. There are a couple of cases that this won't work for: first, in IE, a selection can contain a `ControlRange` (see http://msdn.microsoft.com/en-us/library/ms537447%28v=vs.85%29.aspx) rather than a `TextRange`, in which case `parentElement()` will cause an error. You can filter this case out: `else if(document.selection && document.selection.type != "Control")`. Second, if there's no selection or caret, `getRangeAt(0)` could throw an error, but that won't happen so long as the editable element has the focus. – Tim Down Feb 06 '11 at 15:58
  • Tim, you're right, it will make problems if there is a controlRange inside the selection. But the requested thing is the caret, you can simply collapse() the range, and nothing will be inside :) – Dr.Molle Feb 06 '11 at 16:31