jquery.steps.js 54 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042
  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")._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><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. * Removes the control functionality completely and transforms the current state to the initial HTML structure.
  1176. *
  1177. * @method destroy
  1178. * @chainable
  1179. **/
  1180. $.fn.steps.destroy = function ()
  1181. {
  1182. return destroy(this, getOptions(this));
  1183. };
  1184. /**
  1185. * Triggers the onFinishing and onFinished event.
  1186. *
  1187. * @method finish
  1188. **/
  1189. $.fn.steps.finish = function ()
  1190. {
  1191. finishStep(this, getState(this));
  1192. };
  1193. /**
  1194. * Gets the current step index.
  1195. *
  1196. * @method getCurrentIndex
  1197. * @return {Integer} The actual step index (zero-based)
  1198. * @for steps
  1199. **/
  1200. $.fn.steps.getCurrentIndex = function ()
  1201. {
  1202. return getState(this).currentIndex;
  1203. };
  1204. /**
  1205. * Gets the current step object.
  1206. *
  1207. * @method getCurrentStep
  1208. * @return {Object} The actual step object
  1209. **/
  1210. $.fn.steps.getCurrentStep = function ()
  1211. {
  1212. return getStep(this, getState(this).currentIndex);
  1213. };
  1214. /**
  1215. * Gets a specific step object by index.
  1216. *
  1217. * @method getStep
  1218. * @param index {Integer} An integer that belongs to the position of a step
  1219. * @return {Object} A specific step object
  1220. **/
  1221. $.fn.steps.getStep = function (index)
  1222. {
  1223. return getStep(this, index);
  1224. };
  1225. /**
  1226. * Inserts a new step to a specific position.
  1227. *
  1228. * @method insert
  1229. * @param index {Integer} The position (zero-based) to add
  1230. * @param step {Object} The step object to add
  1231. * @example
  1232. * $("#wizard").steps().insert(0, {
  1233. * title: "Title",
  1234. * content: "", // optional
  1235. * contentMode: "async", // optional
  1236. * contentUrl: "/Content/Step/1" // optional
  1237. * });
  1238. * @chainable
  1239. **/
  1240. $.fn.steps.insert = function (index, step)
  1241. {
  1242. return insertStep(this, getOptions(this), getState(this), index, step);
  1243. };
  1244. /**
  1245. * Routes to the next step.
  1246. *
  1247. * @method next
  1248. * @return {Boolean} Indicates whether the action executed
  1249. **/
  1250. $.fn.steps.next = function ()
  1251. {
  1252. return goToNextStep(this, getOptions(this), getState(this));
  1253. };
  1254. /**
  1255. * Routes to the previous step.
  1256. *
  1257. * @method previous
  1258. * @return {Boolean} Indicates whether the action executed
  1259. **/
  1260. $.fn.steps.previous = function ()
  1261. {
  1262. return goToPreviousStep(this, getOptions(this), getState(this));
  1263. };
  1264. /**
  1265. * Removes a specific step by an given index.
  1266. *
  1267. * @method remove
  1268. * @param index {Integer} The position (zero-based) of the step to remove
  1269. * @return Indecates whether the item is removed.
  1270. **/
  1271. $.fn.steps.remove = function (index)
  1272. {
  1273. return removeStep(this, getOptions(this), getState(this), index);
  1274. };
  1275. /**
  1276. * Sets a specific step object by index.
  1277. *
  1278. * @method setStep
  1279. * @param index {Integer} An integer that belongs to the position of a step
  1280. * @param step {Object} The step object to change
  1281. **/
  1282. $.fn.steps.setStep = function (index, step)
  1283. {
  1284. throw new Error("Not yet implemented!");
  1285. };
  1286. /**
  1287. * Skips an certain amount of steps.
  1288. *
  1289. * @method skip
  1290. * @param count {Integer} The amount of steps that should be skipped
  1291. * @return {Boolean} Indicates whether the action executed
  1292. **/
  1293. $.fn.steps.skip = function (count)
  1294. {
  1295. throw new Error("Not yet implemented!");
  1296. };
  1297. /**
  1298. * An enum represents the different content types of a step and their loading mechanisms.
  1299. *
  1300. * @class contentMode
  1301. * @for steps
  1302. **/
  1303. var contentMode = $.fn.steps.contentMode = {
  1304. /**
  1305. * HTML embedded content
  1306. *
  1307. * @readOnly
  1308. * @property html
  1309. * @type Integer
  1310. * @for contentMode
  1311. **/
  1312. html: 0,
  1313. /**
  1314. * IFrame embedded content
  1315. *
  1316. * @readOnly
  1317. * @property iframe
  1318. * @type Integer
  1319. * @for contentMode
  1320. **/
  1321. iframe: 1,
  1322. /**
  1323. * Async embedded content
  1324. *
  1325. * @readOnly
  1326. * @property async
  1327. * @type Integer
  1328. * @for contentMode
  1329. **/
  1330. async: 2
  1331. };
  1332. /**
  1333. * An enum represents the orientation of the steps navigation.
  1334. *
  1335. * @class stepsOrientation
  1336. * @for steps
  1337. **/
  1338. var stepsOrientation = $.fn.steps.stepsOrientation = {
  1339. /**
  1340. * Horizontal orientation
  1341. *
  1342. * @readOnly
  1343. * @property horizontal
  1344. * @type Integer
  1345. * @for stepsOrientation
  1346. **/
  1347. horizontal: 0,
  1348. /**
  1349. * Vertical orientation
  1350. *
  1351. * @readOnly
  1352. * @property vertical
  1353. * @type Integer
  1354. * @for stepsOrientation
  1355. **/
  1356. vertical: 1
  1357. };
  1358. /**
  1359. * An enum that represents the various transition animations.
  1360. *
  1361. * @class transitionEffect
  1362. * @for steps
  1363. **/
  1364. var transitionEffect = $.fn.steps.transitionEffect = {
  1365. /**
  1366. * No transition animation
  1367. *
  1368. * @readOnly
  1369. * @property none
  1370. * @type Integer
  1371. * @for transitionEffect
  1372. **/
  1373. none: 0,
  1374. /**
  1375. * Fade in transition
  1376. *
  1377. * @readOnly
  1378. * @property fade
  1379. * @type Integer
  1380. * @for transitionEffect
  1381. **/
  1382. fade: 1,
  1383. /**
  1384. * Slide up transition
  1385. *
  1386. * @readOnly
  1387. * @property slide
  1388. * @type Integer
  1389. * @for transitionEffect
  1390. **/
  1391. slide: 2,
  1392. /**
  1393. * Slide left transition
  1394. *
  1395. * @readOnly
  1396. * @property slideLeft
  1397. * @type Integer
  1398. * @for transitionEffect
  1399. **/
  1400. slideLeft: 3
  1401. };
  1402. var stepModel = $.fn.steps.stepModel = {
  1403. title: "",
  1404. content: "",
  1405. contentUrl: "",
  1406. contentMode: contentMode.html,
  1407. contentLoaded: false
  1408. };
  1409. /**
  1410. * An object that represents the default settings.
  1411. * There are two possibities to override the sub-properties.
  1412. * Either by doing it generally (global) or on initialization.
  1413. *
  1414. * @static
  1415. * @class defaults
  1416. * @for steps
  1417. * @example
  1418. * // Global approach
  1419. * $.steps.defaults.headerTag = "h3";
  1420. * @example
  1421. * // Initialization approach
  1422. * $("#wizard").steps({ headerTag: "h3" });
  1423. **/
  1424. var defaults = $.fn.steps.defaults = {
  1425. /**
  1426. * The header tag is used to find the step button text within the declared wizard area.
  1427. *
  1428. * @property headerTag
  1429. * @type String
  1430. * @default "h1"
  1431. * @for defaults
  1432. **/
  1433. headerTag: "h1",
  1434. /**
  1435. * The body tag is used to find the step content within the declared wizard area.
  1436. *
  1437. * @property bodyTag
  1438. * @type String
  1439. * @default "div"
  1440. * @for defaults
  1441. **/
  1442. bodyTag: "div",
  1443. /**
  1444. * The content container tag which will be used to wrap all step contents.
  1445. *
  1446. * @property contentContainerTag
  1447. * @type String
  1448. * @default "div"
  1449. * @for defaults
  1450. **/
  1451. contentContainerTag: "div",
  1452. /**
  1453. * The action container tag which will be used to wrap the pagination navigation.
  1454. *
  1455. * @property actionContainerTag
  1456. * @type String
  1457. * @default "div"
  1458. * @for defaults
  1459. **/
  1460. actionContainerTag: "div",
  1461. /**
  1462. * The steps container tag which will be used to wrap the steps navigation.
  1463. *
  1464. * @property stepsContainerTag
  1465. * @type String
  1466. * @default "div"
  1467. * @for defaults
  1468. **/
  1469. stepsContainerTag: "div",
  1470. /**
  1471. * The css class which will be added to the outer component wrapper.
  1472. *
  1473. * @property cssClass
  1474. * @type String
  1475. * @default "wizard"
  1476. * @for defaults
  1477. * @example
  1478. * <div class="wizard">
  1479. * ...
  1480. * </div>
  1481. **/
  1482. cssClass: "wizard",
  1483. /**
  1484. * The css class which will be used for floating scenarios.
  1485. *
  1486. * @property clearFixCssClass
  1487. * @type String
  1488. * @default "clearfix"
  1489. * @for defaults
  1490. **/
  1491. clearFixCssClass: "clearfix",
  1492. /**
  1493. * Determines whether the steps are vertically or horizontally oriented.
  1494. *
  1495. * @property stepsOrientation
  1496. * @type stepsOrientation
  1497. * @default horizontal
  1498. * @for defaults
  1499. * @since 1.0.0
  1500. **/
  1501. stepsOrientation: stepsOrientation.horizontal,
  1502. /*
  1503. * Tempplates
  1504. */
  1505. /**
  1506. * The title template which will be used to create a step button.
  1507. *
  1508. * @property titleTemplate
  1509. * @type String
  1510. * @default "<span class=\"number\">#index#.</span> #title#"
  1511. * @for defaults
  1512. **/
  1513. titleTemplate: "<span class=\"number\">#index#.</span> #title#",
  1514. /**
  1515. * The loading template which will be used to create the loading animation.
  1516. *
  1517. * @property loadingTemplate
  1518. * @type String
  1519. * @default "<span class=\"spinner\"></span> #text#"
  1520. * @for defaults
  1521. **/
  1522. loadingTemplate: "<span class=\"spinner\"></span> #text#",
  1523. /*
  1524. * Behaviour
  1525. */
  1526. /**
  1527. * Sets the focus to the first wizard instance in order to enable the key navigation from the begining if `true`.
  1528. *
  1529. * @property autoFocus
  1530. * @type Boolean
  1531. * @default false
  1532. * @for defaults
  1533. * @since 0.9.4
  1534. **/
  1535. autoFocus: false,
  1536. /**
  1537. * Enables all steps from the begining if `true` (all steps are clickable).
  1538. *
  1539. * @property enableAllSteps
  1540. * @type Boolean
  1541. * @default false
  1542. * @for defaults
  1543. **/
  1544. enableAllSteps: false,
  1545. /**
  1546. * Enables keyboard navigation if `true` (arrow left and arrow right).
  1547. *
  1548. * @property enableKeyNavigation
  1549. * @type Boolean
  1550. * @default true
  1551. * @for defaults
  1552. **/
  1553. enableKeyNavigation: true,
  1554. /**
  1555. * Enables pagination if `true`.
  1556. *
  1557. * @property enablePagination
  1558. * @type Boolean
  1559. * @default true
  1560. * @for defaults
  1561. **/
  1562. enablePagination: true,
  1563. /**
  1564. * Suppresses pagination if a form field is focused.
  1565. *
  1566. * @property suppressPaginationOnFocus
  1567. * @type Boolean
  1568. * @default true
  1569. * @for defaults
  1570. **/
  1571. suppressPaginationOnFocus: true,
  1572. /**
  1573. * Enables cache for async loaded or iframe embedded content.
  1574. *
  1575. * @property enableContentCache
  1576. * @type Boolean
  1577. * @default true
  1578. * @for defaults
  1579. **/
  1580. enableContentCache: true,
  1581. /**
  1582. * Shows the cancel button if enabled.
  1583. *
  1584. * @property enableCancelButton
  1585. * @type Boolean
  1586. * @default false
  1587. * @for defaults
  1588. **/
  1589. enableCancelButton: false,
  1590. /**
  1591. * Shows the finish button if enabled.
  1592. *
  1593. * @property enableFinishButton
  1594. * @type Boolean
  1595. * @default true
  1596. * @for defaults
  1597. **/
  1598. enableFinishButton: true,
  1599. /**
  1600. * Not yet implemented.
  1601. *
  1602. * @property preloadContent
  1603. * @type Boolean
  1604. * @default false
  1605. * @for defaults
  1606. **/
  1607. preloadContent: false,
  1608. /**
  1609. * Shows the finish button always (on each step; right beside the next button) if `true`.
  1610. * Otherwise the next button will be replaced by the finish button if the last step becomes active.
  1611. *
  1612. * @property showFinishButtonAlways
  1613. * @type Boolean
  1614. * @default false
  1615. * @for defaults
  1616. **/
  1617. showFinishButtonAlways: false,
  1618. /**
  1619. * Prevents jumping to a previous step.
  1620. *
  1621. * @property forceMoveForward
  1622. * @type Boolean
  1623. * @default false
  1624. * @for defaults
  1625. **/
  1626. forceMoveForward: false,
  1627. /**
  1628. * Saves the current state (step position) to a cookie.
  1629. * By coming next time the last active step becomes activated.
  1630. *
  1631. * @property saveState
  1632. * @type Boolean
  1633. * @default false
  1634. * @for defaults
  1635. **/
  1636. saveState: false,
  1637. /**
  1638. * The position to start on (zero-based).
  1639. *
  1640. * @property startIndex
  1641. * @type Integer
  1642. * @default 0
  1643. * @for defaults
  1644. **/
  1645. startIndex: 0,
  1646. /*
  1647. * Animation Effect Configuration
  1648. */
  1649. /**
  1650. * The animation effect which will be used for step transitions.
  1651. *
  1652. * @property transitionEffect
  1653. * @type transitionEffect
  1654. * @default none
  1655. * @for defaults
  1656. **/
  1657. transitionEffect: transitionEffect.none,
  1658. /**
  1659. * Animation speed for step transitions (in milliseconds).
  1660. *
  1661. * @property transitionEffectSpeed
  1662. * @type Integer
  1663. * @default 200
  1664. * @for defaults
  1665. **/
  1666. transitionEffectSpeed: 200,
  1667. /*
  1668. * Events
  1669. */
  1670. /**
  1671. * Fires before the step changes and can be used to prevent step changing by returning `false`.
  1672. * Very useful for form validation.
  1673. *
  1674. * @property onStepChanging
  1675. * @type Event
  1676. * @default function (event, currentIndex, newIndex) { return true; }
  1677. * @for defaults
  1678. **/
  1679. onStepChanging: function (event, currentIndex, newIndex) { return true; },
  1680. /**
  1681. * Fires after the step has change.
  1682. *
  1683. * @property onStepChanged
  1684. * @type Event
  1685. * @default function (event, currentIndex, priorIndex) { }
  1686. * @for defaults
  1687. **/
  1688. onStepChanged: function (event, currentIndex, priorIndex) { },
  1689. /**
  1690. * Fires after cancelation.
  1691. *
  1692. * @property onCanceled
  1693. * @type Event
  1694. * @default function (event) { }
  1695. * @for defaults
  1696. **/
  1697. onCanceled: function (event) { },
  1698. /**
  1699. * Fires before finishing and can be used to prevent completion by returning `false`.
  1700. * Very useful for form validation.
  1701. *
  1702. * @property onFinishing
  1703. * @type Event
  1704. * @default function (event, currentIndex) { return true; }
  1705. * @for defaults
  1706. **/
  1707. onFinishing: function (event, currentIndex) { return true; },
  1708. /**
  1709. * Fires after completion.
  1710. *
  1711. * @property onFinished
  1712. * @type Event
  1713. * @default function (event, currentIndex) { }
  1714. * @for defaults
  1715. **/
  1716. onFinished: function (event, currentIndex) { },
  1717. /**
  1718. * Fires after async content is loaded.
  1719. *
  1720. * @property onContentLoaded
  1721. * @type Event
  1722. * @default function (event, index) { }
  1723. * @for defaults
  1724. **/
  1725. onContentLoaded: function (event, currentIndex) { },
  1726. /**
  1727. * Fires when the wizard is initialized.
  1728. *
  1729. * @property onInit
  1730. * @type Event
  1731. * @default function (event) { }
  1732. * @for defaults
  1733. **/
  1734. onInit: function (event, currentIndex) { },
  1735. /**
  1736. * Contains all labels.
  1737. *
  1738. * @property labels
  1739. * @type Object
  1740. * @for defaults
  1741. **/
  1742. labels: {
  1743. /**
  1744. * Label for the cancel button.
  1745. *
  1746. * @property cancel
  1747. * @type String
  1748. * @default "Cancel"
  1749. * @for defaults
  1750. **/
  1751. cancel: "取消",
  1752. /**
  1753. * This label is important for accessability reasons.
  1754. * Indicates which step is activated.
  1755. *
  1756. * @property current
  1757. * @type String
  1758. * @default "current step:"
  1759. * @for defaults
  1760. **/
  1761. current: "当前步骤::",
  1762. /**
  1763. * This label is important for accessability reasons and describes the kind of navigation.
  1764. *
  1765. * @property pagination
  1766. * @type String
  1767. * @default "Pagination"
  1768. * @for defaults
  1769. * @since 0.9.7
  1770. **/
  1771. pagination: "分页",
  1772. /**
  1773. * Label for the finish button.
  1774. *
  1775. * @property finish
  1776. * @type String
  1777. * @default "Finish"
  1778. * @for defaults
  1779. **/
  1780. finish: "完成",
  1781. /**
  1782. * Label for the next button.
  1783. *
  1784. * @property next
  1785. * @type String
  1786. * @default "Next"
  1787. * @for defaults
  1788. **/
  1789. next: "下一步",
  1790. /**
  1791. * Label for the previous button.
  1792. *
  1793. * @property previous
  1794. * @type String
  1795. * @default "Previous"
  1796. * @for defaults
  1797. **/
  1798. previous: "上一步",
  1799. /**
  1800. * Label for the loading animation.
  1801. *
  1802. * @property loading
  1803. * @type String
  1804. * @default "Loading ..."
  1805. * @for defaults
  1806. **/
  1807. loading: "加载中 ..."
  1808. }
  1809. };
  1810. })(jQuery);