Reputation: 2431
In my form i have a zend_form_element_textarea. For this element i add a validator StringLength like this:
$this->addElement('textarea', 'text', array('label' => 'F_MESSAGE_SMS_TEXT', 'required' => true, 'class' => 'fieldLiveLimit', 'limit' => 160));
$this->text->addValidator('StringLength', false, array('max' => 160));
and i use a script javascript for show live countdown characters:
//Text field or text area limit - get limit by field parameter
$(".fieldLiveLimit").each(function () {
var characters = $(this).attr('limit');
var remaining = calcDifference(characters, $(this).val());
if ($('.limitCounter').length > 0) {
$(this).after($('.limitCounter').first().clone());
$(this).next('.limitCounter').children('span').html(remaining);
} else {
$(this).after($("<div class='limitCounter'>" + translate('L_LIMIT_COUNTER', [remaining]) + "</div>"));
}
checkClassCounter(remaining, $(this));
$(this).bind('textchange', function (event, previousText) {
remaining = calcDifference(characters, $(this).val());
checkClassCounter(remaining, $(this));
if ($(this).val().length > characters) {
$(this).val($(this).val().substr(0, characters));
} else {
$(this).next('.limitCounter').children('span').html(remaining);
}
});
function calcDifference(characters, value) {
return characters - parseInt(value.length);
}
function checkClassCounter(remaining, element) {
if (parseInt(element.val().length) == 0) {
element.next(".limitCounter").hide();
} else {
element.next(".limitCounter").show();
if (remaining <= 10) {
element.next(".limitCounter").addClass('red-message');
} else {
element.next(".limitCounter").removeClass('red-message');
}
}
}
});
this works well, except for one thing. If inside the text area there are the new lines, the validator zend the new line it counts as two characters, while my JS script as one. who is wrong? I think the zend validator, but it seems really strange as a thing and then ask to you!
Upvotes: 1
Views: 1123
Reputation: 2730
It has to do with the line breaks, as user Pankrates already pointed out in his comment.
In fact, this problem is a lot more complex than it seems at first, because it has at least two dimensions:
val()
function: "At present, using .val() on textarea elements strips carriage return characters from the browser-reported value." jQuery documentation.\r\n
are counted. See here or here for related questions on SO. However, on all browsers I have installed on my system (Firefox 20.0 and Chrome 26.0), \r\n
are counted as two characters, so I cannot confirm this.See this little code snippet for a demonstration:
<?php
$str1 = "test\nstring";
$str2 = "test\r\nstring";
?>
<textarea id="text1"><?php echo $str1 ?></textarea>jQuery: <span id="jquery1"></span>, JS: <span id="js1"></span>, PHP: <?php echo iconv_strlen($str1) ?>
<textarea id="text2"><?php echo $str2 ?></textarea>jQuery: <span id="jquery2"></span>, JS: <span id="js2"></span>, PHP: <?php echo iconv_strlen($str2) ?>
<script type="text/javascript">
$(document).ready(function() {
$("#jquery1").text($("#text1").val().length);
$("#js1").text("<?php echo str_replace(array("\n", "\r"), array('\n', '\r'), $str1) ?>".length);
$("#jquery2").text($("#text2").val().length);
$("#js2").text("<?php echo str_replace(array("\n", "\r"), array('\n', '\r'), $str2) ?>".length);
});
</script>
For the first box it gives me jQuery: 11, JS: 11, PHP: 11
, but for the second box I get jQuery: 11, JS: 12, PHP: 12
.
There are several solutions I can think of (none of which is ideal):
Zend_Filter_PregReplace
in your form to replace all \r\n
with \n
. Pro: Counting will be consistent with that of jQuery's val()
and relatively easy. Con: You are destroying the user's line break which might lead to unwanted results.Zend_Validate_StringLength
so that you can replace \r\n
by \n
in the isValid()
method. Pro: Will preserve the user's line break, Con: You might get a valid result that is longer then 200 characters, because \r\n
is counted as one character and you need to introduce a new class.\r\n
: Pro: Simple, Con: If you have users that have \n
as line break char, it again will give you inconsistent results.I hope this answer show you some directions on how you can tackle this situation depending on your app's context.
Upvotes: 1