2010-05-16 10 views
13

J'ai lu quelques articles sur le positionnement du curseur, mais aucun ne semble répondre à mon problème particulier.JavaScript 'contenteditable' - Obtenir/régler la position du curseur

  1. J'ai 2 divs (div1 et DIV2)
  2. div1 = non modifiable div
  3. DIV2 = contenteditable div
  4. les deux divs contiennent contenu exact même
  5. quand l'utilisateur clique sur div1, il se cache, et div2 apparaît dans un endroit précis et l'utilisateur peut modifier

Le problème: Je veux que le caret apparaisse dans un endroit précis sur div2 comme div1

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

Une façon de faire?

Merci -

+0

Bonjour, avez-vous trouvé une solution? Je suis confronté au même problème qui me rend fou ... –

Répondre

7

Réponse courte: Vous ne pouvez pas

Réponse longue: Le problème que vous devrez faire face est que vous serez en mesure d'obtenir (x, y) les coordonnées de l'événement click sur div1, mais n'importe quelle implémentation de la position du curseur tout en vous demandant de connaître la position du curseur dans le contenu (qui est le nombre de caractères précédant le curseur).

Pour convertir les coordonnées (x, y) en une position de caractère, vous devez connaître le nombre de caractères avant (c'est-à-dire gauche sur la ligne actuelle et plus, si le texte est ltr). Si vous utilisez une police de largeur fixe, vous pouvez simplifier le problème en mappant une coordonnée (x, y) en une coordonnée (ligne, colonne) sur une grille de caractères.

Cependant, vous êtes toujours confronté au 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 dans dolor, vous savez que le personnage est la 1ère à la 2ème ligne, mais sans savoir l'algorithme d'emballage il n'y a aucun moyen que vous aurez sachez que c'est le treizième personnage de "Lorem ipsum dolor sit ...". Et il n'y a aucune garantie qu'un tel algorithme d'emballage est identique entre les navigateurs et la plate-forme.

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

+0

en utilisant 2 divs car je permets à l'utilisateur de DRAGER div autour, ce qui interfère avec le SELECTION du texte (mise en surbrillance pour le rendre gras par exemple). – OneNerd

+0

en pensant peut-être que je peux obtenir des coordonnées et déclencher l'événement click() avec les mêmes coordonnées sur div2 - va essayer de voir comment cela fonctionne. – OneNerd

+0

@OneNerd: Je me pencherais vers une poignée ou quelque chose pour le glisser, mais sans savoir ce que le reste de votre interface utilisateur est, je ne sais pas si cela a du sens pour ce que vous faites. –

0

Il semble que vous essayez de faire un montage en ligne ... avez-vous regardé le plugin jeditable?

1

Vous pouvez insérer un minuscule élément d'écartement sur le curseur, prendre sa position et l'enlever. Pour une gamme de navigateurs croisés et une bibliothèque de sélection, voir rangy.

+0

+1 pour rangy. Essayer de gérer les gammes de votre propre chef est une catastrophe –

0

Lorsque vous cliquez sur un élément, un objet Selection de longueur zéro est créé (récupérez-le à partir de element.getSelection(), où element est la div en question). Le focusOffset de cet objet vous permettra de savoir que vous avez cliqué, par exemple, sur le 74ème caractère de cette div (c'est la chose qu'Adrien a dit être impossible dans une réponse différente).

1

vous pouvez, au fond, vous devez définir le contenu temporaire modifiable sur votre premier div pour attraper caret 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 d'obtenir/définir la méthode de caret :)

modifier> voici mon propre, (live demo)

 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); 
     } 
0

lire la position du curseur dans le texte, puis définir la position caret dans la fenêtre d'édition.