Seleção de texto em foco usando jQuery não funciona no Safari e Chrome

85

Eu tenho o seguinte código jQuery (semelhante a esta pergunta ) que funciona no Firefox e IE, mas falha (sem erros, simplesmente não funciona) no Chrome e no Safari. Alguma ideia para uma solução alternativa?

$("#souper_fancy").focus(function() { $(this).select() });
user140550
fonte
Eu quero um comportamento exato no safari de iPad / iPhone. Isso não está funcionando em navegadores de iPod / iPhone. qualquer pista. A resposta aceita abaixo é apenas para Chrome / safari baseado em desktop.
Anand,
5
Observação: a resposta aceita aqui resolve apenas metade do problema. Isso faz com que a seleção funcione, mas torna difícil desmarcá-la com cliques subsequentes. Uma solução melhor pode ser encontrada aqui: stackoverflow.com/questions/3380458/…
SDC

Respostas:

188

É o evento onmouseup que está fazendo com que a seleção seja desmarcada, então você só precisa adicionar:

$("#souper_fancy").mouseup(function(e){
    e.preventDefault();
});

fonte
3
Mais informações sobre o bug aqui: code.google.com/p/chromium/issues/detail?id=4505
Rajat
Como fazer o mesmo usando Prototype?
tehfink
Você também pode tentar vincular ao evento 'click' e evitar ter que fazer duas vinculações.
uglymunky
@uglymunky Dependendo do que você está fazendo, a vinculação ao evento de clique não funcionará em todos os casos - afinal, há outros meios de selecionar um campo de entrada além de clicar nele, e você quer que eles funcionem bem (por exemplo, tabulação nele)
Tacroy
2
Eu quero um comportamento exato no safari de iPad / iPhone. Isso não está funcionando em navegadores de iPod / iPhone. qualquer pista.
Anand
25
$('#randomfield').focus(function(event) {
    setTimeout(function() {$('#randomfield').select();}, 0);
});
Alex0007
fonte
3
Esta é a melhor resposta se você estiver tentando selecionar texto em um campo de formulário para um aplicativo PhoneGap em execução no Android. Isso dá uma indicação visual ao usuário de que o texto foi selecionado, enquanto a resposta aceita não.
BallisticPugh de
4

Isso funciona bem para elementos input type = "text". Que tipo de elemento é #souper_fancy?

$("#souper_fancy").focus(function() {
    $(this).select();
});
Joe Chung
fonte
é um elemento type = "text". Eu tentei $ ("input [type = text]") também. Ainda não funciona com o jQuery 1.3.2 no Safari.
user140550
3

Apenas prevenir o padrão no mouseup faz com que a seleção de texto esteja sempre ATIVADA. O evento MOUSEUP é responsável por limpar a seleção de texto. No entanto, ao impedir seu comportamento padrão, você não consegue desmarcar o texto usando o mouse.

Para evitar isso e fazer com que a seleção de texto funcione novamente, você pode definir um sinalizador em FOCUS, lê-lo em MOUSEUP e redefini-lo para que os eventos MOUSEUP futuros funcionem conforme o esperado.

$("#souper_fancy").focus(function() {
    $(this).select();

    //set flag for preventing MOUSEUP event....
    $this.data("preventMouseUp", true);
});

$("#souper_fancy").mouseup(function(e) {
    var preventEvent = $this.data("preventMouseUp");

    //only prevent default if the flag is TRUE
    if (preventEvent) {
        e.preventDefault();
    }

    //reset flag so MOUSEUP event deselect the text
    $this.data("preventMouseUp", false);
});
ThiagoPXP
fonte
1

Embora funcione para selecioná-lo no IE, Firefox, Chrome, Safari e Opera, não permite que você o edite clicando uma segunda vez no Firefox, Chrome e Safari. Não totalmente certo, mas acho que isso pode ser devido a esses 3 navegadores reemitirem um evento de foco, embora o campo já tenha o foco, portanto, nunca permitindo que você insira o cursor (já que você está selecionando-o novamente), enquanto no IE e o Opera parece que não está fazendo isso, então o evento de foco não foi disparado novamente e, portanto, o cursor foi inserido.

Eu encontrei uma solução melhor neste post Stack que não tem esse problema e funciona em todos os navegadores.

johntrepreneur
fonte
1

Isso deve funcionar também no Chrome:

$("#souper_fancy").focus(function() {
    var tempSouper = $(this);
    setTimeout(function(){
        tempSouper.select();
    },100);
});
rubiwachs
fonte
Considere adicionar feedback construtivo sobre por que OP vê o problema e sua solução o corrige.
Mirko Adari
1

Como há oscilações quando você usa setTimeout, há outra solução baseada em eventos. Desta forma, o evento 'focus' anexa o evento 'mouseup' e o manipulador de eventos se desconecta novamente.

    function selectAllOnFocus(e) {
    if (e.type == "mouseup") { // Prevent default and detach the handler
        console.debug("Mouse is up. Preventing default.");
        e.preventDefault();
        $(e.target).off('mouseup', selectAllOnFocus);
        return;
    }
    $(e.target).select();
    console.debug("Selecting all text");
    $(e.target).on('mouseup', selectAllOnFocus);
}

Em seguida, conecte o primeiro evento

    $('.varquantity').on('focus', selectAllOnFocus);
user2941872
fonte
1

Use setSelectionRange()dentro de um retorno de chamada para requestAnimationFrame():

$(document).on('focus', '._selectTextOnFocus', (e) => {
    var input = e.currentTarget;
    var initialType = e.currentTarget.type;

    requestAnimationFrame(() => {
        // input.select() is not supported on iOS
        // If setSelectionRange is use on a number input in Chrome it throws an exception,
        // so here we switch to type text first.
        input.type = "text";
        input.setSelectionRange(0, Number.MAX_SAFE_INTEGER || 9999);
        input.type = initialType;
    });
});

Use em setSelectionRange()vez de, select()pois select()não funciona no Safari móvel (consulte Selecionando texto programaticamente em um campo de entrada em dispositivos iOS (Safari móvel) ).

É necessário aguardar requestAnimationFrameantes de selecionar o texto, caso contrário, o elemento não será rolado corretamente para a visualização após o teclado ser ativado no iOS.

Ao usá- setSelectionRange()lo, é importante definir o tipo de entrada para text, caso contrário, pode lançar exceções no Chrome (consulte selectionStart / selectionEnd em input type = "número" não mais permitido no Chrome ).

Andrewh
fonte
0

Se alguém se deparar com esse problema, eu tenho aqui uma solução JS pura que está (no momento) funcionando em todos os navegadores incl Móvel

<input type="text" value="Hello world..." onFocus="window.setTimeout(() => this.select());">

(sem setTimeout () não funciona no Safari, Safari móvel e MS Edge)

Claudio
fonte