steps-rails 1.0.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2015 @@
1
+ /*!
2
+ * jQuery Steps v1.0.7 - 05/07/2014
3
+ * Copyright (c) 2014 Rafael Staib (http://www.jquery-steps.com)
4
+ * Licensed under MIT http://www.opensource.org/licenses/MIT
5
+ */
6
+ ;(function ($, undefined)
7
+ {
8
+ $.fn.extend({
9
+ _aria: function (name, value)
10
+ {
11
+ return this.attr("aria-" + name, value);
12
+ },
13
+
14
+ _removeAria: function (name)
15
+ {
16
+ return this.removeAttr("aria-" + name);
17
+ },
18
+
19
+ _enableAria: function (enable)
20
+ {
21
+ return (enable == null || enable) ?
22
+ this.removeClass("disabled")._aria("disabled", "false") :
23
+ this.addClass("disabled")._aria("disabled", "true");
24
+ },
25
+
26
+ _showAria: function (show)
27
+ {
28
+ return (show == null || show) ?
29
+ this.show()._aria("hidden", "false") :
30
+ this.hide()._aria("hidden", "true");
31
+ },
32
+
33
+ _selectAria: function (select)
34
+ {
35
+ return (select == null || select) ?
36
+ this.addClass("current")._aria("selected", "true") :
37
+ this.removeClass("current")._aria("selected", "false");
38
+ },
39
+
40
+ _id: function (id)
41
+ {
42
+ return (id) ? this.attr("id", id) : this.attr("id");
43
+ }
44
+ });
45
+
46
+ if (!String.prototype.format)
47
+ {
48
+ String.prototype.format = function()
49
+ {
50
+ var args = (arguments.length === 1 && $.isArray(arguments[0])) ? arguments[0] : arguments;
51
+ var formattedString = this;
52
+ for (var i = 0; i < args.length; i++)
53
+ {
54
+ var pattern = new RegExp("\\{" + i + "\\}", "gm");
55
+ formattedString = formattedString.replace(pattern, args[i]);
56
+ }
57
+ return formattedString;
58
+ };
59
+ }
60
+
61
+ /**
62
+ * A global unique id count.
63
+ *
64
+ * @static
65
+ * @private
66
+ * @property _uniqueId
67
+ * @type Integer
68
+ **/
69
+ var _uniqueId = 0;
70
+
71
+ /**
72
+ * The plugin prefix for cookies.
73
+ *
74
+ * @final
75
+ * @private
76
+ * @property _cookiePrefix
77
+ * @type String
78
+ **/
79
+ var _cookiePrefix = "jQu3ry_5teps_St@te_";
80
+
81
+ /**
82
+ * Suffix for the unique tab id.
83
+ *
84
+ * @final
85
+ * @private
86
+ * @property _tabSuffix
87
+ * @type String
88
+ * @since 0.9.7
89
+ **/
90
+ var _tabSuffix = "-t-";
91
+
92
+ /**
93
+ * Suffix for the unique tabpanel id.
94
+ *
95
+ * @final
96
+ * @private
97
+ * @property _tabpanelSuffix
98
+ * @type String
99
+ * @since 0.9.7
100
+ **/
101
+ var _tabpanelSuffix = "-p-";
102
+
103
+ /**
104
+ * Suffix for the unique title id.
105
+ *
106
+ * @final
107
+ * @private
108
+ * @property _titleSuffix
109
+ * @type String
110
+ * @since 0.9.7
111
+ **/
112
+ var _titleSuffix = "-h-";
113
+
114
+ /**
115
+ * An error message for an "index out of range" error.
116
+ *
117
+ * @final
118
+ * @private
119
+ * @property _indexOutOfRangeErrorMessage
120
+ * @type String
121
+ **/
122
+ var _indexOutOfRangeErrorMessage = "Index out of range.";
123
+
124
+ /**
125
+ * An error message for an "missing corresponding element" error.
126
+ *
127
+ * @final
128
+ * @private
129
+ * @property _missingCorrespondingElementErrorMessage
130
+ * @type String
131
+ **/
132
+ var _missingCorrespondingElementErrorMessage = "One or more corresponding step {0} are missing.";
133
+
134
+ /**
135
+ * Adds a step to the cache.
136
+ *
137
+ * @static
138
+ * @private
139
+ * @method addStepToCache
140
+ * @param wizard {Object} A jQuery wizard object
141
+ * @param step {Object} The step object to add
142
+ **/
143
+ function addStepToCache(wizard, step)
144
+ {
145
+ getSteps(wizard).push(step);
146
+ }
147
+
148
+ function analyzeData(wizard, options, state)
149
+ {
150
+ var stepTitles = wizard.children(options.headerTag),
151
+ stepContents = wizard.children(options.bodyTag);
152
+
153
+ // Validate content
154
+ if (stepTitles.length > stepContents.length)
155
+ {
156
+ throwError(_missingCorrespondingElementErrorMessage, "contents");
157
+ }
158
+ else if (stepTitles.length < stepContents.length)
159
+ {
160
+ throwError(_missingCorrespondingElementErrorMessage, "titles");
161
+ }
162
+
163
+ var startIndex = options.startIndex;
164
+
165
+ state.stepCount = stepTitles.length;
166
+
167
+ // Tries to load the saved state (step position)
168
+ if (options.saveState && $.cookie)
169
+ {
170
+ var savedState = $.cookie(_cookiePrefix + getUniqueId(wizard));
171
+ // Sets the saved position to the start index if not undefined or out of range
172
+ var savedIndex = parseInt(savedState, 0);
173
+ if (!isNaN(savedIndex) && savedIndex < state.stepCount)
174
+ {
175
+ startIndex = savedIndex;
176
+ }
177
+ }
178
+
179
+ state.currentIndex = startIndex;
180
+
181
+ stepTitles.each(function (index)
182
+ {
183
+ var item = $(this), // item == header
184
+ content = stepContents.eq(index),
185
+ modeData = content.data("mode"),
186
+ mode = (modeData == null) ? contentMode.html : getValidEnumValue(contentMode,
187
+ (/^\s*$/.test(modeData) || isNaN(modeData)) ? modeData : parseInt(modeData, 0)),
188
+ contentUrl = (mode === contentMode.html || content.data("url") === undefined) ?
189
+ "" : content.data("url"),
190
+ contentLoaded = (mode !== contentMode.html && content.data("loaded") === "1"),
191
+ step = $.extend({}, stepModel, {
192
+ title: item.html(),
193
+ content: (mode === contentMode.html) ? content.html() : "",
194
+ contentUrl: contentUrl,
195
+ contentMode: mode,
196
+ contentLoaded: contentLoaded
197
+ });
198
+
199
+ addStepToCache(wizard, step);
200
+ });
201
+ }
202
+
203
+ /**
204
+ * Triggers the onCanceled event.
205
+ *
206
+ * @static
207
+ * @private
208
+ * @method cancel
209
+ * @param wizard {Object} The jQuery wizard object
210
+ **/
211
+ function cancel(wizard)
212
+ {
213
+ wizard.triggerHandler("canceled");
214
+ }
215
+
216
+ function decreaseCurrentIndexBy(state, decreaseBy)
217
+ {
218
+ return state.currentIndex - decreaseBy;
219
+ }
220
+
221
+ /**
222
+ * Removes the control functionality completely and transforms the current state to the initial HTML structure.
223
+ *
224
+ * @static
225
+ * @private
226
+ * @method destroy
227
+ * @param wizard {Object} A jQuery wizard object
228
+ **/
229
+ function destroy(wizard, options)
230
+ {
231
+ var eventNamespace = getEventNamespace(wizard);
232
+
233
+ // Remove virtual data objects from the wizard
234
+ wizard.unbind(eventNamespace).removeData("uid").removeData("options")
235
+ .removeData("state").removeData("steps").removeData("eventNamespace")
236
+ .find(".actions a").unbind(eventNamespace);
237
+
238
+ // Remove attributes and CSS classes from the wizard
239
+ wizard.removeClass(options.clearFixCssClass + " vertical");
240
+
241
+ var contents = wizard.find(".content > *");
242
+
243
+ // Remove virtual data objects from panels and their titles
244
+ contents.removeData("loaded").removeData("mode").removeData("url");
245
+
246
+ // Remove attributes, CSS classes and reset inline styles on all panels and their titles
247
+ contents.removeAttr("id").removeAttr("role").removeAttr("tabindex")
248
+ .removeAttr("class").removeAttr("style")._removeAria("labelledby")
249
+ ._removeAria("hidden");
250
+
251
+ // Empty panels if the mode is set to 'async' or 'iframe'
252
+ wizard.find(".content > [data-mode='async'],.content > [data-mode='iframe']").empty();
253
+
254
+ var wizardSubstitute = $("<{0} class=\"{1}\"></{0}>".format(wizard.get(0).tagName, wizard.attr("class")));
255
+
256
+ var wizardId = wizard._id();
257
+ if (wizardId != null && wizardId !== "")
258
+ {
259
+ wizardSubstitute._id(wizardId);
260
+ }
261
+
262
+ wizardSubstitute.html(wizard.find(".content").html());
263
+ wizard.after(wizardSubstitute);
264
+ wizard.remove();
265
+
266
+ return wizardSubstitute;
267
+ }
268
+
269
+ /**
270
+ * Triggers the onFinishing and onFinished event.
271
+ *
272
+ * @static
273
+ * @private
274
+ * @method finishStep
275
+ * @param wizard {Object} The jQuery wizard object
276
+ * @param state {Object} The state container of the current wizard
277
+ **/
278
+ function finishStep(wizard, state)
279
+ {
280
+ var currentStep = wizard.find(".steps li").eq(state.currentIndex);
281
+
282
+ if (wizard.triggerHandler("finishing", [state.currentIndex]))
283
+ {
284
+ currentStep.addClass("done").removeClass("error");
285
+ wizard.triggerHandler("finished", [state.currentIndex]);
286
+ }
287
+ else
288
+ {
289
+ currentStep.addClass("error");
290
+ }
291
+ }
292
+
293
+ /**
294
+ * Gets or creates if not exist an unique event namespace for the given wizard instance.
295
+ *
296
+ * @static
297
+ * @private
298
+ * @method getEventNamespace
299
+ * @param wizard {Object} A jQuery wizard object
300
+ * @return {String} Returns the unique event namespace for the given wizard
301
+ */
302
+ function getEventNamespace(wizard)
303
+ {
304
+ var eventNamespace = wizard.data("eventNamespace");
305
+
306
+ if (eventNamespace == null)
307
+ {
308
+ eventNamespace = "." + getUniqueId(wizard);
309
+ wizard.data("eventNamespace", eventNamespace);
310
+ }
311
+
312
+ return eventNamespace;
313
+ }
314
+
315
+ function getStepAnchor(wizard, index)
316
+ {
317
+ var uniqueId = getUniqueId(wizard);
318
+
319
+ return wizard.find("#" + uniqueId + _tabSuffix + index);
320
+ }
321
+
322
+ function getStepPanel(wizard, index)
323
+ {
324
+ var uniqueId = getUniqueId(wizard);
325
+
326
+ return wizard.find("#" + uniqueId + _tabpanelSuffix + index);
327
+ }
328
+
329
+ function getStepTitle(wizard, index)
330
+ {
331
+ var uniqueId = getUniqueId(wizard);
332
+
333
+ return wizard.find("#" + uniqueId + _titleSuffix + index);
334
+ }
335
+
336
+ function getOptions(wizard)
337
+ {
338
+ return wizard.data("options");
339
+ }
340
+
341
+ function getState(wizard)
342
+ {
343
+ return wizard.data("state");
344
+ }
345
+
346
+ function getSteps(wizard)
347
+ {
348
+ return wizard.data("steps");
349
+ }
350
+
351
+ /**
352
+ * Gets a specific step object by index.
353
+ *
354
+ * @static
355
+ * @private
356
+ * @method getStep
357
+ * @param index {Integer} An integer that belongs to the position of a step
358
+ * @return {Object} A specific step object
359
+ **/
360
+ function getStep(wizard, index)
361
+ {
362
+ var steps = getSteps(wizard);
363
+
364
+ if (index < 0 || index >= steps.length)
365
+ {
366
+ throwError(_indexOutOfRangeErrorMessage);
367
+ }
368
+
369
+ return steps[index];
370
+ }
371
+
372
+ /**
373
+ * Gets or creates if not exist an unique id from the given wizard instance.
374
+ *
375
+ * @static
376
+ * @private
377
+ * @method getUniqueId
378
+ * @param wizard {Object} A jQuery wizard object
379
+ * @return {String} Returns the unique id for the given wizard
380
+ */
381
+ function getUniqueId(wizard)
382
+ {
383
+ var uniqueId = wizard.data("uid");
384
+
385
+ if (uniqueId == null)
386
+ {
387
+ uniqueId = wizard._id();
388
+ if (uniqueId == null)
389
+ {
390
+ uniqueId = "steps-uid-".concat(_uniqueId);
391
+ wizard._id(uniqueId);
392
+ }
393
+
394
+ _uniqueId++;
395
+ wizard.data("uid", uniqueId);
396
+ }
397
+
398
+ return uniqueId;
399
+ }
400
+
401
+ /**
402
+ * Gets a valid enum value by checking a specific enum key or value.
403
+ *
404
+ * @static
405
+ * @private
406
+ * @method getValidEnumValue
407
+ * @param enumType {Object} Type of enum
408
+ * @param keyOrValue {Object} Key as `String` or value as `Integer` to check for
409
+ */
410
+ function getValidEnumValue(enumType, keyOrValue)
411
+ {
412
+ validateArgument("enumType", enumType);
413
+ validateArgument("keyOrValue", keyOrValue);
414
+
415
+ // Is key
416
+ if (typeof keyOrValue === "string")
417
+ {
418
+ var value = enumType[keyOrValue];
419
+ if (value === undefined)
420
+ {
421
+ throwError("The enum key '{0}' does not exist.", keyOrValue);
422
+ }
423
+
424
+ return value;
425
+ }
426
+ // Is value
427
+ else if (typeof keyOrValue === "number")
428
+ {
429
+ for (var key in enumType)
430
+ {
431
+ if (enumType[key] === keyOrValue)
432
+ {
433
+ return keyOrValue;
434
+ }
435
+ }
436
+
437
+ throwError("Invalid enum value '{0}'.", keyOrValue);
438
+ }
439
+ // Type is not supported
440
+ else
441
+ {
442
+ throwError("Invalid key or value type.");
443
+ }
444
+ }
445
+
446
+ /**
447
+ * Routes to the next step.
448
+ *
449
+ * @static
450
+ * @private
451
+ * @method goToNextStep
452
+ * @param wizard {Object} The jQuery wizard object
453
+ * @param options {Object} Settings of the current wizard
454
+ * @param state {Object} The state container of the current wizard
455
+ * @return {Boolean} Indicates whether the action executed
456
+ **/
457
+ function goToNextStep(wizard, options, state)
458
+ {
459
+ return paginationClick(wizard, options, state, increaseCurrentIndexBy(state, 1));
460
+ }
461
+
462
+ /**
463
+ * Routes to the previous step.
464
+ *
465
+ * @static
466
+ * @private
467
+ * @method goToPreviousStep
468
+ * @param wizard {Object} The jQuery wizard object
469
+ * @param options {Object} Settings of the current wizard
470
+ * @param state {Object} The state container of the current wizard
471
+ * @return {Boolean} Indicates whether the action executed
472
+ **/
473
+ function goToPreviousStep(wizard, options, state)
474
+ {
475
+ return paginationClick(wizard, options, state, decreaseCurrentIndexBy(state, 1));
476
+ }
477
+
478
+ /**
479
+ * Routes to a specific step by a given index.
480
+ *
481
+ * @static
482
+ * @private
483
+ * @method goToStep
484
+ * @param wizard {Object} The jQuery wizard object
485
+ * @param options {Object} Settings of the current wizard
486
+ * @param state {Object} The state container of the current wizard
487
+ * @param index {Integer} The position (zero-based) to route to
488
+ * @return {Boolean} Indicates whether the action succeeded or failed
489
+ **/
490
+ function goToStep(wizard, options, state, index)
491
+ {
492
+ if (index < 0 || index >= state.stepCount)
493
+ {
494
+ throwError(_indexOutOfRangeErrorMessage);
495
+ }
496
+
497
+ if (options.forceMoveForward && index < state.currentIndex)
498
+ {
499
+ return;
500
+ }
501
+
502
+ var oldIndex = state.currentIndex;
503
+ if (wizard.triggerHandler("stepChanging", [state.currentIndex, index]))
504
+ {
505
+ // Save new state
506
+ state.currentIndex = index;
507
+ saveCurrentStateToCookie(wizard, options, state);
508
+
509
+ // Change visualisation
510
+ refreshStepNavigation(wizard, options, state, oldIndex);
511
+ refreshPagination(wizard, options, state);
512
+ loadAsyncContent(wizard, options, state);
513
+ startTransitionEffect(wizard, options, state, index, oldIndex);
514
+
515
+ wizard.triggerHandler("stepChanged", [index, oldIndex]);
516
+ }
517
+ else
518
+ {
519
+ wizard.find(".steps li").eq(oldIndex).addClass("error");
520
+ }
521
+
522
+ return true;
523
+ }
524
+
525
+ function increaseCurrentIndexBy(state, increaseBy)
526
+ {
527
+ return state.currentIndex + increaseBy;
528
+ }
529
+
530
+ /**
531
+ * Initializes the component.
532
+ *
533
+ * @static
534
+ * @private
535
+ * @method initialize
536
+ * @param options {Object} The component settings
537
+ **/
538
+ function initialize(options)
539
+ {
540
+ /*jshint -W040 */
541
+ var opts = $.extend(true, {}, defaults, options);
542
+
543
+ return this.each(function ()
544
+ {
545
+ var wizard = $(this);
546
+ var state = {
547
+ currentIndex: opts.startIndex,
548
+ currentStep: null,
549
+ stepCount: 0,
550
+ transitionElement: null
551
+ };
552
+
553
+ // Create data container
554
+ wizard.data("options", opts);
555
+ wizard.data("state", state);
556
+ wizard.data("steps", []);
557
+
558
+ analyzeData(wizard, opts, state);
559
+ render(wizard, opts, state);
560
+ registerEvents(wizard, opts);
561
+
562
+ // Trigger focus
563
+ if (opts.autoFocus && _uniqueId === 0)
564
+ {
565
+ getStepAnchor(wizard, opts.startIndex).focus();
566
+ }
567
+ });
568
+ }
569
+
570
+ /**
571
+ * Inserts a new step to a specific position.
572
+ *
573
+ * @static
574
+ * @private
575
+ * @method insertStep
576
+ * @param wizard {Object} The jQuery wizard object
577
+ * @param options {Object} Settings of the current wizard
578
+ * @param state {Object} The state container of the current wizard
579
+ * @param index {Integer} The position (zero-based) to add
580
+ * @param step {Object} The step object to add
581
+ * @example
582
+ * $("#wizard").steps().insert(0, {
583
+ * title: "Title",
584
+ * content: "", // optional
585
+ * contentMode: "async", // optional
586
+ * contentUrl: "/Content/Step/1" // optional
587
+ * });
588
+ * @chainable
589
+ **/
590
+ function insertStep(wizard, options, state, index, step)
591
+ {
592
+ if (index < 0 || index > state.stepCount)
593
+ {
594
+ throwError(_indexOutOfRangeErrorMessage);
595
+ }
596
+
597
+ // TODO: Validate step object
598
+
599
+ // Change data
600
+ step = $.extend({}, stepModel, step);
601
+ insertStepToCache(wizard, index, step);
602
+ if (state.currentIndex !== state.stepCount && state.currentIndex >= index)
603
+ {
604
+ state.currentIndex++;
605
+ saveCurrentStateToCookie(wizard, options, state);
606
+ }
607
+ state.stepCount++;
608
+
609
+ var contentContainer = wizard.find(".content"),
610
+ header = $("<{0}>{1}</{0}>".format(options.headerTag, step.title)),
611
+ body = $("<{0}></{0}>".format(options.bodyTag));
612
+
613
+ if (step.contentMode == null || step.contentMode === contentMode.html)
614
+ {
615
+ body.html(step.content);
616
+ }
617
+
618
+ if (index === 0)
619
+ {
620
+ contentContainer.prepend(body).prepend(header);
621
+ }
622
+ else
623
+ {
624
+ getStepPanel(wizard, (index - 1)).after(body).after(header);
625
+ }
626
+
627
+ renderBody(wizard, state, body, index);
628
+ renderTitle(wizard, options, state, header, index);
629
+ refreshSteps(wizard, options, state, index);
630
+ if (index === state.currentIndex)
631
+ {
632
+ refreshStepNavigation(wizard, options, state);
633
+ }
634
+ refreshPagination(wizard, options, state);
635
+
636
+ return wizard;
637
+ }
638
+
639
+ /**
640
+ * Inserts a step object to the cache at a specific position.
641
+ *
642
+ * @static
643
+ * @private
644
+ * @method insertStepToCache
645
+ * @param wizard {Object} A jQuery wizard object
646
+ * @param index {Integer} The position (zero-based) to add
647
+ * @param step {Object} The step object to add
648
+ **/
649
+ function insertStepToCache(wizard, index, step)
650
+ {
651
+ getSteps(wizard).splice(index, 0, step);
652
+ }
653
+
654
+ /**
655
+ * Handles the keyup DOM event for pagination.
656
+ *
657
+ * @static
658
+ * @private
659
+ * @event keyup
660
+ * @param event {Object} An event object
661
+ */
662
+ function keyUpHandler(event)
663
+ {
664
+ var wizard = $(this),
665
+ options = getOptions(wizard),
666
+ state = getState(wizard);
667
+
668
+ if (options.suppressPaginationOnFocus && wizard.find(":focus").is(":input"))
669
+ {
670
+ event.preventDefault();
671
+ return false;
672
+ }
673
+
674
+ var keyCodes = { left: 37, right: 39 };
675
+ if (event.keyCode === keyCodes.left)
676
+ {
677
+ event.preventDefault();
678
+ goToPreviousStep(wizard, options, state);
679
+ }
680
+ else if (event.keyCode === keyCodes.right)
681
+ {
682
+ event.preventDefault();
683
+ goToNextStep(wizard, options, state);
684
+ }
685
+ }
686
+
687
+ /**
688
+ * Loads and includes async content.
689
+ *
690
+ * @static
691
+ * @private
692
+ * @method loadAsyncContent
693
+ * @param wizard {Object} A jQuery wizard object
694
+ * @param options {Object} Settings of the current wizard
695
+ * @param state {Object} The state container of the current wizard
696
+ */
697
+ function loadAsyncContent(wizard, options, state)
698
+ {
699
+ if (state.stepCount > 0)
700
+ {
701
+ var currentStep = getStep(wizard, state.currentIndex);
702
+
703
+ if (!options.enableContentCache || !currentStep.contentLoaded)
704
+ {
705
+ switch (getValidEnumValue(contentMode, currentStep.contentMode))
706
+ {
707
+ case contentMode.iframe:
708
+ wizard.find(".content > .body").eq(state.currentIndex).empty()
709
+ .html("<iframe src=\"" + currentStep.contentUrl + "\" frameborder=\"0\" scrolling=\"no\" />")
710
+ .data("loaded", "1");
711
+ break;
712
+
713
+ case contentMode.async:
714
+ var currentStepContent = getStepPanel(wizard, state.currentIndex)._aria("busy", "true")
715
+ .empty().append(renderTemplate(options.loadingTemplate, { text: options.labels.loading }));
716
+
717
+ $.ajax({ url: currentStep.contentUrl, cache: false }).done(function (data)
718
+ {
719
+ currentStepContent.empty().html(data)._aria("busy", "false").data("loaded", "1");
720
+ });
721
+ break;
722
+ }
723
+ }
724
+ }
725
+ }
726
+
727
+ /**
728
+ * Fires the action next or previous click event.
729
+ *
730
+ * @static
731
+ * @private
732
+ * @method paginationClick
733
+ * @param wizard {Object} The jQuery wizard object
734
+ * @param options {Object} Settings of the current wizard
735
+ * @param state {Object} The state container of the current wizard
736
+ * @param index {Integer} The position (zero-based) to route to
737
+ * @return {Boolean} Indicates whether the event fired successfully or not
738
+ **/
739
+ function paginationClick(wizard, options, state, index)
740
+ {
741
+ var oldIndex = state.currentIndex;
742
+
743
+ if (index >= 0 && index < state.stepCount && !(options.forceMoveForward && index < state.currentIndex))
744
+ {
745
+ var anchor = getStepAnchor(wizard, index),
746
+ parent = anchor.parent(),
747
+ isDisabled = parent.hasClass("disabled");
748
+
749
+ // Enable the step to make the anchor clickable!
750
+ parent._enableAria();
751
+ anchor.click();
752
+
753
+ // An error occured
754
+ if (oldIndex === state.currentIndex && isDisabled)
755
+ {
756
+ // Disable the step again if current index has not changed; prevents click action.
757
+ parent._enableAria(false);
758
+ return false;
759
+ }
760
+
761
+ return true;
762
+ }
763
+
764
+ return false;
765
+ }
766
+
767
+ /**
768
+ * Fires when a pagination click happens.
769
+ *
770
+ * @static
771
+ * @private
772
+ * @event click
773
+ * @param event {Object} An event object
774
+ */
775
+ function paginationClickHandler(event)
776
+ {
777
+ event.preventDefault();
778
+
779
+ var anchor = $(this),
780
+ wizard = anchor.parent().parent().parent().parent(),
781
+ options = getOptions(wizard),
782
+ state = getState(wizard),
783
+ href = anchor.attr("href");
784
+
785
+ switch (href.substring(href.lastIndexOf("#") + 1))
786
+ {
787
+ case "cancel":
788
+ cancel(wizard);
789
+ break;
790
+
791
+ case "finish":
792
+ finishStep(wizard, state);
793
+ break;
794
+
795
+ case "next":
796
+ goToNextStep(wizard, options, state);
797
+ break;
798
+
799
+ case "previous":
800
+ goToPreviousStep(wizard, options, state);
801
+ break;
802
+ }
803
+ }
804
+
805
+ /**
806
+ * Refreshs the visualization state for the entire pagination.
807
+ *
808
+ * @static
809
+ * @private
810
+ * @method refreshPagination
811
+ * @param wizard {Object} A jQuery wizard object
812
+ * @param options {Object} Settings of the current wizard
813
+ * @param state {Object} The state container of the current wizard
814
+ */
815
+ function refreshPagination(wizard, options, state)
816
+ {
817
+ if (options.enablePagination)
818
+ {
819
+ var finish = wizard.find(".actions a[href$='#finish']").parent(),
820
+ next = wizard.find(".actions a[href$='#next']").parent();
821
+
822
+ if (!options.forceMoveForward)
823
+ {
824
+ var previous = wizard.find(".actions a[href$='#previous']").parent();
825
+ previous._enableAria(state.currentIndex > 0);
826
+ }
827
+
828
+ if (options.enableFinishButton && options.showFinishButtonAlways)
829
+ {
830
+ finish._enableAria(state.stepCount > 0);
831
+ next._enableAria(state.stepCount > 1 && state.stepCount > (state.currentIndex + 1));
832
+ }
833
+ else
834
+ {
835
+ finish._showAria(options.enableFinishButton && state.stepCount === (state.currentIndex + 1));
836
+ next._showAria(state.stepCount === 0 || state.stepCount > (state.currentIndex + 1)).
837
+ _enableAria(state.stepCount > (state.currentIndex + 1) || !options.enableFinishButton);
838
+ }
839
+ }
840
+ }
841
+
842
+ /**
843
+ * Refreshs the visualization state for the step navigation (tabs).
844
+ *
845
+ * @static
846
+ * @private
847
+ * @method refreshStepNavigation
848
+ * @param wizard {Object} A jQuery wizard object
849
+ * @param options {Object} Settings of the current wizard
850
+ * @param state {Object} The state container of the current wizard
851
+ * @param [oldIndex] {Integer} The index of the prior step
852
+ */
853
+ function refreshStepNavigation(wizard, options, state, oldIndex)
854
+ {
855
+ var currentOrNewStepAnchor = getStepAnchor(wizard, state.currentIndex),
856
+ currentInfo = $("<span class=\"current-info audible\">" + options.labels.current + " </span>"),
857
+ stepTitles = wizard.find(".content > .title");
858
+
859
+ if (oldIndex != null)
860
+ {
861
+ var oldStepAnchor = getStepAnchor(wizard, oldIndex);
862
+ oldStepAnchor.parent().addClass("done").removeClass("error")._selectAria(false);
863
+ stepTitles.eq(oldIndex).removeClass("current").next(".body").removeClass("current");
864
+ currentInfo = oldStepAnchor.find(".current-info");
865
+ currentOrNewStepAnchor.focus();
866
+ }
867
+
868
+ currentOrNewStepAnchor.prepend(currentInfo).parent()._selectAria().removeClass("done")._enableAria();
869
+ stepTitles.eq(state.currentIndex).addClass("current").next(".body").addClass("current");
870
+ }
871
+
872
+ /**
873
+ * Refreshes step buttons and their related titles beyond a certain position.
874
+ *
875
+ * @static
876
+ * @private
877
+ * @method refreshSteps
878
+ * @param wizard {Object} A jQuery wizard object
879
+ * @param options {Object} Settings of the current wizard
880
+ * @param state {Object} The state container of the current wizard
881
+ * @param index {Integer} The start point for refreshing ids
882
+ */
883
+ function refreshSteps(wizard, options, state, index)
884
+ {
885
+ var uniqueId = getUniqueId(wizard);
886
+
887
+ for (var i = index; i < state.stepCount; i++)
888
+ {
889
+ var uniqueStepId = uniqueId + _tabSuffix + i,
890
+ uniqueBodyId = uniqueId + _tabpanelSuffix + i,
891
+ uniqueHeaderId = uniqueId + _titleSuffix + i,
892
+ title = wizard.find(".title").eq(i)._id(uniqueHeaderId);
893
+
894
+ wizard.find(".steps a").eq(i)._id(uniqueStepId)
895
+ ._aria("controls", uniqueBodyId).attr("href", "#" + uniqueHeaderId)
896
+ .html(renderTemplate(options.titleTemplate, { index: i + 1, title: title.html() }));
897
+ wizard.find(".body").eq(i)._id(uniqueBodyId)
898
+ ._aria("labelledby", uniqueHeaderId);
899
+ }
900
+ }
901
+
902
+ function registerEvents(wizard, options)
903
+ {
904
+ var eventNamespace = getEventNamespace(wizard);
905
+
906
+ wizard.bind("canceled" + eventNamespace, options.onCanceled);
907
+ wizard.bind("finishing" + eventNamespace, options.onFinishing);
908
+ wizard.bind("finished" + eventNamespace, options.onFinished);
909
+ wizard.bind("stepChanging" + eventNamespace, options.onStepChanging);
910
+ wizard.bind("stepChanged" + eventNamespace, options.onStepChanged);
911
+
912
+ if (options.enableKeyNavigation)
913
+ {
914
+ wizard.bind("keyup" + eventNamespace, keyUpHandler);
915
+ }
916
+
917
+ wizard.find(".actions a").bind("click" + eventNamespace, paginationClickHandler);
918
+ }
919
+
920
+ /**
921
+ * Removes a specific step by an given index.
922
+ *
923
+ * @static
924
+ * @private
925
+ * @method removeStep
926
+ * @param wizard {Object} A jQuery wizard object
927
+ * @param options {Object} Settings of the current wizard
928
+ * @param state {Object} The state container of the current wizard
929
+ * @param index {Integer} The position (zero-based) of the step to remove
930
+ * @return Indecates whether the item is removed.
931
+ **/
932
+ function removeStep(wizard, options, state, index)
933
+ {
934
+ // Index out of range and try deleting current item will return false.
935
+ if (index < 0 || index >= state.stepCount || state.currentIndex === index)
936
+ {
937
+ return false;
938
+ }
939
+
940
+ // Change data
941
+ removeStepFromCache(wizard, index);
942
+ if (state.currentIndex > index)
943
+ {
944
+ state.currentIndex--;
945
+ saveCurrentStateToCookie(wizard, options, state);
946
+ }
947
+ state.stepCount--;
948
+
949
+ getStepTitle(wizard, index).remove();
950
+ getStepPanel(wizard, index).remove();
951
+ getStepAnchor(wizard, index).parent().remove();
952
+
953
+ // Set the "first" class to the new first step button
954
+ if (index === 0)
955
+ {
956
+ wizard.find(".steps li").first().addClass("first");
957
+ }
958
+
959
+ // Set the "last" class to the new last step button
960
+ if (index === state.stepCount)
961
+ {
962
+ wizard.find(".steps li").eq(index).addClass("last");
963
+ }
964
+
965
+ refreshSteps(wizard, options, state, index);
966
+ refreshPagination(wizard, options, state);
967
+
968
+ return true;
969
+ }
970
+
971
+ function removeStepFromCache(wizard, index)
972
+ {
973
+ getSteps(wizard).splice(index, 1);
974
+ }
975
+
976
+ /**
977
+ * Transforms the base html structure to a more sensible html structure.
978
+ *
979
+ * @static
980
+ * @private
981
+ * @method render
982
+ * @param wizard {Object} A jQuery wizard object
983
+ * @param options {Object} Settings of the current wizard
984
+ * @param state {Object} The state container of the current wizard
985
+ **/
986
+ function render(wizard, options, state)
987
+ {
988
+ // Create a content wrapper and copy HTML from the intial wizard structure
989
+ var wrapperTemplate = "<{0} class=\"{1}\">{2}</{0}>",
990
+ orientation = getValidEnumValue(stepsOrientation, options.stepsOrientation),
991
+ verticalCssClass = (orientation === stepsOrientation.vertical) ? " vertical" : "",
992
+ contentWrapper = $(wrapperTemplate.format(options.contentContainerTag, "content " + options.clearFixCssClass, wizard.html())),
993
+ stepsWrapper = $(wrapperTemplate.format(options.stepsContainerTag, "steps " + options.clearFixCssClass, "<ul role=\"tablist\"></ul>")),
994
+ stepTitles = contentWrapper.children(options.headerTag),
995
+ stepContents = contentWrapper.children(options.bodyTag);
996
+
997
+ // Transform the wizard wrapper and remove the inner HTML
998
+ wizard.attr("role", "application").empty().append(stepsWrapper).append(contentWrapper)
999
+ .addClass(options.cssClass + " " + options.clearFixCssClass + verticalCssClass);
1000
+
1001
+ // Add WIA-ARIA support
1002
+ stepContents.each(function (index)
1003
+ {
1004
+ renderBody(wizard, state, $(this), index);
1005
+ });
1006
+
1007
+ stepTitles.each(function (index)
1008
+ {
1009
+ renderTitle(wizard, options, state, $(this), index);
1010
+ });
1011
+
1012
+ refreshStepNavigation(wizard, options, state);
1013
+ renderPagination(wizard, options, state);
1014
+ }
1015
+
1016
+ /**
1017
+ * Transforms the body to a proper tabpanel.
1018
+ *
1019
+ * @static
1020
+ * @private
1021
+ * @method renderBody
1022
+ * @param wizard {Object} A jQuery wizard object
1023
+ * @param body {Object} A jQuery body object
1024
+ * @param index {Integer} The position of the body
1025
+ */
1026
+ function renderBody(wizard, state, body, index)
1027
+ {
1028
+ var uniqueId = getUniqueId(wizard),
1029
+ uniqueBodyId = uniqueId + _tabpanelSuffix + index,
1030
+ uniqueHeaderId = uniqueId + _titleSuffix + index;
1031
+
1032
+ body._id(uniqueBodyId).attr("role", "tabpanel")._aria("labelledby", uniqueHeaderId)
1033
+ .addClass("body")._showAria(state.currentIndex === index);
1034
+ }
1035
+
1036
+ /**
1037
+ * Renders a pagination if enabled.
1038
+ *
1039
+ * @static
1040
+ * @private
1041
+ * @method renderPagination
1042
+ * @param wizard {Object} A jQuery wizard object
1043
+ * @param options {Object} Settings of the current wizard
1044
+ * @param state {Object} The state container of the current wizard
1045
+ */
1046
+ function renderPagination(wizard, options, state)
1047
+ {
1048
+ if (options.enablePagination)
1049
+ {
1050
+ var pagination = "<{0} class=\"actions {1}\"><ul role=\"menu\" aria-label=\"{2}\">{3}</ul></{0}>",
1051
+ buttonTemplate = "<li><a href=\"#{0}\" role=\"menuitem\">{1}</a></li>",
1052
+ buttons = "";
1053
+
1054
+ if (!options.forceMoveForward)
1055
+ {
1056
+ buttons += buttonTemplate.format("previous", options.labels.previous);
1057
+ }
1058
+
1059
+ buttons += buttonTemplate.format("next", options.labels.next);
1060
+
1061
+ if (options.enableFinishButton)
1062
+ {
1063
+ buttons += buttonTemplate.format("finish", options.labels.finish);
1064
+ }
1065
+
1066
+ if (options.enableCancelButton)
1067
+ {
1068
+ buttons += buttonTemplate.format("cancel", options.labels.cancel);
1069
+ }
1070
+
1071
+ wizard.append(pagination.format(options.actionContainerTag, options.clearFixCssClass,
1072
+ options.labels.pagination, buttons));
1073
+
1074
+ refreshPagination(wizard, options, state);
1075
+ loadAsyncContent(wizard, options, state);
1076
+ }
1077
+ }
1078
+
1079
+ /**
1080
+ * Renders a template and replaces all placeholder.
1081
+ *
1082
+ * @static
1083
+ * @private
1084
+ * @method renderTemplate
1085
+ * @param template {String} A template
1086
+ * @param substitutes {Object} A list of substitute
1087
+ * @return {String} The rendered template
1088
+ */
1089
+ function renderTemplate(template, substitutes)
1090
+ {
1091
+ var matches = template.match(/#([a-z]*)#/gi);
1092
+
1093
+ for (var i = 0; i < matches.length; i++)
1094
+ {
1095
+ var match = matches[i],
1096
+ key = match.substring(1, match.length - 1);
1097
+
1098
+ if (substitutes[key] === undefined)
1099
+ {
1100
+ throwError("The key '{0}' does not exist in the substitute collection!", key);
1101
+ }
1102
+
1103
+ template = template.replace(match, substitutes[key]);
1104
+ }
1105
+
1106
+ return template;
1107
+ }
1108
+
1109
+ /**
1110
+ * Transforms the title to a step item button.
1111
+ *
1112
+ * @static
1113
+ * @private
1114
+ * @method renderTitle
1115
+ * @param wizard {Object} A jQuery wizard object
1116
+ * @param options {Object} Settings of the current wizard
1117
+ * @param state {Object} The state container of the current wizard
1118
+ * @param header {Object} A jQuery header object
1119
+ * @param index {Integer} The position of the header
1120
+ */
1121
+ function renderTitle(wizard, options, state, header, index)
1122
+ {
1123
+ var uniqueId = getUniqueId(wizard),
1124
+ uniqueStepId = uniqueId + _tabSuffix + index,
1125
+ uniqueBodyId = uniqueId + _tabpanelSuffix + index,
1126
+ uniqueHeaderId = uniqueId + _titleSuffix + index,
1127
+ stepCollection = wizard.find(".steps > ul"),
1128
+ title = renderTemplate(options.titleTemplate, {
1129
+ index: index + 1,
1130
+ title: header.html()
1131
+ }),
1132
+ stepItem = $("<li role=\"tab\"><a id=\"" + uniqueStepId + "\" href=\"#" + uniqueHeaderId +
1133
+ "\" aria-controls=\"" + uniqueBodyId + "\">" + title + "</a></li>");
1134
+
1135
+ stepItem._enableAria(options.enableAllSteps || state.currentIndex > index);
1136
+
1137
+ if (state.currentIndex > index)
1138
+ {
1139
+ stepItem.addClass("done");
1140
+ }
1141
+
1142
+ header._id(uniqueHeaderId).attr("tabindex", "-1").addClass("title");
1143
+
1144
+ if (index === 0)
1145
+ {
1146
+ stepCollection.prepend(stepItem);
1147
+ }
1148
+ else
1149
+ {
1150
+ stepCollection.find("li").eq(index - 1).after(stepItem);
1151
+ }
1152
+
1153
+ // Set the "first" class to the new first step button
1154
+ if (index === 0)
1155
+ {
1156
+ stepCollection.find("li").removeClass("first").eq(index).addClass("first");
1157
+ }
1158
+
1159
+ // Set the "last" class to the new last step button
1160
+ if (index === (state.stepCount - 1))
1161
+ {
1162
+ stepCollection.find("li").removeClass("last").eq(index).addClass("last");
1163
+ }
1164
+
1165
+ // Register click event
1166
+ stepItem.children("a").bind("click" + getEventNamespace(wizard), stepClickHandler);
1167
+ }
1168
+
1169
+ /**
1170
+ * Saves the current state to a cookie.
1171
+ *
1172
+ * @static
1173
+ * @private
1174
+ * @method saveCurrentStateToCookie
1175
+ * @param wizard {Object} A jQuery wizard object
1176
+ * @param options {Object} Settings of the current wizard
1177
+ * @param state {Object} The state container of the current wizard
1178
+ */
1179
+ function saveCurrentStateToCookie(wizard, options, state)
1180
+ {
1181
+ if (options.saveState && $.cookie)
1182
+ {
1183
+ $.cookie(_cookiePrefix + getUniqueId(wizard), state.currentIndex);
1184
+ }
1185
+ }
1186
+
1187
+ function startTransitionEffect(wizard, options, state, index, oldIndex)
1188
+ {
1189
+ var stepContents = wizard.find(".content > .body"),
1190
+ effect = getValidEnumValue(transitionEffect, options.transitionEffect),
1191
+ effectSpeed = options.transitionEffectSpeed,
1192
+ newStep = stepContents.eq(index),
1193
+ currentStep = stepContents.eq(oldIndex);
1194
+
1195
+ switch (effect)
1196
+ {
1197
+ case transitionEffect.fade:
1198
+ case transitionEffect.slide:
1199
+ var hide = (effect === transitionEffect.fade) ? "fadeOut" : "slideUp",
1200
+ show = (effect === transitionEffect.fade) ? "fadeIn" : "slideDown";
1201
+
1202
+ state.transitionElement = newStep;
1203
+ currentStep[hide](effectSpeed, function ()
1204
+ {
1205
+ var wizard = $(this)._showAria(false).parent().parent(),
1206
+ state = getState(wizard);
1207
+
1208
+ if (state.transitionElement)
1209
+ {
1210
+ state.transitionElement[show](effectSpeed, function ()
1211
+ {
1212
+ $(this)._showAria();
1213
+ });
1214
+ state.transitionElement = null;
1215
+ }
1216
+ }).promise();
1217
+ break;
1218
+
1219
+ case transitionEffect.slideLeft:
1220
+ var outerWidth = currentStep.outerWidth(true),
1221
+ posFadeOut = (index > oldIndex) ? -(outerWidth) : outerWidth,
1222
+ posFadeIn = (index > oldIndex) ? outerWidth : -(outerWidth);
1223
+
1224
+ currentStep.animate({ left: posFadeOut }, effectSpeed,
1225
+ function () { $(this)._showAria(false); }).promise();
1226
+ newStep.css("left", posFadeIn + "px")._showAria()
1227
+ .animate({ left: 0 }, effectSpeed).promise();
1228
+ break;
1229
+
1230
+ default:
1231
+ currentStep._showAria(false);
1232
+ newStep._showAria();
1233
+ break;
1234
+ }
1235
+ }
1236
+
1237
+ /**
1238
+ * Fires when a step click happens.
1239
+ *
1240
+ * @static
1241
+ * @private
1242
+ * @event click
1243
+ * @param event {Object} An event object
1244
+ */
1245
+ function stepClickHandler(event)
1246
+ {
1247
+ event.preventDefault();
1248
+
1249
+ var anchor = $(this),
1250
+ wizard = anchor.parent().parent().parent().parent(),
1251
+ options = getOptions(wizard),
1252
+ state = getState(wizard),
1253
+ oldIndex = state.currentIndex;
1254
+
1255
+ if (anchor.parent().is(":not(.disabled):not(.current)"))
1256
+ {
1257
+ var href = anchor.attr("href"),
1258
+ position = parseInt(href.substring(href.lastIndexOf("-") + 1), 0);
1259
+
1260
+ goToStep(wizard, options, state, position);
1261
+ }
1262
+
1263
+ // If nothing has changed
1264
+ if (oldIndex === state.currentIndex)
1265
+ {
1266
+ getStepAnchor(wizard, oldIndex).focus();
1267
+ return false;
1268
+ }
1269
+ }
1270
+
1271
+ function throwError(message)
1272
+ {
1273
+ if (arguments.length > 1)
1274
+ {
1275
+ message = message.format(Array.prototype.slice.call(arguments, 1));
1276
+ }
1277
+
1278
+ throw new Error(message);
1279
+ }
1280
+
1281
+ /**
1282
+ * Checks an argument for null or undefined and throws an error if one check applies.
1283
+ *
1284
+ * @static
1285
+ * @private
1286
+ * @method validateArgument
1287
+ * @param argumentName {String} The name of the given argument
1288
+ * @param argumentValue {Object} The argument itself
1289
+ */
1290
+ function validateArgument(argumentName, argumentValue)
1291
+ {
1292
+ if (argumentValue == null)
1293
+ {
1294
+ throwError("The argument '{0}' is null or undefined.", argumentName);
1295
+ }
1296
+ }
1297
+
1298
+ /**
1299
+ * Represents a jQuery wizard plugin.
1300
+ *
1301
+ * @class steps
1302
+ * @constructor
1303
+ * @param [method={}] The name of the method as `String` or an JSON object for initialization
1304
+ * @param [params=]* {Array} Additional arguments for a method call
1305
+ * @chainable
1306
+ **/
1307
+ $.fn.steps = function (method)
1308
+ {
1309
+ if ($.fn.steps[method])
1310
+ {
1311
+ return $.fn.steps[method].apply(this, Array.prototype.slice.call(arguments, 1));
1312
+ }
1313
+ else if (typeof method === "object" || !method)
1314
+ {
1315
+ return initialize.apply(this, arguments);
1316
+ }
1317
+ else
1318
+ {
1319
+ $.error("Method " + method + " does not exist on jQuery.steps");
1320
+ }
1321
+ };
1322
+
1323
+ /**
1324
+ * Adds a new step.
1325
+ *
1326
+ * @method add
1327
+ * @param step {Object} The step object to add
1328
+ * @chainable
1329
+ **/
1330
+ $.fn.steps.add = function (step)
1331
+ {
1332
+ var state = getState(this);
1333
+ return insertStep(this, getOptions(this), state, state.stepCount, step);
1334
+ };
1335
+
1336
+ /**
1337
+ * Removes the control functionality completely and transforms the current state to the initial HTML structure.
1338
+ *
1339
+ * @method destroy
1340
+ * @chainable
1341
+ **/
1342
+ $.fn.steps.destroy = function ()
1343
+ {
1344
+ return destroy(this, getOptions(this));
1345
+ };
1346
+
1347
+ /**
1348
+ * Triggers the onFinishing and onFinished event.
1349
+ *
1350
+ * @method finish
1351
+ **/
1352
+ $.fn.steps.finish = function ()
1353
+ {
1354
+ finishStep(this, getState(this));
1355
+ };
1356
+
1357
+ /**
1358
+ * Gets the current step index.
1359
+ *
1360
+ * @method getCurrentIndex
1361
+ * @return {Integer} The actual step index (zero-based)
1362
+ * @for steps
1363
+ **/
1364
+ $.fn.steps.getCurrentIndex = function ()
1365
+ {
1366
+ return getState(this).currentIndex;
1367
+ };
1368
+
1369
+ /**
1370
+ * Gets the current step object.
1371
+ *
1372
+ * @method getCurrentStep
1373
+ * @return {Object} The actual step object
1374
+ **/
1375
+ $.fn.steps.getCurrentStep = function ()
1376
+ {
1377
+ return getStep(this, getState(this).currentIndex);
1378
+ };
1379
+
1380
+ /**
1381
+ * Gets a specific step object by index.
1382
+ *
1383
+ * @method getStep
1384
+ * @param index {Integer} An integer that belongs to the position of a step
1385
+ * @return {Object} A specific step object
1386
+ **/
1387
+ $.fn.steps.getStep = function (index)
1388
+ {
1389
+ return getStep(this, index);
1390
+ };
1391
+
1392
+ /**
1393
+ * Inserts a new step to a specific position.
1394
+ *
1395
+ * @method insert
1396
+ * @param index {Integer} The position (zero-based) to add
1397
+ * @param step {Object} The step object to add
1398
+ * @example
1399
+ * $("#wizard").steps().insert(0, {
1400
+ * title: "Title",
1401
+ * content: "", // optional
1402
+ * contentMode: "async", // optional
1403
+ * contentUrl: "/Content/Step/1" // optional
1404
+ * });
1405
+ * @chainable
1406
+ **/
1407
+ $.fn.steps.insert = function (index, step)
1408
+ {
1409
+ return insertStep(this, getOptions(this), getState(this), index, step);
1410
+ };
1411
+
1412
+ /**
1413
+ * Routes to the next step.
1414
+ *
1415
+ * @method next
1416
+ * @return {Boolean} Indicates whether the action executed
1417
+ **/
1418
+ $.fn.steps.next = function ()
1419
+ {
1420
+ return goToNextStep(this, getOptions(this), getState(this));
1421
+ };
1422
+
1423
+ /**
1424
+ * Routes to the previous step.
1425
+ *
1426
+ * @method previous
1427
+ * @return {Boolean} Indicates whether the action executed
1428
+ **/
1429
+ $.fn.steps.previous = function ()
1430
+ {
1431
+ return goToPreviousStep(this, getOptions(this), getState(this));
1432
+ };
1433
+
1434
+ /**
1435
+ * Removes a specific step by an given index.
1436
+ *
1437
+ * @method remove
1438
+ * @param index {Integer} The position (zero-based) of the step to remove
1439
+ * @return Indecates whether the item is removed.
1440
+ **/
1441
+ $.fn.steps.remove = function (index)
1442
+ {
1443
+ return removeStep(this, getOptions(this), getState(this), index);
1444
+ };
1445
+
1446
+ /**
1447
+ * Sets a specific step object by index.
1448
+ *
1449
+ * @method setStep
1450
+ * @param index {Integer} An integer that belongs to the position of a step
1451
+ * @param step {Object} The step object to change
1452
+ **/
1453
+ $.fn.steps.setStep = function (index, step)
1454
+ {
1455
+ throw new Error("Not yet implemented!");
1456
+ };
1457
+
1458
+ /**
1459
+ * Skips an certain amount of steps.
1460
+ *
1461
+ * @method skip
1462
+ * @param count {Integer} The amount of steps that should be skipped
1463
+ * @return {Boolean} Indicates whether the action executed
1464
+ **/
1465
+ $.fn.steps.skip = function (count)
1466
+ {
1467
+ throw new Error("Not yet implemented!");
1468
+ };
1469
+
1470
+ /**
1471
+ * An enum represents the different content types of a step and their loading mechanisms.
1472
+ *
1473
+ * @class contentMode
1474
+ * @for steps
1475
+ **/
1476
+ var contentMode = $.fn.steps.contentMode = {
1477
+ /**
1478
+ * HTML embedded content
1479
+ *
1480
+ * @readOnly
1481
+ * @property html
1482
+ * @type Integer
1483
+ * @for contentMode
1484
+ **/
1485
+ html: 0,
1486
+
1487
+ /**
1488
+ * IFrame embedded content
1489
+ *
1490
+ * @readOnly
1491
+ * @property iframe
1492
+ * @type Integer
1493
+ * @for contentMode
1494
+ **/
1495
+ iframe: 1,
1496
+
1497
+ /**
1498
+ * Async embedded content
1499
+ *
1500
+ * @readOnly
1501
+ * @property async
1502
+ * @type Integer
1503
+ * @for contentMode
1504
+ **/
1505
+ async: 2
1506
+ };
1507
+
1508
+ /**
1509
+ * An enum represents the orientation of the steps navigation.
1510
+ *
1511
+ * @class stepsOrientation
1512
+ * @for steps
1513
+ **/
1514
+ var stepsOrientation = $.fn.steps.stepsOrientation = {
1515
+ /**
1516
+ * Horizontal orientation
1517
+ *
1518
+ * @readOnly
1519
+ * @property horizontal
1520
+ * @type Integer
1521
+ * @for stepsOrientation
1522
+ **/
1523
+ horizontal: 0,
1524
+
1525
+ /**
1526
+ * Vertical orientation
1527
+ *
1528
+ * @readOnly
1529
+ * @property vertical
1530
+ * @type Integer
1531
+ * @for stepsOrientation
1532
+ **/
1533
+ vertical: 1
1534
+ };
1535
+
1536
+ /**
1537
+ * An enum that represents the various transition animations.
1538
+ *
1539
+ * @class transitionEffect
1540
+ * @for steps
1541
+ **/
1542
+ var transitionEffect = $.fn.steps.transitionEffect = {
1543
+ /**
1544
+ * No transition animation
1545
+ *
1546
+ * @readOnly
1547
+ * @property none
1548
+ * @type Integer
1549
+ * @for transitionEffect
1550
+ **/
1551
+ none: 0,
1552
+
1553
+ /**
1554
+ * Fade in transition
1555
+ *
1556
+ * @readOnly
1557
+ * @property fade
1558
+ * @type Integer
1559
+ * @for transitionEffect
1560
+ **/
1561
+ fade: 1,
1562
+
1563
+ /**
1564
+ * Slide up transition
1565
+ *
1566
+ * @readOnly
1567
+ * @property slide
1568
+ * @type Integer
1569
+ * @for transitionEffect
1570
+ **/
1571
+ slide: 2,
1572
+
1573
+ /**
1574
+ * Slide left transition
1575
+ *
1576
+ * @readOnly
1577
+ * @property slideLeft
1578
+ * @type Integer
1579
+ * @for transitionEffect
1580
+ **/
1581
+ slideLeft: 3
1582
+ };
1583
+
1584
+ var stepModel = $.fn.steps.stepModel = {
1585
+ title: "",
1586
+ content: "",
1587
+ contentUrl: "",
1588
+ contentMode: contentMode.html,
1589
+ contentLoaded: false
1590
+ };
1591
+
1592
+ /**
1593
+ * An object that represents the default settings.
1594
+ * There are two possibities to override the sub-properties.
1595
+ * Either by doing it generally (global) or on initialization.
1596
+ *
1597
+ * @static
1598
+ * @class defaults
1599
+ * @for steps
1600
+ * @example
1601
+ * // Global approach
1602
+ * $.steps.defaults.headerTag = "h3";
1603
+ * @example
1604
+ * // Initialization approach
1605
+ * $("#wizard").steps({ headerTag: "h3" });
1606
+ **/
1607
+ var defaults = $.fn.steps.defaults = {
1608
+ /**
1609
+ * The header tag is used to find the step button text within the declared wizard area.
1610
+ *
1611
+ * @property headerTag
1612
+ * @type String
1613
+ * @default "h1"
1614
+ * @for defaults
1615
+ **/
1616
+ headerTag: "h1",
1617
+
1618
+ /**
1619
+ * The body tag is used to find the step content within the declared wizard area.
1620
+ *
1621
+ * @property bodyTag
1622
+ * @type String
1623
+ * @default "div"
1624
+ * @for defaults
1625
+ **/
1626
+ bodyTag: "div",
1627
+
1628
+ /**
1629
+ * The content container tag which will be used to wrap all step contents.
1630
+ *
1631
+ * @property contentContainerTag
1632
+ * @type String
1633
+ * @default "div"
1634
+ * @for defaults
1635
+ **/
1636
+ contentContainerTag: "div",
1637
+
1638
+ /**
1639
+ * The action container tag which will be used to wrap the pagination navigation.
1640
+ *
1641
+ * @property actionContainerTag
1642
+ * @type String
1643
+ * @default "div"
1644
+ * @for defaults
1645
+ **/
1646
+ actionContainerTag: "div",
1647
+
1648
+ /**
1649
+ * The steps container tag which will be used to wrap the steps navigation.
1650
+ *
1651
+ * @property stepsContainerTag
1652
+ * @type String
1653
+ * @default "div"
1654
+ * @for defaults
1655
+ **/
1656
+ stepsContainerTag: "div",
1657
+
1658
+ /**
1659
+ * The css class which will be added to the outer component wrapper.
1660
+ *
1661
+ * @property cssClass
1662
+ * @type String
1663
+ * @default "wizard"
1664
+ * @for defaults
1665
+ * @example
1666
+ * <div class="wizard">
1667
+ * ...
1668
+ * </div>
1669
+ **/
1670
+ cssClass: "wizard",
1671
+
1672
+ /**
1673
+ * The css class which will be used for floating scenarios.
1674
+ *
1675
+ * @property clearFixCssClass
1676
+ * @type String
1677
+ * @default "clearfix"
1678
+ * @for defaults
1679
+ **/
1680
+ clearFixCssClass: "clearfix",
1681
+
1682
+ /**
1683
+ * Determines whether the steps are vertically or horizontally oriented.
1684
+ *
1685
+ * @property stepsOrientation
1686
+ * @type stepsOrientation
1687
+ * @default horizontal
1688
+ * @for defaults
1689
+ * @since 1.0.0
1690
+ **/
1691
+ stepsOrientation: stepsOrientation.horizontal,
1692
+
1693
+ /*
1694
+ * Tempplates
1695
+ */
1696
+
1697
+ /**
1698
+ * The title template which will be used to create a step button.
1699
+ *
1700
+ * @property titleTemplate
1701
+ * @type String
1702
+ * @default "<span class=\"number\">#index#.</span> #title#"
1703
+ * @for defaults
1704
+ **/
1705
+ titleTemplate: "<span class=\"number\">#index#.</span> #title#",
1706
+
1707
+ /**
1708
+ * The loading template which will be used to create the loading animation.
1709
+ *
1710
+ * @property loadingTemplate
1711
+ * @type String
1712
+ * @default "<span class=\"spinner\"></span> #text#"
1713
+ * @for defaults
1714
+ **/
1715
+ loadingTemplate: "<span class=\"spinner\"></span> #text#",
1716
+
1717
+ /*
1718
+ * Behaviour
1719
+ */
1720
+
1721
+ /**
1722
+ * Sets the focus to the first wizard instance in order to enable the key navigation from the begining if `true`.
1723
+ *
1724
+ * @property autoFocus
1725
+ * @type Boolean
1726
+ * @default false
1727
+ * @for defaults
1728
+ * @since 0.9.4
1729
+ **/
1730
+ autoFocus: false,
1731
+
1732
+ /**
1733
+ * Enables all steps from the begining if `true` (all steps are clickable).
1734
+ *
1735
+ * @property enableAllSteps
1736
+ * @type Boolean
1737
+ * @default false
1738
+ * @for defaults
1739
+ **/
1740
+ enableAllSteps: false,
1741
+
1742
+ /**
1743
+ * Enables keyboard navigation if `true` (arrow left and arrow right).
1744
+ *
1745
+ * @property enableKeyNavigation
1746
+ * @type Boolean
1747
+ * @default true
1748
+ * @for defaults
1749
+ **/
1750
+ enableKeyNavigation: true,
1751
+
1752
+ /**
1753
+ * Enables pagination if `true`.
1754
+ *
1755
+ * @property enablePagination
1756
+ * @type Boolean
1757
+ * @default true
1758
+ * @for defaults
1759
+ **/
1760
+ enablePagination: true,
1761
+
1762
+ /**
1763
+ * Suppresses pagination if a form field is focused.
1764
+ *
1765
+ * @property suppressPaginationOnFocus
1766
+ * @type Boolean
1767
+ * @default true
1768
+ * @for defaults
1769
+ **/
1770
+ suppressPaginationOnFocus: true,
1771
+
1772
+ /**
1773
+ * Enables cache for async loaded or iframe embedded content.
1774
+ *
1775
+ * @property enableContentCache
1776
+ * @type Boolean
1777
+ * @default true
1778
+ * @for defaults
1779
+ **/
1780
+ enableContentCache: true,
1781
+
1782
+ /**
1783
+ * Shows the cancel button if enabled.
1784
+ *
1785
+ * @property enableCancelButton
1786
+ * @type Boolean
1787
+ * @default false
1788
+ * @for defaults
1789
+ **/
1790
+ enableCancelButton: false,
1791
+
1792
+ /**
1793
+ * Shows the finish button if enabled.
1794
+ *
1795
+ * @property enableFinishButton
1796
+ * @type Boolean
1797
+ * @default true
1798
+ * @for defaults
1799
+ **/
1800
+ enableFinishButton: true,
1801
+
1802
+ /**
1803
+ * Not yet implemented.
1804
+ *
1805
+ * @property preloadContent
1806
+ * @type Boolean
1807
+ * @default false
1808
+ * @for defaults
1809
+ **/
1810
+ preloadContent: false,
1811
+
1812
+ /**
1813
+ * Shows the finish button always (on each step; right beside the next button) if `true`.
1814
+ * Otherwise the next button will be replaced by the finish button if the last step becomes active.
1815
+ *
1816
+ * @property showFinishButtonAlways
1817
+ * @type Boolean
1818
+ * @default false
1819
+ * @for defaults
1820
+ **/
1821
+ showFinishButtonAlways: false,
1822
+
1823
+ /**
1824
+ * Prevents jumping to a previous step.
1825
+ *
1826
+ * @property forceMoveForward
1827
+ * @type Boolean
1828
+ * @default false
1829
+ * @for defaults
1830
+ **/
1831
+ forceMoveForward: false,
1832
+
1833
+ /**
1834
+ * Saves the current state (step position) to a cookie.
1835
+ * By coming next time the last active step becomes activated.
1836
+ *
1837
+ * @property saveState
1838
+ * @type Boolean
1839
+ * @default false
1840
+ * @for defaults
1841
+ **/
1842
+ saveState: false,
1843
+
1844
+ /**
1845
+ * The position to start on (zero-based).
1846
+ *
1847
+ * @property startIndex
1848
+ * @type Integer
1849
+ * @default 0
1850
+ * @for defaults
1851
+ **/
1852
+ startIndex: 0,
1853
+
1854
+ /*
1855
+ * Animation Effect Configuration
1856
+ */
1857
+
1858
+ /**
1859
+ * The animation effect which will be used for step transitions.
1860
+ *
1861
+ * @property transitionEffect
1862
+ * @type transitionEffect
1863
+ * @default none
1864
+ * @for defaults
1865
+ **/
1866
+ transitionEffect: transitionEffect.none,
1867
+
1868
+ /**
1869
+ * Animation speed for step transitions (in milliseconds).
1870
+ *
1871
+ * @property transitionEffectSpeed
1872
+ * @type Integer
1873
+ * @default 200
1874
+ * @for defaults
1875
+ **/
1876
+ transitionEffectSpeed: 200,
1877
+
1878
+ /*
1879
+ * Events
1880
+ */
1881
+
1882
+ /**
1883
+ * Fires before the step changes and can be used to prevent step changing by returning `false`.
1884
+ * Very useful for form validation.
1885
+ *
1886
+ * @property onStepChanging
1887
+ * @type Event
1888
+ * @default function (event, currentIndex, newIndex) { return true; }
1889
+ * @for defaults
1890
+ **/
1891
+ onStepChanging: function (event, currentIndex, newIndex) { return true; },
1892
+
1893
+ /**
1894
+ * Fires after the step has change.
1895
+ *
1896
+ * @property onStepChanged
1897
+ * @type Event
1898
+ * @default function (event, currentIndex, priorIndex) { }
1899
+ * @for defaults
1900
+ **/
1901
+ onStepChanged: function (event, currentIndex, priorIndex) { },
1902
+
1903
+ /**
1904
+ * Fires after cancelation.
1905
+ *
1906
+ * @property onCanceled
1907
+ * @type Event
1908
+ * @default function (event) { }
1909
+ * @for defaults
1910
+ **/
1911
+ onCanceled: function (event) { },
1912
+
1913
+ /**
1914
+ * Fires before finishing and can be used to prevent completion by returning `false`.
1915
+ * Very useful for form validation.
1916
+ *
1917
+ * @property onFinishing
1918
+ * @type Event
1919
+ * @default function (event, currentIndex) { return true; }
1920
+ * @for defaults
1921
+ **/
1922
+ onFinishing: function (event, currentIndex) { return true; },
1923
+
1924
+ /**
1925
+ * Fires after completion.
1926
+ *
1927
+ * @property onFinished
1928
+ * @type Event
1929
+ * @default function (event, currentIndex) { }
1930
+ * @for defaults
1931
+ **/
1932
+ onFinished: function (event, currentIndex) { },
1933
+
1934
+ /**
1935
+ * Contains all labels.
1936
+ *
1937
+ * @property labels
1938
+ * @type Object
1939
+ * @for defaults
1940
+ **/
1941
+ labels: {
1942
+ /**
1943
+ * Label for the cancel button.
1944
+ *
1945
+ * @property cancel
1946
+ * @type String
1947
+ * @default "Cancel"
1948
+ * @for defaults
1949
+ **/
1950
+ cancel: "Cancel",
1951
+
1952
+ /**
1953
+ * This label is important for accessability reasons.
1954
+ * Indicates which step is activated.
1955
+ *
1956
+ * @property current
1957
+ * @type String
1958
+ * @default "current step:"
1959
+ * @for defaults
1960
+ **/
1961
+ current: "current step:",
1962
+
1963
+ /**
1964
+ * This label is important for accessability reasons and describes the kind of navigation.
1965
+ *
1966
+ * @property pagination
1967
+ * @type String
1968
+ * @default "Pagination"
1969
+ * @for defaults
1970
+ * @since 0.9.7
1971
+ **/
1972
+ pagination: "Pagination",
1973
+
1974
+ /**
1975
+ * Label for the finish button.
1976
+ *
1977
+ * @property finish
1978
+ * @type String
1979
+ * @default "Finish"
1980
+ * @for defaults
1981
+ **/
1982
+ finish: "Finish",
1983
+
1984
+ /**
1985
+ * Label for the next button.
1986
+ *
1987
+ * @property next
1988
+ * @type String
1989
+ * @default "Next"
1990
+ * @for defaults
1991
+ **/
1992
+ next: "Next",
1993
+
1994
+ /**
1995
+ * Label for the previous button.
1996
+ *
1997
+ * @property previous
1998
+ * @type String
1999
+ * @default "Previous"
2000
+ * @for defaults
2001
+ **/
2002
+ previous: "Previous",
2003
+
2004
+ /**
2005
+ * Label for the loading animation.
2006
+ *
2007
+ * @property loading
2008
+ * @type String
2009
+ * @default "Loading ..."
2010
+ * @for defaults
2011
+ **/
2012
+ loading: "Loading ..."
2013
+ }
2014
+ };
2015
+ })(jQuery);