2 * SmartWizard 2.0 plugin
3 * jQuery Wizard control Plugin
6 * http://www.techlaboratory.net
7 * http://tech-laboratory.blogspot.com
11 $.fn.smartWizard = function(action) {
12 var options = $.extend({}, $.fn.smartWizard.defaults, action);
15 return this.each(function(){
17 var curStepIdx = options.selected;
18 var steps = $("ul > li > a[href^='#step-']", obj); // Get all anchors in this array
20 var loader,msgBox,elmActionBar,elmStepContainer,btNext,btPrevious,btFinish;
22 elmActionBar = $('.actionBar',obj);
23 if(elmActionBar.length == 0){
24 elmActionBar = $('<div></div>').addClass("actionBar");
27 msgBox = $('.msgBox',obj);
28 if(msgBox.length == 0){
29 msgBox = $('<div class="msgBox"><div class="content"></div><a href="#" class="close">X</a></div>');
30 elmActionBar.append(msgBox);
33 $('.close',msgBox).click(function() {
34 msgBox.fadeOut("normal");
39 // Method calling logic
40 if (!action || action === 'init' || typeof action === 'object') {
42 }else if (action === 'showMessage') {
43 //showMessage(Array.prototype.slice.call( args, 1 ));
44 var ar = Array.prototype.slice.call( args, 1 );
47 }else if (action === 'setError') {
48 var ar = Array.prototype.slice.call( args, 1 );
49 setError(ar[0].stepnum,ar[0].iserror);
51 }else if (action === 'setDone') {
52 var ar = Array.prototype.slice.call( args, 1 );
53 setDone(ar[0].stepnum,ar[0].isdone);
56 $.error( 'Method ' + action + ' does not exist' );
60 var allDivs =obj.children('div'); //$("div", obj);
61 obj.children('ul').addClass("anchor");
62 allDivs.addClass("content");
64 loader = $('<div>Loading</div>').addClass("loader");
65 elmActionBar = $('<div></div>').addClass("actionBar");
66 elmStepContainer = $('<div></div>').addClass("stepContainer");
67 btNext = $('<a>'+options.labelNext+'</a>').attr("href","#").addClass("buttonNext");
68 btPrevious = $('<a>'+options.labelPrevious+'</a>').attr("href","#").addClass("buttonPrevious");
69 btFinish = $('<a>'+options.labelFinish+'</a>').attr("href","#").addClass("buttonFinish");
71 // highlight steps with errors
72 if(options.errorSteps && options.errorSteps.length>0){
73 $.each(options.errorSteps, function(i, n){
79 elmStepContainer.append(allDivs);
80 elmActionBar.append(loader);
81 obj.append(elmStepContainer);
82 obj.append(elmActionBar);
83 if (options.includeFinishButton) {
84 elmActionBar.append(btFinish);
86 elmActionBar.append(btNext).append(btPrevious);
87 contentWidth = elmStepContainer.width();
89 $(btNext).click(function() {
90 if($(this).hasClass('buttonDisabled')){
96 $(btPrevious).click(function() {
97 if($(this).hasClass('buttonDisabled')){
100 doBackwardProgress();
103 $(btFinish).click(function() {
104 if(!$(this).hasClass('buttonDisabled')){
105 if($.isFunction(options.onFinish)) {
106 if(!options.onFinish.call(this,$(steps))){
110 var frm = obj.parents('form');
111 if(frm && frm.length){
120 $(steps).bind("click", function(e){
121 if(steps.index(this) == curStepIdx){
124 var nextStepIdx = steps.index(this);
125 var isDone = steps.eq(nextStepIdx).attr("isDone") - 0;
127 LoadContent(nextStepIdx);
132 // Enable keyboard navigation
133 if(options.keyNavigation){
134 $(document).keyup(function(e){
135 if(e.which==39){ // Right Arrow
137 }else if(e.which==37){ // Left Arrow
138 doBackwardProgress();
144 // Show the first slected step
145 LoadContent(curStepIdx);
148 function prepareSteps(){
149 if(!options.enableAllSteps){
150 $(steps, obj).removeClass("selected").removeClass("done").addClass("disabled");
151 $(steps, obj).attr("isDone",0);
153 $(steps, obj).removeClass("selected").removeClass("disabled").addClass("done");
154 $(steps, obj).attr("isDone",1);
157 $(steps, obj).each(function(i){
158 $($(this).attr("href"), obj).hide();
159 $(this).attr("rel",i+1);
163 function LoadContent(stepIdx){
164 var selStep = steps.eq(stepIdx);
165 var ajaxurl = options.contentURL;
166 var hasContent = selStep.data('hasContent');
168 if(ajaxurl && ajaxurl.length>0){
169 if(options.contentCache && hasContent){
175 data: ({step_number : stepNum}),
177 beforeSend: function(){ loader.show(); },
178 error: function(){loader.hide();},
179 success: function(res){
181 if(res && res.length>0){
182 selStep.data('hasContent',true);
183 $($(selStep, obj).attr("href"), obj).html(res);
194 function showStep(stepIdx){
195 var selStep = steps.eq(stepIdx);
196 var curStep = steps.eq(curStepIdx);
197 if(stepIdx != curStepIdx){
198 if($.isFunction(options.onLeaveStep)) {
199 if(!options.onLeaveStep.call(this,$(curStep))){
204 if (options.updateHeight)
205 elmStepContainer.height($($(selStep, obj).attr("href"), obj).outerHeight());
206 if(options.transitionEffect == 'slide'){
207 $($(curStep, obj).attr("href"), obj).slideUp("fast",function(e){
208 $($(selStep, obj).attr("href"), obj).slideDown("fast");
209 curStepIdx = stepIdx;
210 SetupStep(curStep,selStep);
212 } else if(options.transitionEffect == 'fade'){
213 $($(curStep, obj).attr("href"), obj).fadeOut("fast",function(e){
214 $($(selStep, obj).attr("href"), obj).fadeIn("fast");
215 curStepIdx = stepIdx;
216 SetupStep(curStep,selStep);
218 } else if(options.transitionEffect == 'slideleft'){
220 var curElementLeft = 0;
221 if(stepIdx > curStepIdx){
222 nextElmLeft1 = contentWidth + 10;
224 curElementLeft = 0 - $($(curStep, obj).attr("href"), obj).outerWidth();
226 nextElmLeft1 = 0 - $($(selStep, obj).attr("href"), obj).outerWidth() + 20;
228 curElementLeft = 10 + $($(curStep, obj).attr("href"), obj).outerWidth();
230 if(stepIdx == curStepIdx){
231 nextElmLeft1 = $($(selStep, obj).attr("href"), obj).outerWidth() + 20;
233 curElementLeft = 0 - $($(curStep, obj).attr("href"), obj).outerWidth();
235 $($(curStep, obj).attr("href"), obj).animate({left:curElementLeft},"fast",function(e){
236 $($(curStep, obj).attr("href"), obj).hide();
240 $($(selStep, obj).attr("href"), obj).css("left",nextElmLeft1);
241 $($(selStep, obj).attr("href"), obj).show();
242 $($(selStep, obj).attr("href"), obj).animate({left:nextElmLeft2},"fast",function(e){
243 curStepIdx = stepIdx;
244 SetupStep(curStep,selStep);
247 $($(curStep, obj).attr("href"), obj).hide();
248 $($(selStep, obj).attr("href"), obj).show();
249 curStepIdx = stepIdx;
250 SetupStep(curStep,selStep);
255 function SetupStep(curStep,selStep){
256 $(curStep, obj).removeClass("selected");
257 $(curStep, obj).addClass("done");
259 $(selStep, obj).removeClass("disabled");
260 $(selStep, obj).removeClass("done");
261 $(selStep, obj).addClass("selected");
262 $(selStep, obj).attr("isDone",1);
264 if($.isFunction(options.onShowStep)) {
265 if(!options.onShowStep.call(this,$(selStep))){
271 function doForwardProgress(){
272 var nextStepIdx = curStepIdx + 1;
273 if(steps.length <= nextStepIdx){
274 if(!options.cycleSteps){
279 LoadContent(nextStepIdx);
282 function doBackwardProgress(){
283 var nextStepIdx = curStepIdx-1;
285 if(!options.cycleSteps){
288 nextStepIdx = steps.length - 1;
290 LoadContent(nextStepIdx);
293 function adjustButton(){
294 if(!options.cycleSteps){
296 $(btPrevious).addClass("buttonDisabled");
298 $(btPrevious).removeClass("buttonDisabled");
300 if((steps.length-1) <= curStepIdx){
301 $(btNext).addClass("buttonDisabled");
303 $(btNext).removeClass("buttonDisabled");
307 if(!steps.hasClass('disabled') || options.enableFinishButton){
308 $(btFinish).removeClass("buttonDisabled");
310 $(btFinish).addClass("buttonDisabled");
314 function showMessage(msg){
315 $('.content',msgBox).html(msg);
319 function setError(stepnum,iserror){
321 $(steps.eq(stepnum-1), obj).addClass('error')
323 $(steps.eq(stepnum-1), obj).removeClass("error");
327 function setDone(stepnum,isdone){
329 $(steps.eq(stepnum-1), obj).removeClass("selected").removeClass("disabled").addClass('done')
331 $(steps.eq(stepnum-1), obj).removeClass("done");
337 // Default Properties and Events
338 $.fn.smartWizard.defaults = {
339 selected: 0, // Selected Step, 0 = first step
340 keyNavigation: true, // Enable/Disable key navigation(left and right keys are used if enabled)
341 enableAllSteps: false,
343 transitionEffect: 'fade', // Effect on navigation, none/fade/slide/slideleft
344 contentURL:null, // content url, Enables Ajax content loading
345 contentCache:true, // cache step contents, if false content is fetched always from ajax url
346 cycleSteps: false, // cycle step navigation
347 includeFinishButton: true, // whether to show a Finish button
348 enableFinishButton: false, // make finish button enabled always
349 errorSteps:[], // Array Steps with errors
351 labelPrevious:'Previous',
352 labelFinish:'Finish',
353 onLeaveStep: null, // triggers when leaving a step
354 onShowStep: null, // triggers when showing a step
355 onFinish: null // triggers when Finish button is clicked