Selecione todo o texto DIV com um único clique do mouse

135

Como destacar / selecionar o conteúdo de uma tag DIV quando o usuário clica no DIV ... a idéia é que todo o texto seja realçado / selecionado para que o usuário não precise realçar manualmente o texto com o mouse e, potencialmente, perdeu um pouco do texto?

Por exemplo, digamos que temos um DIV como abaixo:

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

... e quando o usuário clica em qualquer um desses URL, o texto completo do URL é destacado para que você possa arrastar facilmente o texto selecionado pelo navegador ou copiar o URL completo com um clique direito.

Obrigado!

Acyra
fonte

Respostas:

192

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>

Agora você deve passar o ID como argumento, que neste caso é "selecionável", mas é mais global, permitindo que você o use em qualquer lugar várias vezes sem usar, como chiborg mencionou, o jQuery.

Denis Sadowski
fonte
8
BTW, você pode facilmente transformar isso em um manipulador de eventos jQuery click substituindo document.getElementById('selectable')por this. Em seguida, você pode adicionar a funcionalidade de maneira discreta a vários elementos, por exemplo, várias divs em um contêiner: jQuery('#selectcontainer div').click(selectText);
chiborg
3
Isso funciona bem no Chrome, FF, Safari (Mac) e Chrome e IE (Windows 9+, 8 não testado). Mas não parece funcionar no Safari no iPad Mini (iOS6) ou no iPhone 4, não tenho certeza sobre outros iOS ou Android.
Protótipo
1
Por este artigo, a consulta if (window.getSelection) {deve vir em primeiro lugar para o Opera ( quirksmode.org/dom/range_intro.html )
protótipo
1
Esta solução parece não funcionar no ie11. Alguma idéia do porquê?
Swiss Mister
5
Na versão 36+ do Chrome, isso retornará o erro "Seleção descontínua não é suportada". A solução é adicionar window.getSelection().removeAllRanges();anteswindow.getSelection().addRange(range);
nHaskins
121

ATUALIZAÇÃO 2017:

Para selecionar a chamada de conteúdo do nó:

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

Isso funciona em todos os navegadores modernos, incluindo o IE9 + (no modo de padrões).

Exemplo executável:

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>


A resposta original abaixo está obsoleta, pois window.getSelection().addRange(range); foi preterida

Resposta original:

Todos os exemplos acima usam:

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

mas o problema é que ele seleciona o próprio nó, incluindo a tag DIV etc.

Para selecionar o texto do nó de acordo com a pergunta do OP que você precisa chamar:

    range.selectNodeContents( ... )

Portanto, o snippet completo seria:

    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
fonte
Você também pode usar, em thisvez de obter o elemento com base no ID, desde que esteja dentro do clickouvinte do elemento .
Zach Saucier
44

Existe uma solução 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-selecté uma especificação do módulo CSS de nível 4, que atualmente é uma propriedade CSS rascunho e não padrão, mas os navegadores a suportam bem - consulte # search = user-select .

Leia mais sobre a seleção de usuários aqui no MDN e brinque com ele aqui no w3scools

Mino
fonte
3
+1 solução elegante impressionante impressionante! Testado em setembro de 2017 e funciona perfeitamente no FireFox e Chrome, mas NÃO NO MICROSOFT EDGE !? Alguma idéia por que não e como consertar isso? obrigado!
Sam
13

A resposta do Neuroxik foi realmente útil. Eu tive apenas um problema com o Chrome, porque quando eu cliquei em uma div externa, ela não funcionou. Eu poderia resolvê-lo removendo os intervalos antigos antes de adicionar o novo intervalo:

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
fonte
9

Para itens editáveis ​​por conteúdo (não entradas regulares, é necessário usar selectNodeContents (em vez de apenas selectNode).

NOTA: Todas as referências a "document.selection" e "createTextRange ()" são para o IE 8 e inferior ... Você provavelmente não precisará oferecer suporte a esse monstro se estiver tentando fazer coisas complicadas 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);

}
prumo
fonte
6

Usando um campo da área de texto, você pode usar este: (Via 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>

É assim que vejo a maioria dos sites. Eles apenas o estilizam com CSS, para que não pareça uma área de texto.

Tyler Carter
fonte
por que não apenas this.focus();this.select();?
Taha Paksu 23/06
5

Este trecho fornece a funcionalidade necessária . O que você precisa fazer é adicionar um evento à div que ativa o fnSelect nele. Um hack rápido que você não deveria fazer e possivelmente não funcionaria seria assim:

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

Obviamente, assumindo que o link ao snippet havia sido incluído.

Simon Scarfe
fonte
5

Achei útil agrupar essa função como um plugin 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);
        }
    });
}

Assim, torna-se uma solução reutilizável. Então você pode fazer isso:

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

E será selecionado teste na div.

vitmalina
fonte
1
Lembre-se de chamar window.getSelection (). RemoveAllRanges (); como no código de Josillo. Além disso: eu recomendaria colocar window.getSelect como a primeira opção, pois esse é o padrão HTML5 e document.selection é o antigo fallback do IE para o IE8 e versões anteriores.
Jan Aagaard
3

Que tal esta solução simples? :)

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

Claro que não é uma construção div, como você mencionou, mas ainda assim funcionou para mim.

Niko Lay
fonte
1
Solução concisa, mas isso não explica o texto em um elemento que não seja um campo de entrada ou área de texto.
21818 JoePC
3

Niko Lay: Que tal esta solução simples? :)

`<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 após:

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

Apenas esta parte onclick = "this.select ();" id = "selecionável" no meu código funcionou bem. Seleciona tudo na minha caixa de código com um clique do mouse.

Obrigado pela ajuda Niko Lay!

Igor B.
fonte
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);
        }
    });
}

A resposta acima não está funcionando no Chrome porque o addRange remove o intervalo adicionado anterior. Eu não encontrei nenhuma solução para isso ao lado de seleção falsa com css.

Christopher Gibała
fonte
Para alguém, esse código pode ser útil, pois eu testei e o encontrei trabalhando na versão mais recente do Chrome: $ .fn.selectText = function () {return $ (this) .each (function (index, el) {if (document. seleção) {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 (intervalo);}}); }
Haider Abbas
0

Facilmente alcançado com a propriedade css user-select definida para todos. Como isso:

div.anyClass {
  user-select: all;
}

tirmey
fonte