2011-09-11 22 views
6

Quiero utilizar la función getSelection para seleccionar palabras de artículos en un cuadro de vista.Seleccionar palabra completa con getSelection

Aquí está mi código: http://jsfiddle.net/xQKNh/2/.

Ahora quiero preguntar, ¿cómo usar JavaScript para seleccionar la palabra completa?

Para la explicación,

Is your question about programming? 

En mi código, si decido r question about pro, el view box mostrará

r question about pro 

Pero, ¿cómo hacer que las palabras completadas? De forma que produzca:

your question about programming. 

código Javascript:

function getSelected() { 
    if(window.getSelection) { return window.getSelection(); } 
    else if(document.getSelection) { return document.getSelection(); } 
    else { 
    var selection = document.selection && document.selection.createRange(); 
    if(selection.text) { return selection.text; } 
    return false; 
    } 
    return false; 
} 
$(document).ready(function() { 
    $('#content-area').mouseup(function() { 
    var selection = getSelected(); 
    if(selection && (selection = new String(selection).replace(/^\s+|\s+$/g,''))) { 
     $('#show-text').html(selection) 
    } 
    }); 
}); 

Respuesta

16

Las versiones recientes de los navegadores Firefox y WebKit tienen incorporado un método modify() (vea también work-in-progress spec) del objeto Selection para hacer esto. IE ha tenido una forma completamente diferente de hacerlo desde la versión 4. En cualquier caso, este método tiene la ventaja significativa de trabajar a través de los límites del elemento.

El siguiente ejemplo funciona en IE 4+, Firefox 4+ y Safari y Chrome en las versiones lanzadas en los últimos años. Opera aún no tiene soporte para el método modify() de los objetos Selection.

Actualización 20 de octubre de 2011

he reescrito que esto en realidad (en su mayoría) funciona en este momento (que no funcionaba correctamente en los navegadores no-IE antes, como se señaló en los comentarios). Desafortunadamente, la expansión de la selección es demasiado codiciosa en no-IE y amplía la selección a la siguiente palabra si ya se ha seleccionado una palabra completa, pero no puedo ver una manera fácil de evitar esto en este momento.

Actualización 11 de junio de 2012

ahora he actualizado esto con una mejora de this answer to a related question. Gracias a Matt M y a Fong-Wan Chau por esto.

Demostración en directo: http://jsfiddle.net/rrvw4/23/

Código:

function snapSelectionToWord() { 
    var sel; 

    // Check for existence of window.getSelection() and that it has a 
    // modify() method. IE 9 has both selection APIs but no modify() method. 
    if (window.getSelection && (sel = window.getSelection()).modify) { 
     sel = window.getSelection(); 
     if (!sel.isCollapsed) { 

      // Detect if selection is backwards 
      var range = document.createRange(); 
      range.setStart(sel.anchorNode, sel.anchorOffset); 
      range.setEnd(sel.focusNode, sel.focusOffset); 
      var backwards = range.collapsed; 
      range.detach(); 

      // modify() works on the focus of the selection 
      var endNode = sel.focusNode, endOffset = sel.focusOffset; 
      sel.collapse(sel.anchorNode, sel.anchorOffset); 

      var direction = []; 
      if (backwards) { 
       direction = ['backward', 'forward']; 
      } else { 
       direction = ['forward', 'backward']; 
      } 

      sel.modify("move", direction[0], "character"); 
      sel.modify("move", direction[1], "word"); 
      sel.extend(endNode, endOffset); 
      sel.modify("extend", direction[1], "character"); 
      sel.modify("extend", direction[0], "word"); 
     } 
    } else if ((sel = document.selection) && sel.type != "Control") { 
     var textRange = sel.createRange(); 
     if (textRange.text) { 
      textRange.expand("word"); 
      // Move the end back to not include the word's trailing space(s), 
      // if necessary 
      while (/\s$/.test(textRange.text)) { 
       textRange.moveEnd("character", -1); 
      } 
      textRange.select(); 
     } 
    } 
} 
+1

Gracias por sonar.Esto parece una mejor respuesta. –

+0

@James: una respuesta de solo rango junto con una cosa basada en 'TextRange' para IE más antiguo cubrirá más navegadores que mi respuesta, por lo que dependiendo de los requisitos del OP, la suya puede ser mejor. –

+0

dos de ustedes son excelentes personas. gracias dos de ustedes, así que cambio la marca a tim, pero también gracias a james –

5

El truco aquí es usar DOM ranges. Luego puede expandir el rango en cualquier dirección hasta que golpee un espacio. Entonces (advertencia, no se ha probado exhaustivamente):

function getSelected() { 
    if(window.getSelection) { return window.getSelection(); } 
    else if(document.getSelection) { return document.getSelection(); } 
    else { 
    var selection = document.selection && document.selection.createRange(); 
    if(selection.text) { return selection.text; } 
    return false; 
    } 
    return false; 
} 

function expand(range) { 
    if (range.collapsed) { 
     return; 
    } 

    while (range.toString()[0].match(/\w/)) { 
     range.setStart(range.startContainer, range.startOffset - 1); 
    } 

    while (range.toString()[range.toString().length - 1].match(/\w/)) { 
     range.setEnd(range.endContainer, range.endOffset + 1); 
    } 
} 

$(document).ready(function() { 
    $('#content-area').mouseup(function() { 
    var selectionRange = getSelected().getRangeAt(0); 
    var start = selectionRange.startOffset; 
    expand(selectionRange); 
    var selection = selectionRange.toString(); 
    if(selection && (selection = new String(selection).replace(/^\s+|\s+$/g,''))) { 
     $('#show-text').html(selection) 
    } 
    }); 
}); 

La optimización se deja como un ejercicio para el lector.

+0

gran trabajo, gracias por darme una lección. –

+0

¡Gracias también, fue un problema interesante! –

+1

Esto no funcionará cuando las partes de una palabra estén contenidas en elementos diferentes. Tampoco funcionará en IE <9, que no tiene soporte para 'window.getSelection()' o 'Range'. –

Cuestiones relacionadas