Zend Form TextArea带有倒计时字符和StringLength Validator - 不同的calc

时间:2013-04-12 09:51:19

标签: zend-framework zend-form zend-validate

在我的表格中,我有一个zend_form_element_textarea。对于这个元素,我添加一个验证器StringLength,如下所示:

$this->addElement('textarea', 'text', array('label' => 'F_MESSAGE_SMS_TEXT', 'required' => true, 'class' => 'fieldLiveLimit', 'limit' => 160));
$this->text->addValidator('StringLength', false, array('max' => 160));

我使用脚本javascript显示实时倒计时字符:

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

除了一件事,这很有效。如果在文本区域内有新行,则验证器将新行计为两个字符,而我的JS脚本为一个。 谁错了?我认为是zend验证器,但它看起来很奇怪,然后问你!

1 个答案:

答案 0 :(得分:1)

这与换行符有关,正如Pankrates用户在他的评论中已经指出的那样。

事实上,这个问题比起初看起来要复杂得多,因为它至少有两个维度:

  1. jQuery剥离val()函数中的回车符:“目前,在textarea元素上使用.val()从浏览器报告的值中删除回车符。” { {3}}。
  2. 浏览器与\r\n的换行符的计算方式不一致。有关SO的相关问题,请参阅jQuery documentationhere。但是,在我的系统上安装的所有浏览器(Firefox 20.0和Chrome 26.0)上,\r\n都算作两个字符,所以我无法确认。
  3. 请参阅此小代码片段进行演示:

    <?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>
    

    对于第一个框,它会给我jQuery: 11, JS: 11, PHP: 11,但对于第二个框,我得到jQuery: 11, JS: 12, PHP: 12

    我能想到几种解决方案(其中没有一种是理想的):

    1. 使用表单中的Zend_Filter_PregReplace将所有\r\n替换为\n。 Pro:计数将与jQuery的val()一致并且相对容易。 Con:您正在销毁用户的换行符,这可能会导致不必要的结果。
    2. here Zend_Validate_StringLength,以便您可以在\r\n方法中将\n替换为isValid()。 Pro:将保留用户的换行符Con:您可能会得到一个超过200个字符的有效结果,因为\r\n被计为一个字符,您需要引入一个新类。
    3. 使用Decorate将所有换行符替换为\r\n:Pro:简单,Con:如果您的用户有\n作为换行符,则会再次使您不一致结果。
    4. 我希望这个答案会根据您应用的具体情况向您展示如何解决这种情况。