Нет описания

dropdown.js 5.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. (function ($) {
  2. /**
  3. * The constructor of the dropdown object
  4. * @param {object} element The menu element.
  5. * @returns {object} The dropdown menu object.
  6. */
  7. function um_dropdownMenu(element) {
  8. var self = {
  9. get: function(){
  10. return self;
  11. },
  12. show: function () {
  13. self.hideAll();
  14. /* add dropdown into the <body> */
  15. self.$menu = self.$element.find('.um-new-dropdown');
  16. if ( !self.$menu.length ) {
  17. self.$menu = $('div.um-new-dropdown[data-element="' + self.data.element + '"]').first();
  18. }
  19. self.$dropdown = self.$menu.clone();
  20. self.$dropdown.on('click', 'li a', self.itemHandler); /* add the handler for menu items */
  21. $(window).on('resize', self.updatePosition); /* update the position on window resize */
  22. $(document.body).append(self.$dropdown);
  23. /* trigger event */
  24. self.$element.trigger('um_new_dropdown_render', {
  25. dropdown_layout: self.$dropdown,
  26. trigger: self.data.trigger,
  27. element: self.data.elemen,
  28. obj: self.$element
  29. });
  30. /* set styles and show */
  31. self.$dropdown.css(self.calculatePosition()).show();
  32. self.$element.addClass('um-new-dropdown-shown').data('um-new-dropdown-show', true);
  33. return self;
  34. },
  35. hide: function () {
  36. if ( self.$dropdown && self.$dropdown.is(':visible') ) {
  37. $(window).off('resize', self.updatePosition);
  38. self.$dropdown.remove();
  39. self.$element.removeClass('um-new-dropdown-shown').data('um-new-dropdown-show', false);
  40. }
  41. return self;
  42. },
  43. hideAll: function () {
  44. self.hide();
  45. $('body > div.um-new-dropdown').remove();
  46. $('.um-new-dropdown-shown').removeClass('um-new-dropdown-shown').data('um-new-dropdown-show', false);
  47. return self;
  48. },
  49. calculatePosition: function () {
  50. var offset = self.$element.offset(),
  51. rect = self.$element.get(0).getBoundingClientRect(),
  52. height = self.$dropdown.innerHeight() || 150,
  53. width = self.data.width || 150,
  54. place = '';
  55. var css = {
  56. position: 'absolute',
  57. width: width + 'px'
  58. };
  59. /* vertical position */
  60. if ( window.innerHeight - rect.bottom > height ) {
  61. css.top = offset.top + rect.height + 'px';
  62. place += 'bottom';
  63. } else {
  64. place += 'top';
  65. css.top = offset.top - height + 'px';
  66. }
  67. /* horisontal position */
  68. if ( offset.left > width || offset.left > window.innerWidth / 2 ) {
  69. css.left = offset.left + rect.width - width + 'px';
  70. place += '-left';
  71. } else {
  72. css.left = offset.left + 'px';
  73. place += '-right';
  74. }
  75. /* border */
  76. switch ( place ) {
  77. case 'bottom-right':
  78. css.borderRadius = '0px 5px 5px 5px';
  79. break;
  80. case 'bottom-left':
  81. css.borderRadius = '5px 0px 5px 5px';
  82. break;
  83. case 'top-right':
  84. css.borderRadius = '5px 5px 5px 0px';
  85. break;
  86. case 'top-left':
  87. css.borderRadius = '5px 5px 0px 5px';
  88. break;
  89. }
  90. return css;
  91. },
  92. updatePosition: function () {
  93. if ( self.$dropdown && self.$dropdown.is(':visible') ) {
  94. self.$dropdown.css(self.calculatePosition());
  95. }
  96. return self;
  97. },
  98. itemHandler: function (e) {
  99. e.stopPropagation();
  100. /* trigger 'click' in the original menu */
  101. var attrClass = $(e.currentTarget).attr('class');
  102. self.$menu.find('li a[class="' + attrClass + '"]').trigger('click');
  103. /* hide dropdown */
  104. self.hide();
  105. },
  106. triggerHandler: function (e) {
  107. e.stopPropagation();
  108. self.$element = $(e.currentTarget);
  109. if ( self.$element.data('um-new-dropdown-show') ) {
  110. self.hide();
  111. } else {
  112. self.show();
  113. }
  114. }
  115. };
  116. self.$menu = $(element);
  117. self.data = self.$menu.data();
  118. self.$element = self.$menu.closest(self.data.element);
  119. if ( !self.$element.length ) {
  120. self.$element = $(self.data.element).first();
  121. }
  122. self.$dropdown = $(document.body).children('div[data-element="' + self.data.element + '"]');
  123. if ( typeof self.data.initted === 'undefined' ) {
  124. self.$menu.data('initted', true);
  125. $(document.body).on(self.data.trigger, self.data.element, self.triggerHandler);
  126. }
  127. if ( typeof um_dropdownMenu.globalHandlersInitted === 'undefined' ) {
  128. um_dropdownMenu.globalHandlersInitted = true;
  129. $(document.body).on('click', function (e) {
  130. if ( !$(e.target).closest('.um-new-dropdown').length ) {
  131. self.hideAll();
  132. }
  133. });
  134. }
  135. return self;
  136. }
  137. /* Add the method um_dropdownMenu() to the jQuery */
  138. $.fn.um_dropdownMenu = function (action) {
  139. if ( typeof action === 'string' && action ) {
  140. return this.map( function (i, menu) {
  141. var obj = um_dropdownMenu( menu );
  142. return typeof obj[action] === 'function' ? obj[action]() : obj[action];
  143. } ).toArray();
  144. } else {
  145. return this.each( function (i, menu) {
  146. um_dropdownMenu( menu );
  147. } );
  148. }
  149. };
  150. })(jQuery);
  151. function um_init_new_dropdown() {
  152. jQuery('.um-new-dropdown').um_dropdownMenu();
  153. }
  154. /* Init all dropdown menus on page load */
  155. jQuery( document ).ready( function($) {
  156. um_init_new_dropdown();
  157. });