web-dev-qa-db-fra.com

Insérer html au caret dans une div contenteditable

J'ai un div avec contenteditable set et je saisis la frappe en utilisant jquery pour appeler preventDefault () lorsque la touche Entrée est enfoncée. Semblable à cette question qui insère du texte au curseur, je voudrais insérer directement du code HTML, par souci de clarté, nous dirons que c'est une balise br. Utiliser la réponse à la question ci-dessus fonctionne réellement dans IE car il utilise la méthode range.pasteHTML, mais dans les autres navigateurs, la balise br apparaîtrait sous forme de texte brut et non de HTML. Comment modifier le répondre pour insérer du HTML et pas du texte?

67
Niall

Dans la plupart des navigateurs, vous pouvez utiliser la méthode insertNode() de la plage obtenue à partir de la sélection. Dans IE <9, vous pouvez utiliser pasteHTML(), comme vous l'avez mentionné. Vous trouverez ci-dessous une fonction permettant de le faire dans tous les principaux navigateurs. Si le contenu est déjà sélectionné, il est remplacé, c'est donc effectivement une opération de collage.En outre, j'ai ajouté du code pour placer le curseur après la fin du contenu inséré.

jsFiddle: http://jsfiddle.net/jwvha/1/

Code:

function pasteHtmlAtCaret(html) {
    var sel, range;
    if (window.getSelection) {
        // IE9 and non-IE
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();

            // Range.createContextualFragment() would be useful here but is
            // only relatively recently standardized and is not supported in
            // some 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);

            // Preserve the selection
            if (lastNode) {
                range = range.cloneRange();
                range.setStartAfter(lastNode);
                range.collapse(true);
                sel.removeAllRanges();
                sel.addRange(range);
            }
        }
    } else if (document.selection && document.selection.type != "Control") {
        // IE < 9
        document.selection.createRange().pasteHTML(html);
    }
}

UPDATE 21 AOÛT 2013

Comme demandé dans les commentaires, voici un exemple mis à jour avec un paramètre supplémentaire qui spécifie si le contenu inséré doit être sélectionné ou non.

Démo: http://jsfiddle.net/timdown/jwvha/527/

Code:

function pasteHtmlAtCaret(html, selectPastedContent) {
    var sel, range;
    if (window.getSelection) {
        // IE9 and non-IE
        sel = window.getSelection();
        if (sel.getRangeAt && sel.rangeCount) {
            range = sel.getRangeAt(0);
            range.deleteContents();

            // Range.createContextualFragment() would be useful here but is
            // only relatively recently standardized and is not supported in
            // some 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);
            }
            var firstNode = frag.firstChild;
            range.insertNode(frag);

            // Preserve the selection
            if (lastNode) {
                range = range.cloneRange();
                range.setStartAfter(lastNode);
                if (selectPastedContent) {
                    range.setStartBefore(firstNode);
                } else {
                    range.collapse(true);
                }
                sel.removeAllRanges();
                sel.addRange(range);
            }
        }
    } else if ( (sel = document.selection) && sel.type != "Control") {
        // IE < 9
        var originalRange = sel.createRange();
        originalRange.collapse(true);
        sel.createRange().pasteHTML(html);
        if (selectPastedContent) {
            range = sel.createRange();
            range.setEndPoint("StartToStart", originalRange);
            range.select();
        }
    }
}
173
Tim Down
var doc = document.getElementById("your_iframe").contentWindow.document;

// IE <= 10
if (document.selection){
    var range = doc.selection.createRange();
        range.pasteHTML("<b>Some bold text</b>");

// IE 11 && Firefox, Opera .....
}else if(document.getSelection){
    var range = doc.getSelection().getRangeAt(0);
    var nnode = doc.createElement("b");
    range.surroundContents(nnode);
    nnode.innerHTML = "Some bold text";
};
12
user3126867

en lisant rapidement et en espérant ne pas être en dehors du sujet, voici une piste pour ceux qui, comme moi, ont besoin d'insérer du code au niveau du curseur d'un div:

document.getElementById('editeur').contentWindow.document.execCommand('insertHTML', false, '<br />');

'editeur' est iframe:

<iframe id="editeur" src="contenu_editeur_wysiwyg.php">
</iframe>

contenu_editeur_wysiwyg.php:

<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
</head>
<body>
<div>
</div>
</body>
</html>

n'oubliez pas:

document.getElementById('editeur').contentDocument.designMode = "on";
0
delaio