0

I'm writing a user script to edit the whole html page: one of the features I will include would allow to edit the selected text as raw HTML. This look easy, just insert<xmp>at the beginning of the selection, and </xmp> at the end.

// from https://stackoverflow.com/a/8288313/2284570
var insertHtmlBeforeSelection, insertHtmlAfterSelection;
(function() {
    function createInserter(isBefore) {
        return function(html) {
            var sel, range, node;
            if (window.getSelection) {
                // IE9 and non-IE
                sel = window.getSelection();
                if (sel.getRangeAt && sel.rangeCount) {
                    range = window.getSelection().getRangeAt(0);
                    range.collapse(isBefore);

                    // Range.createContextualFragment() would be useful here but is
                    // non-standard and not supported in all browsers (IE9, for one)
                    var el = document.createElement("div");
                    el.innerHTML = html;
                    var frag = document.createDocumentFragment(), node, lastNode;
                    while ( (node = el.firstChild) ) {
                        lastNode = frag.appendChild(node);
                    }
                range.insertNode(frag);
                }
           } else if (document.selection && document.selection.createRange) {
                // IE < 9
                range = document.selection.createRange();
                range.collapse(isBefore);
                range.pasteHTML(html);
            }
        }
    }

    insertHtmlBeforeSelection = createInserter(true);
    insertHtmlAfterSelection = createInserter(false);
})();

function ConvertToRaw() {
    insertHtmlBeforeSelection('<xmp>');
    insertHtmlAfterSelection('<xmp>');
}

This would be invoked by alt+c when text is selected. invoking alt+c again would remove the<xmp>tags which would have resulted to rendered version back.

Since the<xmp>tag is deprecated, how I can do this by scripting? If I encode the characters, it would be hard to decode them back without affecting previous ones...

Community
  • 1
  • 1
user2284570
  • 2,891
  • 3
  • 26
  • 74
  • Just make sure to encode all the characters (that is, including `&`) and decoding will work fine. – Ry- Sep 06 '14 at 22:13
  • 1
    @minitech : and if there are encoded characters with `&`in the original html? How to not decode them? It's far cheaper to make a list of the dynamics positions of the inserted ``tags, but I would like to avoid it. – user2284570 Sep 06 '14 at 22:15
  • Why xmp and not pre? I thought I read that xmp might be deprecated. – jamesmortensen Sep 06 '14 at 22:34
  • @user2284570: If you encode `&`, you’re encoding `<` into `&lt;` for example. It works fine. – Ry- Sep 06 '14 at 22:37
  • 1
    @jmort253: `
    ` doesn’t have the same effect of not interpreting its contents as HTML, i.e. `<b></b>` is equivalent to `<b>`.
    – Ry- Sep 06 '14 at 22:38
  • @minitech : Ok I will repeat it [one more time](http://stackoverflow.com/questions/25705136/how-to-switch-to-raw-html-in-contenteditable-for-in-place-editing?noredirect=1#comment40180420_25705136) : what if there's `&lt;`in the original html *(before the edit)*. I can't see how to not decode it in the back process. – user2284570 Sep 06 '14 at 22:42
  • 1
    Then it will end up `&amp;lt;`. You sound sick of “explaining” how this “doesn’t work” to me, though, so I’ll recommend that you perhaps *just try it* and take my leave. – Ry- Sep 06 '14 at 22:46

1 Answers1

1

I use a textarea for the raw html and a contenteditable div for the rendered html. To shuttle between them I use jQuery

//rendered -> raw
$("#raw").text($("#rendered").html());

//raw -> rendered
$("#rendered").html($("#raw").text());

The escaping and un-escaping is done by jQuery.

I have a global flag editmode the value of which is switched between "raw" and "rendered" by the onfocus events of the div and the textarea.

For edits to rendered html there are quite a few events going on because there's a toolbar for formatting but essentially at any point where I change the rendered html I check the flag and if necessary push to the textarea.

For edits to the textarea I hook onkeyup, onkeydown and onmouseup (for paste) to detect change, then check the flag and if necessary push to rendered.

Peter Wone
  • 17,965
  • 12
  • 82
  • 134
  • **'Sighh' :-(** You can't call a script url from a generic user script *(I said it in the beginning of my question)*. additionally, I'm planning an offline use. So, if you didn't know it, user scripts implies no javascript APIs *(like Jquery)*. – user2284570 Oct 28 '14 at 13:18
  • $("#something") can be directly replaced by document.getElementById("something") and .html()/.text() with innerHTML/Text. This conversion is hardly a challenge. I am surprised a world-weary promethean like yourself didn't think of it instantly. – Peter Wone Nov 10 '14 at 23:13
  • `getElementById("something").Text` will strip the html tags... It won't encode them. – user2284570 Nov 10 '14 at 23:38
  • innerHTML and DIY. If you can't write your own then copy from eg jQuery. – Peter Wone Nov 11 '14 at 23:05
  • Ok, It seems your right, but`$("#raw").text()`will [strip html tags](http://api.jquery.com/text/#text). I can't use getElementById("something").Text.getElementById("something").innerHTML. – user2284570 Nov 12 '14 at 22:03