smartwizard.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647
  1. /*!
  2. * SmartWizard v4.3.1
  3. * The awesome jQuery step wizard plugin with Bootstrap support
  4. * http://www.techlaboratory.net/smartwizard
  5. *
  6. * Created by Dipu Raj
  7. * http://dipuraj.me
  8. *
  9. * Licensed under the terms of the MIT License
  10. * https://github.com/techlab/SmartWizard/blob/master/LICENSE
  11. */
  12. ;(function ($, window, document, undefined) {
  13. "use strict";
  14. // Default options
  15. var defaults = {
  16. selected: 0, // Initial selected step, 0 = first step
  17. keyNavigation: true, // Enable/Disable keyboard navigation(left and right keys are used if enabled)
  18. autoAdjustHeight: true, // Automatically adjust content height
  19. cycleSteps: false, // Allows to cycle the navigation of steps
  20. backButtonSupport: true, // Enable the back button support
  21. useURLhash: true, // Enable selection of the step based on url hash
  22. showStepURLhash: true, // Show url hash based on step
  23. lang: { // Language variables for button
  24. next: 'Next',
  25. previous: 'Previous'
  26. },
  27. toolbarSettings: {
  28. toolbarPosition: 'bottom', // none, top, bottom, both
  29. toolbarButtonPosition: 'end', // start, end
  30. showNextButton: true, // show/hide a Next button
  31. showPreviousButton: true, // show/hide a Previous button
  32. toolbarExtraButtons: [] // Extra buttons to show on toolbar, array of jQuery input/buttons elements
  33. },
  34. anchorSettings: {
  35. anchorClickable: true, // Enable/Disable anchor navigation
  36. enableAllAnchors: false, // Activates all anchors clickable all times
  37. markDoneStep: true, // Add done css
  38. markAllPreviousStepsAsDone: true, // When a step selected by url hash, all previous steps are marked done
  39. removeDoneStepOnNavigateBack: false, // While navigate back done step after active step will be cleared
  40. enableAnchorOnDoneStep: true // Enable/Disable the done steps navigation
  41. },
  42. contentURL: null, // content url, Enables Ajax content loading. Can also set as data data-content-url on anchor
  43. contentCache: true, // cache step contents, if false content is fetched always from ajax url
  44. ajaxSettings: {}, // Ajax extra settings
  45. disabledSteps: [], // Array Steps disabled
  46. errorSteps: [], // Highlight step with errors
  47. hiddenSteps: [], // Hidden steps
  48. theme: 'default', // theme for the wizard, related css need to include for other than default theme
  49. transitionEffect: 'none', // Effect on navigation, none/slide/fade
  50. transitionSpeed: '400'
  51. };
  52. // The plugin constructor
  53. function SmartWizard(element, options) {
  54. // Merge user settings with default, recursively
  55. this.options = $.extend(true, {}, defaults, options);
  56. // Main container element
  57. this.main = $(element);
  58. // Navigation bar element
  59. this.nav = this.main.children('ul');
  60. // Step anchor elements
  61. this.steps = $("li > a", this.nav);
  62. // Content container
  63. this.container = this.main.children('div');
  64. // Content pages
  65. this.pages = this.container.children('div');
  66. // Active step index
  67. this.current_index = null;
  68. // Backward compatibility
  69. this.options.toolbarSettings.toolbarButtonPosition = this.options.toolbarSettings.toolbarButtonPosition === 'right' ? 'end' : this.options.toolbarSettings.toolbarButtonPosition;
  70. this.options.toolbarSettings.toolbarButtonPosition = this.options.toolbarSettings.toolbarButtonPosition === 'left' ? 'start' : this.options.toolbarSettings.toolbarButtonPosition;
  71. // Default fix
  72. this.options.theme = this.options.theme === null || this.options.theme === '' ? 'default' : this.options.theme;
  73. // Call initial method
  74. this.init();
  75. }
  76. $.extend(SmartWizard.prototype, {
  77. init: function () {
  78. // Set the elements
  79. this._setElements();
  80. // Add toolbar
  81. this._setToolbar();
  82. // Assign plugin events
  83. this._setEvents();
  84. var idx = this.options.selected;
  85. // Get selected step from the url
  86. if (this.options.useURLhash) {
  87. // Get step number from url hash if available
  88. var hash = window.location.hash;
  89. if (hash && hash.length > 0) {
  90. var elm = $("a[href*='" + hash + "']", this.nav);
  91. if (elm.length > 0) {
  92. var id = this.steps.index(elm);
  93. idx = id >= 0 ? id : idx;
  94. }
  95. }
  96. }
  97. if (idx > 0 && this.options.anchorSettings.markDoneStep && this.options.anchorSettings.markAllPreviousStepsAsDone) {
  98. // Mark previous steps of the active step as done
  99. this.steps.eq(idx).parent('li').prevAll().addClass("done");
  100. }
  101. // Show the initial step
  102. this._showStep(idx);
  103. },
  104. // PRIVATE FUNCTIONS
  105. _setElements: function () {
  106. // Set the main element
  107. this.main.addClass('sw-main sw-theme-' + this.options.theme);
  108. // Set anchor elements
  109. this.nav.addClass('nav nav-tabs step-anchor').children('li').addClass('nav-item').children('a').addClass('nav-link'); // nav-justified nav-pills
  110. // Make the anchor clickable
  111. if (this.options.anchorSettings.enableAllAnchors !== false && this.options.anchorSettings.anchorClickable !== false) {
  112. this.steps.parent('li').addClass('clickable');
  113. }
  114. // Set content container
  115. this.container.addClass('sw-container tab-content');
  116. // Set content pages
  117. this.pages.addClass('tab-pane step-content');
  118. // Disabled steps
  119. var mi = this;
  120. if (this.options.disabledSteps && this.options.disabledSteps.length > 0) {
  121. $.each(this.options.disabledSteps, function (i, n) {
  122. mi.steps.eq(n).parent('li').addClass('disabled');
  123. });
  124. }
  125. // Error steps
  126. if (this.options.errorSteps && this.options.errorSteps.length > 0) {
  127. $.each(this.options.errorSteps, function (i, n) {
  128. mi.steps.eq(n).parent('li').addClass('danger');
  129. });
  130. }
  131. // Hidden steps
  132. if (this.options.hiddenSteps && this.options.hiddenSteps.length > 0) {
  133. $.each(this.options.hiddenSteps, function (i, n) {
  134. mi.steps.eq(n).parent('li').addClass('hidden');
  135. });
  136. }
  137. return true;
  138. },
  139. _setToolbar: function () {
  140. // Skip right away if the toolbar is not enabled
  141. if (this.options.toolbarSettings.toolbarPosition === 'none') {
  142. return true;
  143. }
  144. // Create the toolbar buttons
  145. var btnNext = this.options.toolbarSettings.showNextButton !== false ? $('<button></button>').text(this.options.lang.next).addClass('btn btn-secondary sw-btn-next').attr('type', 'button') : null;
  146. var btnPrevious = this.options.toolbarSettings.showPreviousButton !== false ? $('<button></button>').text(this.options.lang.previous).addClass('btn btn-secondary sw-btn-prev').attr('type', 'button') : null;
  147. var btnGroup = $('<div></div>').addClass('btn-group mr-2 sw-btn-group').attr('role', 'group').append(btnPrevious, btnNext);
  148. // Add extra toolbar buttons
  149. var btnGroupExtra = null;
  150. if (this.options.toolbarSettings.toolbarExtraButtons && this.options.toolbarSettings.toolbarExtraButtons.length > 0) {
  151. btnGroupExtra = $('<div></div>').addClass('btn-group mr-2 sw-btn-group-extra').attr('role', 'group');
  152. $.each(this.options.toolbarSettings.toolbarExtraButtons, function (i, n) {
  153. btnGroupExtra.append(n.clone(true));
  154. });
  155. }
  156. var toolbarTop, toolbarBottom;
  157. // Append toolbar based on the position
  158. switch (this.options.toolbarSettings.toolbarPosition) {
  159. case 'top':
  160. toolbarTop = $('<div></div>').addClass('btn-toolbar sw-toolbar sw-toolbar-top justify-content-' + this.options.toolbarSettings.toolbarButtonPosition);
  161. toolbarTop.append(btnGroup);
  162. if (this.options.toolbarSettings.toolbarButtonPosition === 'start') {
  163. toolbarTop.prepend(btnGroupExtra);
  164. } else {
  165. toolbarTop.append(btnGroupExtra);
  166. }
  167. this.container.before(toolbarTop);
  168. break;
  169. case 'bottom':
  170. toolbarBottom = $('<div></div>').addClass('btn-toolbar sw-toolbar sw-toolbar-bottom justify-content-' + this.options.toolbarSettings.toolbarButtonPosition);
  171. toolbarBottom.append(btnGroup);
  172. if (this.options.toolbarSettings.toolbarButtonPosition === 'start') {
  173. toolbarBottom.prepend(btnGroupExtra);
  174. } else {
  175. toolbarBottom.append(btnGroupExtra);
  176. }
  177. this.container.after(toolbarBottom);
  178. break;
  179. case 'both':
  180. toolbarTop = $('<div></div>').addClass('btn-toolbar sw-toolbar sw-toolbar-top justify-content-' + this.options.toolbarSettings.toolbarButtonPosition);
  181. toolbarTop.append(btnGroup);
  182. if (this.options.toolbarSettings.toolbarButtonPosition === 'start') {
  183. toolbarTop.prepend(btnGroupExtra);
  184. } else {
  185. toolbarTop.append(btnGroupExtra);
  186. }
  187. this.container.before(toolbarTop);
  188. toolbarBottom = $('<div></div>').addClass('btn-toolbar sw-toolbar sw-toolbar-bottom justify-content-' + this.options.toolbarSettings.toolbarButtonPosition);
  189. toolbarBottom.append(btnGroup.clone(true));
  190. if (btnGroupExtra !== null) {
  191. if (this.options.toolbarSettings.toolbarButtonPosition === 'start') {
  192. toolbarBottom.prepend(btnGroupExtra.clone(true));
  193. } else {
  194. toolbarBottom.append(btnGroupExtra.clone(true));
  195. }
  196. }
  197. this.container.after(toolbarBottom);
  198. break;
  199. default:
  200. toolbarBottom = $('<div></div>').addClass('btn-toolbar sw-toolbar sw-toolbar-bottom justify-content-' + this.options.toolbarSettings.toolbarButtonPosition);
  201. toolbarBottom.append(btnGroup);
  202. if (this.options.toolbarSettings.toolbarButtonPosition === 'start') {
  203. toolbarBottom.append(btnGroupExtra);
  204. } else {
  205. toolbarBottom.append(btnGroupExtra);
  206. }
  207. this.container.after(toolbarBottom);
  208. break;
  209. }
  210. return true;
  211. },
  212. _setEvents: function () {
  213. // Anchor click event
  214. var mi = this;
  215. $(this.steps).on("click", function (e) {
  216. e.preventDefault();
  217. if (mi.options.anchorSettings.anchorClickable === false) {
  218. return true;
  219. }
  220. var idx = mi.steps.index(this);
  221. if (mi.options.anchorSettings.enableAnchorOnDoneStep === false && mi.steps.eq(idx).parent('li').hasClass('done')) {
  222. return true;
  223. }
  224. if (idx !== mi.current_index) {
  225. if (mi.options.anchorSettings.enableAllAnchors !== false && mi.options.anchorSettings.anchorClickable !== false) {
  226. mi._showStep(idx);
  227. } else {
  228. if (mi.steps.eq(idx).parent('li').hasClass('done')) {
  229. mi._showStep(idx);
  230. }
  231. }
  232. }
  233. });
  234. // Next button event
  235. $('.sw-btn-next', this.main).on("click", function (e) {
  236. e.preventDefault();
  237. mi._showNext();
  238. });
  239. // Previous button event
  240. $('.sw-btn-prev', this.main).on("click", function (e) {
  241. e.preventDefault();
  242. mi._showPrevious();
  243. });
  244. // Keyboard navigation event
  245. if (this.options.keyNavigation) {
  246. $(document).keyup(function (e) {
  247. mi._keyNav(e);
  248. });
  249. }
  250. // Back/forward browser button event
  251. if (this.options.backButtonSupport) {
  252. $(window).on('hashchange', function (e) {
  253. if (!mi.options.useURLhash) {
  254. return true;
  255. }
  256. if (window.location.hash) {
  257. var elm = $("a[href*='" + window.location.hash + "']", mi.nav);
  258. if (elm && elm.length > 0) {
  259. e.preventDefault();
  260. mi._showStep(mi.steps.index(elm));
  261. }
  262. }
  263. });
  264. }
  265. return true;
  266. },
  267. _showNext: function () {
  268. var si = this.current_index + 1;
  269. // Find the next not disabled step
  270. for (var i = si; i < this.steps.length; i++) {
  271. if (!this.steps.eq(i).parent('li').hasClass('disabled') && !this.steps.eq(i).parent('li').hasClass('hidden')) {
  272. si = i;
  273. break;
  274. }
  275. }
  276. if (this.steps.length <= si) {
  277. if (!this.options.cycleSteps) {
  278. return false;
  279. }
  280. si = 0;
  281. }
  282. this._showStep(si);
  283. return true;
  284. },
  285. _showPrevious: function () {
  286. var si = this.current_index - 1;
  287. // Find the previous not disabled step
  288. for (var i = si; i >= 0; i--) {
  289. if (!this.steps.eq(i).parent('li').hasClass('disabled') && !this.steps.eq(i).parent('li').hasClass('hidden')) {
  290. si = i;
  291. break;
  292. }
  293. }
  294. if (0 > si) {
  295. if (!this.options.cycleSteps) {
  296. return false;
  297. }
  298. si = this.steps.length - 1;
  299. }
  300. this._showStep(si);
  301. return true;
  302. },
  303. _showStep: function (idx) {
  304. // If step not found, skip
  305. if (!this.steps.eq(idx)) {
  306. return false;
  307. }
  308. // If current step is requested again, skip
  309. if (idx == this.current_index) {
  310. return false;
  311. }
  312. // If it is a disabled step, skip
  313. if (this.steps.eq(idx).parent('li').hasClass('disabled') || this.steps.eq(idx).parent('li').hasClass('hidden')) {
  314. return false;
  315. }
  316. // Load step content
  317. this._loadStepContent(idx);
  318. return true;
  319. },
  320. _loadStepContent: function (idx) {
  321. var mi = this;
  322. // Get current step elements
  323. var curTab = this.steps.eq(this.current_index);
  324. // Get the direction of step navigation
  325. var stepDirection = '';
  326. var elm = this.steps.eq(idx);
  327. var contentURL = elm.data('content-url') && elm.data('content-url').length > 0 ? elm.data('content-url') : this.options.contentURL;
  328. if (this.current_index !== null && this.current_index !== idx) {
  329. stepDirection = this.current_index < idx ? "forward" : "backward";
  330. }
  331. // Trigger "leaveStep" event
  332. if (this.current_index !== null && this._triggerEvent("leaveStep", [curTab, this.current_index, stepDirection]) === false) {
  333. return false;
  334. }
  335. if (contentURL && contentURL.length > 0 && (!elm.data('has-content') || !this.options.contentCache)) {
  336. // Get ajax content and then show step
  337. var selPage = elm.length > 0 ? $(elm.attr("href"), this.main) : null;
  338. var ajaxSettings = $.extend(true, {}, {
  339. url: contentURL,
  340. type: "POST",
  341. data: { step_number: idx },
  342. dataType: "text",
  343. beforeSend: function () {
  344. mi._loader('show');
  345. },
  346. error: function (jqXHR, status, message) {
  347. mi._loader('hide');
  348. $.error(message);
  349. },
  350. success: function (res) {
  351. if (res && res.length > 0) {
  352. elm.data('has-content', true);
  353. selPage.html(res);
  354. }
  355. mi._loader('hide');
  356. mi._transitPage(idx);
  357. }
  358. }, this.options.ajaxSettings);
  359. $.ajax(ajaxSettings);
  360. } else {
  361. // Show step
  362. this._transitPage(idx);
  363. }
  364. return true;
  365. },
  366. _transitPage: function (idx) {
  367. var mi = this;
  368. // Get current step elements
  369. var curTab = this.steps.eq(this.current_index);
  370. var curPage = curTab.length > 0 ? $(curTab.attr("href"), this.main) : null;
  371. // Get step to show elements
  372. var selTab = this.steps.eq(idx);
  373. var selPage = selTab.length > 0 ? $(selTab.attr("href"), this.main) : null;
  374. // Get the direction of step navigation
  375. var stepDirection = '';
  376. if (this.current_index !== null && this.current_index !== idx) {
  377. stepDirection = this.current_index < idx ? "forward" : "backward";
  378. }
  379. var stepPosition = 'middle';
  380. if (idx === 0) {
  381. stepPosition = 'first';
  382. } else if (idx === this.steps.length - 1) {
  383. stepPosition = 'final';
  384. }
  385. this.options.transitionEffect = this.options.transitionEffect.toLowerCase();
  386. this.pages.finish();
  387. if (this.options.transitionEffect === 'slide') {
  388. // normal slide
  389. if (curPage && curPage.length > 0) {
  390. curPage.slideUp('fast', this.options.transitionEasing, function () {
  391. selPage.slideDown(mi.options.transitionSpeed, mi.options.transitionEasing);
  392. });
  393. } else {
  394. selPage.slideDown(this.options.transitionSpeed, this.options.transitionEasing);
  395. }
  396. } else if (this.options.transitionEffect === 'fade') {
  397. // normal fade
  398. if (curPage && curPage.length > 0) {
  399. curPage.fadeOut('fast', this.options.transitionEasing, function () {
  400. selPage.fadeIn('fast', mi.options.transitionEasing, function () {
  401. $(this).show();
  402. });
  403. });
  404. } else {
  405. selPage.fadeIn(this.options.transitionSpeed, this.options.transitionEasing, function () {
  406. $(this).show();
  407. });
  408. }
  409. } else {
  410. if (curPage && curPage.length > 0) {
  411. curPage.hide();
  412. }
  413. selPage.show();
  414. }
  415. // Change the url hash to new step
  416. this._setURLHash(selTab.attr("href"));
  417. // Update controls
  418. this._setAnchor(idx);
  419. // Set the buttons based on the step
  420. this._setButtons(idx);
  421. // Fix height with content
  422. this._fixHeight(idx);
  423. // Update the current index
  424. this.current_index = idx;
  425. // Trigger "showStep" event
  426. this._triggerEvent("showStep", [selTab, this.current_index, stepDirection, stepPosition]);
  427. return true;
  428. },
  429. _setAnchor: function (idx) {
  430. // Current step anchor > Remove other classes and add done class
  431. this.steps.eq(this.current_index).parent('li').removeClass("active");
  432. if (this.options.anchorSettings.markDoneStep !== false && this.current_index !== null) {
  433. this.steps.eq(this.current_index).parent('li').addClass("done");
  434. if (this.options.anchorSettings.removeDoneStepOnNavigateBack !== false) {
  435. this.steps.eq(idx).parent('li').nextAll().removeClass("done");
  436. }
  437. }
  438. // Next step anchor > Remove other classes and add active class
  439. this.steps.eq(idx).parent('li').removeClass("done").addClass("active");
  440. return true;
  441. },
  442. _setButtons: function (idx) {
  443. // Previous/Next Button enable/disable based on step
  444. if (!this.options.cycleSteps) {
  445. if (0 >= idx) {
  446. $('.sw-btn-prev', this.main).addClass("disabled");
  447. } else {
  448. $('.sw-btn-prev', this.main).removeClass("disabled");
  449. }
  450. if (this.steps.length - 1 <= idx) {
  451. $('.sw-btn-next', this.main).addClass("disabled");
  452. } else {
  453. $('.sw-btn-next', this.main).removeClass("disabled");
  454. }
  455. }
  456. return true;
  457. },
  458. // HELPER FUNCTIONS
  459. _keyNav: function (e) {
  460. var mi = this;
  461. // Keyboard navigation
  462. switch (e.which) {
  463. case 37:
  464. // left
  465. mi._showPrevious();
  466. e.preventDefault();
  467. break;
  468. case 39:
  469. // right
  470. mi._showNext();
  471. e.preventDefault();
  472. break;
  473. default:
  474. return; // exit this handler for other keys
  475. }
  476. },
  477. _fixHeight: function (idx) {
  478. // Auto adjust height of the container
  479. if (this.options.autoAdjustHeight) {
  480. var selPage = this.steps.eq(idx).length > 0 ? $(this.steps.eq(idx).attr("href"), this.main) : null;
  481. this.container.finish().animate({ minHeight: selPage.outerHeight() }, this.options.transitionSpeed, function () {});
  482. }
  483. return true;
  484. },
  485. _triggerEvent: function (name, params) {
  486. // Trigger an event
  487. var e = $.Event(name);
  488. this.main.trigger(e, params);
  489. if (e.isDefaultPrevented()) {
  490. return false;
  491. }
  492. return e.result;
  493. },
  494. _setURLHash: function (hash) {
  495. if (this.options.showStepURLhash && window.location.hash !== hash) {
  496. window.location.hash = hash;
  497. }
  498. },
  499. _loader: function (action) {
  500. switch (action) {
  501. case 'show':
  502. this.main.addClass('sw-loading');
  503. break;
  504. case 'hide':
  505. this.main.removeClass('sw-loading');
  506. break;
  507. default:
  508. this.main.toggleClass('sw-loading');
  509. }
  510. },
  511. // PUBLIC FUNCTIONS
  512. theme: function (v) {
  513. if (this.options.theme === v) {
  514. return false;
  515. }
  516. this.main.removeClass('sw-theme-' + this.options.theme);
  517. this.options.theme = v;
  518. this.main.addClass('sw-theme-' + this.options.theme);
  519. // Trigger "themeChanged" event
  520. this._triggerEvent("themeChanged", [this.options.theme]);
  521. },
  522. next: function () {
  523. this._showNext();
  524. },
  525. prev: function () {
  526. this._showPrevious();
  527. },
  528. reset: function () {
  529. // Trigger "beginReset" event
  530. if (this._triggerEvent("beginReset") === false) {
  531. return false;
  532. }
  533. // Reset all elements and classes
  534. this.container.stop(true);
  535. this.pages.stop(true);
  536. this.pages.hide();
  537. this.current_index = null;
  538. this._setURLHash(this.steps.eq(this.options.selected).attr("href"));
  539. $(".sw-toolbar", this.main).remove();
  540. this.steps.removeClass();
  541. this.steps.parents('li').removeClass();
  542. this.steps.data('has-content', false);
  543. this.init();
  544. // Trigger "endReset" event
  545. this._triggerEvent("endReset");
  546. },
  547. stepState: function (stepArray, state) {
  548. var mi = this;
  549. stepArray = $.isArray(stepArray) ? stepArray : [stepArray];
  550. var selSteps = $.grep(this.steps, function (n, i) {
  551. return $.inArray(i, stepArray) !== -1; // && i !== mi.current_index
  552. });
  553. if (selSteps && selSteps.length > 0) {
  554. switch (state) {
  555. case 'disable':
  556. $(selSteps).parents('li').addClass('disabled');
  557. break;
  558. case 'enable':
  559. $(selSteps).parents('li').removeClass('disabled');
  560. break;
  561. case 'hide':
  562. $(selSteps).parents('li').addClass('hidden');
  563. break;
  564. case 'show':
  565. $(selSteps).parents('li').removeClass('hidden');
  566. break;
  567. case 'error-on':
  568. $(selSteps).parents('li').addClass('danger');
  569. break;
  570. case 'error-off':
  571. $(selSteps).parents('li').removeClass('danger');
  572. break;
  573. }
  574. }
  575. }
  576. });
  577. // Wrapper for the plugin
  578. $.fn.smartWizard = function (options) {
  579. var args = arguments;
  580. var instance;
  581. if (options === undefined || typeof options === 'object') {
  582. return this.each(function () {
  583. if (!$.data(this, "smartWizard")) {
  584. $.data(this, "smartWizard", new SmartWizard(this, options));
  585. }
  586. });
  587. } else if (typeof options === 'string' && options[0] !== '_' && options !== 'init') {
  588. instance = $.data(this[0], 'smartWizard');
  589. if (options === 'destroy') {
  590. $.data(this, 'smartWizard', null);
  591. }
  592. if (instance instanceof SmartWizard && typeof instance[options] === 'function') {
  593. return instance[options].apply(instance, Array.prototype.slice.call(args, 1));
  594. } else {
  595. return this;
  596. }
  597. }
  598. };
  599. })(jQuery, window, document);