collapse-native.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /* Native Javascript for Bootstrap 3 | Collapse
  2. -----------------------------------------------*/
  3. // COLLAPSE DEFINITION
  4. // ===================
  5. var Collapse = function( element, options ) {
  6. // initialization element
  7. element = queryElement(element);
  8. // set options
  9. options = options || {};
  10. // event targets and constants
  11. var accordion = null, collapse = null, self = this,
  12. accordionData = element[getAttribute]('data-parent'),
  13. activeCollapse, activeElement,
  14. // component strings
  15. component = 'collapse',
  16. collapsed = 'collapsed',
  17. isAnimating = 'isAnimating',
  18. // private methods
  19. openAction = function(collapseElement,toggle) {
  20. bootstrapCustomEvent.call(collapseElement, showEvent, component);
  21. collapseElement[isAnimating] = true;
  22. addClass(collapseElement,collapsing);
  23. removeClass(collapseElement,component);
  24. collapseElement[style][height] = collapseElement[scrollHeight] + 'px';
  25. emulateTransitionEnd(collapseElement, function() {
  26. collapseElement[isAnimating] = false;
  27. collapseElement[setAttribute](ariaExpanded,'true');
  28. toggle[setAttribute](ariaExpanded,'true');
  29. removeClass(collapseElement,collapsing);
  30. addClass(collapseElement, component);
  31. addClass(collapseElement, inClass);
  32. collapseElement[style][height] = '';
  33. bootstrapCustomEvent.call(collapseElement, shownEvent, component);
  34. });
  35. },
  36. closeAction = function(collapseElement,toggle) {
  37. bootstrapCustomEvent.call(collapseElement, hideEvent, component);
  38. collapseElement[isAnimating] = true;
  39. collapseElement[style][height] = collapseElement[scrollHeight] + 'px'; // set height first
  40. removeClass(collapseElement,component);
  41. removeClass(collapseElement, inClass);
  42. addClass(collapseElement, collapsing);
  43. collapseElement[offsetWidth]; // force reflow to enable transition
  44. collapseElement[style][height] = '0px';
  45. emulateTransitionEnd(collapseElement, function() {
  46. collapseElement[isAnimating] = false;
  47. collapseElement[setAttribute](ariaExpanded,'false');
  48. toggle[setAttribute](ariaExpanded,'false');
  49. removeClass(collapseElement,collapsing);
  50. addClass(collapseElement,component);
  51. collapseElement[style][height] = '';
  52. bootstrapCustomEvent.call(collapseElement, hiddenEvent, component);
  53. });
  54. },
  55. getTarget = function() {
  56. var href = element.href && element[getAttribute]('href'),
  57. parent = element[getAttribute](dataTarget),
  58. id = href || ( parent && parent.charAt(0) === '#' ) && parent;
  59. return id && queryElement(id);
  60. };
  61. // public methods
  62. this.toggle = function(e) {
  63. e[preventDefault]();
  64. if (!hasClass(collapse,inClass)) { self.show(); }
  65. else { self.hide(); }
  66. };
  67. this.hide = function() {
  68. if ( collapse[isAnimating] ) return;
  69. closeAction(collapse,element);
  70. addClass(element,collapsed);
  71. };
  72. this.show = function() {
  73. if ( accordion ) {
  74. activeCollapse = queryElement('.'+component+'.'+inClass,accordion);
  75. activeElement = activeCollapse && (queryElement('['+dataTarget+'="#'+activeCollapse.id+'"]', accordion)
  76. || queryElement('[href="#'+activeCollapse.id+'"]',accordion) );
  77. }
  78. if ( !collapse[isAnimating] || activeCollapse && !activeCollapse[isAnimating] ) {
  79. if ( activeElement && activeCollapse !== collapse ) {
  80. closeAction(activeCollapse,activeElement);
  81. addClass(activeElement,collapsed);
  82. }
  83. openAction(collapse,element);
  84. removeClass(element,collapsed);
  85. }
  86. };
  87. // init
  88. if ( !(stringCollapse in element ) ) { // prevent adding event handlers twice
  89. on(element, clickEvent, self.toggle);
  90. }
  91. collapse = getTarget();
  92. collapse[isAnimating] = false; // when true it will prevent click handlers
  93. accordion = queryElement(options.parent) || accordionData && getClosest(element, accordionData);
  94. element[stringCollapse] = self;
  95. };
  96. // COLLAPSE DATA API
  97. // =================
  98. supports[push]( [ stringCollapse, Collapse, '['+dataToggle+'="collapse"]' ] );