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() });
user140550
źródło
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();
});

źródło
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);
});
Alex0007
źródło
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();
});
Joe Chung
źródło
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);
});
ThiagoPXP
źródło
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.

johntrepreneur
źródło
1

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

$("#souper_fancy").focus(function() {
    var tempSouper = $(this);
    setTimeout(function(){
        tempSouper.select();
    },100);
});
rubiwachs
źródło
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);
user2941872
źródło
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 ).

andrewh
źródło
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)

Claudio
źródło