2010-05-19 6 views
28

Я использую контентные элементы div в своем веб-приложении, и я пытаюсь найти решение, позволяющее ограничить количество символов, разрешенных в этой области, и как только предел будет удачен, попытка чтобы вводить символы просто ничего не делает. Это то, что я до сих пор:Ограничение количества символов в ContentEditable div

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

Это действительно ограничивает количество символов до числа, указанного на «Макс», однако, как только текст района устанавливается на Jquery .text() Функция курсор возвращается в исходное положение к началу области. Поэтому, если пользователь продолжает печатать, введенные символы будут вставлены в начале текста, и последний символ текста будет удален. Так что, действительно, мне нужен какой-то способ держать курсор в конце текста контентной области.

ответ

40

Как насчет передачи объекта event объекта вашей функции и вызова e.preventDefault(), если максимум достигнут?

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

Хотя, возможно, вам придется сделать немного больше, чтобы позволить пользователю делать такие вещи, как «удалить».


EDIT:

Добавлена ​​поддержка для ключа 'Удалить'.


EDIT 2:

Кроме того, вы, вероятно, избавиться от keyup обработчика. keydown должно быть достаточно.

+0

работает как шарм! :-) Я также добавил условные обозначения для клавиш со стрелками и backspace/delete, кроме того, что он отлично работает. –

+8

Вставка через контекстное меню или меню редактирования все равно может привести к превышению пользователем. –

+0

@Tim Down - очень верно. Неизбежно (насколько мне известно), если используется contentEditable div, поскольку нет события 'change'. Мое решение было специфическим для вопроса. Твой очень точно покрывает общий недостаток представленного подхода. – user113716

11

Во-первых, это раздражает пользователя: я бы предложил вместо этого сделать что-то похожее на поле комментариев StackOverflow, которое позволяет вам вводить столько или меньше, как вам нравится, показывает вам сообщение о том, сколько символов вы набрали и слишком ли много или слишком мало, и отказывается предоставить комментарий, длина которого недействительна.

Во-вторых, если вам действительно необходимо ограничить длину текста, заменив все содержимое <div> на каждое нажатие клавиши, если содержимое слишком длинное, излишне дорого и сделает редактор невосприимчивым к более медленным машинам. Я предлагаю обработать событие keypress и просто запретить вставлять символ с помощью preventDefault() на событие (или в IE, установив returnValue события true, при условии, что вы используете attachEvent). Это не помешает пользователю вставлять текст, поэтому вам нужно обработать событие paste (которого нет в Opera или Firefox < 3, так что для этого вам понадобится какое-то решение для опроса) , Поскольку вы не сможете получить доступ к предварительно вставленному контенту, у вас не будет никакого способа узнать, приведет ли паста к личным ограничениям, поэтому вам нужно будет установить таймер, чтобы снова проверить длину после пасты. Все, что имеет место, первый вариант кажется мне предпочтительным.

+1

Очень хорошие моменты. Тим, я полностью забыл принять меры по вставке учетной записи или любой способ получить текст в редакторе, который не будет генерировать событие нажатия клавиши. И да, я никогда не был в восторге от решения об замене всего контента, это был просто быстрый первоначальный удар по проблеме. Так что теперь, глядя на него, мне просто нужно пойти с решением разрешить неограниченное количество символов, но предупредить пользователя о том, когда они закончились, и не разрешить сохранение содержимого. –

+0

это ответ – MorganTiley

+0

Событие 'input' может обрабатывать случай' paste'. – Lewis

0
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

Более обобщенно пересмотр @ user113716 Ответим, который не работает на нескольких contenteditable полей (он подсчитывает общее количество символов для всех элементов, соответствующих указанным идентификатором, так что вы можете ввести только количество символов общей на странице).

Это решение позволяет использовать общий класс и независимо от количества символов в каждом разрешающем контент поле.

HTML-:

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

И 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(); 
    } 
} 
16

Простой способ для достижения этой цели:

<div onkeypress="return (this.innerText.length <= 256)" contenteditable="true"> 
+0

Samurai, содержимое может быть удалено. Кнопка «Backspace» не будет считаться нажатием клавиши. –

+0

Я смутил 'keypress' с' keydown'. В случае нажатия клавиши это не будет препятствовать пользователю вставлять текст в нем, который превышает максимальную длину, но ключ возврата и удаления действительно «безопасен». – Sumurai8

+0

путь проще, чем другие ответы. –

3

следующее решение также рассматривает клавиши управления (которые соответствуют к непечатаемым символам).

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

Если вы хотите, чтобы это работало с классами. Другими словами, элемент будет иметь возможность разделить имена классов и до сих пор имеют свой собственный уникальный счет:

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(); 
    } 
} 
1
$("[contenteditable=true]").keydown(function(e) { 
    var max = $(this).attr("maxlength"); 
    if (e.which != 8 && $(this).text().length > max) { 
     e.preventDefault(); 
    } 
}); 
2

Это самый лучший способ сделать это наиболее обобщающие форму и просто отлично работает для меня!

<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

Это так, как я сделал это с помощью JQuery привязки, что делает его легким для меня, просто добавив свойство ввода данных длины в редактируемый элемент контента. Просто добавьте код javascript в любом месте документа.

$(document).ready(function(){ 
 
\t // Excempt keys(arrows, del, backspace, home, end); 
 
\t var excempt = [37,38,39,40,46,8,36,35]; 
 
\t // Loop through every editiable thing 
 
\t $("[contenteditable='true']").each(function(index,elem) { 
 
\t  var $elem = $(elem); 
 
\t  // Check for a property called data-input-length="value" (<div contenteditiable="true" data-input-length="100">) 
 
\t  var length = $elem.data('input-length'); 
 
\t  // Validation of value 
 
\t  if(!isNaN(length)) { 
 
\t  \t // Register keydown handler 
 
\t   $elem.on('keydown',function(evt){ 
 
\t   \t // If the key isn't excempt AND the text is longer than length stop the action. 
 
\t    if(excempt.indexOf(evt.which) === -1 && $elem.text().length > length) { 
 
\t    evt.preventDefault(); 
 
\t    return false; 
 
\t    } 
 
\t   }); 
 
\t  } 
 
\t }); 
 
});
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>

+0

Это не сработает, если вы вставляете текст. – zihaow