1 | /* |
||
2 | * SmartWizard 3.3.1 plugin |
||
3 | * jQuery Wizard control Plugin |
||
4 | * by Dipu |
||
5 | * |
||
6 | * Refactored and extended: |
||
7 | * https://github.com/mstratman/jQuery-Smart-Wizard |
||
8 | * |
||
9 | * Original URLs: |
||
10 | * http://www.techlaboratory.net |
||
11 | * http://tech-laboratory.blogspot.com |
||
12 | */ |
||
13 | |||
14 | function SmartWizard(target, options) { |
||
15 | this.target = target; |
||
16 | this.options = options; |
||
17 | this.curStepIdx = options.selected; |
||
18 | this.steps = $(target).children("ul").children("li").children("a"); // Get all anchors |
||
19 | this.contentWidth = 0; |
||
20 | this.msgBox = $('<div class="msgBox"><div class="content"></div><a href="#" class="close">X</a></div>'); |
||
21 | this.elmStepContainer = $('<div></div>').addClass("stepContainer"); |
||
22 | this.loader = $('<div>Loading</div>').addClass("loader"); |
||
23 | this.buttons = { |
||
24 | next : $('<a>'+options.labelNext+'</a>').attr("href","#").addClass("btn btn-success"), |
||
25 | previous : $('<a>'+options.labelPrevious+'</a>').attr("href","#").addClass("btn btn-primary"), |
||
26 | finish : $('<a>'+options.labelFinish+'</a>').attr("href","#").addClass("btn btn-default") |
||
27 | }; |
||
28 | |||
29 | /* |
||
30 | * Private functions |
||
31 | */ |
||
32 | |||
33 | var _init = function($this) { |
||
34 | var elmActionBar = $('<div></div>').addClass("actionBar"); |
||
35 | //elmActionBar.append($this.msgBox); |
||
36 | $('.close',$this.msgBox).click(function() { |
||
37 | $this.msgBox.fadeOut("normal"); |
||
38 | return false; |
||
39 | }); |
||
40 | |||
41 | var allDivs = $this.target.children('div'); |
||
42 | // CHeck if ul with steps has been added by user, if not add them |
||
43 | if($this.target.children('ul').length == 0 ){ |
||
44 | var ul = $("<ul/>"); |
||
45 | target.prepend(ul) |
||
46 | |||
47 | // for each div create a li |
||
48 | allDivs.each(function(i,e){ |
||
49 | var title = $(e).first().children(".StepTitle").text(); |
||
50 | var s = $(e).attr("id") |
||
51 | // if referenced div has no id, add one. |
||
52 | if (s==undefined){ |
||
53 | s = "step-"+(i+1) |
||
54 | $(e).attr("id",s); |
||
55 | } |
||
56 | var span = $("<span/>").addClass("stepDesc").text(title); |
||
57 | var li = $("<li></li>").append($("<a></a>").attr("href", "#" + s).append($("<label></label>").addClass("stepNumber").text(i + 1)).append(span)); |
||
58 | ul.append(li); |
||
59 | }); |
||
60 | // (re)initialise the steps property |
||
61 | $this.steps = $(target).children("ul").children("li").children("a"); // Get all anchors |
||
62 | } |
||
63 | $this.target.children('ul').addClass("anchor"); |
||
64 | allDivs.addClass("wizard_content"); |
||
65 | |||
66 | // highlight steps with errors |
||
67 | if($this.options.errorSteps && $this.options.errorSteps.length>0){ |
||
68 | $.each($this.options.errorSteps, function(i, n){ |
||
69 | $this.setError({ stepnum: n, iserror:true }); |
||
70 | }); |
||
71 | } |
||
72 | |||
73 | $this.elmStepContainer.append(allDivs); |
||
74 | //elmActionBar.append($this.loader); |
||
75 | $this.target.append($this.elmStepContainer); |
||
76 | |||
77 | if ($this.options.includeFinishButton){ |
||
78 | elmActionBar.append($this.buttons.finish) |
||
79 | } |
||
80 | |||
81 | elmActionBar.append($this.buttons.next) |
||
82 | .append($this.buttons.previous); |
||
83 | $this.target.append(elmActionBar); |
||
84 | this.contentWidth = $this.elmStepContainer.width(); |
||
85 | |||
86 | $($this.buttons.next).click(function() { |
||
87 | $this.goForward(); |
||
88 | return false; |
||
89 | }); |
||
90 | $($this.buttons.previous).click(function() { |
||
91 | $this.goBackward(); |
||
92 | return false; |
||
93 | }); |
||
94 | $($this.buttons.finish).click(function() { |
||
95 | if(!$(this).hasClass('buttonDisabled')){ |
||
96 | if($.isFunction($this.options.onFinish)) { |
||
97 | var context = { fromStep: $this.curStepIdx + 1 }; |
||
98 | if(!$this.options.onFinish.call(this,$($this.steps), context)){ |
||
99 | return false; |
||
100 | } |
||
101 | }else{ |
||
102 | var frm = $this.target.parents('form'); |
||
103 | if(frm && frm.length){ |
||
104 | frm.submit(); |
||
105 | } |
||
106 | } |
||
107 | } |
||
108 | return false; |
||
109 | }); |
||
110 | |||
111 | $($this.steps).bind("click", function(e){ |
||
0 ignored issues
–
show
|
|||
112 | if($this.steps.index(this) == $this.curStepIdx){ |
||
113 | return false; |
||
114 | } |
||
115 | var nextStepIdx = $this.steps.index(this); |
||
116 | var isDone = $this.steps.eq(nextStepIdx).attr("isDone") - 0; |
||
117 | if(isDone == 1){ |
||
118 | _loadContent($this, nextStepIdx); |
||
119 | } |
||
120 | return false; |
||
121 | }); |
||
122 | |||
123 | // Enable keyboard navigation |
||
124 | if($this.options.keyNavigation){ |
||
125 | $(document).keyup(function(e){ |
||
126 | if(e.which==39){ // Right Arrow |
||
127 | $this.goForward(); |
||
128 | }else if(e.which==37){ // Left Arrow |
||
129 | $this.goBackward(); |
||
130 | } |
||
131 | }); |
||
132 | } |
||
133 | // Prepare the steps |
||
134 | _prepareSteps($this); |
||
135 | // Show the first slected step |
||
136 | _loadContent($this, $this.curStepIdx); |
||
137 | }; |
||
138 | |||
139 | var _prepareSteps = function($this) { |
||
140 | if(! $this.options.enableAllSteps){ |
||
141 | $($this.steps, $this.target).removeClass("selected").removeClass("done").addClass("disabled"); |
||
142 | $($this.steps, $this.target).attr("isDone",0); |
||
143 | }else{ |
||
144 | $($this.steps, $this.target).removeClass("selected").removeClass("disabled").addClass("done"); |
||
145 | $($this.steps, $this.target).attr("isDone",1); |
||
146 | } |
||
147 | |||
148 | $($this.steps, $this.target).each(function(i){ |
||
149 | $($(this).attr("href").replace(/^.+#/, '#'), $this.target).hide(); |
||
150 | $(this).attr("rel",i+1); |
||
151 | }); |
||
152 | }; |
||
153 | |||
154 | var _step = function ($this, selStep) { |
||
155 | return $( |
||
156 | $(selStep, $this.target).attr("href").replace(/^.+#/, '#'), |
||
157 | $this.target |
||
158 | ); |
||
159 | }; |
||
160 | |||
161 | var _loadContent = function($this, stepIdx) { |
||
162 | var selStep = $this.steps.eq(stepIdx); |
||
163 | var ajaxurl = $this.options.contentURL; |
||
164 | var ajaxurl_data = $this.options.contentURLData; |
||
165 | var hasContent = selStep.data('hasContent'); |
||
166 | var stepNum = stepIdx+1; |
||
167 | if (ajaxurl && ajaxurl.length>0) { |
||
168 | if ($this.options.contentCache && hasContent) { |
||
169 | _showStep($this, stepIdx); |
||
170 | } else { |
||
171 | var ajax_args = { |
||
172 | url: ajaxurl, |
||
173 | type: $this.options.ajaxType, |
||
174 | data: ({step_number : stepNum}), |
||
175 | dataType: "text", |
||
176 | beforeSend: function(){ |
||
177 | $this.loader.show(); |
||
178 | }, |
||
179 | error: function(){ |
||
180 | $this.loader.hide(); |
||
181 | }, |
||
182 | success: function(res){ |
||
183 | $this.loader.hide(); |
||
184 | if(res && res.length>0){ |
||
185 | selStep.data('hasContent',true); |
||
186 | _step($this, selStep).html(res); |
||
187 | _showStep($this, stepIdx); |
||
188 | } |
||
189 | } |
||
190 | }; |
||
191 | if (ajaxurl_data) { |
||
192 | ajax_args = $.extend(ajax_args, ajaxurl_data(stepNum)); |
||
193 | } |
||
194 | $.ajax(ajax_args); |
||
195 | } |
||
196 | }else{ |
||
197 | _showStep($this,stepIdx); |
||
198 | } |
||
199 | }; |
||
200 | |||
201 | var _showStep = function($this, stepIdx) { |
||
202 | var selStep = $this.steps.eq(stepIdx); |
||
203 | var curStep = $this.steps.eq($this.curStepIdx); |
||
204 | if(stepIdx != $this.curStepIdx){ |
||
205 | if($.isFunction($this.options.onLeaveStep)) { |
||
206 | var context = { fromStep: $this.curStepIdx+1, toStep: stepIdx+1 }; |
||
207 | if (! $this.options.onLeaveStep.call($this,$(curStep), context)){ |
||
208 | return false; |
||
209 | } |
||
210 | } |
||
211 | } |
||
212 | //$this.elmStepContainer.height(_step($this, selStep).outerHeight()); |
||
213 | var prevCurStepIdx = $this.curStepIdx; |
||
214 | $this.curStepIdx = stepIdx; |
||
215 | if ($this.options.transitionEffect == 'slide'){ |
||
216 | _step($this, curStep).slideUp("fast",function(e){ |
||
0 ignored issues
–
show
|
|||
217 | _step($this, selStep).slideDown("fast"); |
||
218 | _setupStep($this,curStep,selStep); |
||
219 | }); |
||
220 | } else if ($this.options.transitionEffect == 'fade'){ |
||
221 | _step($this, curStep).fadeOut("fast",function(e){ |
||
0 ignored issues
–
show
|
|||
222 | _step($this, selStep).fadeIn("fast"); |
||
223 | _setupStep($this,curStep,selStep); |
||
224 | }); |
||
225 | } else if ($this.options.transitionEffect == 'slideleft'){ |
||
226 | var nextElmLeft = 0; |
||
227 | var nextElmLeft1 = null; |
||
0 ignored issues
–
show
|
|||
228 | var nextElmLeft = null; |
||
0 ignored issues
–
show
Comprehensibility
Naming
Best Practice
introduced
by
The variable
nextElmLeft already seems to be declared on line 226 . Consider using another variable name or omitting the var keyword.
This check looks for variables that are declared in multiple lines. There may be several reasons for this. In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs. If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared. ![]() |
|||
229 | var curElementLeft = 0; |
||
230 | if(stepIdx > prevCurStepIdx){ |
||
231 | nextElmLeft1 = $this.elmStepContainer.width() + 10; |
||
232 | nextElmLeft2 = 0; |
||
0 ignored issues
–
show
|
|||
233 | curElementLeft = 0 - _step($this, curStep).outerWidth(); |
||
234 | } else { |
||
235 | nextElmLeft1 = 0 - _step($this, selStep).outerWidth() + 20; |
||
236 | nextElmLeft2 = 0; |
||
237 | curElementLeft = 10 + _step($this, curStep).outerWidth(); |
||
238 | } |
||
239 | if (stepIdx == prevCurStepIdx) { |
||
240 | nextElmLeft1 = $($(selStep, $this.target).attr("href"), $this.target).outerWidth() + 20; |
||
241 | nextElmLeft2 = 0; |
||
242 | curElementLeft = 0 - $($(curStep, $this.target).attr("href"), $this.target).outerWidth(); |
||
0 ignored issues
–
show
|
|||
243 | } else { |
||
244 | $($(curStep, $this.target).attr("href"), $this.target).animate({left:curElementLeft},"fast",function(e){ |
||
0 ignored issues
–
show
|
|||
245 | $($(curStep, $this.target).attr("href"), $this.target).hide(); |
||
246 | }); |
||
247 | } |
||
248 | |||
249 | _step($this, selStep).css("left",nextElmLeft1).show().animate({left:nextElmLeft2},"fast",function(e){ |
||
0 ignored issues
–
show
|
|||
250 | _setupStep($this,curStep,selStep); |
||
251 | }); |
||
252 | } else { |
||
253 | _step($this, curStep).hide(); |
||
254 | _step($this, selStep).show(); |
||
255 | _setupStep($this,curStep,selStep); |
||
256 | } |
||
257 | return true; |
||
258 | }; |
||
259 | |||
260 | var _setupStep = function($this, curStep, selStep) { |
||
261 | $(curStep, $this.target).removeClass("selected"); |
||
262 | $(curStep, $this.target).addClass("done"); |
||
263 | |||
264 | $(selStep, $this.target).removeClass("disabled"); |
||
265 | $(selStep, $this.target).removeClass("done"); |
||
266 | $(selStep, $this.target).addClass("selected"); |
||
267 | |||
268 | $(selStep, $this.target).attr("isDone",1); |
||
269 | |||
270 | _adjustButton($this); |
||
271 | |||
272 | if($.isFunction($this.options.onShowStep)) { |
||
273 | var context = { fromStep: parseInt($(curStep).attr('rel')), toStep: parseInt($(selStep).attr('rel')) }; |
||
274 | if(! $this.options.onShowStep.call(this,$(selStep),context)){ |
||
275 | return false; |
||
276 | } |
||
277 | } |
||
278 | if ($this.options.noForwardJumping) { |
||
0 ignored issues
–
show
There is no return statement if
$this.options.noForwardJumping is false . Are you sure this is correct? If so, consider adding return; explicitly.
This check looks for functions where a Consider this little piece of code function isBig(a) {
if (a > 5000) {
return "yes";
}
}
console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined
The function This behaviour may not be what you had intended. In any case, you can add a
![]() |
|||
279 | // +2 == +1 (for index to step num) +1 (for next step) |
||
280 | for (var i = $this.curStepIdx + 2; i <= $this.steps.length; i++) { |
||
281 | $this.disableStep(i); |
||
282 | } |
||
0 ignored issues
–
show
|
|||
283 | } |
||
284 | }; |
||
285 | |||
286 | var _adjustButton = function($this) { |
||
287 | if (! $this.options.cycleSteps){ |
||
288 | if (0 >= $this.curStepIdx) { |
||
289 | $($this.buttons.previous).addClass("buttonDisabled"); |
||
290 | if ($this.options.hideButtonsOnDisabled) { |
||
291 | $($this.buttons.previous).hide(); |
||
292 | } |
||
293 | }else{ |
||
294 | $($this.buttons.previous).removeClass("buttonDisabled"); |
||
295 | if ($this.options.hideButtonsOnDisabled) { |
||
296 | $($this.buttons.previous).show(); |
||
297 | } |
||
298 | } |
||
299 | if (($this.steps.length-1) <= $this.curStepIdx){ |
||
300 | $($this.buttons.next).addClass("buttonDisabled"); |
||
301 | if ($this.options.hideButtonsOnDisabled) { |
||
302 | $($this.buttons.next).hide(); |
||
303 | } |
||
304 | }else{ |
||
305 | $($this.buttons.next).removeClass("buttonDisabled"); |
||
306 | if ($this.options.hideButtonsOnDisabled) { |
||
307 | $($this.buttons.next).show(); |
||
308 | } |
||
309 | } |
||
310 | } |
||
311 | // Finish Button |
||
312 | $this.enableFinish($this.options.enableFinishButton); |
||
313 | }; |
||
314 | |||
315 | /* |
||
316 | * Public methods |
||
317 | */ |
||
318 | |||
319 | SmartWizard.prototype.goForward = function(){ |
||
320 | var nextStepIdx = this.curStepIdx + 1; |
||
321 | if (this.steps.length <= nextStepIdx){ |
||
322 | if (! this.options.cycleSteps){ |
||
323 | return false; |
||
324 | } |
||
325 | nextStepIdx = 0; |
||
326 | } |
||
327 | _loadContent(this, nextStepIdx); |
||
0 ignored issues
–
show
|
|||
328 | }; |
||
329 | |||
330 | SmartWizard.prototype.goBackward = function(){ |
||
331 | var nextStepIdx = this.curStepIdx-1; |
||
332 | if (0 > nextStepIdx){ |
||
333 | if (! this.options.cycleSteps){ |
||
334 | return false; |
||
335 | } |
||
336 | nextStepIdx = this.steps.length - 1; |
||
337 | } |
||
338 | _loadContent(this, nextStepIdx); |
||
0 ignored issues
–
show
|
|||
339 | }; |
||
340 | |||
341 | SmartWizard.prototype.goToStep = function(stepNum){ |
||
342 | var stepIdx = stepNum - 1; |
||
343 | if (stepIdx >= 0 && stepIdx < this.steps.length) { |
||
344 | _loadContent(this, stepIdx); |
||
345 | } |
||
346 | }; |
||
347 | SmartWizard.prototype.enableStep = function(stepNum) { |
||
348 | var stepIdx = stepNum - 1; |
||
349 | if (stepIdx == this.curStepIdx || stepIdx < 0 || stepIdx >= this.steps.length) { |
||
350 | return false; |
||
351 | } |
||
352 | var step = this.steps.eq(stepIdx); |
||
353 | $(step, this.target).attr("isDone",1); |
||
354 | $(step, this.target).removeClass("disabled").removeClass("selected").addClass("done"); |
||
0 ignored issues
–
show
|
|||
355 | } |
||
356 | SmartWizard.prototype.disableStep = function(stepNum) { |
||
357 | var stepIdx = stepNum - 1; |
||
358 | if (stepIdx == this.curStepIdx || stepIdx < 0 || stepIdx >= this.steps.length) { |
||
359 | return false; |
||
360 | } |
||
361 | var step = this.steps.eq(stepIdx); |
||
362 | $(step, this.target).attr("isDone",0); |
||
363 | $(step, this.target).removeClass("done").removeClass("selected").addClass("disabled"); |
||
0 ignored issues
–
show
|
|||
364 | } |
||
365 | SmartWizard.prototype.currentStep = function() { |
||
366 | return this.curStepIdx + 1; |
||
367 | } |
||
368 | |||
369 | SmartWizard.prototype.showMessage = function (msg) { |
||
370 | $('.content', this.msgBox).html(msg); |
||
371 | this.msgBox.show(); |
||
372 | } |
||
373 | |||
374 | SmartWizard.prototype.enableFinish = function (enable) { |
||
375 | // Controll status of finish button dynamically |
||
376 | // just call this with status you want |
||
377 | this.options.enableFinishButton = enable; |
||
378 | if (this.options.includeFinishButton){ |
||
379 | if (!this.steps.hasClass('disabled') || this.options.enableFinishButton){ |
||
380 | $(this.buttons.finish).removeClass("buttonDisabled"); |
||
381 | if (this.options.hideButtonsOnDisabled) { |
||
382 | $(this.buttons.finish).show(); |
||
383 | } |
||
384 | }else{ |
||
385 | $(this.buttons.finish).addClass("buttonDisabled"); |
||
386 | if (this.options.hideButtonsOnDisabled) { |
||
387 | $(this.buttons.finish).hide(); |
||
388 | } |
||
389 | } |
||
390 | } |
||
391 | return this.options.enableFinishButton; |
||
392 | } |
||
393 | |||
394 | SmartWizard.prototype.hideMessage = function () { |
||
395 | this.msgBox.fadeOut("normal"); |
||
396 | } |
||
397 | SmartWizard.prototype.showError = function(stepnum) { |
||
398 | this.setError(stepnum, true); |
||
399 | } |
||
400 | SmartWizard.prototype.hideError = function(stepnum) { |
||
401 | this.setError(stepnum, false); |
||
402 | } |
||
403 | SmartWizard.prototype.setError = function(stepnum,iserror) { |
||
404 | if (typeof stepnum == "object") { |
||
405 | iserror = stepnum.iserror; |
||
406 | stepnum = stepnum.stepnum; |
||
407 | } |
||
408 | |||
409 | if (iserror){ |
||
410 | $(this.steps.eq(stepnum-1), this.target).addClass('error') |
||
411 | }else{ |
||
412 | $(this.steps.eq(stepnum-1), this.target).removeClass("error"); |
||
413 | } |
||
414 | } |
||
415 | |||
416 | SmartWizard.prototype.fixHeight = function(){ |
||
417 | var height = 0; |
||
418 | |||
419 | var selStep = this.steps.eq(this.curStepIdx); |
||
420 | var stepContainer = _step(this, selStep); |
||
421 | stepContainer.children().each(function() { |
||
422 | if($(this).is(':visible')) { |
||
423 | height += $(this).outerHeight(true); |
||
424 | } |
||
425 | }); |
||
426 | |||
427 | // These values (5 and 20) are experimentally chosen. |
||
428 | stepContainer.height(height + 5); |
||
429 | this.elmStepContainer.height(height + 20); |
||
430 | } |
||
431 | |||
432 | _init(this); |
||
433 | }; |
||
434 | |||
435 | |||
436 | |||
437 | (function($){ |
||
438 | |||
439 | $.fn.smartWizard = function(method) { |
||
440 | var args = arguments; |
||
441 | var rv = undefined; |
||
0 ignored issues
–
show
Unused Code
Comprehensibility
introduced
by
|
|||
442 | var allObjs = this.each(function() { |
||
443 | var wiz = $(this).data('smartWizard'); |
||
444 | if (typeof method == 'object' || ! method || ! wiz) { |
||
445 | var options = $.extend({}, $.fn.smartWizard.defaults, method || {}); |
||
446 | if (! wiz) { |
||
0 ignored issues
–
show
There is no return statement if
!wiz is false . Are you sure this is correct? If so, consider adding return; explicitly.
This check looks for functions where a Consider this little piece of code function isBig(a) {
if (a > 5000) {
return "yes";
}
}
console.log(isBig(5001)); //returns yes
console.log(isBig(42)); //returns undefined
The function This behaviour may not be what you had intended. In any case, you can add a
![]() |
|||
447 | wiz = new SmartWizard($(this), options); |
||
448 | $(this).data('smartWizard', wiz); |
||
0 ignored issues
–
show
|
|||
449 | } |
||
450 | } else { |
||
451 | if (typeof SmartWizard.prototype[method] == "function") { |
||
452 | rv = SmartWizard.prototype[method].apply(wiz, Array.prototype.slice.call(args, 1)); |
||
453 | return rv; |
||
454 | } else { |
||
0 ignored issues
–
show
|
|||
455 | $.error('Method ' + method + ' does not exist on jQuery.smartWizard'); |
||
0 ignored issues
–
show
|
|||
456 | } |
||
457 | } |
||
458 | }); |
||
459 | if (rv === undefined) { |
||
460 | return allObjs; |
||
461 | } else { |
||
0 ignored issues
–
show
|
|||
462 | return rv; |
||
463 | } |
||
464 | }; |
||
465 | |||
466 | // Default Properties and Events |
||
467 | $.fn.smartWizard.defaults = { |
||
468 | selected: 0, // Selected Step, 0 = first step |
||
469 | keyNavigation: true, // Enable/Disable key navigation(left and right keys are used if enabled) |
||
470 | enableAllSteps: false, |
||
471 | transitionEffect: 'fade', // Effect on navigation, none/fade/slide/slideleft |
||
472 | contentURL:null, // content url, Enables Ajax content loading |
||
473 | contentCache:true, // cache step contents, if false content is fetched always from ajax url |
||
474 | cycleSteps: false, // cycle step navigation |
||
475 | enableFinishButton: false, // make finish button enabled always |
||
476 | hideButtonsOnDisabled: false, // when the previous/next/finish buttons are disabled, hide them instead? |
||
477 | errorSteps:[], // Array Steps with errors |
||
478 | labelNext:'Next', |
||
479 | labelPrevious:'Previous', |
||
480 | labelFinish:'Finish', |
||
481 | noForwardJumping: false, |
||
482 | ajaxType: "POST", |
||
483 | onLeaveStep: null, // triggers when leaving a step |
||
484 | onShowStep: null, // triggers when showing a step |
||
485 | onFinish: null, // triggers when Finish button is clicked |
||
486 | includeFinishButton : true // Add the finish button |
||
487 | }; |
||
488 | |||
489 | })(jQuery); |
||
490 |
This check looks for parameters in functions that are not used in the function body and are not followed by other parameters which are used inside the function.