foundation.dropdown.js 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. ;(function ($, window, document, undefined) {
  2. 'use strict';
  3. Foundation.libs.dropdown = {
  4. name : 'dropdown',
  5. version : '5.0.0',
  6. settings : {
  7. active_class: 'open',
  8. is_hover: false,
  9. opened: function(){},
  10. closed: function(){}
  11. },
  12. init : function (scope, method, options) {
  13. Foundation.inherit(this, 'throttle');
  14. this.bindings(method, options);
  15. },
  16. events : function (scope) {
  17. var self = this;
  18. $(this.scope)
  19. .off('.dropdown')
  20. .on('click.fndtn.dropdown', '[data-dropdown]', function (e) {
  21. var settings = $(this).data('dropdown-init');
  22. e.preventDefault();
  23. if (!settings.is_hover || Modernizr.touch) self.toggle($(this));
  24. })
  25. .on('mouseenter.fndtn.dropdown', '[data-dropdown], [data-dropdown-content]', function (e) {
  26. var $this = $(this);
  27. clearTimeout(self.timeout);
  28. if ($this.data('dropdown')) {
  29. var dropdown = $('#' + $this.data('dropdown')),
  30. target = $this;
  31. } else {
  32. var dropdown = $this;
  33. target = $("[data-dropdown='" + dropdown.attr('id') + "']");
  34. }
  35. var settings = target.data('dropdown-init');
  36. if (settings.is_hover) self.open.apply(self, [dropdown, target]);
  37. })
  38. .on('mouseleave.fndtn.dropdown', '[data-dropdown], [data-dropdown-content]', function (e) {
  39. var $this = $(this);
  40. self.timeout = setTimeout(function () {
  41. if ($this.data('dropdown')) {
  42. var settings = $this.data('dropdown-init');
  43. if (settings.is_hover) self.close.call(self, $('#' + $this.data('dropdown')));
  44. } else {
  45. var target = $('[data-dropdown="' + $(this).attr('id') + '"]'),
  46. settings = target.data('dropdown-init');
  47. if (settings.is_hover) self.close.call(self, $this);
  48. }
  49. }.bind(this), 150);
  50. })
  51. .on('click.fndtn.dropdown', function (e) {
  52. var parent = $(e.target).closest('[data-dropdown-content]');
  53. if ($(e.target).data('dropdown') || $(e.target).parent().data('dropdown')) {
  54. return;
  55. }
  56. if (!($(e.target).data('revealId')) &&
  57. (parent.length > 0 && ($(e.target).is('[data-dropdown-content]') ||
  58. $.contains(parent.first()[0], e.target)))) {
  59. e.stopPropagation();
  60. return;
  61. }
  62. self.close.call(self, $('[data-dropdown-content]'));
  63. })
  64. .on('opened.fndtn.dropdown', '[data-dropdown-content]', this.settings.opened)
  65. .on('closed.fndtn.dropdown', '[data-dropdown-content]', this.settings.closed);
  66. $(window)
  67. .off('.dropdown')
  68. .on('resize.fndtn.dropdown', self.throttle(function () {
  69. self.resize.call(self);
  70. }, 50)).trigger('resize');
  71. },
  72. close: function (dropdown) {
  73. var self = this;
  74. dropdown.each(function () {
  75. if ($(this).hasClass(self.settings.active_class)) {
  76. $(this)
  77. .css(Foundation.rtl ? 'right':'left', '-99999px')
  78. .removeClass(self.settings.active_class);
  79. $(this).trigger('closed');
  80. }
  81. });
  82. },
  83. open: function (dropdown, target) {
  84. this
  85. .css(dropdown
  86. .addClass(this.settings.active_class), target);
  87. dropdown.trigger('opened');
  88. },
  89. toggle : function (target) {
  90. var dropdown = $('#' + target.data('dropdown'));
  91. if (dropdown.length === 0) {
  92. // No dropdown found, not continuing
  93. return;
  94. }
  95. this.close.call(this, $('[data-dropdown-content]').not(dropdown));
  96. if (dropdown.hasClass(this.settings.active_class)) {
  97. this.close.call(this, dropdown);
  98. } else {
  99. this.close.call(this, $('[data-dropdown-content]'))
  100. this.open.call(this, dropdown, target);
  101. }
  102. },
  103. resize : function () {
  104. var dropdown = $('[data-dropdown-content].open'),
  105. target = $("[data-dropdown='" + dropdown.attr('id') + "']");
  106. if (dropdown.length && target.length) {
  107. this.css(dropdown, target);
  108. }
  109. },
  110. css : function (dropdown, target) {
  111. var offset_parent = dropdown.offsetParent(),
  112. position = target.offset();
  113. position.top -= offset_parent.offset().top;
  114. position.left -= offset_parent.offset().left;
  115. if (this.small()) {
  116. dropdown.css({
  117. position : 'absolute',
  118. width: '95%',
  119. 'max-width': 'none',
  120. top: position.top + target.outerHeight()
  121. });
  122. dropdown.css(Foundation.rtl ? 'right':'left', '2.5%');
  123. } else {
  124. if (!Foundation.rtl && $(window).width() > dropdown.outerWidth() + target.offset().left) {
  125. var left = position.left;
  126. if (dropdown.hasClass('right')) {
  127. dropdown.removeClass('right');
  128. }
  129. } else {
  130. if (!dropdown.hasClass('right')) {
  131. dropdown.addClass('right');
  132. }
  133. var left = position.left - (dropdown.outerWidth() - target.outerWidth());
  134. }
  135. dropdown.attr('style', '').css({
  136. position : 'absolute',
  137. top: position.top + target.outerHeight(),
  138. left: left
  139. });
  140. }
  141. return dropdown;
  142. },
  143. small : function () {
  144. return matchMedia(Foundation.media_queries.small).matches &&
  145. !matchMedia(Foundation.media_queries.medium).matches;
  146. },
  147. off: function () {
  148. $(this.scope).off('.fndtn.dropdown');
  149. $('html, body').off('.fndtn.dropdown');
  150. $(window).off('.fndtn.dropdown');
  151. $('[data-dropdown-content]').off('.fndtn.dropdown');
  152. this.settings.init = false;
  153. },
  154. reflow : function () {}
  155. };
  156. }(jQuery, this, this.document));