JavaScript "contenteditable" - obtention/réglage de la position Caret

j'ai lu quelques billets sur le positionnement du caret, mais aucun ne semble répondre à mon problème particulier.

  1. j'ai 2 divs ( div1 et div2)
  2. div1 = div non éditable
  3. div2 = contenteditable div
  4. les deux divs contiennent exactement le même contenu
  5. lorsque l'utilisateur clique sur div1, il obtient caché, et div2 apparaît dans l'emplacement exact et l'utilisateur peut edit

Le problème: je veux que le curseur apparaisse dans l'emplacement exact sur div2 comme div1

donc, j'ai besoin d'un moyen pour lire l'emplacement où l'utilisateur clique sur div1, et puis quand div2 apparaît placer le curseur / caret dans ce même emplacement, donc un getCaretLocation (in_div_id) et setCaretLocation (in_div_id) ensemble de fonctions.

de Toute façon de le faire?

Merci

13
demandé sur OneNerd 2010-05-16 21:10:01

6 réponses

courte réponse : Vous ne pouvez pas

réponse: le problème que vous rencontrerez est que vous serez en mesure d'obtenir les coordonnées (x,y) pour l'événement de clic sur div1, mais toute implémentation de la position de caret tout en exigeant que vous connaissiez la position du caret dans le contenu (qui est le nombre de caractères précédant le caret).

pour convertir les coordonnées (x, y) en une position de caractère, vous devez savoir combien de caractères il y avait avant. (IE. à gauche sur la ligne en cours et au-dessus, si le texte est ltr).

Si vous utilisez une police à largeur fixe, vous pouvez simplifier le problème : cartographie d'un (x,y) les coordonnées (ligne, colonne) de coordonner sur une grille de caractères.

cependant, vous rencontrez toujours le problème de ne pas savoir comment le texte est enveloppé. Par exemple :

------------------
|Lorem ipsum     |
|dolor sit amet  |
|consectetur     |
|adipiscing elit |
------------------

Si l'utilisateur clique sur le d dolor, vous savez que le personnage est la 1ère à la 2ème ligne, mais sans connaissant l'algorithme d'enrubannage, il n'y a pas moyen que vous sachiez que c'est le 13e personnage de "Lorem ipsum dolor sit...". Et il n'y a aucune garantie qu'un tel algorithme d'enrubannage soit identique à travers les navigateurs et la plate-forme.

maintenant, ce que je me demande c'est pourquoi vous utiliseriez 2 synced différents div en premier lieu ? Ne serait-il pas plus facile d'utiliser une seule div et de définir son contenu à éditable lorsque l'utilisateur clique (ou survole) ?

7
répondu Adrien 2010-05-16 18:25:14

vous pouvez insérer un minuscule élément de portée au caret, obtenir sa position, et l'enlever. Pour une bibliothèque de sélection et de portée de navigateur croisées, voir longiligne.

1
répondu Oscar Broman 2011-02-01 09:11:52

vous pouvez, fondamentalement, vous avez besoin de définir temporaire contenu modifiable sur votre première div pour attraper signe pos

$('div1').hover(function()
{ $(this).attr('contenteditable','true');
},function()
{ $(this).removeAttr('contenteditable');
}).mouseup(function()
{   var t = $(this);
    // get caret position and remove content editable
    var caret = t.getCaret();
    t.removeAttr('contenteditable');
    // do your div switch stuff
    ...
    // and apply saved caret position
    $('div2').setCaret(caret);
});

maintenant juste besoin de get/set signe méthode :)

modifier > voici mon propre, (démonstration)

        getSelection:function($e)
        {   if(undefined === window.getSelection) return false;
            var range = window.getSelection().getRangeAt(0);

            function getTreeOffset($root,$node)
            {   if($node.parents($root).length === 0) return false; // is node child of root ?
                var tree = [], treesize = 0;
                while(1)
                {   if($node.is($root)) break;
                    var index, $parent = $node.parent();
                    index = $parent.contents().index($node);
                    if(index !== -1) { tree[treesize++] = index; } $node = $parent;
                };  return tree.reverse();
            }

            var start = getTreeOffset($e,$(range.startContainer));
            var end   = getTreeOffset($e,$(range.endContainer));

            if(start & end === false) return false;

            return {start:start,end:end,startOffset:range.startOffset,endOffset:range.endOffset};
        }, setSelection:function($e,s,win)
        {   $e.focus(); if(s === false) return; var sel = win.getSelection(); sel.removeAllRanges();

            function getNode($e,s)
            {   var node = $e;
                for( var n=0;n<s.length;n++ )
                {   var index = s[n]; if(index < 0) break;
                    node = node.contents(':eq('+index+')');
                }   return node.get(0);
            }

            var start = getNode($e,s.start), end = getNode($e,s.end), range = win.document.createRange();
            range.setStart(start,s.startOffset); range.setEnd(end,s.endOffset); sel.addRange(range);
        }
1
répondu r043v 2012-12-26 13:22:10

Il semble que vous essayez de faire une modification intégrée... avez-vous regardé l' jeditable plugin?

0
répondu Mottie 2010-05-17 00:49:43

Lorsque vous cliquez sur un élément, une Sélection d'objets de longueur zéro est créé (l'obtenir à partir d'élément.getSelection (), où element est la div en question). Le focus offset de cet objet vous fera savoir que vous avez cliqué sur, par exemple, le 74ème caractère de cette div (C'est la chose qui Adrien dit était impossible dans une réponse différente).

0
répondu Ironfrost 2012-06-15 13:43:28

Lire la position de caret dans le texte et ensuite définir la position de caret dans votre fenêtre d'édition.

0
répondu Mario 2013-12-19 11:24:45