web-dev-qa-db-fra.com

Limiter le nombre de lignes dans textarea

Je cherche un javascript qui puisse limiter le nombre de lignes (par ligne, j'entends du texte terminé en appuyant sur Entrée sur le clavier), que l'utilisateur peut entrer dans textarea. J'ai trouvé des solutions, mais elles ne fonctionnent tout simplement pas ou ne se comportent pas vraiment étrangement ... La meilleure solution serait un plugin jquery capable de faire le travail - quelque chose comme CharLimit , mais il devrait pouvoir limiter Le nombre de lignes de texte n'est pas le nombre de caractères.

34
empi

This might help (il vaut probablement mieux utiliser jQuery, onDomReady et ajouter discrètement l'événement keydown à la zone de texte), mais testé dans IE7 et FF3:

<html>
  <head><title>Test</title></head>
  <body>
    <script type="text/javascript">
      var keynum, lines = 1;

      function limitLines(obj, e) {
        // IE
        if(window.event) {
          keynum = e.keyCode;
        // Netscape/Firefox/Opera
        } else if(e.which) {
          keynum = e.which;
        }

        if(keynum == 13) {
          if(lines == obj.rows) {
            return false;
          }else{
            lines++;
          }
        }
      }
      </script>
    <textarea rows="4" onkeydown="return limitLines(this, event)"></textarea>
  </body>
</html>

* Edit - explication: La touche est saisie si la touche ENTER est enfoncée et n'ajoute pas de nouvelle ligne si les lignes de la zone de texte ont le même numéro que les lignes de la zone de texte. Sinon, il augmente le nombre de lignes.

Edit # 2: Considérant que les gens viennent toujours à cette réponse, je pensais que je le mettrais à jour pour gérer coller, supprimer et couper, du mieux que je peux.

<html>

<head>
    <title>Test</title>
    <style>
        .limit-me {
            height: 500px;
            width: 500px;
        }
    </style>
</head>

<body>
<textarea rows="4" class="limit-me"></textarea>

<script>
    var lines = 1;

    function getKeyNum(e) {
        var keynum;
        // IE
        if (window.event) {
            keynum = e.keyCode;
            // Netscape/Firefox/Opera
        } else if (e.which) {
            keynum = e.which;
        }

        return keynum;
    }

    var limitLines = function (e) {
        var keynum = getKeyNum(e);

        if (keynum === 13) {
            if (lines >= this.rows) {
                e.stopPropagation();
                e.preventDefault();
            } else {
                lines++;
            }
        }
    };

    var setNumberOfLines = function (e) {
        lines = getNumberOfLines(this.value);
    };

    var limitPaste = function (e) {
        var clipboardData, pastedData;

        // Stop data actually being pasted into div
        e.stopPropagation();
        e.preventDefault();

        // Get pasted data via clipboard API
        clipboardData = e.clipboardData || window.clipboardData;
        pastedData = clipboardData.getData('Text');

        var pastedLines = getNumberOfLines(pastedData);

        // Do whatever with pasteddata
        if (pastedLines <= this.rows) {
            lines = pastedLines;
            this.value = pastedData;
        }
        else if (pastedLines > this.rows) {
            // alert("Too many lines pasted ");
            this.value = pastedData
                .split(/\r\n|\r|\n/)
                .slice(0, this.rows)
                .join("\n ");
        }
    };

    function getNumberOfLines(str) {
        if (str) {
            return str.split(/\r\n|\r|\n/).length;
        }

        return 1;
    }

    var limitedElements = document.getElementsByClassName('limit-me');

    Array.from(limitedElements).forEach(function (element) {
        element.addEventListener('keydown', limitLines);
        element.addEventListener('keyup', setNumberOfLines);
        element.addEventListener('cut', setNumberOfLines);
        element.addEventListener('paste', limitPaste);
    });
</script>
</body>
</html>
23
marktucks

Comment faire avec jQuery:

Lier à l'événement keyDown de textarea.

function limitTextareaLine(e) {
    if(e.keyCode == 13 && $(this).val().split("\n").length >= $(this).attr('rows')) { 
        return false;
    }
}
15
Maciej

Cette solution fonctionne:

<script type="text/javascript">
    function limitTextarea(textarea, maxLines, maxChar) {
        var lines = textarea.value.replace(/\r/g, '').split('\n'), lines_removed, char_removed, i;
        if (maxLines && lines.length > maxLines) {
            lines = lines.slice(0, maxLines);
            lines_removed = 1
        }
        if (maxChar) {
            i = lines.length;
            while (i-- > 0) if (lines[i].length > maxChar) {
                lines[i] = lines[i].slice(0, maxChar);
                char_removed = 1
            }
            if (char_removed || lines_removed) {
                textarea.value = lines.join('\n')
            }
        }
    }
</script>

et la zone de texte serait

<asp:TextBox ID="myWishTB" runat="server" Height="185px" TextMode="MultiLine" 
             Style="overflow: auto;" Width="95%" 
             onkeyup="limitTextarea(this,10,80)">
</asp:TextBox>

en HTML normal:

<textarea id="textareaID" onkeyup="limitTextarea(this,5,100)" cols="20" rows="5">   </textarea>

(Fait avec jQuery). Ce n'est pas parfait mais se soucie de l'emballage. Ne dépend pas seulement de la fin de la ligne (\ n). 
jquery scroll event a des problèmes dans mozilla et firefox si la propriété de dépassement de capacité css dans textarea n'est pas automatique, sinon supprimez les lignes correspondantes et définissez le dépassement de capacité masqué. Pourrait aider le redimensionnement css: aucun et hauteur fixe.

$('#textarea').scroll(function () {
    $(this).css("overflow", "hidden");      /* for the mozilla browser problem */
    $(this).animate({scrollTop: $(this).outerHeight()});
    while ($(this).scrollTop() > 0) {       /* for the copy and paste case */               
        lines=$(this).val().slice(0,-1);
        $(this).val(lines);
    }
    $(this).css("overflow", "auto");        /* For the mozilla browser problem */
});
3

Le nombre de lignes visibles/d'affichage pour un bloc de texte donné varie selon les navigateurs, les polices utilisées, etc. Vous devez définir au minimum une police et une taille de police spécifiques pour pouvoir compter de manière semi-fiable. lignes d'affichage.

UPDATE: Je vois l'édition. Ensuite, quelque chose comme le code kevchadders devrait bien vous convenir. Vous aurez besoin de js qui compte les caractères et les\r\n et vérifie par rapport à une limite définie par l'utilisateur. De plus, si vous n'utilisez pas son script, veillez à en utiliser un qui implique une vérification d'intervalle de temps et/ou les événements onKeyDown/onKeyUp de la zone de texte. C'est peut-être pour cette raison que certains scripts que vous avez testés semblent "se comporter étrangement".

3
alphadogg

exemple jQuery. Cela fonctionne à la fois pour taper et coller.

  //Limit to # of rows in textarea or arbitrary # of rows
  $('#yourtextarea').bind('change keyup', function(event) {
    //Option 1: Limit to # of rows in textarea
    rows = $(this).attr('rows');
    //Optiion 2: Limit to arbitrary # of rows
    rows = 6;

    var value = '';
    var splitval = $(this).val().split("\n");

    for(var a=0;a<rows && typeof splitval[a] != 'undefined';a++) {
      if(a>0) value += "\n";
      value += splitval[a];
    }
    $(this).val(value);
  });
2
user158456

C'est fondamentalement la même chose que la réponse d'Ivan, en utilisant jQuery. Je l'ai testé pour un projet personnel; semble bien fonctionner.

<script type="text/javascript" charset="utf-8">
  $(function() 
  {
    function getLines(id)
    {
      return $('#' + id).val().split("\n").length
    }

  $('#testing').keyup(function() 
  {
    var allowedNumberOfLines = 4;

    if(getLines('testing') > allowedNumberOfLines)
    {
      modifiedText = $(this).val().split("\n").slice(0, allowedNumberOfLines);
      $(this).val(modifiedText.join("\n"));
    }
  });
});
</script>
1
northland_denmark

Je l'ai étendu un peu pour détecter même le débordement sans un saut de ligne manuel. Ceci est pour la taille de texte fixe avec "débordement: caché".

Pour le moment, ma solution réduit la taille de la police si elle ne correspond pas à textarea. Et le rend encore plus grand si possible.

var keynum, allowedLines = 5, defaultFontSize = 13/*px*/;

$(document).ready(function() {
    $("textarea").keydown(function(e, obj) {
        if(window.event)
            keynum = e.keyCode;
        else if (e.which)
            keynum = e.which;

        if (keynum == 13 && allowedLines <= $(this).val().split("\n").length)
            return false;
    });
    $("textarea").keyup(function(e, obj) {
        // Avoid copy-paste
        if (allowedLines < $(this).val().split("\n").length) {              
            lines = $(this).val().split("\n").slice(0, allowedLines);
            $(this).val( lines.join('\n') );
        }

        // Check overflow
        if ((this.clientHeight < this.scrollHeight)) {
            while ((this.clientHeight < this.scrollHeight)) {
                currFontSize = $(this).css('font-size');
                finalNum = parseFloat(currFontSize, 11);
                stringEnding = currFontSize.slice(-2);
                $(this).css('font-size', (finalNum-1) + stringEnding);
            }
        } else if ($(this).css('fontSize') != defaultFontSize+'px')  {
            while ($(this).css('font-size') != defaultFontSize+'px') {
                // First lets increase the font size
                currFontSize = $(this).css('font-size');
                finalNum = parseFloat(currFontSize, 11);
                stringEnding = currFontSize.slice(-2);
                $(this).css('font-size', (finalNum+1) + stringEnding);
                // lets loop until its enough or it gets overflow again
                if(this.clientHeight < this.scrollHeight) {
                    // there was an overflow and we have to recover the value
                    $(this).css('font-size', currFontSize);
                    break;
                }
            }
        }
    });
});
0
vellotis