title: Minimal JavaScript wysiwyg - remove tag from selected text if already exists
body: <p>I am making a minimal JavaScript WYSIWYG control.</p>
  
  <p>I don't want to use document.execCommand because it doesn't allow arbitrary HTML, it's inconsistent across browsers etc.</p>
  
  <p>Here is what I have so far stripped down to minimum working code:</p>
  
  <p><a href="http://jsfiddle.net/2WxQn/1/" rel="nofollow">http://jsfiddle.net/2WxQn/1/</a></p>
  
  <pre class="lang-html prettyprint-override"><code>&lt;button data-action="strong"&gt;&lt;strong&gt;b&lt;/strong&gt;&lt;/button&gt;
  &lt;button data-action="em"&gt;&lt;em&gt;i&lt;/em&gt;&lt;/button&gt;
  &lt;button data-action="u"&gt;&lt;u&gt;u&lt;/u&gt;&lt;/button&gt;
  &lt;p contenteditable&gt;The quick brown fox jumps over the lazy dog.&lt;/p&gt;
  &lt;script src="http://code.jquery.com/jquery-1.9.1.min.js"&gt;&lt;/script&gt;
  &lt;script&gt;
    $( 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;           
      });
    });
  &lt;/script&gt;
  </code></pre>
  
  <p>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?</p>
  
  <p>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 :)</p>
  
  <p>EDIT: obviously if somebody else posts a working solution, I will accept their answer rather than mine if it is better.</p>
  
  <p>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?</p>