jquery.bootstrap.wizard.js 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*!
  2. * jQuery twitter bootstrap wizard plugin
  3. * Examples and documentation at: http://github.com/VinceG/twitter-bootstrap-wizard
  4. * version 1.0
  5. * Requires jQuery v1.3.2 or later
  6. * Supports Bootstrap 2.2.x, 2.3.x, 3.0
  7. * Dual licensed under the MIT and GPL licenses:
  8. * http://www.opensource.org/licenses/mit-license.php
  9. * http://www.gnu.org/licenses/gpl.html
  10. * Authors: Vadim Vincent Gabriel (http://vadimg.com), Jason Gill (www.gilluminate.com)
  11. */
  12. ;(function($) {
  13. var bootstrapWizardCreate = function(element, options) {
  14. var element = $(element);
  15. var obj = this;
  16. // selector skips any 'li' elements that do not contain a child with a tab data-toggle
  17. var baseItemSelector = 'li:has([data-toggle="tab"])';
  18. // Merge options with defaults
  19. var $settings = $.extend({}, $.fn.bootstrapWizard.defaults, options);
  20. var $activeTab = null;
  21. var $navigation = null;
  22. this.rebindClick = function(selector, fn)
  23. {
  24. selector.unbind('click', fn).bind('click', fn);
  25. }
  26. this.fixNavigationButtons = function() {
  27. // Get the current active tab
  28. if(!$activeTab.length) {
  29. // Select first one
  30. $navigation.find('a:first').tab('show');
  31. $activeTab = $navigation.find(baseItemSelector + ':first');
  32. }
  33. // See if we're currently in the first/last then disable the previous and last buttons
  34. $($settings.previousSelector, element).toggleClass('disabled', (obj.firstIndex() >= obj.currentIndex()));
  35. $($settings.nextSelector, element).toggleClass('disabled', (obj.currentIndex() >= obj.navigationLength()));
  36. // We are unbinding and rebinding to ensure single firing and no double-click errors
  37. obj.rebindClick($($settings.nextSelector, element), obj.next);
  38. obj.rebindClick($($settings.previousSelector, element), obj.previous);
  39. obj.rebindClick($($settings.lastSelector, element), obj.last);
  40. obj.rebindClick($($settings.firstSelector, element), obj.first);
  41. if($settings.onTabShow && typeof $settings.onTabShow === 'function' && $settings.onTabShow($activeTab, $navigation, obj.currentIndex())===false){
  42. return false;
  43. }
  44. };
  45. this.next = function(e) {
  46. // If we clicked the last then dont activate this
  47. if(element.hasClass('last')) {
  48. return false;
  49. }
  50. if($settings.onNext && typeof $settings.onNext === 'function' && $settings.onNext($activeTab, $navigation, obj.nextIndex())===false){
  51. return false;
  52. }
  53. // Did we click the last button
  54. $index = obj.nextIndex();
  55. if($index > obj.navigationLength()) {
  56. } else {
  57. $navigation.find(baseItemSelector + ':eq('+$index+') a').tab('show');
  58. }
  59. };
  60. this.previous = function(e) {
  61. // If we clicked the first then dont activate this
  62. if(element.hasClass('first')) {
  63. return false;
  64. }
  65. if($settings.onPrevious && typeof $settings.onPrevious === 'function' && $settings.onPrevious($activeTab, $navigation, obj.previousIndex())===false){
  66. return false;
  67. }
  68. $index = obj.previousIndex();
  69. if($index < 0) {
  70. } else {
  71. $navigation.find(baseItemSelector + ':eq('+$index+') a').tab('show');
  72. }
  73. };
  74. this.first = function(e) {
  75. if($settings.onFirst && typeof $settings.onFirst === 'function' && $settings.onFirst($activeTab, $navigation, obj.firstIndex())===false){
  76. return false;
  77. }
  78. // If the element is disabled then we won't do anything
  79. if(element.hasClass('disabled')) {
  80. return false;
  81. }
  82. $navigation.find(baseItemSelector + ':eq(0) a').tab('show');
  83. };
  84. this.last = function(e) {
  85. if($settings.onLast && typeof $settings.onLast === 'function' && $settings.onLast($activeTab, $navigation, obj.lastIndex())===false){
  86. return false;
  87. }
  88. // If the element is disabled then we won't do anything
  89. if(element.hasClass('disabled')) {
  90. return false;
  91. }
  92. $navigation.find(baseItemSelector + ':eq('+obj.navigationLength()+') a').tab('show');
  93. };
  94. this.currentIndex = function() {
  95. return $navigation.find(baseItemSelector).index($activeTab);
  96. };
  97. this.firstIndex = function() {
  98. return 0;
  99. };
  100. this.lastIndex = function() {
  101. return obj.navigationLength();
  102. };
  103. this.getIndex = function(e) {
  104. return $navigation.find(baseItemSelector).index(e);
  105. };
  106. this.nextIndex = function() {
  107. return $navigation.find(baseItemSelector).index($activeTab) + 1;
  108. };
  109. this.previousIndex = function() {
  110. return $navigation.find(baseItemSelector).index($activeTab) - 1;
  111. };
  112. this.navigationLength = function() {
  113. return $navigation.find(baseItemSelector).length - 1;
  114. };
  115. this.activeTab = function() {
  116. return $activeTab;
  117. };
  118. this.nextTab = function() {
  119. return $navigation.find(baseItemSelector + ':eq('+(obj.currentIndex()+1)+')').length ? $navigation.find(baseItemSelector + ':eq('+(obj.currentIndex()+1)+')') : null;
  120. };
  121. this.previousTab = function() {
  122. if(obj.currentIndex() <= 0) {
  123. return null;
  124. }
  125. return $navigation.find(baseItemSelector + ':eq('+parseInt(obj.currentIndex()-1)+')');
  126. };
  127. this.show = function(index) {
  128. return element.find(baseItemSelector + ':eq(' + index + ') a').tab('show');
  129. };
  130. this.disable = function(index) {
  131. $navigation.find(baseItemSelector + ':eq('+index+')').addClass('disabled');
  132. };
  133. this.enable = function(index) {
  134. $navigation.find(baseItemSelector + ':eq('+index+')').removeClass('disabled');
  135. };
  136. this.hide = function(index) {
  137. $navigation.find(baseItemSelector + ':eq('+index+')').hide();
  138. };
  139. this.display = function(index) {
  140. $navigation.find(baseItemSelector + ':eq('+index+')').show();
  141. };
  142. this.remove = function(args) {
  143. var $index = args[0];
  144. var $removeTabPane = typeof args[1] != 'undefined' ? args[1] : false;
  145. var $item = $navigation.find(baseItemSelector + ':eq('+$index+')');
  146. // Remove the tab pane first if needed
  147. if($removeTabPane) {
  148. var $href = $item.find('a').attr('href');
  149. $($href).remove();
  150. }
  151. // Remove menu item
  152. $item.remove();
  153. };
  154. var innerTabClick = function (e) {
  155. // Get the index of the clicked tab
  156. var clickedIndex = $navigation.find(baseItemSelector).index($(e.currentTarget).parent(baseItemSelector));
  157. if($settings.onTabClick && typeof $settings.onTabClick === 'function' && $settings.onTabClick($activeTab, $navigation, obj.currentIndex(), clickedIndex)===false){
  158. return false;
  159. }
  160. };
  161. var innerTabShown = function (e) { // use shown instead of show to help prevent double firing
  162. $element = $(e.target).parent();
  163. var nextTab = $navigation.find(baseItemSelector).index($element);
  164. // If it's disabled then do not change
  165. if($element.hasClass('disabled')) {
  166. return false;
  167. }
  168. if($settings.onTabChange && typeof $settings.onTabChange === 'function' && $settings.onTabChange($activeTab, $navigation, obj.currentIndex(), nextTab)===false){
  169. return false;
  170. }
  171. $activeTab = $element; // activated tab
  172. obj.fixNavigationButtons();
  173. };
  174. this.resetWizard = function() {
  175. // remove the existing handlers
  176. $('a[data-toggle="tab"]', $navigation).off('click', innerTabClick);
  177. $('a[data-toggle="tab"]', $navigation).off('shown shown.bs.tab', innerTabShown);
  178. // reset elements based on current state of the DOM
  179. $navigation = element.find('ul:first', element);
  180. $activeTab = $navigation.find(baseItemSelector + '.active', element);
  181. // re-add handlers
  182. $('a[data-toggle="tab"]', $navigation).on('click', innerTabClick);
  183. $('a[data-toggle="tab"]', $navigation).on('shown shown.bs.tab', innerTabShown);
  184. obj.fixNavigationButtons();
  185. };
  186. $navigation = element.find('ul:first', element);
  187. $activeTab = $navigation.find(baseItemSelector + '.active', element);
  188. if(!$navigation.hasClass($settings.tabClass)) {
  189. $navigation.addClass($settings.tabClass);
  190. }
  191. // Load onInit
  192. if($settings.onInit && typeof $settings.onInit === 'function'){
  193. $settings.onInit($activeTab, $navigation, 0);
  194. }
  195. // Load onShow
  196. if($settings.onShow && typeof $settings.onShow === 'function'){
  197. $settings.onShow($activeTab, $navigation, obj.nextIndex());
  198. }
  199. $('a[data-toggle="tab"]', $navigation).on('click', innerTabClick);
  200. // attach to both shown and shown.bs.tab to support Bootstrap versions 2.3.2 and 3.0.0
  201. $('a[data-toggle="tab"]', $navigation).on('shown shown.bs.tab', innerTabShown);
  202. this.fixNavigationButtons();
  203. };
  204. $.fn.bootstrapWizard = function(options) {
  205. //expose methods
  206. if (typeof options == 'string') {
  207. var args = Array.prototype.slice.call(arguments, 1)
  208. if(args.length === 1) {
  209. args.toString();
  210. }
  211. return this.data('bootstrapWizard')[options](args);
  212. }
  213. return this.each(function(index){
  214. var element = $(this);
  215. // Return early if this element already has a plugin instance
  216. if (element.data('bootstrapWizard')) return;
  217. // pass options to plugin constructor
  218. var wizard = new bootstrapWizardCreate(element, options);
  219. // Store plugin object in this element's data
  220. element.data('bootstrapWizard', wizard);
  221. });
  222. };
  223. // expose options
  224. $.fn.bootstrapWizard.defaults = {
  225. tabClass: 'nav nav-pills',
  226. nextSelector: '.wizard li.next',
  227. previousSelector: '.wizard li.previous',
  228. firstSelector: '.wizard li.first',
  229. lastSelector: '.wizard li.last',
  230. onShow: null,
  231. onInit: null,
  232. onNext: null,
  233. onPrevious: null,
  234. onLast: null,
  235. onFirst: null,
  236. onTabChange: null,
  237. onTabClick: null,
  238. onTabShow: null
  239. };
  240. })(jQuery);