Tuesday, August 7, 2012

JQueryMobile List Item Helper

I have been working through some mobile web prototypes recently using jQueryMobile.  The mobile web application itself is a client of WCF services.  As part of the application I wanted to use the basic linked list format with some additional information.  Since these have to be attached to the DOM and rendered on the client side, I found myself wanting to retrieve a list of data contracts on the server side and have the DocumentReady function turn them into a linked list. Since the server side page_load code executes prior to the DocumentReady code on the client side, it gives us the opportunity to retrieve the data needed and place items in the DOM for linked list creation.  I found a viable solution for accomplishing this task and thought it seemed like a good item to walk through.

jQueryMobile list anatomy
The list markup is fairly straightforward and has additional attributes for data-role to drive jQueryMobile.  Here is a snippet for a small sample list:

<div data-role="content">
  <div class="content-primary">
    <ul data-role="listview">
    <li><a href="index.html">Acura</a></li>
    <li><a href="index.html">Audi</a></li>
    <li><a href="index.html">BMW</a></li>
    <li><a href="index.html">Cadillac</a></li>
    <li><a href="index.html">Chrysler</a></li>
    <li><a href="index.html">Dodge</a></li>
    <li><a href="index.html">Ferrari</a></li>   
    </ul>
  </div>
</div>

This all works really well if you can hard-code the items in your list, which in this case I could not.  The number of items had to be dynamic as well as the href attribute.  In order to accomplish this, I made the following modifications to the snippet:
<div data-role="content">
  <div class="content-primary">
    <ul runat="server" id="carList" data-role="listview">
    </ul>
  </div>
</div>

In short, I made the control run at the server, gave it an id and removed all of the items from the list.  So my next step is to dynamically add the items to the list from the C# code behind.  The first thing to do was create a helper object to create items for me.  I wanted to be able to dynamically format these items to have a header, details and possibly a thumbnail image.  In order to accomplish this, I had this class take a title, a list of strings, the href location and an image if one was required.  Here is the helper code I used:
public static class jQueryMobileHelper
{
public static HtmlGenericControl buildListItem(String headerDescription, 
    List<String>items, String urlLocation)
{
  HtmlGenericControl li = new HtmlGenericControl("li");
  HtmlGenericControl anchor = new HtmlGenericControl("a");
  HtmlGenericControl h3 = new HtmlGenericControl("h3");
  anchor.Controls.Add(h3);
  h3.InnerText = headerDescription;
  foreach (String detail in items)
  {
    HtmlGenericControl p = new HtmlGenericControl("p");
    p.InnerText = detail;
    anchor.Controls.Add(p);
  }
  anchor.Attributes.Add("href", urlLocation);
  anchor.Attributes.Add("target", "_self");            
  li.Controls.Add(anchor);
  return li;
}

public static HtmlGenericControl buildListItemWithThumbnail(String headerDescription, 
     List<String>items, String urlLocation, String imageLocation)
{
  HtmlGenericControl li = new HtmlGenericControl("li");
  HtmlGenericControl anchor = new HtmlGenericControl("a");
  HtmlGenericControl h3 = new HtmlGenericControl("h3");
  HtmlGenericControl img = new HtmlGenericControl("img");

  img.Attributes.Add("src", imageLocation);
  img.Attributes.Add("style", "height: 70px; width: 70px");
  img.Attributes.Add("display", "inline-block");
  img.Attributes.Add("alt", "image");

  anchor.Controls.Add(img);
  anchor.Controls.Add(h3);
  h3.InnerText = headerDescription;
  foreach (String detail in items)
  {
    HtmlGenericControl p = new HtmlGenericControl("p");
    p.InnerText = detail;
    anchor.Controls.Add(p);
  }
  anchor.Attributes.Add("href", urlLocation);
  anchor.Attributes.Add("target", "_self");
  li.Controls.Add(anchor);
  return li;
}
Next I looped through the items I had in my collection and created the list items.  As part of this routine, I just appended the items to the list control as follows:

List<String>items = new List<String>();
foreach (CarInfo car in cars)
{
   items.Add(car.Make);
   items.Add(car.ModelYear);
   items.Add(car.Price.ToString("C"));
   carList.Controls.Add(jQueryMobileHelper.buildListItemWithThumbnail(car.Model,items,
          String.Format("carDetail.aspx?carId={0}",car.ID),
          car.ThumbnailLocation ));
}
This gives you a list formatted similarly to the examples on the jQueryMobile site.  But, allows you to build them dynamically from the server side based on your existing services.