jQuery如何覆盖默认的验证错误信息显示方式,改为弹出窗或工具提示形式(CSS)?

70

我想用一个div代替标签来覆盖默认的错误消息标签。我已经看过这篇文章,知道如何做,但是我的CSS限制让我很困扰。我该如何像以下示例之一显示它:

示例#1 (Dojo) - 必须输入无效输入才能看到错误信息
示例#2

下面是将错误标签覆盖为div元素的示例代码:

$(document).ready(function(){
            $("#myForm").validate({
                rules: {
                    "elem.1": {
                        required: true,
                        digits: true
                    },
                    "elem.2": {
                        required: true
                    }
                },
                errorElement: "div"
            });                  
        });

现在我对CSS部分一无所知,但是这里有它的代码:

div.error {
        position:absolute;
        margin-top:-21px;
     margin-left:150px;
     border:2px solid #C0C097;
        background-color:#fff;
        color:white;
        padding:3px;
        text-align:left;
        z-index:1;
        color:#333333;
     font:100% arial,helvetica,clean,sans-serif;
     font-size:15px;
     font-weight:bold;  
    }

更新:

好的,我现在正在使用这段代码,但是图像和弹出窗口上的位置比边框大,这可以调整为高度动态吗?

if (element.attr('type') == 'radio' || element.attr('type') == 'checkbox') {
   element = element.parent();

   offset = element.offset();
   error.insertBefore(element)
   error.addClass('message');  // add a class to the wrapper
   error.css('position', 'absolute');
   error.css('left', offset.left + element.outerWidth());
   error.css('top', offset.top - (element.height() / 2)); // Not working for Radio, displays towards the bottom of the element. also need to test with checkbox
} else {
   // Error placement for single elements
   offset = element.offset();
   error.insertBefore(element)
   error.addClass('message');  // add a class to the wrapper
   error.css('position', 'absolute');
   error.css('left', offset.left + element.outerWidth());
   error.css('top', offset.top - (element.height() / 2));
}

这里的 CSS 与下方的 CSS 代码相同(指你的 CSS 代码)

HTML

<span>
<input type="radio" class="checkbox" value="P" id="radio_P" name="radio_group_name"/>
<label for="radio_P">P</label>
<input type="radio" class="checkbox" value="S" id="radio_S" name="radio_group_name"/>
<label for="radio_S">S</label>
</span>

您能同时添加HTML表单代码吗?仅凭JavaScript很难确定为何无法使用收音机。 - Nadia Alramli
我在我的回答中添加了更多细节和预览。代码确实可行。如果你想自定义错误消息,你可以添加更多的 CSS,但基本功能已经都在那里了。 - Nadia Alramli
我已经删除了 errorPlacement 函数,并且没有它也可以正常工作。我感到困惑,因为我想使用您提供的内容,但它没有正确地运行。 - Phill Pafford
我也注意到 error.insertBefore (element) 结尾缺少 ;。请将其更改为 error.insertBefore (element); 否则它可能无法在 IE 上工作。 - Nadia Alramli
如果你正在使用Firefox,尝试使用Firebug来调试代码执行。在错误放置函数上添加一个停止点,看看是否出了什么问题。 - Nadia Alramli
显示剩余3条评论
7个回答

187
你可以使用errorPlacement选项,使用少量的CSS覆盖错误消息的显示。因为单独的CSS不足以产生您需要的效果。
$(document).ready(function(){
    $("#myForm").validate({
        rules: {
            "elem.1": {
                required: true,
                digits: true
            },
            "elem.2": {
                required: true
            }
        },
        errorElement: "div",
        wrapper: "div",  // a wrapper around the error message
        errorPlacement: function(error, element) {
            offset = element.offset();
            error.insertBefore(element)
            error.addClass('message');  // add a class to the wrapper
            error.css('position', 'absolute');
            error.css('left', offset.left + element.outerWidth());
            error.css('top', offset.top);
        }

    });
});

您可以通过修改 left 和 top CSS 属性,将错误消息显示在元素的顶部、左侧、右侧或底部。

例如,要在顶部显示错误:

    errorPlacement: function(error, element) {
        element.before(error);
        offset = element.offset();
        error.css('left', offset.left);
        error.css('top', offset.top - element.outerHeight());
    }

等等。更多选项可以参考jQuery关于CSS的文档

这是我使用的CSS。效果与您想要的完全一样。尽可能少地使用CSS:

div.message{
    background: transparent url(msg_arrow.gif) no-repeat scroll left center;
    padding-left: 7px;
}

div.error{
    background-color:#F3E6E6;
    border-color: #924949;
    border-style: solid solid solid none;
    border-width: 2px;
    padding: 5px;
}

这是您需要的背景图片:

alt text
(来源:scriptiny.com)

如果您想在一组选项或字段后显示错误消息,则将所有元素分组到一个容器内,如 'div' 或 'fieldset' 中。为它们全部添加一个特殊类 'group'。然后在 errorPlacement 函数的开始处添加以下代码:

errorPlacement: function(error, element) {
    if (element.hasClass('group')){
        element = element.parent();
    }
    ...// continue as previously explained

如果您只想处理特定情况,可以使用attr代替:

if (element.attr('type') == 'radio'){
    element = element.parent();
}

这应该足以在父元素旁边显示错误消息。

您可能需要将父元素的宽度改为小于100%。


我尝试了您的代码,对我来说完全正常。这是一个预览: alt text

我只是对消息填充进行了非常小的调整,使其适合行:

div.error {
    padding: 2px 5px;
}

您可以更改这些数字来增加/减少顶部/底部或左侧/右侧的填充。您还可以为错误消息添加高度和宽度。如果仍然有问题,请尝试用div替换span。

<div class="group">
<input type="radio" class="checkbox" value="P" id="radio_P" name="radio_group_name"/>
<label for="radio_P">P</label>
<input type="radio" class="checkbox" value="S" id="radio_S" name="radio_group_name"/>
<label for="radio_S">S</label>
</div>

然后给容器设置宽度(这非常重要)

div.group {
    width: 50px; /* or any other value */
}

关于空白页。正如我所说,我尝试了你的代码,它对我有效。可能是你代码中其他部分导致了这个问题。


还有一件事,当我有一个单选框或复选框组时,错误提示框会显示在我需要选择的某些选项上。有没有办法在组后面显示? - Phill Pafford
使用验证插件与您的代码,我点击提交按钮,弹出窗口按预期出现,但当我输入值以使弹出窗口消失时,整个页面变空白。有什么想法吗? - Phill Pafford
1
@Phill,我很乐意帮忙。但最好将此作为另一个问题发布。主要是因为如果我再编辑这篇文章,它将变成社区维基。评论不适合作为答案。而且,将此作为另一个问题发布将获得更多关注和可能更好的解决方案。从你发的链接来看,他们正在做一项困难的技术操作来显示箭头。应该有更好的方法来完成这个操作。 - Nadia Alramli
2
@Nadia - 哇,你在这里发布了一个很棒的答案。它对我的类似问题帮助很大。我非常 impressed 你对CSS和jQuery的掌握能力。不错的贡献!! - David Robbins
1
定位是相对于文档的,在你的例子中,如果它在模态弹出窗口或类似的情况下,它将无法工作。 我使用以下代码解决了这个问题:error.css('left', $(element).position().left + $(element).width() + 10); error.css('top', $(element).position().top); - kiteloop
显示剩余8条评论

3
我使用jQuery BeautyTips来实现您所说的小气泡效果。 我不使用验证插件,所以在那方面我不能提供太多帮助,但是样式化和显示BeautyTips非常容易。 您应该研究一下它。 不像CSS规则那么简单,因为您需要使用画布元素并包含一个额外的javascript文件,以便IE与之协作。

或者,如果您不想快速自定义气泡的颜色,您可以使用像第二个示例那样的背景图像。 - Paolo Bergantino
我一直在研究美容技巧,但无法让其与验证插件和错误显示配合工作。还有其他想法吗? - Phill Pafford

2

很遗憾,由于我的新手声望,我无法发表评论,但是我有一个解决屏幕变空白问题的方法,或者至少这是对我有效的方法。不要在errorPlacement函数内设置包装器类,而是在设置包装器类型时立即设置它。

$('#myForm').validate({
    errorElement: "div",
    wrapper: "div class=\"message\"",
    errorPlacement: function(error, element) {
        offset = element.offset();
        error.insertBefore(element);
        //error.addClass('message');  // add a class to the wrapper
        error.css('position', 'absolute');
        error.css('left', offset.left + element.outerWidth() + 5);
        error.css('top', offset.top - 3);
    }

我认为这样做可以让验证器知道要删除哪些div元素,而不是所有的。这对我有用,但我不完全确定原因,如果有人能详细解释一下,那可能会对其他人有很大帮助。

});


2
那个答案真的帮了我,对我的情况来说,我需要过滤掉一些元素,并对它们的错误 div 进行特殊的对齐。
errorPlacement:function(error,element) {
    if (element.attr("id") == "special_element") {
        // special align
    } else { // default error scheme
        error.insertAfter(element);
    }
}

2

几点需要注意:

首先,我认为对于一个单选框fieldset来说,你并不需要一个验证错误,因为你可以默认勾选其中一个字段。大多数人更愿意纠正而不是提供解决方案。例如:

   Age: (*) 12 - 18 | () 19 - 30 | 31 - 50 

如果人们不想选择默认答案,他们更有可能将其更改为正确答案。如果他们看到它为空白,他们更可能认为“与你无关”并跳过它。

其次,我能够在没有任何定位属性的情况下获得您想要的效果。您只需向表单(或表单的div,无论哪种)添加右填充,以提供足够的空间来容纳您的错误,并确保您的错误将适合该区域。然后,您预先设置了一个名为“error”的css类,并将其设置为具有负边距顶部,大约是输入字段高度的距离,以及左边距,大约是从左侧到填充右侧应该开始的距离。我尝试了一下,虽然不是很好,但只需要三个属性就可以使用,不需要浮动或绝对定位:

   <style type="text/css">
    .error {
        width: 13em; /* Ensures that the div won't exceed right padding of form */
        margin-top: -1.5em;  /*Moves the div up to the same level as input */
        margin-left: 11em;   /*Moves div to the right */
        font-size: .9em;     /*Makes sure that the error div is smaller than input */
    }

   <form>
   <label for="name">Name:</label><input id="name" type="textbox" />
   <div class="error"><<< This field is required!</div>
   <label for="numb">Phone:</label><input id="numb" type="textbox" />
   <div class="error"><<< This field is required!</div>
   </form>

谢谢您的回复,但客户希望单选按钮为空,并强制用户选择一个选项。我会研究一下您的CSS :) - Phill Pafford
我喜欢这个,除了单选框和复选框,你能也允许它们吗? - Phill Pafford
这在IE6中显示不正常(还没有检查其他版本) - Phill Pafford
我正在使用name属性将单选框/复选框分组,这样可以吗? - Phill Pafford
你可以使用名称将它们作为数据分组,以便于处理数据的脚本(和JS)使用,但是你应该使用 fieldset 元素来分组输入,就像一个包装器一样。试试看,大多数浏览器会自动在 fieldsets 周围放置边框,这很好。 - Anthony
显示剩余4条评论

1
将以下CSS添加到您的.validate方法中,以更改CSS或功能。
 errorElement: "div",
    wrapper: "div",
    errorPlacement: function(error, element) {
        offset = element.offset();
        error.insertAfter(element)
        error.css('color','red');
    }

0
如果你能提供一些关于为什么需要用 div 替换 label 的理由,那肯定会有所帮助...
另外,你能粘贴一个有帮助的示例吗(http://dpaste.com/http://pastebin.com/)?

默认操作是将标签放置在带有错误的元素旁边,这会导致错误元素右侧的元素移动。想要将错误元素显示为悬停/浮动在其他元素上方的工具提示弹出窗口。 - Phill Pafford
抱歉,我无法发布我想要的错误div的图像,但是上面的两个示例都有类似于我想要的内容。谢谢。 - Phill Pafford

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接