in

Platinum Bay

Peace, Love, and...

This Blog

Syndication


.NETicated

Favorite Image Icons with jQuery and MVC

User experience, that’s the name of the game these days. Green screens and console applications are (hopefully) becoming a thing of the past. In the web world, this means a more fluid and asynchronous experience. In my last post, I gave a quick introduction to using jQuery and MVC to perform asynchronous requests to the browser. In this post, I will expand on that topic and show how to build a favorite image icon.

The concept is pretty simple. For example, in the Twitter web UI, an empty star image appears on the right side of a tweet if you mouse over it.If the star is clicked, the icon changes to a flashing dot, and then to a yellow star indicating that the tweet has been favorited. It’s a neat, asynchronous effect, and it’s fairly simple to achieve.

First, we need three images. Here are the images that Twitter uses:

Next, a CSS style is defined for the off, on, and loading states. The purpose of each style is to allow style switching to not only change the picture, but also to allow the state to be determined through the style class assigned.

.favimgoff, .favimgon, .imgload { width: 16px; height: 16px; border: 0px; background-repeat: no-repeat; }
.favimgoff { background-image: url(images/icon_star_empty.gif); }
.favimgon { background-image: url(images/icon_star_full.gif); }
.imgload { background-image: url(images/icon_throbber.gif); }

On the MVC side, an action is needed to handle the server processing.

public JsonResult SetOrRemoveUserFavorite(int favoriteId)
{
JsonResult result = new JsonResult();

// do work here, and set SetOn to the proper state
result.Data = new { Success = true, SetOn = true };

return result;
}

Next, on the client side, add an image tag with the class attribute and id set. The image is set to a one pixel transparent gif otherwise certain browsers may not render the background image.

<img class="favimgoff" src="<%= Url.Content("~/Content/images/spacer.gif")%>" id="1" />

Finally, jQuery on the client side takes care of the tying it all together:

$('.favimgoff, .favimgon').click(function() {
var $favimg = $(this);
if ($favimg.attr('class') != 'imgload') {
$favimg.removeClass().addClass(
'imgload');
$.getJSON(
'<%= Url.Action("SetOrRemoveUserFavorite", "Services") %>', {
favoriteId: $favimg.attr(
'id')
},
function(json) {
if (json.Success) {
if (json.SetOn) {
$favimg.removeClass().addClass(
'favimgon');
}
else {
$favimg.removeClass().addClass(
'favimgoff');
}
}
else {
alert(
'Favorite could not be set. Please refresh the page and try again.');
}
});
}
});

Let’s step through the jQuery script. First, define the click event handler for both classes, and get a reference to the image clicked:

$('.favimgoff, .favimgon').click(function() {
var $favimg = $(this);

Next, to avoid any duplicate action taken while the process is run, make sure the image isn’t in the loading state. This is necessary because jQuery will still have an event reference to the original image even when the class changes from the original two classes of on or off.

if ($favimg.attr('class') != 'imgload') {

Next, remove any existing class and add the loading class so the user gets feedback that their action is being processed:

$favimg.removeClass().addClass('imgload');

Then, make a server call to the action defined, and pass the id of the item as a parameter to the action:

$.getJSON('<%= Url.Action("SetOrRemoveUserFavorite", "Services") %>', {
favoriteId: $favimg.attr(
'id')
},
function(json) {
if (json.Success) {

Finally, based on the SetOn value returned from the server call, remove the loading class and set the appropriate class:

if (json.SetOn) {
$favimg.removeClass().addClass(
'favimgon');
}
else {
$favimg.removeClass().addClass(
'favimgoff');
}

If by chance the server call fails and Success is false, alert the user:

alert('Favorite could not be set. Please refresh the page and try again.');

That’s it. Utilizing the baked-in goodness of jQuery and ASP.NET MVC, providing a rich, asynchronous user experience doesn’t have to be complex.

Published Aug 29 2009, 08:01 PM by Steve
Filed under: , ,

Comments

August 30, 2009 11:19 PM

Pingback from  ASP.NET MVC Archived Blog Posts, Page 1

 

August 31, 2009 6:56 AM

Pingback from  Dew Drop &#8211; August 31, 2009 | Alvin Ashcraft&#039;s Morning Dew

 

August 31, 2009 12:18 PM

Thank you for submitting this cool story - Trackback from DotNetShoutout

 

August 31, 2009 7:35 PM

In my last two posts ( jQuery and MVC: JSON and Favorite Image Icons with jQuery and MVC ) I covered

 

September 1, 2009 8:03 AM

Great post. Would be better with an image sprite, so that the replacement images appear instantly.

Portman
 

October 6, 2009 5:04 PM

Pingback from  Favorite Image Icons with jQuery and MVC &#8211; .NETicated | My Web Development Bookmarks

 

February 23, 2010 10:11 AM

Buy soma. Buying soma without a prescription. Buy soma online. Buy soma in florida.

 

Leave a Comment

(required )  
(optional )
(required )  
Add

About Steve

Steve Andrews is an independent consultant, INETA speaker, and Microsoft MVP for Visual Studio ALM. He has been working in technology for over ten years focusing on custom application development and Application Lifecycle Management. Steve is also Microsoft and IBM certified and a community fanatic having led sessions at nearly 100 events across North America. When he's not developing software solutions or engaging with the community about software technology, Steve is a closet singer and songwriter and plays the guitar and keys. Occasionally, Steve even gets to sleep. Occasionally.
Powered by Community Server (Commercial Edition), by Telligent Systems
© Platinum Bay | Some Rights Reserved Creative Commons License

Disclaimer: The information in this weblog is provided "AS IS" with no warranties, and confers no rights. This weblog does not represent the thoughts, intentions, plans or strategies of my employer. It is solely my opinion. Feel free to challenge me, disagree with me, or tell me I'm completely nuts in the comments section of each blog entry, but I reserve the right to delete any comment for any reason whatsoever (abusive, profane, rude, or annonymous comments) - so keep it polite, please.