Keil
Keil

Reputation: 220

caret positionning in contentEditable containing dom images

I'm having problems with setting caret position in a contentEditable iframe, as soon as I add an ":)" emoticon.

How would you manage?

Here is a basic template:

<!DOCTYPE html>
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
    <script type="text/javascript">
        var init = function () { // initialization

            this.editor = $('#wysiwyg');
            this.editor.curWin = this.editor.prop('contentWindow');
            this.editor.curDoc = this.editor.curWin.document;
            this.editor.curDoc.designMode = "On";
            this.editor.curBody = $(this.curDoc).contents().find('body');
            this.editor.html = function (data) { // shortcut to set innerHTML
                if (typeof data == "undefined")
                    return this.curBody.html();
                this.curBody.html(data);
                return $(this);
            };
            var emoji = function (data) { // replace every :) by an image
                return data.replace(':)', '<img src="http:\/\/dean.resplace.net\/blog\/wp-content\/uploads\/2011\/10\/wlEmoticon-smile1.png"\/>');
            };
            var self = this;
            this.editor.contents().find('body').keypress(function (ev) { // handler on key pressed
                var me = $(this);

                setTimeout(function () { // timeout so that the iframe is containing the last character inputed
                    var sel = self.editor.curWin.getSelection();
                    var offset = sel.focusOffset;

                    me.html( emoji( me.html() ) );

                    var body = $(self.editor.curDoc).find('body').get(0);
                    sel.collapse(body, offset); //here is where i set positionning
                    return;
                }, 100);
                return true;
            });

        };
    </script>
</head>
<body onload="init()">
    <iframe id="wysiwyg"></iframe>
</body>
</html>

StackOverflow demands that i add more context to explain the code sections, but for me it seems to be clear. So sorry to add so more "cool story bro" comments but i can't see what i can explain more than this. Anyway, i'm open to any question.

Upvotes: 0

Views: 626

Answers (1)

rlemon
rlemon

Reputation: 17666

Quick fix... check to see if a replacement is being made... if there is one being made then readjust the caret. otherwise leave it be.

var init = function() { // initialization
    this.editor = $('#wysiwyg');
    this.editor.curWin = this.editor.prop('contentWindow');
    this.editor.curDoc = this.editor.curWin.document;
    this.editor.curDoc.designMode = "On";
    this.editor.curBody = $(this.curDoc).contents().find('body');
    this.editor.html = function(data) { // shortcut to set innerHTML
        if (typeof data == "undefined") return this.curBody.html();
        this.curBody.html(data);
        return $(this);
    };
    var emoji = function(data) { // replace every :) by an image
        var tmp = data;
        tmp = tmp.replace(':)', '<img src="http:\/\/dean.resplace.net\/blog\/wp-content\/uploads\/2011\/10\/wlEmoticon-smile1.png"\/>');
        if (tmp !== data) {
            return [true, tmp];
        }
        return [false, tmp];
    };
    var self = this;
    this.editor.contents().find('body').keypress(function(ev) { // handler on key pressed
        var me = $(this);
        var res = emoji(me.html());
        if (res[0]) {
            setTimeout(function() { // timeout so that the iframe is containing the last character inputed
                var sel = self.editor.curWin.getSelection();
                var offset = sel.focusOffset;

                me.html(res[1]);

                var body = $(self.editor.curDoc).find('body').get(0);
                sel.collapse(body, offset); //here is where i set positionning
                return;

            }, 100);
        }
        return true;
    });

};
init();​

Upvotes: 1

Related Questions