web-dev-qa-db-fra.com

La sélection de texte mis au point à l'aide de jQuery ne fonctionne pas dans Safari et Chrome

J'ai le code jQuery suivant (similaire à cette question ) qui fonctionne dans Firefox et IE, mais échoue (aucune erreur, cela ne fonctionne pas) dans Chrome et Safari. Des idées pour une solution de contournement?

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

C'est l'événement onmouseup qui entraîne la désélection de la sélection. Il suffit donc d'ajouter:

$("#souper_fancy").mouseup(function(e){
    e.preventDefault();
});
186
keithnorm
$('#randomfield').focus(function(event) {
    setTimeout(function() {$('#randomfield').select();}, 0);
});
24
Alex0007

Cela fonctionne très bien pour les éléments input type = "text". Quel type d'élément est #souper_fancy?

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

Le simple fait d'empêcher l'utilisation de la souris par défaut entraîne l'activation permanente de la sélection de texte. L'événement MOUSEUP est chargé d'effacer la sélection de texte. Cependant, en empêchant son comportement par défaut, vous ne pouvez pas désélectionner le texte à l'aide de la souris.

Pour éviter cela et faire en sorte que la sélection de texte fonctionne à nouveau, vous pouvez définir un indicateur sur FOCUS, le lire dans MOUSEUP et le réinitialiser pour que les futurs événements MOUSEUP fonctionnent comme prévu.

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

Bien que cela fonctionne pour le sélectionner dans IE, Firefox, Chrome, Safari et Opera, il ne vous laissera pas le modifier en cliquant une seconde fois dans Firefox, Chrome et Safari. Pas tout à fait sûr, mais je pense que cela peut être dû au fait que ces 3 navigateurs réémettent un événement focus même si le champ a déjà le focus, vous ne permettant donc jamais d'insérer le curseur (puisque vous le sélectionnez à nouveau), alors que dans IE et Opera semble ne pas le faire, l’événement de focus n’a pas été déclenché à nouveau et le curseur est donc inséré.

J'ai trouvé un meilleur correctif dans cet article de Stack qui n'a pas ce problème et fonctionne dans tous les navigateurs.

1
johntrepreneur

Comme il y a un scintillement lorsque vous utilisez setTimeout, il existe une autre solution basée sur un événement ..____. Ainsi, l'événement 'focus' associe l'événement 'mouseup' et le gestionnaire d'événements se détache à nouveau.

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

Puis câblez le premier événement

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

Cela devrait également fonctionner en chrome:

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

Utilisez setSelectionRange() dans un rappel à 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;
    });
});

Utilisez setSelectionRange() au lieu de select() car select() ne fonctionne pas dans Safari mobile (voir Sélection par programme du texte dans un champ de saisie sur les appareils iOS (Safari mobile) ).

Il est nécessaire d’attendre avec requestAnimationFrame avant de sélectionner le texte, sinon l’élément ne défile pas correctement après le passage du clavier sur iOS.

Lorsque vous utilisez setSelectionRange(), il est important de définir le type d'entrée sur text, sinon des exceptions peuvent être levées sous Chrome (voir selectionStart/selectionEnd à propos du type d'entrée = "numéro" n'étant plus autorisé dans Chrome ). 

0
andrewh

Si quelqu'un rencontre encore ce problème, je trouve ici une solution JS pure qui fonctionne (pour le moment) sur tous les navigateurs, y compris mobile

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

(sans setTimeout () cela ne fonctionne pas sur Safari, Safari mobile et MS Edge)

0
Claudio