PageRenderTime 50ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/profiles/cod/modules/contrib/jquery_ui/jquery.ui/ui/ui.accordion.js

https://github.com/drupalcampnyc/dcnyc10
JavaScript | 397 lines | 319 code | 51 blank | 27 comment | 53 complexity | f462e28435ff24106dc7e85fe6630cc6 MD5 | raw file
  1. /*
  2. * jQuery UI Accordion 1.6
  3. *
  4. * Copyright (c) 2008 AUTHORS.txt (http://ui.jquery.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 options = this.options;
  17. if ( options.navigation ) {
  18. var current = this.element.find("a").filter(options.navigationFilter);
  19. if ( current.length ) {
  20. if ( current.filter(options.header).length ) {
  21. options.active = current;
  22. } else {
  23. options.active = current.parent().parent().prev();
  24. current.addClass("current");
  25. }
  26. }
  27. }
  28. // calculate active if not specified, using the first header
  29. options.headers = this.element.find(options.header);
  30. options.active = findActive(options.headers, options.active);
  31. // IE7-/Win - Extra vertical space in Lists fixed
  32. if ($.browser.msie) {
  33. this.element.find('a').css('zoom', '1');
  34. }
  35. if (!this.element.hasClass("ui-accordion")) {
  36. this.element.addClass("ui-accordion");
  37. $('<span class="ui-accordion-left"></span>').insertBefore(options.headers);
  38. $('<span class="ui-accordion-right"></span>').appendTo(options.headers);
  39. options.headers.addClass("ui-accordion-header");
  40. }
  41. var maxHeight;
  42. if ( options.fillSpace ) {
  43. maxHeight = this.element.parent().height();
  44. options.headers.each(function() {
  45. maxHeight -= $(this).outerHeight();
  46. });
  47. var maxPadding = 0;
  48. options.headers.next().each(function() {
  49. maxPadding = Math.max(maxPadding, $(this).innerHeight() - $(this).height());
  50. }).height(maxHeight - maxPadding);
  51. } else if ( options.autoHeight ) {
  52. maxHeight = 0;
  53. options.headers.next().each(function() {
  54. maxHeight = Math.max(maxHeight, $(this).outerHeight());
  55. }).height(maxHeight);
  56. }
  57. this.element.attr('role','tablist');
  58. var self=this;
  59. options.headers
  60. .attr('role','tab')
  61. .bind('keydown', function(event) { return self._keydown(event); })
  62. .next()
  63. .attr('role','tabpanel');
  64. options.headers
  65. .not(options.active || "")
  66. .attr('aria-expanded','false')
  67. .attr("tabIndex", "-1")
  68. .next()
  69. .hide();
  70. // make sure at least one header is in the tab order
  71. if (!options.active.length) {
  72. options.headers.eq(0).attr('tabIndex','0');
  73. } else {
  74. options.active
  75. .attr('aria-expanded','true')
  76. .attr("tabIndex", "0")
  77. .parent().andSelf().addClass(options.selectedClass);
  78. }
  79. // only need links in taborder for Safari
  80. if (!$.browser.safari)
  81. options.headers.find('a').attr('tabIndex','-1');
  82. if (options.event) {
  83. this.element.bind((options.event) + ".accordion", clickHandler);
  84. }
  85. },
  86. destroy: function() {
  87. this.options.headers.parent().andSelf().removeClass(this.options.selectedClass);
  88. this.options.headers.prev(".ui-accordion-left").remove();
  89. this.options.headers.children(".ui-accordion-right").remove();
  90. this.options.headers.next().css("display", "");
  91. if ( this.options.fillSpace || this.options.autoHeight ) {
  92. this.options.headers.next().css("height", "");
  93. }
  94. $.removeData(this.element[0], "accordion");
  95. this.element.removeClass("ui-accordion").unbind(".accordion");
  96. },
  97. _keydown: function(event) {
  98. if (this.options.disabled || event.altKey || event.ctrlKey)
  99. return;
  100. var keyCode = $.ui.keyCode;
  101. var length = this.options.headers.length;
  102. var currentIndex = this.options.headers.index(event.target);
  103. var toFocus = false;
  104. switch(event.keyCode) {
  105. case keyCode.RIGHT:
  106. case keyCode.DOWN:
  107. toFocus = this.options.headers[(currentIndex + 1) % length];
  108. break;
  109. case keyCode.LEFT:
  110. case keyCode.UP:
  111. toFocus = this.options.headers[(currentIndex - 1 + length) % length];
  112. break;
  113. case keyCode.SPACE:
  114. case keyCode.ENTER:
  115. return clickHandler.call(this.element[0], { target: event.target });
  116. }
  117. if (toFocus) {
  118. $(event.target).attr('tabIndex','-1');
  119. $(toFocus).attr('tabIndex','0');
  120. toFocus.focus();
  121. return false;
  122. }
  123. return true;
  124. },
  125. activate: function(index) {
  126. // call clickHandler with custom event
  127. clickHandler.call(this.element[0], {
  128. target: findActive( this.options.headers, index )[0]
  129. });
  130. }
  131. });
  132. function scopeCallback(callback, scope) {
  133. return function() {
  134. return callback.apply(scope, arguments);
  135. };
  136. };
  137. function completed(cancel) {
  138. // if removed while animated data can be empty
  139. if (!$.data(this, "accordion")) {
  140. return;
  141. }
  142. var instance = $.data(this, "accordion");
  143. var options = instance.options;
  144. options.running = cancel ? 0 : --options.running;
  145. if ( options.running ) {
  146. return;
  147. }
  148. if ( options.clearStyle ) {
  149. options.toShow.add(options.toHide).css({
  150. height: "",
  151. overflow: ""
  152. });
  153. }
  154. instance._trigger('change', null, options.data);
  155. }
  156. function toggle(toShow, toHide, data, clickedActive, down) {
  157. var options = $.data(this, "accordion").options;
  158. options.toShow = toShow;
  159. options.toHide = toHide;
  160. options.data = data;
  161. var complete = scopeCallback(completed, this);
  162. $.data(this, "accordion")._trigger("changestart", null, options.data);
  163. // count elements to animate
  164. options.running = toHide.size() === 0 ? toShow.size() : toHide.size();
  165. if ( options.animated ) {
  166. var animOptions = {};
  167. if ( !options.alwaysOpen && clickedActive ) {
  168. animOptions = {
  169. toShow: $([]),
  170. toHide: toHide,
  171. complete: complete,
  172. down: down,
  173. autoHeight: options.autoHeight
  174. };
  175. } else {
  176. animOptions = {
  177. toShow: toShow,
  178. toHide: toHide,
  179. complete: complete,
  180. down: down,
  181. autoHeight: options.autoHeight
  182. };
  183. }
  184. if (!options.proxied) {
  185. options.proxied = options.animated;
  186. }
  187. if (!options.proxiedDuration) {
  188. options.proxiedDuration = options.duration;
  189. }
  190. options.animated = $.isFunction(options.proxied) ?
  191. options.proxied(animOptions) : options.proxied;
  192. options.duration = $.isFunction(options.proxiedDuration) ?
  193. options.proxiedDuration(animOptions) : options.proxiedDuration;
  194. var animations = $.ui.accordion.animations,
  195. duration = options.duration,
  196. easing = options.animated;
  197. if (!animations[easing]) {
  198. animations[easing] = function(options) {
  199. this.slide(options, {
  200. easing: easing,
  201. duration: duration || 700
  202. });
  203. };
  204. }
  205. animations[easing](animOptions);
  206. } else {
  207. if ( !options.alwaysOpen && clickedActive ) {
  208. toShow.toggle();
  209. } else {
  210. toHide.hide();
  211. toShow.show();
  212. }
  213. complete(true);
  214. }
  215. toHide.prev().attr('aria-expanded','false').attr("tabIndex", "-1");
  216. toShow.prev().attr('aria-expanded','true').attr("tabIndex", "0").focus();;
  217. }
  218. function clickHandler(event) {
  219. var options = $.data(this, "accordion").options;
  220. if (options.disabled) {
  221. return false;
  222. }
  223. // called only when using activate(false) to close all parts programmatically
  224. if ( !event.target && !options.alwaysOpen ) {
  225. options.active.parent().andSelf().toggleClass(options.selectedClass);
  226. var toHide = options.active.next(),
  227. data = {
  228. options: options,
  229. newHeader: $([]),
  230. oldHeader: options.active,
  231. newContent: $([]),
  232. oldContent: toHide
  233. },
  234. toShow = (options.active = $([]));
  235. toggle.call(this, toShow, toHide, data );
  236. return false;
  237. }
  238. // get the click target
  239. var clicked = $(event.target);
  240. // due to the event delegation model, we have to check if one
  241. // of the parent elements is our actual header, and find that
  242. // otherwise stick with the initial target
  243. clicked = $( clicked.parents(options.header)[0] || clicked );
  244. var clickedActive = clicked[0] == options.active[0];
  245. // if animations are still active, or the active header is the target, ignore click
  246. if (options.running || (options.alwaysOpen && clickedActive)) {
  247. return false;
  248. }
  249. if (!clicked.is(options.header)) {
  250. return;
  251. }
  252. // switch classes
  253. options.active.parent().andSelf().toggleClass(options.selectedClass);
  254. if ( !clickedActive ) {
  255. clicked.parent().andSelf().addClass(options.selectedClass);
  256. }
  257. // find elements to show and hide
  258. var toShow = clicked.next(),
  259. toHide = options.active.next(),
  260. data = {
  261. options: options,
  262. newHeader: clickedActive && !options.alwaysOpen ? $([]) : clicked,
  263. oldHeader: options.active,
  264. newContent: clickedActive && !options.alwaysOpen ? $([]) : toShow,
  265. oldContent: toHide
  266. },
  267. down = options.headers.index( options.active[0] ) > options.headers.index( clicked[0] );
  268. options.active = clickedActive ? $([]) : clicked;
  269. toggle.call(this, toShow, toHide, data, clickedActive, down );
  270. return false;
  271. };
  272. function findActive(headers, selector) {
  273. return selector
  274. ? typeof selector == "number"
  275. ? headers.filter(":eq(" + selector + ")")
  276. : headers.not(headers.not(selector))
  277. : selector === false
  278. ? $([])
  279. : headers.filter(":eq(0)");
  280. }
  281. $.extend($.ui.accordion, {
  282. version: "1.6",
  283. defaults: {
  284. autoHeight: true,
  285. alwaysOpen: true,
  286. animated: 'slide',
  287. event: "click",
  288. header: "a",
  289. navigationFilter: function() {
  290. return this.href.toLowerCase() == location.href.toLowerCase();
  291. },
  292. running: 0,
  293. selectedClass: "selected"
  294. },
  295. animations: {
  296. slide: function(options, additions) {
  297. options = $.extend({
  298. easing: "swing",
  299. duration: 300
  300. }, options, additions);
  301. if ( !options.toHide.size() ) {
  302. options.toShow.animate({height: "show"}, options);
  303. return;
  304. }
  305. var hideHeight = options.toHide.height(),
  306. showHeight = options.toShow.height(),
  307. difference = showHeight / hideHeight,
  308. padding = options.toShow.outerHeight() - options.toShow.height(),
  309. margin = options.toShow.css('marginBottom'),
  310. overflow = options.toShow.css('overflow')
  311. tmargin = options.toShow.css('marginTop');
  312. options.toShow.css({ height: 0, overflow: 'hidden', marginTop: 0, marginBottom: -padding }).show();
  313. options.toHide.filter(":hidden").each(options.complete).end().filter(":visible").animate({height:"hide"},{
  314. step: function(now) {
  315. var current = (hideHeight - now) * difference;
  316. if ($.browser.msie || $.browser.opera) {
  317. current = Math.ceil(current);
  318. }
  319. options.toShow.height( current );
  320. },
  321. duration: options.duration,
  322. easing: options.easing,
  323. complete: function() {
  324. if ( !options.autoHeight ) {
  325. options.toShow.css("height", "auto");
  326. }
  327. options.toShow.css({marginTop: tmargin, marginBottom: margin, overflow: overflow});
  328. options.complete();
  329. }
  330. });
  331. },
  332. bounceslide: function(options) {
  333. this.slide(options, {
  334. easing: options.down ? "easeOutBounce" : "swing",
  335. duration: options.down ? 1000 : 200
  336. });
  337. },
  338. easeslide: function(options) {
  339. this.slide(options, {
  340. easing: "easeinout",
  341. duration: 700
  342. });
  343. }
  344. }
  345. });
  346. })(jQuery);