jquery-steps-rails 1.0.4.1

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