I am making a minimal JavaScript WYSIWYG control.
I don't want to use document.execCommand because it doesn't allow arbitrary HTML, it's inconsistent across browsers etc.
Here is what I have so far stripped down to minimum working code:
<button data-action="strong"><strong>b</strong></button>
<button data-action="em"><em>i</em></button>
<button data-action="u"><u>u</u></button>
<p contenteditable>The quick brown fox jumps over the lazy dog.</p>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script>
$( function(){
$( 'button' ).on( 'click', function(){
var selection = window.getSelection();
var range = selection.getRangeAt( 0 );
var action = $( this ).attr( 'data-action' );
var node = document.createElement( action );
var frag = range.extractContents();
node.appendChild( frag );
range.insertNode( node );
return false;
});
});
</script>
If some of the selection already contains strong tags (or whatever), how do I make it so that clicking the button a second time removes these tags instead of wrapping the selection with a new strong tag?
Writing this question has given me an idea. I will try it now and answer my own question if it works - that way this question is here in case anybody else comes up against this. Otherwise I shall await your assistance with baited breath :)
EDIT: obviously if somebody else posts a working solution, I will accept their answer rather than mine if it is better.
EDIT(2): so my idea didn't pan out. It turns out that something (probably range.insertNode) will magically balance the tags for you. I don't seem to have enough information from selection, range or frag to always know if the selection is inside a given tag. Any ideas?