PageSourceSearch

https://www.limmert.com/assets/js/era/jquery.steps.js

js limmert.com collected 2026-10-05 06:37:19 UTC 53,473 bytes, 1,953 lines download raw bytes

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

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.