Building A Color Picker Using ASP.NET MVC And jQuery

Posted by: Malcolm Sheridan , on 1/7/2010, in Category ASP.NET MVC
Views: 41686
Abstract: The following article demonstrates how to build a color picker tool using ASP.NET MVC and jQuery.
Building A Color Picker Using ASP.NET MVC And jQuery
 
If you've used Microsoft's Ajax Control Toolkit, you'll probably have used a control called the ColorPicker. This is where it displays a list of colors that you can select from in a web page, and have the hex value of that color displayed when you click on it. I thought it would be a good exercise to show you how to do this using ASP.NET MVC and jQuery. Well here's how to do it. The example I’m demonstrating in this article is using the new jQuery 1.4 Alpha 2 release. That code can be downloaded from here. The end result will look like the screen cast below. If you cannot view the screencast shown below for some reason, you can directly view the screencast over here
Update: An updated version of this article can be found here Building A Color Picker Using ASP.NET MVC And jQuery - Update


 


To demonstrate this I’ve created an ASP.NET MVC application. For this example to work I obviously need some colors to display on the web page. Instead of hard coding a list of HTML hex values, the alternative approach is to retrieve the values from a source. The source for this example will be a list of known system colors in Windows. Let's start by creating a Colors controller that will return a HTML table with all the colors. Here's the code to do this:
C#
public class ColorController : Controller
{
      [AcceptVerbs(HttpVerbs.Get)]
      public JsonResult FetchColors()
      {
            var count = 0;
            var sb = new StringBuilder();
            sb.Append("<table><tbody><tr>");
           
            foreach (var color in Enum.GetNames(typeof(KnownColor)))
            {
                var colorValue = ColorTranslator.FromHtml(color);
                var html = string.Format("#{0:X2}{1:X2}{2:X2}",
                                    colorValue.R, colorValue.G, colorValue.B);
                sb.AppendFormat("<td bgcolor=\"{0}\">&nbsp;</td>", html);
                if (count < 20)
                {
                    count++;
                }
                else
                {
                    sb.Append("</tr><tr>");
                    count = 0;
                }
            }
            sb.Append("</tbody></table>");
            return Json(sb.ToString());
      }
}
VB.NET (Conversion Tool)
Public Class ColorController
      Inherits Controller
      <AcceptVerbs(HttpVerbs.Get)> _
      Public Function FetchColors() As JsonResult
             Dim count = 0
                  Dim sb = New StringBuilder()
                  sb.Append("<table><tbody><tr>")
 
                  For Each color In System.Enum.GetNames(GetType(KnownColor))
                        Dim colorValue = ColorTranslator.FromHtml(color)
                        Dim html = String.Format("#{0:X2}{1:X2}{2:X2}", colorValue.R, colorValue.G, colorValue.B)
                        sb.AppendFormat("<td bgcolor=""{0}"">&nbsp;</td>", html)
                        If count < 20 Then
                              count += 1
                        Else
                              sb.Append("</tr><tr>")
                              count = 0
                        End If
                  Next color
                  sb.Append("</tbody></table>")
                  Return Json(sb.ToString())
      End Function
End Class
I've decorated the action to only accept HTTP GET requests from the website by using the AcceptVerbs attribute. 
[AcceptVerbs(HttpVerbs.Get)]
It's important to explicitly state what request an action will accept. This way if a malicious user tries to post data to this action, the request will be ignored by the action. To get the collection of colors from the system I enumerate through the Enum.GetNames method by specifying the type as KnownColors. From there I retrieve the HTML hex value from the following two lines of code:
var colorValue = ColorTranslator.FromHtml(color);
var html = string.Format("#{0:X2}{1:X2}{2:X2}",
      colorValue.R, colorValue.G, colorValue.B);
 
I've also keeping track of how many <td> cells I create per row. Once the count reaches 20, I start a new <tr> row. If I didn't do this then the colors would print out entirely in the first <tr>. Doesn't look too appealing! Finally the generated HTML is returned as a JSON object.
 
All the server side code is finished now. The code below is for the view to render the color picker. I'll explain what I'm doing afterwards:
 
<script language="javascript" type="text/javascript" src="http://code.jquery.com/jquery-1.4a2.js"></script>
<script language="javascript" type="text/javascript">
        $(function() {
            $("#Colors").hide();
            $("#SelectColor").click(function() {
                $.get("/Color/FetchColors", null, function(data) {
                    $("#Colors").html(eval(data));
                });
                $("#Colors").toggle();
            });
 
            $("td").live("mouseover", (function() {
                $("#Sample").css("background-color", $(this).css("background-color"));
                $(this).css("cursor", "pointer");
            }));
 
            $("td").live("click", function() {
                $("#SelectedColor").val($(this).attr("bgcolor"));
            }); 
        }); 
</script>   
<input type="text" id="SelectedColor" name="SelectedColor" readonly="readonly" />
<img src="/Content/Images/cp_button.png" alt="Pick a color" align="absmiddle" id="SelectColor" />
<span id="Sample">&nbsp;&nbsp;&nbsp;&nbsp;</span><br /><br />
<div id="Colors"></div>
 
Firstly when the user clicks on the color palette image, this will trigger the Ajax call to the server. This is done by using jQuery's $.get function. The first parameter is the URL. In ASP.NET MVC you pass in the controller/action. Once the JSON has been returned, I'm assigning it to the Colors <div> tag. 
$("#SelectColor").click(function() {
      $.get("/Color/FetchColors", null, function(data) {
            $("#Colors").html(eval(data));
      });
      $("#Colors").toggle();
});
Because the color selector is being generated dynamically, I can't use bind to bind an event handler to the click and mouseover events. For this to work I need to use jQuery's live event. The live event binds a handler to an event for all current - and future - matched elements:
$("td").live("mouseover", (function() {
      $("#Sample").css("background-color", $(this).css("background-color"));
      $(this).css("cursor", "pointer");
}));
 
$("td").live("click", function() {
      $("#SelectedColor").val($(this).attr("bgcolor"));
});
Now when the user clicks on any color, the hex value will be displayed in the text box. This is a nice and easy way to add more richness to your application through jQuery. The entire source code of this article can be downloaded over here
Give me a +1 if you think it was a good article. Thanks!
Recommended Articles
Malcolm Sheridan is a Microsoft awarded MVP in ASP.NET, a Telerik Insider and a regular presenter at conferences and user groups throughout Australia and New Zealand. Being an ASP.NET guy, his focus is on web technologies and has been for the past 10 years. He loves working with ASP.NET MVC these days and also loves getting his hands dirty with jQuery and JavaScript. He also writes technical articles on ASP.NET for SitePoint and other various websites. Follow him on twitter @malcolmsheridan


Page copy protected against web site content infringement by Copyscape


User Feedback
Comment posted by D on Saturday, January 9, 2010 12:48 PM
I like how people are coming up with alternatives for the Ajax Toolkit but one thing I will say in this case is MVC is intended to separate data from the output. It's a huge no no in my mind to add HTML to your controller. The controller returns a JsonResult which means it should be purely Json and not include HTML. Your script should build and render the HTML client-side.
Comment posted by Malcolm Sheridan on Saturday, January 9, 2010 8:57 PM
@D
I do agree with you that the controller should emit just JSON.  This was just an example of one way to do this.
Comment posted by Wesley on Monday, May 3, 2010 6:38 AM
The code is very very buggy..

Your table row isn't closed;
What if the count of colors is exactly 40?
How about using 'System.Drawing.ColorTranslator.ToHtml(c);'
What's the point of using Json? Why not simply output the HTML or.. use a little piece of JavaScript (way smaller than a complete table) to render the color table dynamically?
Comment posted by Zachary on Monday, May 3, 2010 6:49 PM
This post is featured on the home page of ASP.Net. I have to say I don't find this post very practical or applicable to real-world scenarios.
Comment posted by Malcolm Sheridan on Tuesday, May 4, 2010 3:22 AM
@Wesley
This was just an example.  I wrote an update for this on using html templates here:

http://www.dotnetcurry.com/ShowArticle.aspx?ID=446
Comment posted by rob on Thursday, January 19, 2012 10:04 PM
nice color picker: http://www.websanova.com/plugins/websanova/color-picker

Post your comment
Name:  
E-mail: (Will not be displayed)
Comment:
Insert Cancel