select2.jet.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214
  1. (function ($) {
  2. $.fn.select2.amd.require([
  3. 'select2/utils',
  4. 'select2/dropdown',
  5. 'select2/dropdown/attachBody',
  6. 'select2/dropdown/search',
  7. 'select2/dropdown/minimumResultsForSearch',
  8. 'select2/dropdown/closeOnSelect'
  9. ], function (Utils, DropdownAdapter, AttachBody, DropdownSearch, MinimumResultsForSearch, closeOnSelect) {
  10. AttachBody.prototype._positionDropdown = function () {
  11. var $window = $(window);
  12. var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');
  13. var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');
  14. var newDirection = null;
  15. var position = this.$container.position();
  16. var offset = this.$container.offset();
  17. offset.bottom = offset.top + this.$container.outerHeight(false);
  18. var container = {
  19. height: this.$container.outerHeight(false)
  20. };
  21. container.top = offset.top;
  22. container.bottom = offset.top + container.height;
  23. var dropdown = {
  24. height: this.$dropdown.outerHeight(false)
  25. };
  26. var viewport = {
  27. top: $window.scrollTop(),
  28. bottom: $window.scrollTop() + $window.height()
  29. };
  30. var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);
  31. var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);
  32. var css = {
  33. left: offset.left,
  34. top: container.bottom
  35. };
  36. if (!isCurrentlyAbove && !isCurrentlyBelow) {
  37. newDirection = 'below';
  38. }
  39. if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
  40. newDirection = 'above';
  41. } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
  42. newDirection = 'below';
  43. }
  44. if (newDirection == 'above' ||
  45. (isCurrentlyAbove && newDirection !== 'below')) {
  46. css.top = container.top - dropdown.height;
  47. }
  48. if (newDirection != null) {
  49. this.$dropdown
  50. .removeClass('select2-dropdown--below select2-dropdown--above')
  51. .addClass('select2-dropdown--' + newDirection);
  52. this.$container
  53. .removeClass('select2-container--below select2-container--above')
  54. .addClass('select2-container--' + newDirection);
  55. //hack
  56. var $search = this.$dropdown.find('.select2-search');
  57. if (newDirection == 'above' && $search.is(':first-child')) {
  58. $search.detach().appendTo(this.$dropdown);
  59. } else if (newDirection == 'below' && $search.is(':last-child')) {
  60. $search.detach().prependTo(this.$dropdown);
  61. }
  62. }
  63. this.$dropdownContainer.css(css);
  64. };
  65. AttachBody.prototype.render = function (decorated) {
  66. var $container = $('<span></span>');
  67. var $dropdown = decorated.call(this);
  68. $container.append($dropdown);
  69. this.$dropdownContainer = $container;
  70. //hack
  71. if (this.$element.prop('multiple')) {
  72. this.$dropdown.addClass('select2-multiple-dropdown');
  73. } else {
  74. this.$dropdown.removeClass('select2-multiple-dropdown');
  75. }
  76. return $container;
  77. };
  78. DropdownAdapter.prototype.render = function () {
  79. var buttons = '';
  80. if (this.options.get('multiple')) {
  81. buttons =
  82. '<div class="select2-buttons">' +
  83. '<a href="#" class="select2-buttons-button select2-buttons-button-select-all">' +
  84. django.gettext('select all') +
  85. '</a> ' +
  86. '<a href="#" class="select2-buttons-button select2-buttons-button-deselect-all">' +
  87. django.gettext('deselect all') +
  88. '</a>' +
  89. '</div>';
  90. }
  91. var $dropdown = $(
  92. '<span class="select2-dropdown">' +
  93. buttons +
  94. '<span class="select2-results"></span>' +
  95. '</span>'
  96. );
  97. var $element = this.$element;
  98. $dropdown.find('.select2-buttons-button-select-all').on('click', function(e) {
  99. e.preventDefault();
  100. var selected = [];
  101. $element.find('option').each(function() {
  102. selected.push($(this).val());
  103. });
  104. $element.select2('val', selected);
  105. $element.select2('close');
  106. });
  107. $dropdown.find('.select2-buttons-button-deselect-all').on('click', function(e) {
  108. e.preventDefault();
  109. $element.select2('val', '');
  110. $element.select2('close');
  111. });
  112. $dropdown.attr('dir', this.options.get('dir'));
  113. this.$dropdown = $dropdown;
  114. return $dropdown;
  115. };
  116. var dropdownAdapter = Utils.Decorate(
  117. Utils.Decorate(
  118. DropdownAdapter,
  119. DropdownSearch
  120. ),
  121. AttachBody
  122. );
  123. dropdownAdapter = Utils.Decorate(dropdownAdapter, MinimumResultsForSearch);
  124. dropdownAdapter = Utils.Decorate(dropdownAdapter, closeOnSelect);
  125. $(document).on('select:init', 'select', function() {
  126. var $select = $(this);
  127. if ($select.parents('.empty-form').length > 0) {
  128. return;
  129. }
  130. var settings = {
  131. theme: 'jet',
  132. dropdownAdapter: dropdownAdapter
  133. };
  134. if ($select.hasClass('ajax')) {
  135. var contentTypeId = $select.data('content-type-id');
  136. var appLabel = $select.data('app-label');
  137. var model = $select.data('model');
  138. var objectId = $select.data('object-id');
  139. var pageSize = 100;
  140. settings['ajax'] = {
  141. dataType: 'json',
  142. data: function (params) {
  143. return {
  144. content_type: contentTypeId,
  145. app_label: appLabel,
  146. model: model,
  147. q: params.term,
  148. page: params.page,
  149. page_size: pageSize,
  150. object_id: objectId
  151. };
  152. },
  153. processResults: function (data, params) {
  154. if (data.error) {
  155. return {}
  156. }
  157. params.page = params.page || 1;
  158. var more = (params.page * pageSize) < data.total;
  159. return {
  160. results: data.items,
  161. pagination: {
  162. more: more
  163. }
  164. };
  165. }
  166. };
  167. }
  168. $select.select2(settings);
  169. });
  170. $(document).ready(function() {
  171. $('select').trigger('select:init');
  172. });
  173. });
  174. })(jet.jQuery);