web-dev-qa-db-fra.com

Limitation du nombre de caractères dans un div ContentEditable

J'utilise des éléments div contenteditable dans mon application Web et j'essaie de trouver une solution pour limiter le nombre de caractères autorisés dans la zone. Une fois que la limite est atteinte, tenter de saisir des caractères ne fait tout simplement rien. C'est ce que j'ai jusqu'ici:

var content_id = 'editable_div';

//binding keyup/down events on the contenteditable div
$('#'+content_id).keyup(function(){ check_charcount(content_id, max); });
$('#'+content_id).keydown(function(){ check_charcount(content_id, max); });

function check_charcount(content_id, max)
{   
    if($('#'+content_id).text().length > max)
    {
        $('#'+content_id).text($('#'+content_id).text().substring(0, max));
    }
}

Ceci ne limite pas le nombre de caractères au nombre spécifié par 'max'. Cependant, une fois que le texte de la zone est défini par la fonction jquery .text (), le curseur se réinitialise au début de la zone. Ainsi, si l'utilisateur continue à taper, les nouveaux caractères entrés seront insérés au début du texte et le dernier caractère du texte sera supprimé. Donc, vraiment, j'ai juste besoin d'un moyen de garder le curseur à la fin du texte de la zone pouvant être modifiée. 

32
Bill Dami

Pourquoi ne pas transmettre l'objet event à votre fonction et appeler e.preventDefault() si le maximum est atteint?

var content_id = 'editable_div';  

max = 10;

//binding keyup/down events on the contenteditable div
$('#'+content_id).keyup(function(e){ check_charcount(content_id, max, e); });
$('#'+content_id).keydown(function(e){ check_charcount(content_id, max, e); });

function check_charcount(content_id, max, e)
{   
    if(e.which != 8 && $('#'+content_id).text().length > max)
    {
       // $('#'+content_id).text($('#'+content_id).text().substring(0, max));
       e.preventDefault();
    }
}

Cependant, vous devrez peut-être faire un peu plus pour permettre à l'utilisateur de faire des choses comme «supprimer».


MODIFIER:

Ajout du support pour la clé 'supprimer'.


EDIT 2:

En outre, vous pourriez probablement vous débarrasser du gestionnaire keyup. keydown devrait suffire.

42
user113716

Un moyen simple d'y parvenir:

<div onkeypress="return (this.innerText.length <= 256)" contenteditable="true">
19
Bala Velayutham

Tout d'abord, ce genre de chose est irritant pour l'utilisateur: je suggérerais plutôt de faire quelque chose de similaire au champ de commentaire de StackOverflow, qui vous permet de taper autant ou aussi peu que vous le souhaitez, vous montre un message vous indiquant le nombre de caractères que vous avez tapés et si c'est trop ou trop peu, et refuse de vous laisser soumettre un commentaire dont la longueur n'est pas valide.

Deuxièmement, si vous devez réellement limiter la longueur du texte, remplacer le contenu entier du <div> sur chaque frappe si le contenu est trop long est inutilement coûteux et rendra l'éditeur insensible aux machines lentes. Je suggère de gérer l'événement keypress et d'empêcher simplement le caractère d'être inséré à l'aide de preventDefault() sur l'événement (ou dans IE, en définissant la valeur returnValue de l'événement sur true, en supposant que vous utilisez attachEvent). Cela n'empêchera pas l'utilisateur de coller du texte, vous devrez donc gérer l'événement paste (qui n'existe pas dans Opera ou Firefox <3, vous aurez donc besoin d'une sorte de solution basée sur une interrogation pour ceux-ci). . Etant donné que vous ne pourrez pas accéder au contenu collé à l'avance, vous ne saurez pas si le collage vous emportera au-delà de la limite de caractères. Vous devrez donc définir un minuteur pour vérifier la longueur sous peu. après la pâte. Tout cela étant le cas, la première option me semble préférable.

16
Tim Down

La solution suivante considère également les touches de contrôle (qui correspondent à des caractères non imprimables).

//Maximum number of characters
var max = 200;

$('#editable_div').keydown(function(e) {
    var keycode = e.keyCode;

    //List of keycodes of printable characters from:
    //http://stackoverflow.com/questions/12467240/determine-if-javascript-e-keycode-is-a-printable-non-control-character
    var printable = 
        (keycode > 47 && keycode < 58)   || // number keys
        keycode == 32 || keycode == 13   || // spacebar & return key(s) (if you want to allow carriage returns)
        (keycode > 64 && keycode < 91)   || // letter keys
        (keycode > 95 && keycode < 112)  || // numpad keys
        (keycode > 185 && keycode < 193) || // ;=,-./` (in order)
        (keycode > 218 && keycode < 223);   // [\]' (in order)

    if (printable) {
        //Based on the Bala Velayutham's answer
        return $(this).text().length <= max; 
    }
});
4
Vito Gentile

C’est ce que j’ai fait en liant jQuery, ce qui m’a facilité la tâche en ajoutant simplement une propriété data-input-length à un élément éditable de contenu . Ajoutez simplement le code javascript n’importe où dans votre document.

$(document).ready(function(){
	// Excempt keys(arrows, del, backspace, home, end);
	var excempt = [37,38,39,40,46,8,36,35];
	// Loop through every editiable thing
	$("[contenteditable='true']").each(function(index,elem) {
	    var $elem = $(elem);
	    // Check for a property called data-input-length="value" (<div contenteditiable="true" data-input-length="100">)
	    var length = $elem.data('input-length');
	    // Validation of value
	    if(!isNaN(length)) {
	    	// Register keydown handler
	        $elem.on('keydown',function(evt){
	        	// If the key isn't excempt AND the text is longer than length stop the action.
	            if(excempt.indexOf(evt.which) === -1 && $elem.text().length > length) {
	               evt.preventDefault();
	               return false;
	            }
	        });
	    }
	});
});
div {
  background-color:#eee;
  border: 1px solid black;
  margin:5px;
  width:300px;
  height:100px;
  }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div contenteditable="true" data-input-length="100">
You can type a 100 characters here
</div>
<div contenteditable="true" data-input-length="150">
You can type a 150 characters here
</div>
<div contenteditable="true" data-input-length="10">
You can type a 10 characters here
</div>

4
Tschallacka

Ceci est la meilleure façon de faire cette forme plus généralisée et fonctionne très bien pour moi!

<div contenteditable="true" name="choice1" class="textfield" max="255"></div>
    $('.textfield').on("keypress paste", function (e) {
        if (this.innerHTML.length >= this.getAttribute("max")) {
            e.preventDefault();
            return false;
        }
    });
3
VizardCrawler
$("[contenteditable=true]").keydown(function(e) {
    var max = $(this).attr("maxlength");
    if (e.which != 8 && $(this).text().length > max) {
        e.preventDefault();
    }
});
1
Yuval Perelman

Une révision plus générale de la réponse de @ user113716 qui ne fonctionne pas pour plusieurs champs contenteditables (elle compte le nombre total de caractères pour tous les éléments correspondant à l'id donné, vous ne pouvez donc entrer que max/ total sur la page) .

Cette solution vous permet d'utiliser une classe générale et limite indépendamment le nombre de caractères de chaque champ contenteditable.

le html:

<div contenteditable="true" name="choice1" class="textfield"></div>

Et le JavaScript:

MAX_TEXTINPUT = 10;
TEXTFIELD_CLASS = "textfield"

$(document).ready(function() {

    //binding keyup/down events on the contenteditable div
    $('.'+TEXTFIELD_CLASS).keydown(function(e){ check_charcount(TEXTFIELD_CLASS, MAX_TEXTINPUT, e); });

})

function check_charcount(inputclass, max, e) {   
    var focused = $(document.activeElement)

    if(focused.hasClass(inputclass) && e.which != 8 && $(focused).text().length >= max)
    {
        e.preventDefault();
    }
}
0
Wes Modes
var onKeyPress = function () {
    var keyCode = window.event.keyCode,
        isNumeric = (keyCode > 47 && keyCode < 58),
        isNotEnterKey = !!(window.event.keyCode !== 13);

        (isNotEnterKey) || (this.blur());

        return (isNumeric && this.innerText.length < 3);
};
0
shawndumas

Si vous souhaitez le faire fonctionner avec des classes. En d'autres termes, l'élément serait capable de partager les noms de classe et aurait toujours son propre compte 

var content_id = '.myclass';  

max = 1;
//binding keyup/down events on the contenteditable div
$(content_id).keyup(function(e){ check_charcount(this, max, e); });
$(content_id).keydown(function(e){ check_charcount(this, max, e); });

function check_charcount(elem, max, e){   
    if(e.which != 8 && $(elem).text().length >= max){       
        e.preventDefault();
    }
}
0
Al Serize