Seleccione todo el texto DIV con un solo clic del mouse

136

Cómo resaltar / seleccionar el contenido de una etiqueta DIV cuando el usuario hace clic en el DIV ... la idea es que todo el texto esté resaltado / seleccionado para que el usuario no necesite resaltar manualmente el texto con el mouse y potencialmente te pierdas un poco del texto?

Por ejemplo, supongamos que tenemos un DIV de la siguiente manera:

<div id="selectable">http://example.com/page.htm</div>

... y cuando el usuario hace clic en cualquiera de esa URL, se resalta todo el texto de la URL para que pueda arrastrar fácilmente el texto seleccionado en el navegador, o copiar la URL completa con un clic derecho.

¡Gracias!

Acyra
fuente

Respuestas:

194

function selectText(containerid) {
    if (document.selection) { // IE
        var range = document.body.createTextRange();
        range.moveToElementText(document.getElementById(containerid));
        range.select();
    } else if (window.getSelection) {
        var range = document.createRange();
        range.selectNode(document.getElementById(containerid));
        window.getSelection().removeAllRanges();
        window.getSelection().addRange(range);
    }
}
<div id="selectable" onclick="selectText('selectable')">http://example.com/page.htm</div>

Ahora tiene que pasar el ID como argumento, que en este caso es "seleccionable", pero es más global, lo que le permite usarlo en cualquier lugar varias veces sin usar, como mencionó chiborg, jQuery.

Denis Sadowski
fuente
8
Por cierto, puede convertir esto fácilmente en un controlador de eventos jQuery click reemplazando document.getElementById('selectable')por this. Luego puede agregar la funcionalidad discretamente a varios elementos, por ejemplo, varios divs en un contenedor: jQuery('#selectcontainer div').click(selectText);
chiborg
3
Esto funciona bien en Chrome, FF, Safari (Mac) y Chrome e IE (Windows 9+, 8 no probado). Pero no parece funcionar en Safari en iPad Mini (iOS6) o iPhone 4, no estoy seguro de otros iOS o Android.
prototipo
1
Según este artículo, la consulta if (window.getSelection) {debe ser primero para Opera ( quirksmode.org/dom/range_intro.html )
prototipo del
1
Esta solución parece no funcionar en ie11. ¿Alguna idea de por qué?
Señor suizo
55
En Chrome versión 36+, esto devolverá un error "No se admite la selección no contigua". La solución es agregar window.getSelection().removeAllRanges();anteswindow.getSelection().addRange(range);
nHaskins
122

ACTUALIZACIÓN 2017:

Para seleccionar el contenido del nodo, llame:

window.getSelection().selectAllChildren(
    document.getElementById(id)
);

Esto funciona en todos los navegadores modernos, incluido IE9 + (en modo estándar).

Ejemplo ejecutable:

function select(id) {
  window.getSelection()
    .selectAllChildren(
      document.getElementById("target-div") 
    );
}
#outer-div  { padding: 1rem; background-color: #fff0f0; }
#target-div { padding: 1rem; background-color: #f0fff0; }
button      { margin: 1rem; }
<div id="outer-div">
  <div id="target-div">
    Some content for the 
    <br>Target DIV
  </div>
</div>

<button onclick="select(id);">Click to SELECT Contents of #target-div</button>


La respuesta original a continuación es obsoleta ya que window.getSelection().addRange(range); ha quedado en desuso

Respuesta original

Todos los ejemplos anteriores usan:

    var range = document.createRange();
    range.selectNode( ... );

pero el problema con eso es que selecciona el Nodo en sí, incluida la etiqueta DIV, etc.

Para seleccionar el texto del nodo según la pregunta de OP, debe llamar en su lugar:

    range.selectNodeContents( ... )

Entonces el fragmento completo sería:

    function selectText( containerid ) {

        var node = document.getElementById( containerid );

        if ( document.selection ) {
            var range = document.body.createTextRange();
            range.moveToElementText( node  );
            range.select();
        } else if ( window.getSelection ) {
            var range = document.createRange();
            range.selectNodeContents( node );
            window.getSelection().removeAllRanges();
            window.getSelection().addRange( range );
        }
    }
isapir
fuente
También puede usar en thislugar de obtener el elemento basado en la ID siempre que esté dentro del clickoyente del elemento .
Zach Saucier
44

Hay una solución CSS4 pura:

.selectable{
    -webkit-touch-callout: all; /* iOS Safari */
    -webkit-user-select: all; /* Safari */
    -khtml-user-select: all; /* Konqueror HTML */
    -moz-user-select: all; /* Firefox */
    -ms-user-select: all; /* Internet Explorer/Edge */
    user-select: all; /* Chrome and Opera */

}

user-selectes una especificación de nivel 4 del módulo CSS, que actualmente es una propiedad de borrador y no estándar de CSS, pero los navegadores lo admiten bien - vea # search = user-select .

Lea más sobre selección de usuario aquí en MDN y juegue con él aquí en w3scools

Miño
fuente
3
¡+1 increíble, impresionante, elegante solución! Probado en septiembre de 2017 y funciona perfectamente en Firefox y Chrome, ¿ PERO NO EN MICROSOFT EDGE? ¿Alguna idea de por qué no y cómo solucionarlo? ¡Gracias!
Sam
13

La respuesta de Neuroxik fue realmente útil. Solo tuve un problema con Chrome, porque cuando hice clic en un div externo, no funcionó. Podría resolverlo eliminando los rangos anteriores antes de agregar el nuevo rango:

function selectText(containerid) {
    if (document.selection) {
        var range = document.body.createTextRange();
        range.moveToElementText(document.getElementById(containerid));
        range.select();
    } else if (window.getSelection()) {
        var range = document.createRange();
        range.selectNode(document.getElementById(containerid));
        window.getSelection().removeAllRanges();
        window.getSelection().addRange(range);
    }
}
<div id="selectable" onclick="selectText('selectable')">http://example.com/page.htm</div>
Josillo Debian
fuente
9

Para contenido editable (no entradas regulares, debe usar selectNodeContents (en lugar de solo selectNode).

NOTA: Todas las referencias a "document.selection" y "createTextRange ()" son para IE 8 y versiones inferiores ... Es probable que no necesite admitir ese monstruo si está intentando hacer cosas difíciles como esta.

function selectElemText(elem) {

    //Create a range (a range is a like the selection but invisible)
    var range = document.createRange();

    // Select the entire contents of the element
    range.selectNodeContents(elem);

    // Don't select, just positioning caret:
    // In front 
    // range.collapse();
    // Behind:
    // range.collapse(false);

    // Get the selection object
    var selection = window.getSelection();

    // Remove any current selections
    selection.removeAllRanges();

    // Make the range you have just created the visible selection
    selection.addRange(range);

}
Beto
fuente
6

Usando un campo de área de texto, puede usar esto: (Vía Google)

<form name="select_all">

    <textarea name="text_area" rows="10" cols="80" 
    onClick="javascript:this.form.text_area.focus();this.form.text_area.select();">

    Text Goes Here 

    </textarea>
</form>

Así es como veo que la mayoría de los sitios web lo hacen. Simplemente lo diseñan con CSS para que no se vea como un área de texto.

Tyler Carter
fuente
¿Por qué no solo this.focus();this.select();?
Taha Paksu
5

Este fragmento proporciona la funcionalidad que necesita . Lo que debe hacer es agregar un evento a ese div que active fnSelect en él. Un truco rápido que no deberías hacer y que posiblemente no funcione, se vería así:

document.getElementById("selectable").onclick(function(){
    fnSelect("selectable");
});

Obviamente, suponiendo que se haya incluido el enlace al fragmento.

Simon Scarfe
fuente
5

Me pareció útil envolver esta función como un complemento jQuery:

$.fn.selectText = function () {
    return $(this).each(function (index, el) {
        if (document.selection) {
            var range = document.body.createTextRange();
            range.moveToElementText(el);
            range.select();
        } else if (window.getSelection) {
            var range = document.createRange();
            range.selectNode(el);
            window.getSelection().addRange(range);
        }
    });
}

Por lo tanto, se convierte en una solución reutilizable. Entonces puedes hacer esto:

<div onclick="$(this).selectText()">http://example.com/page.htm</div>

Y se seleccionará prueba en el div.

vitmalina
fuente
1
Recuerde llamar a window.getSelection (). RemoveAllRanges (); como en el código de Josillo. Además: recomendaría poner window.getSelect como la primera opción, ya que este es el estándar HTML5 y document.selection es el antiguo respaldo de IE para IE8 y versiones anteriores.
Jan Aagaard
3

¿Qué tal esta solución simple? :)

<input style="background-color:white; border:1px white solid;" onclick="this.select();" id="selectable" value="http://example.com/page.htm">

Claro que no es construcción div, como mencionaste, pero aún así funcionó para mí.

Niko Lay
fuente
1
Solución concisa, pero esto no tiene en cuenta el texto en un elemento que no sea un campo de entrada o área de texto.
JoePC
3

Niko Lay: ¿Qué tal esta solución simple? :)

`<input style="background-color:white; border:1px white solid;" onclick="this.select();" id="selectable" value="http://example.com/page.htm">`

.....

Código antes:

<textarea rows="20" class="codearea" style="padding:5px;" readonly="readonly">

Código después de:

<textarea rows="20" class="codearea" style="padding:5px;" readonly="readonly" onclick="this.select();" id="selectable">

Solo esta parte onclick = "this.select ();" id = "seleccionable" en mi código funcionó bien. Selecciona todo en mi cuadro de código con un clic del mouse.

Gracias por la ayuda Niko Lay!

Igor B.
fuente
0
$.fn.selectText = function () {
    return $(this).each(function (index, el) {
        if (document.selection) {
            var range = document.body.createTextRange();
            range.moveToElementText(el);
            range.select();
        } else if (window.getSelection) {
            var range = document.createRange();
            range.selectNode(el);
            window.getSelection().addRange(range);
        }
    });
}

La respuesta anterior no funciona en Chrome porque addRange elimina el rango agregado anterior. No encontré ninguna solución para esto además de la selección falsa con css.

Christopher Gibała
fuente
Para alguien, este código puede ser útil, ya que lo probé y encontré que funcionaba en la última versión de Chrome: $ .fn.selectText = function () {return $ (this) .each (function (index, el) {if (document. selección) {var range = document.body.createTextRange (); range.moveToElementText (el); range.select ();} else if (window.getSelection) {var range = document.createRange (); range.selectNode (el ); window.getSelection (). removeAllRanges (); window.getSelection (). addRange (rango);}}); }
Haider Abbas
0

Se logra fácilmente con la propiedad css user-select set to all. Me gusta esto:

div.anyClass {
  user-select: all;
}

tirmey
fuente