core.js 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. define([
  2. 'jquery',
  3. './options',
  4. './utils'
  5. ], function ($, Options, Utils) {
  6. var Select2 = function ($element, options) {
  7. this.$element = $element;
  8. if ($element.attr('id') != null) {
  9. this.id = $element.attr('id');
  10. } else if ($element.attr('name') != null) {
  11. this.id = $element.attr('name') + '-' + Utils.generateChars(2);
  12. } else {
  13. this.id = Utils.generateChars(4);
  14. }
  15. this.id = 'select2-' + this.id;
  16. options = options || {};
  17. options.multiple = options.multiple || $element.prop('multiple');
  18. this.options = new Options(options);
  19. Select2.__super__.constructor.call(this);
  20. // Set up containers and adapters
  21. var DataAdapter = this.options.get('dataAdapter');
  22. this.data = new DataAdapter($element, this.options);
  23. var $container = this.render();
  24. this.$container = $container;
  25. $container.insertAfter(this.$element);
  26. $container.width($element.outerWidth(false));
  27. var SelectionAdapter = this.options.get('selectionAdapter');
  28. this.selection = new SelectionAdapter($element, this.options);
  29. var $selectionContainer = $container.find('.selection');
  30. var $selection = this.selection.render();
  31. $selectionContainer.append($selection);
  32. var DropdownAdapter = this.options.get('dropdownAdapter');
  33. this.dropdown = new DropdownAdapter($element, this.options);
  34. var $dropdownContainer = $container.find('.dropdown-wrapper');
  35. var $dropdown = this.dropdown.render();
  36. $dropdownContainer.append($dropdown);
  37. var ResultsAdapter = this.options.get('resultsAdapter');
  38. this.results = new ResultsAdapter($element, this.options, this.data);
  39. var $resultsContainer = $dropdown.find('.results');
  40. var $results = this.results.render();
  41. $resultsContainer.append($results);
  42. // Bind events
  43. var self = this;
  44. this.data.bind(this, $container);
  45. this.selection.bind(this, $container);
  46. this.dropdown.bind(this, $container);
  47. this.results.bind(this, $container);
  48. this.$element.on('change', function () {
  49. self.data.current(function (data) {
  50. self.trigger('selection:update', {
  51. data: data
  52. });
  53. });
  54. });
  55. this.selection.on('open', function () {
  56. self.open();
  57. });
  58. this.selection.on('close', function () {
  59. self.close();
  60. });
  61. this.selection.on('toggle', function () {
  62. self.toggleDropdown();
  63. });
  64. this.selection.on('results:select', function () {
  65. self.trigger('results:select');
  66. });
  67. this.selection.on('results:previous', function () {
  68. self.trigger('results:previous');
  69. });
  70. this.selection.on('results:next', function () {
  71. self.trigger('results:next');
  72. });
  73. this.selection.on('unselected', function (params) {
  74. self.trigger('unselect', params);
  75. self.close();
  76. });
  77. this.results.on('selected', function (params) {
  78. self.trigger('select', params);
  79. self.close();
  80. });
  81. this.results.on('unselected', function (params) {
  82. self.trigger('unselect', params);
  83. self.close();
  84. });
  85. this.results.on('results:focus', function (params) {
  86. self.trigger('results:focus', params);
  87. });
  88. this.on('open', function () {
  89. $container.addClass('open');
  90. });
  91. this.on('close', function () {
  92. $container.removeClass('open');
  93. });
  94. // Set the initial state
  95. this.data.current(function (initialData) {
  96. self.trigger('selection:update', {
  97. data: initialData
  98. });
  99. });
  100. this.on('query', function (params) {
  101. this.data.query(params, function (data) {
  102. self.trigger('results:all', {
  103. data: data,
  104. query: params
  105. });
  106. });
  107. });
  108. this.trigger('query', {});
  109. // Hide the original select
  110. $element.hide();
  111. $element.attr('tabindex', '-1');
  112. $element.data('select2', this);
  113. };
  114. Utils.Extend(Select2, Utils.Observable);
  115. Select2.prototype.toggleDropdown = function () {
  116. if (this.isOpen()) {
  117. this.close();
  118. } else {
  119. this.open();
  120. }
  121. };
  122. Select2.prototype.open = function () {
  123. if (this.isOpen()) {
  124. return;
  125. }
  126. this.trigger('open');
  127. };
  128. Select2.prototype.close = function () {
  129. if (!this.isOpen()) {
  130. return;
  131. }
  132. this.trigger('close');
  133. };
  134. Select2.prototype.isOpen = function () {
  135. return this.$container.hasClass('open');
  136. };
  137. Select2.prototype.render = function () {
  138. var $container = $(
  139. '<span class="select2 select2-container select2-theme-default">' +
  140. '<span class="selection"></span>' +
  141. '<span class="dropdown-wrapper" aria-hidden="true"></span>' +
  142. '</span>'
  143. );
  144. return $container;
  145. };
  146. return Select2;
  147. });