Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Tuesday, July 31, 2012

Dynamically Generate Form with jQuery and ASP.NET MVC

Hopefully it’s obvious that you probably won’t need to do this very often, but when it’s needed, it’s nice to have available. I thought I’d share this little helper to dynamically create a form, append it to body, and submit it...without AJAX.

First I'll show you how I'm converting my view model to a parameter list and a query string. Basically I've created an extension method that loops through properties and checks if it's an IEnumerable or not. If it is, then I loop through the values of that property. Otherwise, I just add the value. This method does not work with complex types. Typically view models are flat, so this works well most of the time.

The ToQueryString method just calls the ToParameterList, adds a ? to the front and then just selects what it needs from the parameter list.

The jQuery is pretty straight forward. I get the body, create a form with an action, loop through my param list creating a hidden input for each param, append the form to the body, and then submit it.


As always, if you know of a different and/or better way, please let me know.

If you don't need to post, you can just use a get, you could do something like this:


You can download a sample project at GitHub.

Shout it

kick it on DotNetKicks.com

Monday, June 11, 2012

Making Prettier Forms: Converting Checkboxes into Images

A couple weekends ago I went to the Big Design Conference in Dallas (recap coming soon), and I always come back inspired to help the user’s experience with the applications I write. One of the things mentioned (several times) was making forms simpler. Basically, you don’t have to make the end-user feel like they’re filling out a form. There are ways to make it seem less intimidating. One way is to swap out the typically hard-to-click checkbox or radio button with an image. It gives the user a larger click area and it looks nice…at least in my opinion.

Basically, I’m helping a friend with a small project, and the image below is what I wanted to create.

image

If you buy Stephen Anderson's book "Seductive Interaction Design", you will see a similar form to the one above...primarily just the name and contact info stuff. By the way, I definitely recommend this book.

As you can see, the “Select Classification” is not your typical radio button setup. I googled for a bit if there was already a jQuery plugin to do this type of thing and came up empty. I’m sure you almighty readers know of one, but I couldn’t find it…so I made one.

So far I’ve tested it in Firefox, IE9, Chrome, and JAWS, and it works pretty good in all of them. The way I set it up to work is based on the input and label. So you’d have the most accessible standard markup with your preferred styles for the label, and that’s how you get the effect shown above. I think it’s probably better said with code:

So it looks like a pretty typical setup so far, right? You have an input with a label. To make it more accessible, you wrap it with a fieldset and give it a legend. The primary reason you’d do this is to give screen readers some context. If you don’t need to worry about that, you could just as easy wrap it all with a div. You’re going to want to wrap it so your jQuery selector is more precise. After you markup the form, you just add the following JavaScript.

Now you’re all wired up, and you just add in your styles to whichever stylesheet classes you specified. The default stylesheet class names I specified are:

  • .Selected-Checkbox – this class is added to the label after it has been clicked
  • .Checkbox-in-focus – this class is added to the label when the checkbox/radio button is in focus

If you’re not sure the plugin is working properly, you can put it in “testMode”, like this:

$('#classification_radio_wrapper label').checkMate({testMode: true });

If you need to override my default class names, you can do that too by specifying class or focusClass in the options. I might rename class to selectedClass in the near future.

Please leave a comment if you have any questions or feedback.

The source code is available on github at https://github.com/derans/checkMate

The demo is located on 1pg.it at http://1pg.it/v9etvtn5 (also on github as the example.htm file)



Shout it

kick it on DotNetKicks.com

Thursday, June 16, 2011

jQuery Plugin: FunkyFocus v1.1


I used by little plugin in a production environment today and found one bug and a couple needed features.

The bug was with this code:

options.selectorOverride.replace('{id}', this.id);
 
Apparently it only replaces the first {id} found in the string. So I updated that line to this:
 
var selector = options.selectorOverride.replace(/{id}/gi, this.id);

One of the features I needed was a way to ignore certain elements. So I created a new option called notSelector and the default is ‘.ignore’. So basically all the selectors are $(selector).not(options.notSelector).whatever.

I also added a check for when you set the focus of an input via the code-behind in ASP.NET.

You can download the new version here.

Check out the demo here.

Thanks for reading!

kick it on DotNetKicks.com

Thursday, May 26, 2011

New jQuery Plugin: FunkyFocus


So this jQuery plugin was built to help my end-users know immediately what section of a form they’re working on. Also, don’t blame me for the name. It was given to my new plugin by my wife because I couldn’t think of anything “catchy”. Basically what this thing does is changes the background of sections of forms or individual inputs. It’ll be better to post screenshots to get the idea…so…here you go…

image

So as soon as you tab to the password textbox, you get this:

image

Here’s how you use it:

  1. Add a reference to jQuery
  2. Add a reference to the jquery.funkyfocus.js
  3. Add this line afterward: $('form').funkyFocus();

If you want to customize how you use it, you have some options. Here they are:

  • class – default is selected
  • sectionOnly – default is true
  • selectorOverride – default is form#{id} input,form#{id} select,form#{id} textarea

If you don’t want to use selected as your class, you’d use this code:

    $('form').funkyFocus({class: 'yourclassname'});

If you don’t want to change the background, but want to change the individual input, do this:

    $('form').funkyFocus({sectionOnly: false});

It would look something like this (assuming you changed the selected style to have a green background):

image

Here’s the actual plugin code:

(function($) {
    $.fn.funkyFocus = function(options) {
  var defaults = {
    class: 'selected',
    sectionOnly: true,
    selectorOverride: 'form#{id} input,form#{id} select,form#{id} textarea'
  };
  var options = $.extend(defaults, options);
  return this.each(function() {
    var selector = options.selectorOverride.replace('{id}', this.id);
    $(selector).focus(function() {
      if (options.sectionOnly)
        $(this).closest("div").addClass(options.class);
      else
        $(this).addClass(options.class);
    });
    $(selector).blur(function() {
      if (options.sectionOnly)
        $(this).closest("div").removeClass(options.class);
      else
        $(this).removeClass(options.class);
    });
        });
    };
})(jQuery);

If you’d like to know how to create a jQuery plugin, check out this post.

Download the plugin here.

Check out the demo here.

As always, please let me know if there’s a way to improve it. Thanks for reading!

Shout it

kick it on DotNetKicks.com

Sunday, May 22, 2011

Contact Form Revisited with ASP.NET MVC 3, jQuery Validator, & the jQuery Form Plugin




I recently added a partial contact view to my MVC3 project and thought I’d share since I did basically this same post over a year ago with the original MVC. I stopped using the Castle Validation because I’ve found that the MVC3 stuff is working for me now. I also am not using fluentHtml anymore because MVC3 uses that style now.

Okay…let’s get started.

We’ll start with the view model class like the last post. By the way, if you’re not familiar with the way I setup my MVC projects, see this post. (If you read my first Contact Form post, you’re probably experiencing déjà vu).

public class ContactView
{
[Required]
public string Name { get; set; }
[Required, ValidateEmail(ErrorMessage = "Valid email is required.")]
public string Email { get; set; }
[Required]
public string Subject { get; set; }
[Required]
public string Message { get; set; }
}

The Required attribute is exactly what it seems like and it’s part of the System.ComponentModel.DataAnnotations. The default error message is “The [propertyname] is required.”. If you want to reset it, you can do this: [Required(ErrorMessage = “Whatever I want it to be”)].

The ValidateEmail is a custom validation attribute. I didn’t like the looks of having a RegularExpressionAttribute defined there and since email is such a common thing to validate, I made this one:

public class ValidateEmailAttribute : RegularExpressionAttribute
{
public ValidateEmailAttribute(): base(@"[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?")
{
}
}

It just inherits from the RegularExpressionAttribute and passes in the regex to validate an email address. Apparently there is much discussion on how to validate an email address, which I believe is why Microsoft didn’t provide this to us.

So let’s look at the View/XHTML Markup.

@model Sample.Core.UI.Model.ContactView
@using Sample.Core.UI.Helpers
@using (Html.BeginForm("Contact", "Home", FormMethod.Post, new { id = "contactform" }))
{
<fieldset>
<legend>Contact Us</legend>
    <p>
@Html.LabelFor(f => f.Name, "Your Name")<br />
@Html.TextBoxFor(f => f.Name, new { style = "width: 200px", @class="required", accesskey="n" })
</p>
<p>
@Html.LabelFor(f => f.Email, "Your Email")<br />
@Html.TextBoxFor(f => f.Email, new { style = "width: 200px", accesskey = "e" })
</p>
<p>
@Html.LabelFor(f => f.Subject, "Subject")<br />
@Html.TextBoxFor(f => f.Subject, new { style = "width: 200px", accesskey = "p" })
</p>
    <p>
@Html.LabelFor(f => f.Message, "Message")<br />
@Html.TextAreaFor(f => f.Message, new { style = "width: 350px", rows = "4", accesskey = "c" })
</p>
@Html.AntiForgeryToken()
<input type="submit" id="bContact" name="bContact" value="Send Message" accesskey="s" /> 
@Html.DivSuccessMessage("Message sent successfully", "contactsuccess") 
@Html.ValidationSummary("", new { id = "contacterror" })
<noscript><br /><br /><div class="tip">Our contact form may look and act funny because you have JavaScript disabled. For a better experience on thissample.com, please enable JavaScript.</div></noscript>
</fieldset>
}

You can see at the top of the page I specify my view model. I ‘m also referencing a helper namespace for my DivSuccessMessage extension. Basically all it does is checks the ModelState for errors and for ViewData[“success”] not being null and displays the message specified. After that it’s basically a plain ole HTML form.

Okay, now we have our form built with our view model. Below the end of the XHTML above, I have the following jQuery code.

<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.5.2/jquery.min.js"></script>
<script type="text/javascript" src="http://ajax.aspnetcdn.com/ajax/jquery.validate/1.8/jquery.validate.min.js"></script>
<script type="text/javascript" src="http://www.malsup.com/jquery/form/jquery.form.js"></script><script language="javascript" type="text/javascript">
$(document).ready(function () {
var formoptions = { beforeSubmit: function (formData, jqForm, options) {
$("#bContact").attr('value', 'sending...');
$("#bContact").attr('disabled', 'disabled');
}, success: function (data) {
if (data.status == "Success") {
$("#contacterror").hide();
showMessage("#contactsuccess", data.message);
$('.valid').removeClass('valid');
validator.resetForm();
}
else {
$("#contactsuccess").hide();
showMessage("#contacterror", data.message);
}
$("#bContact").attr('value', 'Send Message');
$("#bContact").removeAttr('disabled');
}, dataType: "json"
};jQuery.validator.messages.required = "";
var validator = $("#contactform").validate({
submitHandler: function (form) {
$(form).ajaxSubmit(formoptions);
},
invalidHandler: function (e, validator) {
var errors = validator.numberOfInvalids();
if (errors) {
var message = errors == 1 ? 'You missed 1 field. It has been highlighted.' : 'You missed ' + errors + ' fields.  They have been highlighted.';
showMessage("#contacterror", message);
$("#contactsuccess").hide();
} else {
$("#contacterror").hide();
}
},
messages: { Email: { email: ""} },
rules: {
Subject: "required",
Message: "required",
Email: { required: true, email: true }
},
errorClass: "invalid",
validClass: "valid",
errorContainer: "#contacterror"
});function showMessage(id, message) {
$(id).html(message);
$(id).show();
}
});
</script>

Let’s break this down. First section the formOptions:

var formoptions = { beforeSubmit: function (formData, jqForm, options) {
$("#bContact").attr('value', 'sending...');
$("#bContact").attr('disabled', 'disabled');
}, success: function (data) {
if (data.status == "Success") {
$("#contacterror").hide();
showMessage("#contactsuccess", data.message);
$('.valid').removeClass('valid');
validator.resetForm();
}
else {
$("#contactsuccess").hide();
showMessage("#contacterror", data.message);
}
$("#bContact").attr('value', 'Send Message');
$("#bContact").removeAttr('disabled');
}, dataType: "json"
};

This code is used to define all my options for the jQuery.Form plugin. What it says is this:

  • beforeSubmit – Change the button to say “sending…” and disable it
  • on success – if the status = “Success” then hide the contacterror div, show the success message, manually remove the valid class from my inputs, and reset the form. Otherwise, hide the success message and show the error message with the message received. Regardless, re-enable my button and make it say “Send Message”. (Note: I shouldn’t have to manually remove the valid class, but the resetForm wouldn’t do it for me like it’s supposed to do.)
  • dataType – json received from my action

The validation section:

jQuery.validator.messages.required = "";
var validator = $("#contactform").validate({
submitHandler: function (form) {
$(form).ajaxSubmit(formoptions);
},
invalidHandler: function (e, validator) {
var errors = validator.numberOfInvalids();
if (errors) {
var message = errors == 1 ? 'You missed 1 field. It has been highlighted.' : 'You missed ' + errors + ' fields.  They have been highlighted.';
showMessage("#contacterror", message);
$("#contactsuccess").hide();
} else {
$("#contacterror").hide();
}
},
messages: { Email: { email: ""} },
rules: {
Subject: "required",
Message: "required",
Email: { required: true, email: true }
},
errorClass: "invalid",
validClass: "valid",
errorContainer: "#contacterror"
});

This code defines my validation for the contact form. It says this:

  • Set all messages for required fields to empty by default
  • submitHandler – on submit do this, which it calls the ajaxSubmit contained in the jQuery.Form plugin with our options specified above.
  • invalidHandler – if the form isn’t valid, get the number of errors and show the error message. Otherwise, hide the error message.
  • messages – Defines what the message should be for email, which is empty. I would’ve had to specify the required messages too had I not set them to empty first. Also note that the Email: has to match the ID of one of  your inputs.
    • Example: <input type=”text” id=”whateverid”/> so the messages would looks like this:

      messages: {whateverid: {required: “some message”}}

  • rules – Defines the rules for each input. Phone, Comments are required and Email has required and email. Notice name is required, but not specified here. It’s because I added the required class to the Name input in the XHTML instead of specifying down here so you could see you have options.
  • errorClass – Specifies my style class for when the input is invalid.
  • validClass – Specifies my style class for when the input is valid.
  • errorContainer – Specifies the div I want to show my error messages in.

Final section:

function showMessage(id, message) {
$(id).html(message);
$(id).show();
}

This just finds the container sets the html and shows it.

Okay, so finally here’s what the controller looks like that we mentioned in the @Html.BeginForm() section above.

[HttpPost, ValidateAntiForgeryToken, ValidateInput(true)]
public ActionResult Contact(ContactView view)
{
if (!ModelState.IsValid)
{
if (Request.IsAjaxRequest())
return Json(new { status = "error", message = "All fields are required." });

return View(view);
}    try
{
var notificationService = DI.EmailNotificationService(new EmailNotification(view));
notificationService.Notify();
}
catch (NotificationException)
{
ModelState.AddModelError("notifyerror", "Could not connect to mail server.");
}    if (Request.IsAjaxRequest())
return ModelState.IsValid ? Json(new {status = "Success", message = "Message sent successfully."}) : Json(new {status = "error", message = "Could not connect to mail server."});    return ModelState.IsValid ? Success(view) : View(view);
}

So this action accepts HttpPost, must have a valid Anti-Forgery Token, and it validates the input. First thing it does is verifies the modelstate is valid. The reason for this is that some people run their browser with JavaScript disabled. So we have to account for that in our code and make sure that we are validating on the client-side and on the server-side. So if the ModelState is invalid, we have to check to see if it’s an AJAX request. if it is, we return a Json result with the status of error and a message stating all fields are required. If it’s not an AJAX request, we simply return the view.

If all is valid, we continue and go ahead and send the notification. If the notification bombs, we add an error to the modelstate and then recheck and act accordingly. If you want to know what the notification service looks like, please refer to the first post because it’s all the exact same.

So, this method of coding will work when JavaScript is enabled and disabled and all the data will be validated regardless as well.

Here’s what the screen looks like after just hitting Send Message:

image

Here’s what it looks like after all the fields are valid right before I hit Send Message:

image

After message sent:

image

Please let me know if you have any questions.

Download Demo

Thanks for reading!

Shout it

kick it on DotNetKicks.com

Saturday, January 23, 2010

Basic jQuerying




So a few of my co-workers were wanting to know more about jQuery, so I thought I’d post an entry on the topic…a really basic intro to get people thinking and starting to use it.

There are a few things I love about jQuery and they are…

  1. You can query all your markup
  2. If it’s something with the client-side, there’s a plugin for it!
  3. It’s easy and fun to use

So let’s get started with the most common structure:

$(document).ready(function() {
$(
selectorhere).whateverfunction();

});

You may be wondering what the $ represents and the answer is…it’s a shortcut! jQuery(document) and $(document) are the same thing.


Okay so why do you call .ready all the time? Well one of the nice things about jQuery is that it knows when the DOM (Document Object Model) has loaded so between the brackets will run as soon as that happens. It works as a safety net basically.


The “selectorhere” represents what you want to query the DOM for basically. You can have all types of selectors, but I’ll list a few of the most common that I use.



  1. The class selector $(‘div.classname’)
    so this will search the DOM for anything marked up like this: <div class=”classname”></div>

  2. The id selector $(‘div#maincontent’)
    This will select the div with an id of maincontent like this: <div id=”maincontent”></div>

  3. The html tag selector $(‘a’)
    This will select all the anchors on the page like this: <a href=””></a> or <a name=””></a>

  4. The attribute contains selector $(‘a[href*=something]’)
    This will select all anchors with an href that contains the word something like this: <a href=”http://testsomething.com”></a>

Those are all the basic selectors I use, but you can read more about all the different types at jquery.com


Once you’ve selected what you want, you can do stuff to it/them. For example, say I wanted to add the jQuery datepicker to all textboxes with a class name of “date”. (Note: the jQuery datepicker is part of the jquery-ui library)


Alright so that jQuery code would look like this:

$(document).ready(function() {
$(
'input:text.date').datepicker();
});

So here I’m using the jQuery selector to say get me all inputs of type text with a class name of date. Just like the first little sample from above…really easy to use.


You can see more examples on these posts:



As always, thanks for reading!

kick it on DotNetKicks.com

Thursday, December 31, 2009

jQuery DocumentReady.js – A Best Practice?




I recently noticed some developers creating a DocumentReady.js file and keeping all their document.ready stuff inside of it. I like this practice. I think it’s clean, but I can see how it could get out of hand. Especially if you start adding ALL of your document.ready stuff in there even though it doesn’t pertain to the majority of your pages.

I imagine you’d like to see some examples of things I have in my DocumentReady.js file. Well, I like rounded corners and I found a pretty sweet corners plugin for jQuery, which was the first thing I put in my DocumentReady.js file and it started out looking like this:

    $(document).ready(function() {
$(
'.rounded').corners();
});

So this code says for everything with a rounded class, add the corners. Simple and I have full control and access to it on all of my pages. For more information about jquery.corners, see jquery plugins and jquery.corners demo.


Then I found myself setting the focus on all my forms on each individual page and I thought…this isn’t going to work! I hate all this redundant code and I don’t like it all over the place. I think I’ll add it to my DocumentReady.js file. So I did and it looked something like this:

    $(document).ready(function() {
$(
'.rounded').corners();

var inp = $('.input-validation-error:first').get(0);
if (!inp) var inp = $('input:first').get(0);
if (inp) inp.focus();
});

Okay, so what this says is if there is any items with the input-validation-error class then get the first one. The reason for this is that if there is an error, I want to set the focus to the error and not the first item in the form. So, if there isn’t an error, then I set inp to the first input on the page and then I check if it exists and then I set the focus. The reason I had to add the second check is because this code runs on all my pages and not ALL of them have inputs, so instead of throwing a JavaScript error, I handle it. Obviously if you’re building a basic Web site, you’re not going to want to put this in your DocumentReady.js. The reason I’m doing it is because my project is an application and almost all the screens have form elements.


I also started using a Bootstrapper.js and only reference it on my main template. In the bootstrapper, I have this code:

function IncludeJavaScript(jsFile)
{
document.write(
'<script type="text/javascript" src="'
+ jsFile + '"></script>');
}

IncludeJavaScript(
'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js');
IncludeJavaScript(
'/_j/jquery.corners.min.js');
IncludeJavaScript(
'/_j/DocumentReady.js');

I don’t remember exactly where I first saw this, but I’m pretty sure it was either on the CodeCampServer project or in the ASP.NET MVC in Action sample code download.


So there you have it. Is it a best practice? I’m not sure yet because I just started doing it in the last couple projects, but so far I really like it. What do you think?


As always, please comment if you see anywhere that I could improve or you just have a comment. Thanks for reading!

kick it on DotNetKicks.com

Tuesday, December 29, 2009

JavaScript – Not Required




As an end-user of many different sites, it appears to me that it is becoming increasingly difficult to have JavaScript turned off and increasingly dangerous to have it on. I’m a huge fan of JavaScript, but I think it’s unfair to design my web sites to force my end-users to have JavaScript turned on. So I try and make everything accessible without JavaScript. It might not look as fancy, but everything on my sites function and that’s what’s important.

Take my latest project, my wife’s re-design (not yet published as of this post), we’ve added several JavaScript niceties. However, EVERYTHING still works with JavaScript disabled and we pop-up nice little messages to let the end-user know why something is appearing the way it is. Here’s what we’ve done:

  • We have a group of images that fade in and out using jQuery on the homepage. When JS is disabled, the first picture is displayed and that’s it.
  • We have a Join Mailing List feature that uses ajax via the jquery.form plugin by Mike Alsup, which converts our form into an ajax form otherwise it leaves the default action. When JS is disabled, the call is the same, but our messages are formatted so the end-user will see a specific error or message stating why it’s formatted a certain way. To read more on how we implemented this, see the “jQuery AJAX with ASP.NET MVC” post.
  • For her portfolio page, we used jquery.lightbox, which pops up a nice modal effect for her images. When JS is disabled, every link just links to the picture and the picture pops up in the browser and then the end-user has to click back to get back to the gallery.
  • On her contact page, we use jQuery to decode her email adddress. To get around this issue, we use a real address for the mailto:, but it’s meant for spammers and we display a nice message letting the end-user know why they’re seeing email [[at]] domain [[.]] com. To see more on how we did this, see the “Trick Bots from Stealing Email Address with jQuery...” post.

Bottom line, don’t force users to do something they shouldn’t HAVE to do and make your web site accessible and friendly. Provide <noscript> messages when necessary and try disabling JavaScript on your browser and browsing your web site to see how people feel.

That’s it! As always, please comment if you see anywhere that I could improve or you just have a comment. Thanks for reading!

kick it on DotNetKicks.com

Related Posts Plugin for WordPress, Blogger...