web-dev-qa-db-fra.com

Chrome compte les caractères incorrects dans textarea avec l'attribut maxlength

Voici un exemple:

$(function() {
  $('#test').change(function() {
    $('#length').html($('#test').val().length)
  })
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id=test maxlength=10></textarea>
length = <span id=length>0</span>

Remplissez textarea avec des lignes (un caractère sur une ligne) jusqu'à ce que le navigateur le permette . Lorsque vous avez terminé, laissez textarea et le code js calculera également les caractères.

Donc, dans mon cas, je ne pouvais entrer que 7 caractères (y compris les espaces) avant que Chrome ne m'arrête. Bien que la valeur de l'attribut maxlength soit 10:

imgur

39
Roman Pominov

Vos retours chariot sont considérés comme 2 caractères chacun lorsqu'il s'agit de maxlength.

1\r\n
1\r\n
1\r\n
1

Mais il semble que le javascript seul puisse être l’un des \r\n (je ne sais pas lequel) qui ne fait qu’ajouter à 7 .

27
Neal

Voici comment faire en sorte que votre code javascript corresponde au nombre de caractères que le navigateur pense être dans la zone de texte:

http://jsfiddle.net/FjXgA/53/

$(function () {
    $('#test').keyup(function () {
        var x = $('#test').val();

        var newLines = x.match(/(\r\n|\n|\r)/g);
        var addition = 0;
        if (newLines != null) {
            addition = newLines.length;
        }

        $('#length').html(x.length + addition);
    })
})

En gros, vous comptez seulement le nombre total de sauts de ligne dans la zone de texte et ajoutez 1 au nombre de caractères pour chacun. 

34
Tim

Pour des raisons inconnues, jQuery convertit toujours toutes les nouvelles lignes de la valeur d'un <textarea> en un seul caractère. C'est-à-dire que si le navigateur lui donne \r\n pour une nouvelle ligne, jQuery s'assure qu'il ne s'agit que de \n dans la valeur de retour de .val().

Chrome et Firefox comptent tous deux la longueur des balises <textarea> de la même manière aux fins de "maxlength".

Cependant, la spécification HTTP insiste sur le fait que les nouvelles lignes doivent être représentées par \r\n. Ainsi, jQuery, webkit et Firefox se trompent tous.

Le résultat est que "maxlength" sur les balises <textarea> est pratiquement inutile si votre code côté serveur a vraiment une taille maximale fixe pour une valeur de champ. 

Modifier - À ce stade (fin 2014), il semble que Chrome (38) se comporte correctement. Cependant, Firefox (33) ne compte toujours pas chaque retour imposé comme deux caractères.

14
Pointy

Il semble que la bonne méthode, basée sur la réponse de Pointy ci-dessus, consiste à compter toutes les nouvelles lignes comme deux caractères. Cela uniformisera le contenu des navigateurs et correspondra à ce qui sera envoyé une fois posté.

Ainsi, nous pourrions suivre les spécifications et remplacer toutes les occurrences d’un retour chariot non suivi d’une nouvelle ligne et de toutes les nouvelles lignes non suivies d’un retour chariot avec une paire retour chariot - saut de ligne.

var len = $('#test').val().replace(/\r(?!\n)|\n(?!\r)/g, "\r\n").length;

Utilisez ensuite cette variable pour afficher la longueur de la valeur textarea, ou la limiter, etc.

13
matt

Il semble que javascript considère également la longueur du caractère de nouvelle ligne.

Essayez d'utiliser:


var x = $('#test').val();

x = x.replace(/(\r\n|\n|\r)/g,"");    

$('#length').html(x.length);

Je l'ai utilisé dans votre violon et ça fonctionnait. J'espère que cela t'aides.

3
anuragsn7

En effet, une nouvelle ligne est en réalité de 2 octets, et donc de 2 longs. JavaScript ne le voit pas de cette façon et ne comptera donc que 1, soit 7 (3 nouvelles lignes).

1
Rene Pot

Voici une solution plus universelle, qui remplace la fonction 'val' de jQuery. Fera de cette question dans un article de blog bientôt et un lien ici.

var originalVal = $.fn.val;
$.fn.val = function (value) {
    if (typeof value == 'undefined') {
        // Getter

        if ($(this).is("textarea")) {
            return originalVal.call(this)
                .replace(/\r\n/g, '\n')     // reduce all \r\n to \n
                .replace(/\r/g, '\n')       // reduce all \r to \n (we shouldn't really need this line. this is for paranoia!)
                .replace(/\n/g, '\r\n');    // expand all \n to \r\n

            // this two-step approach allows us to not accidentally catch a perfect \r\n
            //   and turn it into a \r\r\n, which wouldn't help anything.
        }

        return originalVal.call(this);
    }
    else {
        // Setter
        return originalVal.call(this, value);
    }
};
1
Stachu
var value = $('#textarea').val();
var numberOfLineBreaks = (value.match(/\n/g)||[]).length;
$('#textarea').attr("maxlength",500+numberOfLineBreaks);

fonctionne parfaitement sur Google déjà dans IE pour éviter le script! Dans IE, la "ligne de rupture" n'est comptée qu'une seule fois, donc évitez cette solution dans IE!

0
Fabio

Si vous souhaitez obtenir la longueur restante du contenu de la zone de texte, vous pouvez utiliser la correspondance avec la chaîne contenant les sauts de ligne.

HTML:

<textarea id="content" rows="5" cols="15" maxlength="250"></textarea>

JS:

var getContentWidthWithNextLine = function(){
    return 250 - content.length + (content.match(/\n/g)||[]).length;
}
0
Rubi saini