【问题标题】:Zend Form TextArea with countdown characters and StringLength Validator - different calcZend Form TextArea 带有倒计时字符和 StringLength Validator - 不同的计算
【发布时间】:2013-04-12 09:51:18
【问题描述】:

在我的表单中,我有一个 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验证器,不过好像真的是个奇怪的东西然后问你!

【问题讨论】:

  • 只是一个疯狂的猜测:可能与行尾字符的差异有关,即“\n”与“\r\n”。但是,由于这是特定于系统的,并且 javascript 和 zend lib 都在同一个系统上运行,因此应该没有什么不同。不过可能值得研究。

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


【解决方案1】:

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

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

  1. jQuery 去除val() 函数中的回车符:“目前,在 textarea 元素上使用 .val() 会从浏览器报告的值中去除回车符。” jQuery documentation .
  2. 在浏览器中如何计算带有\r\n 的换行符是不一致的。有关 SO 的相关问题,请参阅 herehere。但是,在我系统上安装的所有浏览器(Firefox 20.0 和 Chrome 26.0)上,\r\n 被计为两个字符,因此我无法确认这一点。

查看这个小代码 sn-p 进行演示:

<?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。优点:计数将与jQuery的val()一致,并且相对容易。缺点:您正在破坏用户的换行符,这可能会导致不需要的结果。
  2. Decorate Zend_Validate_StringLength 以便您可以在 isValid() 方法中将 \r\n 替换为 \n。优点:会保留用户的换行符,缺点:你可能会得到一个超过 200 个字符的有效结果,因为\r\n 被计为一个字符,你需要引入一个新类。
  3. 使用jQuery's textarea.valHooks 将所有换行符替换为\r\n:优点:简单,缺点:如果您的用户使用\n 作为换行符,则会再次出现不一致的结果。

我希望这个答案能够为您提供一些指导,告诉您如何根据应用的上下文来解决这种情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多