Sunday, May 3, 2015

Visual Studio Code for Mac | Angular TypeScript Yeoman Setup

Example code for this post can be found on GitHub.

Visual Studio Code on Mac OS X is awesome. In fact, Visual Studio Code is awesome period. I have been using Brackets on OS X for a while now as a free alternative to Sublime. Brackets is good, but I am a Visual Studio junkie in Windows and having Visual Studio in OS X to do front end (angular) and back end (C# / web api) development is just awesome.

To get started with Visual Studio Code on my Mac, I decided to create a new project (Angular, TypeScript, Bootstrap) scaffolded by Yeoman. I want to use Angular as the base front end framework, use TypeScript for all of the front end code, use Bootstrap for responsive rendering and use John Papa's style guide for Angular structure. I figured a lot of people are going to go down the same path, so I might as well share the recipe.

Pre-req app installs

Download and install nodejs Lightweight web server that includes npm, which we will use a lot.

Download and install Git version control client

Download and install mono Cross platform .NET framework, not really a pre-req for pure front end work, but you will need this if you open a Visual Studio project in Visual Studio Code on Mac OS X.

Download and install Visual Studio Code for Mac OS X

Install global npm packages

We will use Node Package Manager (npm) to download and install all of the required packages that will give us a rich front end development environment where we can write code, buid and test with ease. The npm -g option installs packages globally. You only want to use this option for packages that you want to be available across your operating system.

We want to install bower (front end package manager), grunt-cli (task runner/build command line interface), yeoman (scaffolding tool), karma (angular test runner), typescript (type superset for javascript), tsd (definitelyTyped definitions for TypeScript intellisense) and a yeoman generator for angular projects. It makes sense to install all of these globally as they are generally applicable tools for any front end app.

Open an OS X Terminal

Run the following command

$sudo npm install -g bower grunt-cli yo karma jasmine typescript tsd@next generator-angular generator-karma

(sudo will elevate the command to run with administrative privileges and will require your password)

Scaffold and install project packages

Create a directory for your new project

$mkdir ~/Documents/Source/Repos/VsCodeAngularTypeScript

cd into your project directory

$cd ~/Documents/Source/Repos/VsCodeAngularTypeScript/

Run the following commands

$yo angular YourAppNameGoesHere

(yeoman will scaffold a new angular project for you, choose the angular dependencies you want to use)

$grunt serve

This should build the scaffolded angular project, launch a new nodejs server and serve up index.html If you get errors as this point, see what you missed in the previous steps and fix them before proceeding further.

You should see this page pop up in your browser:

Now let's setup TypeScript and TypeScript intellisense for our new project.

Run the following commands: (note we are using the —-save option on all commands to add references to the npm and tsd package configs so they can be easily restored later)

$tsd install jquery --save

(installs jquery TypeScript definition file to typings/jquery and creates/adds the reference in tsd.json - this is a dependency of angular TypeScript definition)

$tsd install angular --save

(installs angular TypeScript definition file to typings/angular and adds a reference in tsd.json)

After the two tsd commands are executed, you will see a few things appear in your project:

  • tsd.json in your root folder
  • typings folder in root
  • typings/tsd.d.ts
  • typings/jquery and typings/angular

The /typings folder contains all of the TypeScript definition files that will be used to generated Intellisense. The /typings folder also contains tsd.d.ts which is a super helpful file that contains references to all other tsd files so you only have to reference a single tsd in your TypeScript files to get Intellisense for all libraries.

Now install some grunt task packages. Run the following commands:

$npm install grunt-ts --save-dev

(installs grunt-ts package, will use the typescript tsc compiler to transpile your ts files to js files and generate maps)

$npm install grunt-tsd@next --save-dev

(installs grunt-tsd package, will keep your typescript definitions up to date)

$npm install grunt-karma --save-dev

(installs grunt-karma package, will be used to run unit tests with karma from grunt)

Let’s make sure that everything is still working nicely, run...

$grunt build

This will run all of the grunt build tasks. If you have any errors, address them before moving on.

Time to create some TypeScript files

The basics are in place, so create a new typescript file. Let’s replace app.js with typescript. For best practice, let’s split up core dependencies, app dependencies and app config into three different file.

Open Visual Studio Code

Now go to File - Open… and open the project directory you created in previous steps.
Create a new file in Visual Studio Code in /app and call it app.core.ts



Now let’s split out angular app module definition and angular dependency injection into app.core.ts.
First off, add a reference at the top of the file to tsd.d.ts so we get intellisense for angular and jquery.



Then delcare an IIFE (closure) using TypeScript. Explicitly set the return type to void for best type practice.

Now add the angular module instantiation and all of the angular dependencies from app.js.



Create another new TypeScript file called app.module.ts. This file will contain our app instantiation and add our core module as a dependency, so we end up with a clean module file and still get all of the core angular dependencies injected.



And finally create app.config.ts and put all of the app config code in there.


Grunt TypeScript Task Setup

Beauty. Now we setup our grunt TypeScript tasks to cleanup definitions if need be and transpile our ts into js. We need to edit our Gruntfile.js to include config, execution and definition of grunt-ts and grunt-tsd.

Open Gruntfile.js in Visual Studio Code

Add a ts watch task to grunt.initConfig : watch {}



Then add ts and tsd task configs to grunt.initConfig



And then tell grunt to load both npm tasks...



Add grunt-ts to grunt.task.run



Add both ts and tsd to the grunt build tasks



Now run...

$grunt ts

This will create .js and .map files in your app/scripts directory for the .ts files we created.

And finally

Now we just need to update index.html with references to our new angular js files. Update script references at the bottom of index.html to the following:



and then run...

$grunt serve

The site should launch in your browser again and everything should still work.

Going forward

When you start development activities, just run...

$grunt serve

Grunt will monitor for file changes as you develop and transpile your TypeScript files into js as you save them.

Saturday, July 30, 2011

Image Upload, Crop and Resize with ASP.NET MVC jQuery Uploadify and jCrop

I need a slick way for my customers to upload, crop and resize photos within my Church Management Software. After doing some research it seems that a bunch of existing libraries and utilities need to be combined to create a functional and slick user experience for this seemingly mundane task. Specifically the platform I want to use is ASP.NET MVC (although this code will work equally well in Java with a few changes) and the best tools for uploading and cropping images seem to be Uploadify and jCrop powered by jQuery (of course.)

I found a lot of examples of each different library used in ASP.NET (and a few in MVC) but the examples where rather simplistic and didn’t really provide an elegant end to end solution tying together these great libraries. So I went ahead and created a nice ASP.NET MVC based sample application that accomplishes the following…

  • Uploads images with Uploadify
  • Stores uploaded images in Cache
  • Crops images using jCrop
  • Resizing images
  • All interactions handled by jQuery AJAX for a smooth UX

image

Uploading Images

I used a great blog post by James McCormack as the base for uploading images with Uploadify and ASP.NET MVC. Basically Uploadify is doing the heavy lifting and I just tied the onComplete event to an ASP.NET MVC Controller method.

$("#fuFileUploader").uploadify({
'hideButton': true, // We use a trick below to overlay a fake html upload button with this hidden flash button
'wmode': 'transparent',
'uploader': '<%= Url.Content("~/Uploadify/uploadify.swf") %>',
'cancelImg': '<%= Url.Content("~/Uploadify/cancel.png") %>',
'buttonText': 'Upload File',
'script': '<%= Url.Action("FileUpload", "Media") %>',
'multi': true,
'auto': true,
'fileExt': '*.jpg;*.gif;*.png;*.jpeg',
'fileDesc' : 'Image Files',
'scriptData': { RequireUploadifySessionSync: true, SecurityToken: UploadifyAuthCookie, SessionId: UploadifySessionId },
'onComplete': function (event, ID, fileObj, response, data) {
response = $.parseJSON(response);
if (response.Status == 'OK') {
$("#pnlUpload").hide();
$("#pnlUploadedImage").show();
$("#imgUploadedImage").attr("src", imageHandler + response.Id);
$('#imgUploadedImage').Jcrop({
onChange: setCoords,
onSelect: setCoords
});
}
}
});


The controller method grabs the image that was uploaded…


public ActionResult FileUpload(MediaAssetUploadModel uploadedFileMeta)
{
Guid newImageId = new Guid();
try
{
newImageId = ProcessUploadedImage(uploadedFileMeta);
}
catch (Exception ex)
{
string errorMsg = string.Format("Error processing image: {0}", ex.Message);
Response.StatusCode = 500;
Response.Write(errorMsg);
return Json(string.Empty);
}

return Json(new { Id = newImageId, Status = "OK" });
}


And then processes it….


private Guid ProcessUploadedImage(MediaAssetUploadModel uploadedFileMeta)
{
// Get the file extension
WorkingImageExtension = Path.GetExtension(uploadedFileMeta.Filename).ToLower();
string[] allowedExtensions = { ".png", ".jpeg", ".jpg", ".gif" }; // Make sure it is an image that can be processed
if (allowedExtensions.Contains(WorkingImageExtension))
{
WorkingImageId = Guid.NewGuid();
Image workingImage = new Bitmap(uploadedFileMeta.fileData.InputStream);
WorkingImage = ImageHelper.ImageToByteArray(workingImage);
}
else
{
throw new Exception("Cannot process files of this type.");
}

return WorkingImageId;
}


And stores the image converted to a byte array in Cache…


#region cached properties

private byte[] WorkingImage
{
get
{
byte[] img = null;

if (HttpContext.Cache[WorkingImageCacheKey] != null)
img = (byte[])HttpContext.Cache[WorkingImageCacheKey];

return img;
}
set
{
HttpContext.Cache.Add(WorkingImageCacheKey,
value,
null,
System.Web.Caching.Cache.NoAbsoluteExpiration,
new TimeSpan(0, 40, 0),
System.Web.Caching.CacheItemPriority.Low,
null);
}
}

private byte[] ModifiedImage
{
get
{
byte[] img = null;
if (HttpContext.Cache[ModifiedImageCacheKey] != null)
img = (byte[])HttpContext.Cache[ModifiedImageCacheKey];
return img;
}
set
{
HttpContext.Cache.Add(ModifiedImageCacheKey,
value,
null,
System.Web.Caching.Cache.NoAbsoluteExpiration,
new TimeSpan(0, 40, 0),
System.Web.Caching.CacheItemPriority.Low,
null);
}
}

#endregion


The image is assigned in id, which is used as the Cache key and is returned back out via json. Once the call is successfully completed an img src attribute is updated to point to a ASHX image handler I wrote that accepts the id as a querystring parameter.


$("#imgUploadedImage").attr("src", imageHandler + response.Id);


The image handler grabs the image out of the cache and then displays it.


public void ProcessRequest (HttpContext context) {
byte[] image = GetImage(context.Request.QueryString["id"], context);
context.Response.Clear();
context.Response.ContentType = "image/pjpeg";
context.Response.BinaryWrite(image);
context.Response.End();
}


Cropping Images


Once the image has been uploaded, jCrop is initialized to allow for image crop selection.


$('#imgUploadedImage').Jcrop({
onChange: setCoords,
onSelect: setCoords
});


If the user selects a region to crop and clicks the crop button a jQuery AJAX call is made to the server. The x, y and width, height crop values are posted to the server and then the server crops the image as specified. A new modified image id is returned via json to the view and then the new cropped image is displayed via the image handler ashx once again.


function cropImage() {
$.ajax({
url: "/Media/CropImage",
type: "POST",
data: { x: x, y: y, w: w, h: h },
success: function (data) {
$('#lblMethodError').hide();
$("#pnlNewImage").show();
$("#imgNewImage").attr("src", imageHandler + data);
},
error: function (xhr, status, error) {
// Show the error
$('#lblMethodError').text(xhr.responseText);
$('#lblMethodError').show();
}
});

}


public JsonResult CropImage(int x, int y, int w, int h)
{
try
{
if (w == 0 && h == 0) // Make sure the user selected a crop area
throw new Exception("A crop selection was not made.");

string imageId = ModifyImage(x, y, w, h, ImageModificationType.Crop);
return Json(imageId);
}
catch (Exception ex)
{
string errorMsg = string.Format("Error cropping image: {0}", ex.Message);
Response.StatusCode = 500;
Response.Write(errorMsg);
return Json(string.Empty);
}
}


Resizing Images


Resizing images follows the same basic pattern. I have hard coded the new image dimensions in the example, but you could easily add a couple of inputs to the view and allow the user to specify the new dimensions.


Download the Example


I put together a full working example that includes all of the code above and is the basis for what I will end up implemented in my SaaS. I hope you find this helpful.


Aaron Schnieder
http://www.churchofficeonline.com

Tuesday, November 30, 2010

Azure SDK 1.3 Beta - System.ServiceModel Exception on Debug

I started using the new Windows Azure 1.3 SDK (BETA) yesterday and after I installed it I began getting a strange error when I tried to run Debug from Visual Studio 2010.


System.ServiceModel.CommunicationObjectFaultedException was unhandled
Message=The communication object, System.ServiceModel.Channels.ServiceChannel, cannot be used for communication because it is in the Faulted state.

This issue drove me crazy for the last day and after much weeping and gnashing of teeth, I figured out what the fix is:

Make sure your web role web.config is writable (i.e. not locked in read-only by source control or the read-only file bit.)

It looks like there is a bug in the Azure SDK 1.3 that is causing the web.config to be written to during the instantiation of the Azure dev fabric roles. If the web.config is read-only, Azure is blocked from editing the file (no actual edits take place that I can find) and the bizarro System.ServiceModel.CommunicationObjectFailedException message bubbles up.

Secondarily.... Make sure that any declarations are moved to . This was a minor issue causing a few hiccups (not the main problem), but I thought it was worth mentioning.

Hope that helps everyone.

Aaron
http://www.churchofficeonline.com

Wednesday, June 2, 2010

jQuery AJAX Validation Using The Validity Plugin

Books I recommend on this subject

The following book is the best reference I have found when working with jQuery. I highly recommend it!

jQuery in Action

jQuery Validity

Input validation is one of those areas that most developers view as a necessary evil. We know that it is necessary and we really do want to ensure that we get good input from our users. But most of us are lazy (me included) and input validation is one of those things that gets done but usually is a quick and dirty implementation. This is partly due to laziness and partly do to input validation being painful.

Thanks to the amazing jQuery Validity plug in, input validation can be really slick, easy and robust enough to work any any scenario. I specifically like the Validity plugin because it supports jQuery AJAX input validation. Other input validation implementations that I have worked with require a form post to take place. However, if you are using jQuery.ajax methods then there isn’t a form and you need to validate the formless input.

Here is the download link for the jQuery Validity plugin: http://code.google.com/p/validity/downloads/list

Here is the documentation for the jQuery Validity plugin: http://validity.thatscaptaintoyou.com/

What It Looks Like

The default UI for the validation feedback is pretty nice, take a look:

jQueryValidityScreenshot

HTML Input

Here is the HTML markup that I used to create the inputs to validate:

<fieldset id="SignUpFields">
<legend>Sign Up</legend>
<label>Name</label>
<input type="text" id="txtbxName" />
<label>Email</label>
<input type="text" id="txtbxEmail" />
<label>Password</label>
<input type="password" id="txtbxPassword" />
<label>Confirm Password</label>
<input type="password" id="txtbxConfirmPassword" />
<label>How Did You Hear About Us?</label>
<input type="text" id="txtbxSource" />
</fieldset>
<button id="btnSubmit">Submit</button>


jQuery and Validity Functions


The jQuery Validity code is extremely straight forward and minimal.


$(function () {
// Handle the click event for the submit button
$('#btnSubmit').click(function () {
// Validate the fields
if (ValidateFields()) {
// All fields are valid, $.ajax POST would go here
$('#SignUpFields').hide();
$('#btnSubmit').hide();
$('#lblResponse').show();
}
});
});

function ValidateFields() {
// Start validation:
$.validity.start();

// Validate fields
$("#txtbxName").require();
$("#txtbxEmail")
.require()
.match("email");

// Validate password strength & match
$("input[type='password']")
.require()
.match(/^.{8,20}$/, "Passwords must be at least 8 characters.")
.equal("Passwords do not match.");

// All of the validator methods have been called:
// End the validation session:
var result = $.validity.end();

// Return whether it's okay to proceed with the Ajax:
return result.valid;
}


That's It!


That's all it takes, very simple and straight forward. Just that tiny bit of Javascript gives you rich input validation and a nice user experience!


Demo Download


Here is a little ASP.NET MVC demo that I threw together using jQuery Validity so you can see it in action and play with it.



- Aaron Schnieder
http://www.churchofficeonline.com

Windows Live Writer Code Snippet Plugin

I love Windows Live Writer as a blogging application and use it pretty much exclusively for writing my blog posts. The only downside is that I have found it difficult to get code snippets formatted correctly in my posts. Luckily a friend of mine, Tyson Swing, turned me on to a great code snippet plugin for Windows Live writer.

CodeSnippet

The Windows Live Writer code snippet plugin is aptly named “CodeSnippet” and you can download it here: http://wlwplugincollection.codeplex.com/ 

This Windows Live Writer code snippet plugin is provided by Leo Vidosola. http://lvildosola.blogspot.com/

Settings

Personally, I have found that the following settings work well for the “CodeSnippet” plug in:

  • Be sure to select the correct code language
  • No Line Numbers
  • No Alternate Lines
  • No Container

Aaron Schnieder
http://www.churchofficeonline.com

Monday, May 3, 2010

jQuery Ajax Error Handling – How To Show Custom Error Messages

Books I recommend on this subject

The following books are the best references I have found when working with jQuery and ASP.NET MVC. I highly recommend both.

jQuery in Action

Pro ASP.NET MVC Framework

So you want to make your error feedback nice for your users…

Kind of an ironic statement isn’t it? We obviously want to avoid errors if at all possible in our applications, but when errors do occur then we want to provide some nice feedback to our users. The worst thing that can happen is to blow up a huge server exception page when something goes wrong or equally bad is not providing any feedback at all and leaving the user in the dark. Although I do not recommend displaying actual .NET Framework exception messages or stack traces to the user in most instances; they are usually not helpful to the user and can be a security concern.

Using the jQuery Ajax methods ($.ajax(), $.get(), $.post(), etc.) to call your controller (in ASP.NET MVC) or web service (in ASP.NET) to perform server side actions (GET, POST, etc.) is a great way to provide a great user experience in ASP.NET applications while also interacting with a server to get or update data. However, if an error occurs on the server, or an exception takes place in the server side methods, then the problem can often be hidden from the user. Because a Postback is not taking place, if you do not handle errors on the jQuery Ajax methods and display some feedback then the user will be left in a state where they have no idea that a problem has occurred. Luckily, we can use the error callback on the jQuery Ajax methods along with some controller information to display some nice error feedback to the user.

Setting up layers to handle and communicate problems

I have defined an Entities assembly that contains an object to be used to provide operation feedback between assemblies and methods.

namespace jQueryCustomErrorHandling.Entities
{
public class OperationResult
{
public bool Success { get; set; }
public string Message { get; set; }
}
}

My persistence and logic methods pass an OperationResult as a return type.

Persistence Layer 

public interface IMyDao
{
OperationResult MyDaoMethod(bool fail);
}
public class MyDao : IMyDao
{
public OperationResult MyDaoMethod(bool fail)
{
var result = new OperationResult() { Success = true };
try
{
if (fail)
throw new Exception("Persistance Error");
}
catch (Exception ex)
{
result.Success = false;
result.Message = ex.Message;
}
return result;
}
}

Logic Layer

public interface IMyLogic
{
OperationResult MyLogicMethod(bool fail);
}
public class MyLogic : IMyLogic
{
private IMyDao _myDao;
public IMyDao MyDao
{
get { return _myDao ?? (_myDao = new MyDao()); }
set { _myDao = value; }
}
public OperationResult MyLogicMethod(bool fail)
{
return MyDao.MyDaoMethod(fail);
}
}

And now communicating the errors to the presentation layer

I have created a controller method that calls the logic layer. Notice that if the OperationResult.Success property is set to false, I throw an exception in the controller method. The catch block handles that exception and sets the Response.StatusCode to an error and then also does a Response.Write of the error message. This is how we communicate with the jQuery error callback that there was an error on the server side.

[AcceptVerbs(HttpVerbs.Post)]
public JsonResult MyPostMethod(bool fail)
{
try
{
// Call the logic layer to make the updates
OperationResult result = MyLogic.MyLogicMethod(fail);
// If the result is a failure, throw an exception
if (!result.Success)
throw new Exception(result.Message);
return Json(result.Message);
}
catch (Exception ex)
{
string errorMsg = string.Format("Error posting data: {0}", ex.Message);
Response.StatusCode = 500;
Response.Write(errorMsg);
return Json(string.Empty);
}
}

The jQuery.ajax configuration looks like this:

function CallAjaxMethod(fail) {
$('#lblMethodError').hide();
$('#lblMethodSuccess').hide();
$.ajax({
type: "POST",
url: "/Home/MyPostMethod",
data: "fail=" + fail,
dataType: "json",
error: function(xhr, status, error) {
// Show the error
$('#lblMethodError').text(xhr.responseText);
$('#lblMethodError').show();
},
success: function(data, textSuccess) {
// show the success message
$('#lblMethodSuccess').show();
}
});
}

The presentation

In the view I simply have two hidden labels that I show or hide depending on whether or not the jQuery.ajax call was successful. I populate the error label with the custom error message from the server in the jQuery.ajax error callback if a problem occurred on the server side.

This provides a nice way to give feedback to the user when problems occur on the server side and also establishes a nice error handling pattern within your projects.

Demo download

I put together a working demo with full source code that you can download below.

- Aaron Schnieder
http://www.churchofficeonline.com

Thursday, April 22, 2010

Best jQuery Libraries, Plug-Ins and Controls

Worried About The Loss Of ASP.NET Controls in MVC? Don’t Be

If you are hesitant of moving to ASP.NET MVC because you are worried about losing all of the awesome ASP.NET controls that you are so used to using, don’t be. Wonderful client side controls already exist to replace most, if not all, of the most used ASP.NET controls (and these controls provide a MUCH BETTER user experience.)

First off, if you are looking for an excellent jQuery book I HIGHLY recommend jQuery in Action

Here are the best jQuery libraries, plug-ins and controls that I have found to date.

What is a CDN (Content Delivery Network)?
http://en.wikipedia.org/wiki/Content_delivery_network

jQuery

The best client site Javascript library to date. Client side development without jQuery just doesn’t make sense.

Information, Documentation & Download http://jquery.com/
Google CDN http://code.google.com/apis/ajaxlibs/documentation/index.html#jquery
Microsoft CDN http://www.asp.net/ajaxlibrary/cdn.ashx

jQueryUI

Excellent user interface controls, interactions and effects that are built on top of the jQuery framework. Provides themes for customized look and feel and out of the box excellent user experience.

  • Calendar control
  • Dialog / Modal control
  • Tab control
  • Accordion control
  • Animation effects
  • Draggable / Droppable interaction
  • Much, much, much more….

Information, Documentation & Download http://jqueryui.com/
Google CDN http://code.google.com/apis/ajaxlibs/documentation/index.html#jqueryUI

Date.js

Sweet library that makes working with dates on the client side infinitely easier. Great for date calculations, date ranges and date validation.

  • Text date references; ‘last week’ will return the date for 7 days ago
  • ‘yesterday’ returns yesterday’s date
  • Date.parse('1 month ago').moveToFirstDayOfMonth() returns the first day of last month
  • Much, much more…

Information, Documentation & Download http://www.datejs.com/

Validity Validation Plug In

The jQuery Validity plug-in is an extremely flexible, lightweight and easy to use validation library. You can validate anything on the fly in any instance. It doesn’t require a form or anything else, just setup the validation rules (there are a bunch of common validations built in) and go.

Information, Documentation & Download http://validity.thatscaptaintoyou.com/

DateRangePicker

The DateRangePicker plug-in from the Filament Group is an awesome little user experience element that makes selecting dates so much nicer. You can select predefined dates or date ranges easily (such as last week, last month, yesterday, etc.) and is the best user experience have seen selecting a date range.

Information, Documentation & Download http://www.filamentgroup.com/lab/date_range_picker_using_jquery_ui_16_and_jquery_ui_css_framework/

jQuery Tools

jQuery Tools is an excellent library of user interface elements. It is fairly lightweight and can add some very nice user experience elements to your applications.

  • Tooltips
  • Overlays
  • Scrollable Galleries
  • Flash Embedding

Information, Documentation & Download http://flowplayer.org/tools/index.html

jqGrid

Ah jqGrid, how I love thee jqGrid. This little beauty is a wonderful Gridview alternative in ASP.NET MVC. I wrote up an overview of using it here: http://www.schnieds.com/2010/01/gridview-in-aspnet-mvc.html

Information, Documentation & Download http://www.trirand.com/blog/

jQuery Templates

jQuery Templates are a way to accomplish DataBinding in ASP.NET MVC. Basically you pre-define some HTML elements and then when the page is rendering you use a jQuery AJAX call to get some data from the server, create instances of the HTML elements, populate the values and then append the items into the DOM. jQuery Templates makes this process very easy. Here is a nice tutorial on using this plug-in: http://publicityson.blogspot.com/2009/11/dynamic-content-using-html-templates.html

Information, Documentation & Download http://plugins.jquery.com/project/jquerytemplate