2010-05-16 23 views
13

He leído algunos postes sobre la colocación del cursor, pero ninguno parece responder a mi tema en particular.JavaScript 'contenteditable' - obtener/establecer Caret Posición

  1. tengo 2 divs (Div1 y Div2)
  2. div1 = no editable div
  3. Div2 div
  4. ambos divs contienen exacta mismo contenido = contentEditable
  5. cuando usuario hace clic en div1, que se oculta, y div2 aparece en la ubicación exacta y el usuario puede editar

El problema: Quiero que el cursor aparezca en la ubicación exacta en div2 como div1

Por lo tanto, necesito un poco de manera de leer la ubicación donde el usuario hace clic en div1, y luego, cuando div2 aparece colocar el cursor/símbolo de intercalación en la misma ubicación, por lo que un getCaretLocation (in_div_id) y setCaretLocation (in_div_id) conjunto de funciones.

Cualquier forma de hacerlo?

Gracias -

+0

Hola, ¿has encontrado una solución? Estoy enfrentando el mismo problema que me vuelve loco. –

Respuesta

7

Respuesta corta: No se puede

Respuesta larga: El problema que se enfrentará es que usted será capaz de obtener (x, y) las coordenadas de el evento de clic en div1, pero cualquier implementación de la posición de intercalación, mientras que requiere conocer la posición de la intercalación en el contenido (que es el número de caracteres que preceden a la intercalación).

Para convertir las coordenadas (x, y) a una posición de carácter, realmente necesita saber cuántos caracteres había antes (es decir, a la izquierda en la línea actual y arriba, si el texto es ltr).

Si se utiliza una fuente de ancho fijo, puede simplificar el problema: el mapeo de una (x, y) de coordenadas a un (línea, columna) de coordenadas en una cuadrícula de carácter.

Sin embargo, todavía se enfrentan al problema de no saber cómo se envuelve el texto. Por ejemplo:

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

Si el usuario hace clic en el d en dolor, usted sabe que el carácter es la primera en la segunda línea, pero sin conocer el algoritmo de envoltura no hay manera de que usted sepa que es el 13 ° personaje en "Lorem ipsum dolor sit ...". Y no hay garantía de que ese algoritmo de ajuste sea idéntico en todos los navegadores y plataformas.

Ahora, lo que me pregunto es ¿para qué usar 2 diferentes sincronizado div en el primer lugar? ¿No sería más fácil usar solo un div y establecer su contenido como editable cuando el usuario hace clic (o se desplaza)?

+0

usando 2 divs porque estoy habilitando al usuario a arrastrar div alrededor, lo cual interfiere con SELECCIONAR el texto (resaltando para poner en negrita, por ejemplo). – OneNerd

+0

pensando que tal vez pueda obtener coordenadas y desencadenar el evento click() con las mismas coordenadas en div2: intentaré ver cómo funciona. – OneNerd

+0

@OneNerd: Me inclino por un tirador o algo por el arrastre, pero sin saber qué es el resto de tu UI, no sabría si tiene sentido lo que estás haciendo. –

0

Parece que estás intentando hacer una edición en línea ... ¿has mirado el plugin jeditable?

1

Puede insertar un elemento span pequeño en el cursor, obtener su posición y quitarlo. Para un rango de explorador cruzado y biblioteca de selección, vea rangy.

+0

+1 para rangy. Tratar de lidiar con los rangos por su cuenta es un desastre –

0

Al hacer clic en un elemento, se crea un objeto Selection con longitud cero (obténgalo de element.getSelection(), donde element es el div en cuestión). El focusOffset de ese objeto le permitirá saber que hizo clic, por ejemplo, en el 74º personaje de ese div (esto es lo que Adrien dijo que era imposible en una respuesta diferente).

1

puede, básicamente, que es necesario establecer de contenido temporal editable en su primera div para atrapar pos caret

$('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); 
}); 

ahora sólo necesita obtener/método de intercalación establecer :)

edición> aquí es la mía, (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

leer la posición del cursor en el texto y luego ajustar la posición del símbolo en la ventana de edición.

Cuestiones relacionadas