Sergio and the sigil

Mozilla Add-Ons in Chicago

Posted by Sergio on 2009-09-17

Later this month I'll be attending the Mozilla Add-Ons Meetup in Chicago.

I'm continually impressed with the extensibility of Mozilla applications and the amazing things people are doing with it. I'm interested in both the extensibility model and in writing a few custom extensions myself, even if it's just for my own use. Given that it's mostly XML and JavaScript, it should be right up my alley.

After seeing a presentation about building Firefox extensions earlier this year I decided I had to look into that more seriously.

So if you're in the area and wants to see what this is all about, this meetup might be a good way to get some info to get going.

ASP.NET MVC with jQuery SuperLoad

Posted by Sergio on 2009-08-23
The other day I wrote about the jQuery SuperLoad plugin but I couldn't offer any real working sample of an application using it. Today I'm here to rectify that and talk about the new sample code I've recently added to the project repository.

Adding products to your shopping cart

The application has a single page, which lists a few books that you can add to your shopping cart. The cart is initially empty and when we add items to it, both the cart item list and the total price (at the top of the page) get updated from a single Ajax call.

The client side

Here's sample of what each of the products' HTML looks like. They each are inside a div which's id contains the product's id.
<div id="product_8" class="product">
	<img src="../../Content/images/prod_8.jpg" align="left" />

	<div class="title">Product 8</div>
	<div class="prodPrice" >$8.88</div>
	Qty: <input type="text" size="2"  maxlength="3" 
				class="quantity" value="1"/>
	<input type="button" value="Add to cart" class="addButton" />
</div>
We just need to fire one Ajax call whenever one of those "Add to cart" buttons is clicked. Here's the code that does that.
$('.addButton').click(function() {
	var prod = $(this).parent('.product');
	var prodId = prod.attr('id').split('_')[1];
	var qty = prod.find('.quantity').val();

	$.superLoad({
		url: '/Shopping/AddItem',
		type: 'POST',
		data: { product: prodId, quantity: qty },
		success: function() { $('#empty').remove(); }
	});
	
});
As you can see, we are making a superLoad() call to the AddItem action in the ShoppingController. Since this is a data modification call, we chose to use an HTTP POST request. The posted data goes in the data option. To tidy up things, we delete the empty text from the cart (if it's still there) once the call completes successfully.

Multiple results from a single action

The challenge on the server side is to come up with a sustainable method of reusing existing actions and combine them in a single action result, formatted to SuperLoad's liking and returned to the browser. To address that issue the sample comes with an implementation of a composite action result class specifically built for the response format we are trying to create. That class is the SuperLoadResult, listed below.
public class SuperLoadResult : ActionResult
{
	public IEnumerable<SuperLoadAjaxContent> ContentItems { get; private set; }

	public SuperLoadResult(params SuperLoadAjaxContent[] contentItems)
	{
		ContentItems = new List<SuperLoadAjaxContent>();
		((List<SuperLoadAjaxContent>)ContentItems).AddRange(contentItems);
	}

	public override void ExecuteResult(ControllerContext context)
	{
		context.HttpContext.Response.ContentType = MediaTypeNames.Text.Html;

		context.HttpContext.Response.Write("<div class=\"ajax-response\">");
		foreach (var item in ContentItems)
		{
			context.HttpContext.Response.Write(
				string.Format("<div class=\"ajax-content\" title=\"{0} {1}\">",
			                  item.Command.CommandText, item.Selector));
			item.GetResult().ExecuteResult(context);
			context.HttpContext.Response.Write("</div>");
		}
		context.HttpContext.Response.Write( "</div>");
	}
}
I bet things will become clearer once I show it being used from the AddItem action. So here it goes.
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult AddItem(int product, int quantity)
{
	var sku = GetProduct(product);
	var item = new CartItem(sku, quantity);
	var cart = GetCurrentCart();
	cart.Items.Add(item);

	//add all the separate action results that we want into 
	// a SuperLoad result, mapping each one to the right 
	// selector and update type.
	return new SuperLoadResult(
		new SuperLoadAjaxContent("#cartTotal", 
		                  SuperLoadCommand.Update, 
						  () => CartTotal(cart)),

		new SuperLoadAjaxContent("#cart", 
		                  SuperLoadCommand.Append, 
						  () => CartItem(item))
		);
}
That last parameter to the SuperLoadAjaxContent's constructor is what will be invoked to provide an ActionResult-derived object, which will be executed and injected in the right place of the combined response. If I needed to update more elements, I could simply pass more instances of SuperLoadAjaxContent to my SuperLoadResult. Both CartTotal and CartItem are regular action methods that return a partial view from an .ascx template. Here's how simple the CartItem action is.
public ActionResult CartItem(CartItem item)
{
	return PartialView("CartItem", item);
}
Again, the entire sample is available for browsing, forking, or downloading at the repository page.

jQuery SuperLoad

Posted by Sergio on 2009-08-21

An important part of working with jQuery is to create plugins to simplify repetitive tasks. I write jQuery plugins all the time for internal consumption of my applications.

Most of them are not of enough general purpose to be shared publicly. Recently I created one that could stand on its own and I chose to make it available if anyone is interested.

Multiple Element Ajax Updates

jQuery SuperLoad came out of the necessity to update more than one element in a page without needing to do everything with JavaScript (and you know I'm not the one that avoids JavaScript).

All of the page elements I needed to update with Ajax came from page segments (partials, user controls, etc) that I had available on my server side. It seemed appropriate to go back to the server to get updated versions of that same HTML. But I didn't want to issue a separate $.ajax() or $(elem).load for each one of them.

Using SuperLoad I can now return something like the following from my server application and have more than one element updated.

<div class="ajax-content">
	<div title="!appendTo #content .shoppingList">
		<li>
			<img src="/images/prod12345.png" class="product-image">
			<div class="prodSummary">
				<div class="prodTitle">ACME Product</div>
				<div class="prodPrice">$12.34</div>
			</div>
		</li>
	</div>
	<div title="!update #orderTotal">
		Total: <span class="totalPrice">$47.22</span>
		<div class="specialOffer">Eligible for free shipping!</div>
	</div>
	<script>
		$('#orderTotal specialOffer').effect('highlight');
	</script>
</div>

All that is needed for this to be correctly applied to the right elements (selected by "#content .shoppingList" and "#orderTotal" is a line of code similar to this example.

$.superLoad({ 
	url: '/shopping/addItem', 
	type: 'POST', 
	data: {product: 12345} 
});

Check the plugin source code comments or the github repository page for more details.

Interview for the Thirsty Developer Podcast

Posted by Sergio on 2009-07-29

It was my turn to be interviewed by Dave and Larry for The Thirsty Developer podcast.

We talked a lot about all things JavaScript, its status, how people learn it (or avoid it), etc. I hope it's an entertaining interview

You can download the interview from the podcast page

Video: WI-INETA JavaScript presentation

Posted by Sergio on 2009-07-17

I finally got around to properly record and publish one of those JavaScript presentations that I have been doing at local users groups. The video and the slide deck are available below.

The video

 

And the slide deck.

If you prefer, you can download the slide deck.