Zaznaczanie tekstu pod fokusem za pomocą jQuery nie działa w Safari i Chrome


85

Mam następujący kod jQuery (podobny do tego pytania ), który działa w Firefoksie i IE, ale nie działa (bez błędów, po prostu nie działa) w Chrome i Safari. Jakieś pomysły na obejście?

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

Chcę dokładnego zachowania w Safari na iPadzie / iPhonie. To nie działa w przeglądarkach iPod / iPhone. jakakolwiek wskazówka. Poniżej zaakceptowana odpowiedź dotyczy tylko przeglądarki Chrome / Safari na komputerze.
Anand

5
Uwaga: zaakceptowana tutaj odpowiedź rozwiązuje tylko połowę problemu. To sprawia, że ​​zaznaczanie działa, ale utrudnia późniejsze cofnięcie zaznaczenia kolejnymi kliknięciami. Lepsze rozwiązanie można znaleźć tutaj: stackoverflow.com/questions/3380458/…
SDC

Odpowiedzi:


188

To zdarzenie onmouseup powoduje odznaczenie zaznaczenia, więc wystarczy dodać:

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

3
Więcej informacji na temat błędu tutaj: code.google.com/p/chromium/issues/detail?id=4505
Rajat

Jak osiągnąć to samo używając Prototype?
tehfink

Możesz także spróbować powiązać ze zdarzeniem „kliknięcie” i uniknąć konieczności tworzenia dwóch powiązań.
uglymunky

@uglymunky W zależności od tego, co robisz, powiązanie ze zdarzeniem kliknięcia nie będzie działać we wszystkich przypadkach - w końcu istnieją inne sposoby zaznaczania pola wejściowego niż kliknięcie go i chcesz, aby również działały (np. tabbing in to it)
Tacroy,

2
Chcę dokładnego zachowania w Safari na iPadzie / iPhonie. To nie działa w przeglądarkach iPod / iPhone. jakakolwiek wskazówka.
Anand

25
$('#randomfield').focus(function(event) {
    setTimeout(function() {$('#randomfield').select();}, 0);
});

3
To najlepsza odpowiedź, jeśli próbujesz zaznaczyć tekst w polu formularza dla aplikacji PhoneGap działającej na Androidzie. Daje to wizualne wskazanie użytkownikowi, że tekst jest zaznaczony, a zaakceptowana odpowiedź nie.
BallisticPugh

4

Działa to dobrze w przypadku elementów input type = "text". Jakim elementem jest #souper_fancy?

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

jest to element typu = "tekst". Próbowałem też $ ("input [type = text]"). Nadal nie działa z jQuery 1.3.2 w Safari.
user140550

3

Samo wyłączenie domyślnego ustawienia myszy powoduje, że zaznaczanie tekstu jest zawsze WŁĄCZONE. Zdarzenie MOUSEUP jest odpowiedzialne za wyczyszczenie zaznaczenia tekstu. Jednak zapobiegając jego domyślnemu zachowaniu, nie można odznaczyć tekstu za pomocą myszy.

Aby tego uniknąć i sprawić, by zaznaczanie tekstu znów działało, możesz ustawić flagę w FOCUS, odczytać ją z MOUSEUP i zresetować, aby przyszłe zdarzenia MOUSEUP działały zgodnie z oczekiwaniami.

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

1

Chociaż działa to w przypadku wybrania go w przeglądarce IE, Firefox, Chrome, Safari i Opera, nie pozwoli ci to edytować, klikając po raz drugi w przeglądarce Firefox, Chrome i Safari. Nie do końca jestem pewien, ale myślę, że może to być spowodowane tym, że te 3 przeglądarki ponownie wydały zdarzenie fokusu, mimo że pole już jest fokusem, więc nigdy nie pozwala na wstawienie kursora (ponieważ wybierasz go ponownie), podczas gdy w IE i Opera wygląda na to, że tego nie robi, więc zdarzenie fokusu nie zostało ponownie uruchomione, a kursor został wstawiony.

Znalazłem lepszą poprawkę w tym poście stosu , który nie ma tego problemu i działa we wszystkich przeglądarkach.


1

Powinno to działać również w chrome:

$("#souper_fancy").focus(function() {
    var tempSouper = $(this);
    setTimeout(function(){
        tempSouper.select();
    },100);
});

Rozważ dodanie konstruktywnej opinii na temat tego, dlaczego OP widzi problem i Twoje rozwiązanie go naprawia.
Mirko Adari

1

Ponieważ podczas korzystania z setTimeout występuje migotanie, istnieje inne rozwiązanie oparte na zdarzeniach. W ten sposób zdarzenie „focus” dołącza zdarzenie „mouseup”, a program obsługi zdarzenia odłącza się ponownie.

    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);
}

Następnie połącz pierwsze zdarzenie

    $('.varquantity').on('focus', selectAllOnFocus);

1

Użyj setSelectionRange()wewnątrz oddzwonienia do 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;
    });
});

Użyj setSelectionRange()zamiast, select()ponieważ select()nie działa w mobilnej przeglądarce Safari (patrz Programowe zaznaczanie tekstu w polu wprowadzania na urządzeniach z systemem iOS (mobilna Safari) ).

Należy poczekać za pomocą requestAnimationFrame przed wybraniem tekstu, w przeciwnym razie element nie zostanie poprawnie przewinięty do widoku po wyświetleniu klawiatury na iOS.

Podczas używania setSelectionRange()ważne jest, aby ustawić typ wejścia na text, w przeciwnym razie może generować wyjątki w Chrome (zobacz selectionStart / selectionEnd on input type = "number", które nie są już dozwolone w Chrome ).


0

Jeśli ktoś ponownie napotka ten problem, mam tutaj czyste rozwiązanie JS, które (w tej chwili) działa na wszystkich przeglądarkach, w tym. mobilny

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

(bez setTimeout () nie działa w Safari, mobilnej przeglądarce Safari i MS Edge)

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.