wizard_steps.js 59 KB

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