PageRenderTime 23ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/demo/multipart/js/ui.accordion.js

https://github.com/mvlwn/jquery-validation
JavaScript | 477 lines | 357 code | 87 blank | 33 comment | 67 complexity | 9c06d7ffb31b8b1f48234ade4abcfd50 MD5 | raw file
  1. /*
  2. * jQuery UI Accordion 1.7.1
  3. *
  4. * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
  5. * Dual licensed under the MIT (MIT-LICENSE.txt)
  6. * and GPL (GPL-LICENSE.txt) licenses.
  7. *
  8. * http://docs.jquery.com/UI/Accordion
  9. *
  10. * Depends:
  11. * ui.core.js
  12. */
  13. (function($) {
  14. $.widget("ui.accordion", {
  15. _init: function() {
  16. var o = this.options, self = this;
  17. this.running = 0;
  18. // if the user set the alwaysOpen option on init
  19. // then we need to set the collapsible option
  20. // if they set both on init, collapsible will take priority
  21. if (o.collapsible == $.ui.accordion.defaults.collapsible &&
  22. o.alwaysOpen != $.ui.accordion.defaults.alwaysOpen) {
  23. o.collapsible = !o.alwaysOpen;
  24. }
  25. if ( o.navigation ) {
  26. var current = this.element.find("a").filter(o.navigationFilter);
  27. if ( current.length ) {
  28. if ( current.filter(o.header).length ) {
  29. this.active = current;
  30. } else {
  31. this.active = current.parent().parent().prev();
  32. current.addClass("ui-accordion-content-active");
  33. }
  34. }
  35. }
  36. this.element.addClass("ui-accordion ui-widget ui-helper-reset");
  37. // in lack of child-selectors in CSS we need to mark top-LIs in a UL-accordion for some IE-fix
  38. if (this.element[0].nodeName == "UL") {
  39. this.element.children("li").addClass("ui-accordion-li-fix");
  40. }
  41. this.headers = this.element.find(o.header).addClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all")
  42. .bind("mouseenter.accordion", function(){ $(this).addClass('ui-state-hover'); })
  43. .bind("mouseleave.accordion", function(){ $(this).removeClass('ui-state-hover'); })
  44. .bind("focus.accordion", function(){ $(this).addClass('ui-state-focus'); })
  45. .bind("blur.accordion", function(){ $(this).removeClass('ui-state-focus'); });
  46. this.headers
  47. .next()
  48. .addClass("ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom");
  49. this.active = this._findActive(this.active || o.active).toggleClass("ui-state-default").toggleClass("ui-state-active").toggleClass("ui-corner-all").toggleClass("ui-corner-top");
  50. this.active.next().addClass('ui-accordion-content-active');
  51. //Append icon elements
  52. $("<span/>").addClass("ui-icon " + o.icons.header).prependTo(this.headers);
  53. this.active.find(".ui-icon").toggleClass(o.icons.header).toggleClass(o.icons.headerSelected);
  54. // IE7-/Win - Extra vertical space in lists fixed
  55. if ($.browser.msie) {
  56. this.element.find('a').css('zoom', '1');
  57. }
  58. this.resize();
  59. //ARIA
  60. this.element.attr('role','tablist');
  61. this.headers
  62. .attr('role','tab')
  63. .bind('keydown', function(event) { return self._keydown(event); })
  64. .next()
  65. .attr('role','tabpanel');
  66. this.headers
  67. .not(this.active || "")
  68. .attr('aria-expanded','false')
  69. .attr("tabIndex", "-1")
  70. .next()
  71. .hide();
  72. // make sure at least one header is in the tab order
  73. if (!this.active.length) {
  74. this.headers.eq(0).attr('tabIndex','0');
  75. } else {
  76. this.active
  77. .attr('aria-expanded','true')
  78. .attr('tabIndex', '0');
  79. }
  80. // only need links in taborder for Safari
  81. if (!$.browser.safari)
  82. this.headers.find('a').attr('tabIndex','-1');
  83. if (o.event) {
  84. this.headers.bind((o.event) + ".accordion", function(event) { return self._clickHandler.call(self, event, this); });
  85. }
  86. },
  87. destroy: function() {
  88. var o = this.options;
  89. this.element
  90. .removeClass("ui-accordion ui-widget ui-helper-reset")
  91. .removeAttr("role")
  92. .unbind('.accordion')
  93. .removeData('accordion');
  94. this.headers
  95. .unbind(".accordion")
  96. .removeClass("ui-accordion-header ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-corner-top")
  97. .removeAttr("role").removeAttr("aria-expanded").removeAttr("tabindex");
  98. this.headers.find("a").removeAttr("tabindex");
  99. this.headers.children(".ui-icon").remove();
  100. var contents = this.headers.next().css("display", "").removeAttr("role").removeClass("ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active");
  101. if (o.autoHeight || o.fillHeight) {
  102. contents.css("height", "");
  103. }
  104. },
  105. _setData: function(key, value) {
  106. if(key == 'alwaysOpen') { key = 'collapsible'; value = !value; }
  107. $.widget.prototype._setData.apply(this, arguments);
  108. },
  109. _keydown: function(event) {
  110. var o = this.options, keyCode = $.ui.keyCode;
  111. if (o.disabled || event.altKey || event.ctrlKey)
  112. return;
  113. var length = this.headers.length;
  114. var currentIndex = this.headers.index(event.target);
  115. var toFocus = false;
  116. switch(event.keyCode) {
  117. case keyCode.RIGHT:
  118. case keyCode.DOWN:
  119. toFocus = this.headers[(currentIndex + 1) % length];
  120. break;
  121. case keyCode.LEFT:
  122. case keyCode.UP:
  123. toFocus = this.headers[(currentIndex - 1 + length) % length];
  124. break;
  125. case keyCode.SPACE:
  126. case keyCode.ENTER:
  127. return this._clickHandler({ target: event.target }, event.target);
  128. }
  129. if (toFocus) {
  130. $(event.target).attr('tabIndex','-1');
  131. $(toFocus).attr('tabIndex','0');
  132. toFocus.focus();
  133. return false;
  134. }
  135. return true;
  136. },
  137. resize: function() {
  138. var o = this.options, maxHeight;
  139. if (o.fillSpace) {
  140. if($.browser.msie) { var defOverflow = this.element.parent().css('overflow'); this.element.parent().css('overflow', 'hidden'); }
  141. maxHeight = this.element.parent().height();
  142. if($.browser.msie) { this.element.parent().css('overflow', defOverflow); }
  143. this.headers.each(function() {
  144. maxHeight -= $(this).outerHeight();
  145. });
  146. var maxPadding = 0;
  147. this.headers.next().each(function() {
  148. maxPadding = Math.max(maxPadding, $(this).innerHeight() - $(this).height());
  149. }).height(Math.max(0, maxHeight - maxPadding))
  150. .css('overflow', 'auto');
  151. } else if ( o.autoHeight ) {
  152. maxHeight = 0;
  153. this.headers.next().each(function() {
  154. maxHeight = Math.max(maxHeight, $(this).outerHeight());
  155. }).height(maxHeight);
  156. }
  157. },
  158. activate: function(index) {
  159. // call clickHandler with custom event
  160. var active = this._findActive(index)[0];
  161. this._clickHandler({ target: active }, active);
  162. },
  163. _findActive: function(selector) {
  164. return selector
  165. ? typeof selector == "number"
  166. ? this.headers.filter(":eq(" + selector + ")")
  167. : this.headers.not(this.headers.not(selector))
  168. : selector === false
  169. ? $([])
  170. : this.headers.filter(":eq(0)");
  171. },
  172. _clickHandler: function(event, target) {
  173. var o = this.options;
  174. if (o.disabled) return false;
  175. // called only when using activate(false) to close all parts programmatically
  176. if (!event.target && o.collapsible) {
  177. this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
  178. .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
  179. this.active.next().addClass('ui-accordion-content-active');
  180. var toHide = this.active.next(),
  181. data = {
  182. options: o,
  183. newHeader: $([]),
  184. oldHeader: o.active,
  185. newContent: $([]),
  186. oldContent: toHide
  187. },
  188. toShow = (this.active = $([]));
  189. this._toggle(toShow, toHide, data);
  190. return false;
  191. }
  192. // get the click target
  193. var clicked = $(event.currentTarget || target);
  194. var clickedIsActive = clicked[0] == this.active[0];
  195. // if animations are still active, or the active header is the target, ignore click
  196. if (this.running || (!o.collapsible && clickedIsActive)) {
  197. return false;
  198. }
  199. // switch classes
  200. this.active.removeClass("ui-state-active ui-corner-top").addClass("ui-state-default ui-corner-all")
  201. .find(".ui-icon").removeClass(o.icons.headerSelected).addClass(o.icons.header);
  202. this.active.next().addClass('ui-accordion-content-active');
  203. if (!clickedIsActive) {
  204. clicked.removeClass("ui-state-default ui-corner-all").addClass("ui-state-active ui-corner-top")
  205. .find(".ui-icon").removeClass(o.icons.header).addClass(o.icons.headerSelected);
  206. clicked.next().addClass('ui-accordion-content-active');
  207. }
  208. // find elements to show and hide
  209. var toShow = clicked.next(),
  210. toHide = this.active.next(),
  211. data = {
  212. options: o,
  213. newHeader: clickedIsActive && o.collapsible ? $([]) : clicked,
  214. oldHeader: this.active,
  215. newContent: clickedIsActive && o.collapsible ? $([]) : toShow.find('> *'),
  216. oldContent: toHide.find('> *')
  217. },
  218. down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
  219. this.active = clickedIsActive ? $([]) : clicked;
  220. this._toggle(toShow, toHide, data, clickedIsActive, down);
  221. return false;
  222. },
  223. _toggle: function(toShow, toHide, data, clickedIsActive, down) {
  224. var o = this.options, self = this;
  225. this.toShow = toShow;
  226. this.toHide = toHide;
  227. this.data = data;
  228. var complete = function() { if(!self) return; return self._completed.apply(self, arguments); };
  229. // trigger changestart event
  230. this._trigger("changestart", null, this.data);
  231. // count elements to animate
  232. this.running = toHide.size() === 0 ? toShow.size() : toHide.size();
  233. if (o.animated) {
  234. var animOptions = {};
  235. if ( o.collapsible && clickedIsActive ) {
  236. animOptions = {
  237. toShow: $([]),
  238. toHide: toHide,
  239. complete: complete,
  240. down: down,
  241. autoHeight: o.autoHeight || o.fillSpace
  242. };
  243. } else {
  244. animOptions = {
  245. toShow: toShow,
  246. toHide: toHide,
  247. complete: complete,
  248. down: down,
  249. autoHeight: o.autoHeight || o.fillSpace
  250. };
  251. }
  252. if (!o.proxied) {
  253. o.proxied = o.animated;
  254. }
  255. if (!o.proxiedDuration) {
  256. o.proxiedDuration = o.duration;
  257. }
  258. o.animated = $.isFunction(o.proxied) ?
  259. o.proxied(animOptions) : o.proxied;
  260. o.duration = $.isFunction(o.proxiedDuration) ?
  261. o.proxiedDuration(animOptions) : o.proxiedDuration;
  262. var animations = $.ui.accordion.animations,
  263. duration = o.duration,
  264. easing = o.animated;
  265. if (!animations[easing]) {
  266. animations[easing] = function(options) {
  267. this.slide(options, {
  268. easing: easing,
  269. duration: duration || 700
  270. });
  271. };
  272. }
  273. animations[easing](animOptions);
  274. } else {
  275. if (o.collapsible && clickedIsActive) {
  276. toShow.toggle();
  277. } else {
  278. toHide.hide();
  279. toShow.show();
  280. }
  281. complete(true);
  282. }
  283. toHide.prev().attr('aria-expanded','false').attr("tabIndex", "-1").blur();
  284. toShow.prev().attr('aria-expanded','true').attr("tabIndex", "0").focus();
  285. },
  286. _completed: function(cancel) {
  287. var o = this.options;
  288. this.running = cancel ? 0 : --this.running;
  289. if (this.running) return;
  290. if (o.clearStyle) {
  291. this.toShow.add(this.toHide).css({
  292. height: "",
  293. overflow: ""
  294. });
  295. }
  296. this._trigger('change', null, this.data);
  297. }
  298. });
  299. $.extend($.ui.accordion, {
  300. version: "1.7.1",
  301. defaults: {
  302. active: null,
  303. alwaysOpen: true, //deprecated, use collapsible
  304. animated: 'slide',
  305. autoHeight: true,
  306. clearStyle: false,
  307. collapsible: false,
  308. event: "click",
  309. fillSpace: false,
  310. header: "> li > :first-child,> :not(li):even",
  311. icons: {
  312. header: "ui-icon-triangle-1-e",
  313. headerSelected: "ui-icon-triangle-1-s"
  314. },
  315. navigation: false,
  316. navigationFilter: function() {
  317. return this.href.toLowerCase() == location.href.toLowerCase();
  318. }
  319. },
  320. animations: {
  321. slide: function(options, additions) {
  322. options = $.extend({
  323. easing: "swing",
  324. duration: 300
  325. }, options, additions);
  326. if ( !options.toHide.size() ) {
  327. options.toShow.animate({height: "show"}, options);
  328. return;
  329. }
  330. if ( !options.toShow.size() ) {
  331. options.toHide.animate({height: "hide"}, options);
  332. return;
  333. }
  334. var overflow = options.toShow.css('overflow'),
  335. percentDone,
  336. showProps = {},
  337. hideProps = {},
  338. fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
  339. originalWidth;
  340. // fix width before calculating height of hidden element
  341. var s = options.toShow;
  342. originalWidth = s[0].style.width;
  343. s.width( parseInt(s.parent().width(),10) - parseInt(s.css("paddingLeft"),10) - parseInt(s.css("paddingRight"),10) - (parseInt(s.css("borderLeftWidth"),10) || 0) - (parseInt(s.css("borderRightWidth"),10) || 0) );
  344. $.each(fxAttrs, function(i, prop) {
  345. hideProps[prop] = 'hide';
  346. var parts = ('' + $.css(options.toShow[0], prop)).match(/^([\d+-.]+)(.*)$/);
  347. showProps[prop] = {
  348. value: parts[1],
  349. unit: parts[2] || 'px'
  350. };
  351. });
  352. options.toShow.css({ height: 0, overflow: 'hidden' }).show();
  353. options.toHide.filter(":hidden").each(options.complete).end().filter(":visible").animate(hideProps,{
  354. step: function(now, settings) {
  355. // only calculate the percent when animating height
  356. // IE gets very inconsistent results when animating elements
  357. // with small values, which is common for padding
  358. if (settings.prop == 'height') {
  359. percentDone = (settings.now - settings.start) / (settings.end - settings.start);
  360. }
  361. options.toShow[0].style[settings.prop] =
  362. (percentDone * showProps[settings.prop].value) + showProps[settings.prop].unit;
  363. },
  364. duration: options.duration,
  365. easing: options.easing,
  366. complete: function() {
  367. if ( !options.autoHeight ) {
  368. options.toShow.css("height", "");
  369. }
  370. options.toShow.css("width", originalWidth);
  371. options.toShow.css({overflow: overflow});
  372. options.complete();
  373. }
  374. });
  375. },
  376. bounceslide: function(options) {
  377. this.slide(options, {
  378. easing: options.down ? "easeOutBounce" : "swing",
  379. duration: options.down ? 1000 : 200
  380. });
  381. },
  382. easeslide: function(options) {
  383. this.slide(options, {
  384. easing: "easeinout",
  385. duration: 700
  386. });
  387. }
  388. }
  389. });
  390. })(jQuery);