70

I'm trying to over ride the default error message label with a div instead of a label. I have looked at this post as well and get how to do it but my limitations with CSS are haunting me. How can I display this like some of these examples:

Example #1 (Dojo) - Must type invalid input to see error display
Example #2

Here is some example code that overrides the error label to a div element

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

Now I'm at a loss on the css part but here it is:

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

UPDATE:

Okay I'm using this code now but the image and the placement on the popup is larger than the border, can this be adjusted to be dynamic is height?

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

the css is the same as below (your css code)

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>
Community
  • 1
  • 1
Phill Pafford
  • 83,471
  • 91
  • 263
  • 383
  • Would you add your HTML form code as well? It's hard to tell why the radio is not working based on the javascript alone. – Nadia Alramli May 20 '09 at 14:47
  • I added more details with a preview to my answer. The code is really working. If you want to customize the error message, more you could add more css but the basics are all there. – Nadia Alramli May 20 '09 at 19:47
  • About the page going blank when you enter values. I don't think it has anything to do with the changes I suggested. If you remove the errorPlacement function do you still get a blank page? if you do, then the issue is not related to this question anymore. It is impossible to tell what is going on without seeing the actual page. Or getting more details. Your example is working perfectly fine for me. The issue is probably due to an uncaught javascript error somewhere else. – Nadia Alramli May 22 '09 at 15:10
  • I did remove the errorPlacement function and it works fine without it. I'm at a lose because I want to use what you have provided but it's not functioning correctly. – Phill Pafford May 22 '09 at 15:36
  • hmm, try to add an alert to the errorPlacement function and see if it gets called when the page goes blank. If that didn't help wrap the inside of the function in a try/catch. Like this: try{ /* the code */} catch(e) {alert(e);} – Nadia Alramli May 22 '09 at 15:49
  • I've also noticed that error.insertBefore(element) is missing a ; at the end. Change it to error.insertBefore(element); otherwise it might not work on IE – Nadia Alramli May 22 '09 at 15:50
  • If you are using firefox, try to use firebug to debug the code execution. Add a stop point on the error placement function and see if anything is going wrong. – Nadia Alramli May 22 '09 at 15:51
  • thanks for all your help I have used some of the code you have provided and in an effort to get something out I used something a little simpler. But I think this is a missing feature in the Validation plug-in for jQuery, You might want to think about creating a plug-in that has two or more display options (Different CSS and Element Placing) for users to use with the validation plug-in. BTW nice blog will be checking this out from now on to see whats new. Thanks again for all your help on this :) – Phill Pafford May 22 '09 at 17:18

7 Answers7

187

You can use the errorPlacement option to override the error message display with little css. Because css on its own will not be enough to produce the effect you need.

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

    });
});

You can play with the left and top css attributes to show the error message on top, left, right or bottom of the element. For example to show the error on the top:

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

And so on. You can refer to jQuery documentation about css for more options.

Here is the css I used. The result looks exactly like the one you want. With as little CSS as possible:

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

And here is the background image you need:

alt text
(source: scriptiny.com)

If you want the error message to be displayed after a group of options or fields. Then group all those elements inside one container a 'div' or a 'fieldset'. Add a special class to all of them 'group' for example. And add the following to the begining of the errorPlacement function:

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

If you only want to handle specific cases you can use attr instead:

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

That should be enough for the error message to be displayed next to the parent element.

You may need to change the width of the parent element to be less than 100%.


I've tried your code and it is working perfectly fine for me. Here is a preview: alt text

I just made a very small adjustment to the message padding to make it fit in the line:

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

You can change those numbers to increase/decrease the padding on top/bottom or left/right. You can also add a height and width to the error message. If you are still having issues, try to replace the span with a div

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

And then give the container a width (this is very important)

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

About the blank page. As I said I tried your code and it is working for me. It might be something else in your code that is causing the issue.

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Nadia Alramli
  • 111,714
  • 37
  • 173
  • 152
  • Thanks I like the errorPlacement option but the CSS is more of what I'm looking for. If you look at the two example links I have given I wanted something to look like those. Thanks again. – Phill Pafford May 18 '09 at 12:33
  • also one other thing, when I have a radio or checkbox group the error div displays over some of the options I need to select. is there a way to display after the group? – Phill Pafford May 18 '09 at 21:11
  • I expanded the answer a little more. If you follow the instructions you will get the result you want. – Nadia Alramli May 18 '09 at 22:10
  • Updated my code above please review and things are very close to what I would like. Thanks :) – Phill Pafford May 20 '09 at 14:31
  • added HTML sorry about that :) – Phill Pafford May 20 '09 at 15:25
  • using the validation plugin with you code I hit submit and the popups come as expected but when I go to eneter in values to make the popups go away my whole page goes blank. any idea as to why? – Phill Pafford May 20 '09 at 15:41
  • The pop over display works well thanks but when I enter in a value into the text field the whole page goes blank. Any thoughts as to why? – Phill Pafford May 22 '09 at 14:31
  • Don't know if your still interested in helping but I did find this jQuery plug-in with kinda what I'm looking for in a CSS sense: http://www.position-absolute.com/articles/jquery-form-validator-because-form-validation-is-a-mess/ Wanted to know how to combine the CSS popup to the validation plugin I'm using instead of this one. I like that it floats above the element and looks like a bubble. Thanks again for any help on this – Phill Pafford Jun 02 '09 at 14:05
  • 1
    @Phill, I'd like to help. But it is better to post this as another question. Mainly because If I edited this post anymore it will end up as a community wiki. And comments are not suitable for answers. Also posting this as another question will get more attention and possible better solutions. As a first look on the link you posted, it seems they are doing a difficult hack to display the arrow. There should be a better way of doing it. – Nadia Alramli Jun 02 '09 at 14:45
  • 2
    @Nadia - wow, you really posted a great answer here. It helped me immensely with a similar issue I had. I am really impressed by your grasp of CSS and jQuery. Nice contribution!! – David Robbins Jul 02 '09 at 03:16
  • 1
    The positioning is relative to document in your example, if this is in modal popup or such it will not work. I used this to solve this problem: `error.css('left', $(element).position().left + $(element).width() + 10); error.css('top', $(element).position().top);` – kiteloop Jun 28 '11 at 11:49
  • These error messages do not reposition themselves when the window resizes. Is there a way to code this solution so the messages are relative to the input element they represent? – Austyn Mahoney Aug 30 '11 at 22:40
  • Does anyone have an updated link for the msg_arrow.gif background image? Or even an example of what it looked like? – Jacob Stamm Sep 20 '16 at 13:16
3

I use jQuery BeautyTips to achieve the little bubble effect you are talking about. I don't use the Validation plugin so I can't really help much there, but it is very easy to style and show the BeautyTips. You should look into it. It's not as simple as just CSS rules, I'm afraid, as you need to use the canvas element and include an extra javascript file for IE to play nice with it.

Paolo Bergantino
  • 480,997
  • 81
  • 517
  • 436
  • Or, if you don't want to be able to quickly customize the bubble's colors, you can use a background image like the 2nd example. – Paolo Bergantino May 15 '09 at 23:12
  • I have looking into Beauty Tips but can't get it to work with the validation plugin with the error display. Any other thoughts? – Phill Pafford May 18 '09 at 12:34
2

Unfortunately I can't comment with my newbie reputation, but I have a solution for the issue of the screen going blank, or at least this is what worked for me. Instead of setting the wrapper class inside of the errorPlacement function, set it immediately when you're setting the wrapper type.

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

});

I'm assuming doing it this way allows the validator to know which div elements to remove, instead of all of them. Worked for me but I'm not entirely sure why, so if someone could elaborate that might help others out a ton.

2

That answer really helped me, in my case i had to filter some elements out and have special aligment on their error div,

errorPlacement:function(error,element) {
    if (element.attr("id") == "special_element") {
        // special align
    } else { // default error scheme
        error.insertAfter(element);
    }
}
Rod
  • 2,046
  • 2
  • 20
  • 24
2

A few things:

First, I don't think you really need a validation error for a radio fieldset because you could just have one of the fields checked by default. Most people would rather correct something then provide something. For instance:

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

is more likely to be changed to the right answer as the person DOESN'T want it to go to the default. If they see it blank, they are more likely to think "none of your business" and skip it.

Second, I was able to get the effect I think you are wanting without any positioning properties. You just add padding-right to the form (or the div of the form, whatever) to provide enough room for your error and make sure your error will fit in that area. Then, you have a pre-set up css class called "error" and you set it as having a negative margin-top roughly the height of your input field and a margin-left about the distance from the left to where your padding-right should start. I tried this out, it's not great, but it works with three properties and requires no floats or absolutes:

   <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>
Anthony
  • 36,459
  • 25
  • 97
  • 163
  • Thanks for your reply but the client would like to have the radio button blank and force the user to select an option. I will look into your CSS :) – Phill Pafford May 21 '09 at 14:30
  • I like this except for the radio and checkboxes, could you allow for that as well? – Phill Pafford May 21 '09 at 19:54
  • this doesn't doesn't display correctly in IE6 (Havent check other versions yet) – Phill Pafford May 21 '09 at 20:11
  • As far as radio and checkboxes, this depends on if you have a group of boxes (fieldset) or just the one. If it's a group, I suggest setting the width of the fieldset so that it leaves that padding mentioned before, and then having your error flag pointing to the whole thing, maybe even adding a class to the fieldset so that it gets a border when it has the flag, so the user knows you mean that group.... – Anthony May 21 '09 at 23:19
  • But you wouldn't really want a flag for one check box, as that doesn't make sense. What if the answer is No to the box, then it's still "done". If you have a group of boxes and they need to check at least two, then again, have the error for the fieldset, not the box. – Anthony May 21 '09 at 23:20
  • So something like:
    Hobbies
    Then, have the error point to the whole group, not one box.
    – Anthony May 21 '09 at 23:22
  • As for IE6, how is off? I don't have IE6 so I can only imagine. My numbers were a bit shabby because I didn't set specific heights and widths to the inputs, fieldsets, etc. So being more precise might fix it, depending on the issue. Then again, my company (a university) as official stated that it will no longer make accommodations for IE6 (which is to say, backwards compatibility won't be taken into account for IE6). I think this is going to be the position taken almost universally over the next year or so. – Anthony May 21 '09 at 23:28
  • I'm using the name attribute to group the radios/checkboxes together would this work? – Phill Pafford May 22 '09 at 14:33
  • You use name to group them together as data for the script that handles the data (and for JS), but you should use the fieldset element to group inputs, like a wrapper. Try it out, most browsers automatically put a border around fieldsets, which is nice. – Anthony May 22 '09 at 15:16
1

Add following css to your .validate method to change the css or functionality

 errorElement: "div",
    wrapper: "div",
    errorPlacement: function(error, element) {
        offset = element.offset();
        error.insertAfter(element)
        error.css('color','red');
    }
0

If you could provide some reason as to why you need to replace the label with a div, that would certainly help...

Also, could you paste a sample that'd be helpful ( http://dpaste.com/ or http://pastebin.com/)

weisjohn
  • 793
  • 5
  • 9
  • the default action is to place the label next to the element with the error, this causes the elements to the right of the error element to shift. wanted the error element to display as a tooltip like popup that hovers/floats over the other elements. – Phill Pafford May 14 '09 at 11:55
  • Sorry don't think I could post an image of the error div I want but the two examples above both have something similar to what I would like. Thanks --Phill – Phill Pafford May 14 '09 at 11:57