text: 
  /*
   * jQuery UI wizard plug-in 0.9.5
   *
   *
   * Copyright (c) 2009 Jan Sundman (jan.sundman[at]aland.net)
   * Copyright (c) 2009 James M. Curran (jamescurran[at]mvps.org)
   
   * Licensed under the MIT licens:
   *   http://www.opensource.org/licenses/mit-license.php
   *   
   *
   * Changelog:
   * version 0.9.5a
   *  Fork of Jan's original by James.   Principal changes:
   *    - Changed API to confirm to jQuery UI standards.  Notably, it's
   *      now called wizard() instead of formwizard(). (a formwizard()
   *      function remains which adapts the old-style calls to the new API)
   *   - Added jQuery UI-ish CSS classes for styling.
   *   - Refactored some code.
   *   - added three new options:
   *    o   validationOptions:  A set of key/value pairs to set as configuration 
   *                properties for the validation plugin. (formerly a separate 
   *                parameter in formwizard)
   *    o   formOptions: A set of key/value pairs to set as configuration 
   *                properties for the form plugin. (formerly a separate parameter 
   *                in formwizard)
   *    o  autoDisableNext:  When set to true, the "Next" button is automatically 
   *                disabled, requiring it be manually enable once the user has 
   *                completed the step. 
   *   - added five new methods
   *    o enableNext() - 
   *    o disableNext() - 
   *    o enableBack() - 
   *    o disableBack() - 
   *    o gotoStep(step) - navigates to the given step.  step can be either a 0-based index, or a jQuery selector.
   *  - added one new callback
   *     o show() - called each time a new panel is displayed.          
   *         function show(evnt, args)
   *              event - standard jQuery UI event object.
   *              args - object with fields:  
   *                 step - jQuery wrapped object of the DIV being displayed.
   *                 stepInx - 0-based index of the DIV.
   *                 backwards - true if reached by clicking "back", false otherwise.
   *      (callback afterNext & afterBack remain, but are depreciated)
   * 
   * version 0.9.5
   * -------------
   * - Fix for enabling optional validation
   *
   * version 0.9.4
   * -------------
   * - Performance fixes for validation of the steps
   * - Performance fixes for rendering of the steps
   * - Introduces a need for input fields in the wizard to be disabled in the html
   *
   * version 0.9.3
   * ------------- 
   * - Fixed the continueToNextStep and backButton.click callback to handle navigation correctly when the 
   * history plugin is not used
   * 
   * version 0.9.2 
   * - A check was added to see if there are multiple links on one step. In the
   * case there are we assume they are radio buttons or checkboxes. Only the
   * one that is checked is considered a valid link. This fixes a bug where links
   * in the form of radio buttons do not work. Credits to adnanshareef for 
   * reporting the bug.  
   * 
   * - Added initial functionality for doing server-side validation 
   * 
   * version 0.9.1 
   * -------------
   * - Addition of afterNext and afterBack callbacks, can be used to do stuff after
   * the rendering of a step has been completed
   * 
   * version 0.9.0 
   * -------------
   * - Initial release
   *
   */
  
  (function ($) {
  
  	$.widget("ui.wizard",
  	{
  		options:
  		{
  			animated: 'fadeIn',
  			historyEnabled: undefined,
  			validationEnabled: undefined,
  			formPluginEnabled: undefined,
  			linkClass: ".link",
  			submitStepClass: ".submit_step",
  			back: ".wizard_back",
  			next: ".wizard_next",
  			help: ".wizard_help",
  			textSubmit: 'Submit',
  			textNext: 'Next',
  			textBack: 'Back',
  			afterNext: undefined,
  			afterBack: undefined,
  			show: undefined,
  			autoNextDisabled: true,
  			serverSideValidationUrls: undefined,
  			formOptions: undefined,
  			validationOptions: {}
  		},
  
  		_init: function () {
  			// if historyEnabled not explicit defined, set it based on presence/absence of jquery.history.js plugin
  			if (this.options.historyEnabled == undefined)
  				this.options.historyEnabled = ($.historyInit != undefined);
  
  			// if formPluginEnabled not explicitly set, set it based on the presents/absence of formOptions
  			if (typeof (this.options.formPluginEnabled) == "undefined")
  				this.options.formPluginEnabled = (this.options.formOptions == null);
  
  			if (this.options.formPluginEnabled) {
  				this.options.formOptions = $.extend({ reset: true, success: function (data) { alert("success"); } }, this.options.formOptions);
  				var formOptionsSuccess = this.options.formOptions.success;
  				var formSettings = $.extend(this.options.formOptions, { success: function (data) {
  					if (formOptions.resetForm) {
  						_navigate(0);
  						if (this.options.historyEnabled) {
  							$.historyLoad(0);
  						}
  						else {
  							_renderStep();
  						}
  					}
  					formOptionsSuccess(data);
  				}
  				});
  			}
  			else {
  				if (typeof (this.options.formOptions) == "undefined")
  					this.options.formOptions = { success: function () { } };
  				else
  					this.options.formOptions.success = function () { };
  			}
  			/**
  			* Initialization
  			*/
  
  			this.element.addClass("ui-wizard ui-widget ui-helper-reset");
  
  			this.steps = this.element.find(".step");
  			this.steps.addClass("ui-wizard-content ui-helper-reset ui-widget-content ui-corner-all")
  
  			this.currentStep = 0;
  			this.previousStep = undefined;
  			this.backButton = this.element.find(this.options.back);
  			this.nextButton = this.element.find(this.options.next);
  			this.helpButton = this.element.find(this.options.help);
  
  			this.backButton.addClass("ui-wizard-content ui-helper-reset ui-state-default ui-state-hover  ui-state-active");
  			this.nextButton.addClass("ui-wizard-content ui-helper-reset ui-state-default ui-state-hover  ui-state-active");
  			this.helpButton.addClass("ui-wizard-content ui-helper-reset ui-state-default  ui-button ui-icon ui-icon-help")
  				.hide();
  
  			jQuery(".help").hide();
  
  			this.activatedSteps = new Array();
  			this.isLastStep = false;
  			var wizard = this;         // for closures in the next lines.
  			this.helpButton.click(function () {
  				jQuery(".help", wizard.steps[wizard.currentStep])
  				.clone()
  				.dialog({
  					resizable: false,
  					autoOpen: true,
  					height: 250,
  					width: 500,
  					modal: true,
  					overlay:
  									{
  										backgroundColor: '#000',
  										opacity: 0.5
  									}
  				});
  			});
  
  			if (this.options.historyEnabled) {
  				if ($.historyInit == undefined) {
  					this.options.historyEnabled = false;
  					alert("the history plugin needs to be included");
  				}
  				else {
  					location.hash = "";
  					$.historyInit(function (hash) { wizard._handleHistory(hash); });
  				}
  			}
  			else {
  				this._handleHistory(0);
  			}
  
  			if (this.options.validationEnabled == undefined)
  				this.options.validationEnabled = (this.options.validationSettings == {});
  
  			if (jQuery().validate == undefined) {
  				if (this.options.validationEnabled) {
  					this.options.validationEnabled = false;
  					alert("the validation plugin needs to be included");
  				}
  			}
  			else if (this.options.validationEnabled) {
  				this.element.validate(this.options.validationSettings);
  			}
  
  			if (this.options.formPluginEnabled && jQuery().ajaxSubmit == undefined) {
  				this.options.formPluginEnabled = false;
  				alert("the form plugin needs to be included");
  			}
  
  			/** 
  			* Navigation event callbacks 
  			*/
  			var wizard = this;         // for closures in the next lines.
  			this.nextButton.click(function () { return wizard._nextButton_click(this); });
  			this.backButton.click(function () { return wizard._backButton_click(this); });
  			this.backButton.val(this.options.textBack).text(this.options.textBack);
  			$("input", this.element).attr("disabled", "disabled");
  			this.steps.hide();
  			this._renderStep();
  			return $(this);
  		},
  
  		destroy: function () {
  			this.element.removeClass("ui-formwizard ui-widget ui-helper-reset");
  			this.steps.removeClass("ui-wizard-content ui-helper-reset ui-widget-content ui-corner-all")
  			this.backButton.removeClass("ui-wizard-content ui-helper-reset ui-state-default ui-state-hover  ui-state-active  ui-state-disabled")
  				.unbind("click");
  			this.nextButton.removeClass("ui-wizard-content ui-helper-reset ui-state-default ui-state-hover  ui-state-active  ui-state-disabled")
  				.unbind("click");
  		},
  
  		/* 
  		***********************************
  		*/
  		activate: function (step) {
  			gotoStep(step);
  		},
  		/* 
  		***********************************
  		*/
  		_backButton_click: function (btn) {
  			if (this.activatedSteps.length > 0) {
  				if (this.options.historyEnabled) {
  					history.back();
  				}
  				else {
  					this._handleHistory(this.activatedSteps[this.activatedSteps.length - 2]);
  				}
  			}
  
  			this._trigger("afterBack");
  
  			return false;
  		},
  		/**
  		* Checks if the step is the last step in a wizard route
  		*
  		* @name checkIflastStep
  		* @type undefined
  		* @param Number step The step to check.
  		*/
  		_checkIflastStep: function (step) {
  			var link = this._getLink($(this.steps[step]));
  
  			this.isLastStep = false;
  
  			if ((("." + link) == this.options.submitStepClass) || (link == undefined && (step * 1) == this.steps.length - 1)) {
  				this.isLastStep = true;
  			}
  		},
  
  		/**
  		* Continues to the next step in the wizard
  		*/
  		_continueToNextStep: function () {
  			this._navigate(this.currentStep);
  			this._renderStep();
  
  			if (this.options.historyEnabled) {
  				$.historyLoad(this.currentStep);
  			}
  			else {
  				this._handleHistory(this.currentStep);
  			}
  
  			this._trigger("afterNext");
  		},
  
  		/* 
  		***********************************
  		*/
  		disableBack: function () {
  			this.backButton.attr('disabled', 'disabled').addClass("ui-state-disabled");
  		},
  
  		/* 
  		***********************************
  		*/
  		disableNext: function () {
  			this.nextButton.attr('disabled', 'disabled').addClass("ui-state-disabled");
  		},
  
  		/* 
  		***********************************
  		*/
  		enableBack: function () {
  			this.backButton.removeAttr("disabled").removeClass("ui-state-disabled");
  		},
  		/* 
  		***********************************
  		*/
  		enableNext: function () {
  			this.nextButton.removeAttr("disabled").removeClass("ui-state-disabled");
  		},
  
  		/**
  		* Finds the valid link for the step (if there is one)
  		*
  		* @name getLink
  		* @type String
  		* @param Number step The step to search for valid links
  		*/
  		_getLink: function (step) {
  			var link = undefined;
  			var links = step.find(this.options.linkClass);
  
  			if (links.length == 1) {
  				link = links.val();
  			}
  			else if (links.length > 1) {
  				// assume that the link is a radio button or checkbox
  				link = step.find(this.options.linkClass + ":checked").val();
  			}
  
  			return link;
  		},
  
  		gotoStep: function (step) {
  			var stepInx;
  			if (typeof (step) == "string")
  				stepInx = this.steps.index($(step));
  			else
  				stepInx = step;
  
  			// If in range, go there.  Otherwise, silently exit.
  			if (stepInx >= 0 && stepInx < this.steps.length) {
  				jQuery(this.steps[this.currentStep]).hide();
  				this._handleHistory(stepInx);
  			}
  		},
  
  		/**
  		* Handles back navigation (and browser back and forward buttons if history is enabled)
  		*
  		* @name handleHistory
  		* @type undefined
  		* @param String hash The hash used in the browser history
  		
  		If hash ==previous step, remove current step from activatedSteps, and then goto previous.
  		Otherwise, add hash to end of activatedSteps, and go there.
  		*/
  		_handleHistory: function (hash) {
  			var direction = false;
  			if (!hash) {
  				hash = 0;
  			}
  			if (this.activatedSteps[this.activatedSteps.length - 2] == hash) {
  				this.activatedSteps.pop();
  				direction = true;
  			}
  			else {
  				this.activatedSteps.push(hash);
  			}
  			this.previousStep = this.currentStep;
  			this.currentStep = hash;
  			this._checkIflastStep(hash);
  			this._renderStep();
  
  			if (this.options.autoNextDisabled)
  				this.disableNext();
  			this._trigger("show", null, { step: $(this.steps[this.currentStep]), stepInx: this.currentStep, backward: direction });
  
  		},
  		moveNext: function () {
  			this._nextButton_click(null);
  		},
  		/**
  		* Decides and sets the current step in the wizard 
  		*
  		* @name navigate
  		* @type undefined
  		* @param Number step The step to navigate from.
  		*/
  		_navigate: function (stepInx) {
  			var step = $(this.steps[stepInx]);
  			var link = this._getLink(step);
  
  			if (link) {
  				var navigationTarget = this.steps.index($("#" + link));
  				if (navigationTarget.length == 0) {
  					return;
  				}
  				else {
  					this.previousStep = this.currentStep;
  					this.currentStep = navigationTarget;
  				}
  
  				this._checkIflastStep(step);
  			}
  			else if (!this.isLastStep) {
  				this.previousStep = this.currentStep;
  				this.currentStep++
  				this._checkIflastStep(this.currentStep);
  			}
  		},
  		/* 
  		***********************************
  		*/
  		_nextButton_click: function (btn) {
  			if (this.options.validationEnabled) {
  				var valid = true;
  				var form = this.element;
  				$.each(form.find("input:enabled, select:enabled"), function () {
  					if (form.validate().element($(this)) == false)
  						valid = false;
  				})
  				if (!valid) return false;
  			}
  
  			if (this.isLastStep) {
  				if (this.options.formPluginEnabled) {
  					this.element.ajaxSubmit(this.options.formSettings);
  					return false;
  				}
  				this.element.submit();
  				return false;
  			}
  
  			// Doing server side validation for the steps
  			if (this.options.serverSideValidationUrls) {
  				var url = "";
  				var errorCallback = undefined;
  				$.each(this.options.serverSideValidationUrls, function () {
  					if (this.validation.step == this.currentStep) {
  						url = this.validation.url;
  						errorCallback = this.validation.error;
  					}
  				});
  
  				if (url != "") {
  					this.element.ajaxSubmit(
  							{ url: url,
  								success: function () { this._continueToNextStep(); },
  								error: function () { errorCallback(); }
  							});
  					alert("server side done");
  					return false;
  				}
  			}
  			this._continueToNextStep();
  			return false;
  		},
  
  		/**
  		* Renders the current step and disables the input fields in other steps
  		*
  		* @name renderStep
  		* @type undefined
  		*/
  		_renderStep: function () {
  			this.enableBack();
  			this.nextButton.val(this.options.textNext).text(this.options.textNext);
  			//            var steps = this._getData('steps');
  
  			if (this.previousStep != undefined) {
  				this.steps.eq(this.previousStep).hide()
  					.find("input")
  					.attr("disabled", "disabled");
  			}
  			var effect = this.options.animated;
  			this.steps.eq(this.currentStep)[effect]()
  			   .find("input").removeAttr("disabled");
  
  			if (this.isLastStep) {
  				for (var i = 0; i < this.activatedSteps.length; i++) {
  					this.steps.eq(this.activatedSteps[i]).find("input").removeAttr("disabled");
  				}
  				this.nextButton.val(this.options.textSubmit).text(this.options.textSubmit);
  			}
  			else if (this.currentStep == 0) {
  				this.disableBack();
  			}
  			this._showHelp();
  		},
  
  		_showHelp: function () {
  			if (jQuery(".help", this.steps[this.currentStep]).length > 0) {
  				this.helpButton.show();
  			}
  			else {
  				this.helpButton.hide();
  			}
  		}
  	});
  
  
  	/**
  	* Creates a wizard of all matched elements
  	*
  	* @constructor
  	* @name $.formwizard
  	* @param Hash wizardSettings A set of key/value pairs to set as configuration properties for the wizard plugin.
  	* @param Hash validationSettings A set of key/value pairs to set as configuration properties for the validation plugin.
  	* @param Hash formOptions A set of key/value pairs to set as configuration properties for the form plugin.
  	*/
  
  	$.fn.formwizard = function (wizardSettings, validationSettings, formOptions) {
  		return this.formwizard($.extend(wizardSettings, { back: ":reset", next: ":submit", autoNextDisabled: false, validationOptions: validationSettings, formOptions: formOptions }));
  	}
  }
  )(jQuery);