123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- define([
- 'jquery',
- './options',
- './utils',
- './keys'
- ], function ($, Options, Utils, KEYS) {
- var Select2 = function ($element, options) {
- this.$element = $element;
- this.id = this._generateId($element);
- options = options || {};
- this.options = new Options(options, $element);
- Select2.__super__.constructor.call(this);
- // Set up containers and adapters
- var DataAdapter = this.options.get('dataAdapter');
- this.data = new DataAdapter($element, this.options);
- var $container = this.render();
- this._placeContainer($container);
- var SelectionAdapter = this.options.get('selectionAdapter');
- this.selection = new SelectionAdapter($element, this.options);
- var $selection = this.selection.render();
- this._placeSelection($selection);
- var DropdownAdapter = this.options.get('dropdownAdapter');
- this.dropdown = new DropdownAdapter($element, this.options);
- var $dropdown = this.dropdown.render();
- this._placeDropdown($dropdown);
- var ResultsAdapter = this.options.get('resultsAdapter');
- this.results = new ResultsAdapter($element, this.options, this.data);
- var $results = this.results.render();
- this._placeResults($results);
- // Bind events
- var self = this;
- // Bind the container to all of the adapters
- this._bindAdapters();
- // Register any DOM event handlers
- this._registerDomEvents();
- // Register any internal event handlers
- this._registerSelectionEvents();
- this._registerDropdownEvents();
- this._registerResultsEvents();
- this._registerEvents();
- // Set the initial state
- this.data.current(function (initialData) {
- self.trigger('selection:update', {
- data: initialData
- });
- });
- // Hide the original select
- $element.hide();
- $element.attr('tabindex', '-1');
- $element.data('select2', this);
- };
- Utils.Extend(Select2, Utils.Observable);
- Select2.prototype._generateId = function ($element) {
- var id = '';
- if ($element.attr('id') != null) {
- id = $element.attr('id');
- } else if ($element.attr('name') != null) {
- id = $element.attr('name') + '-' + Utils.generateChars(2);
- } else {
- id = Utils.generateChars(4);
- }
- id = 'select2-' + id;
- return id;
- };
- Select2.prototype._placeContainer = function ($container) {
- $container.insertAfter(this.$element);
- $container.width(this.$element.outerWidth(false));
- };
- Select2.prototype._placeSelection = function ($selection) {
- var $selectionContainer = this.$container.find('.selection');
- $selectionContainer.append($selection);
- };
- Select2.prototype._placeDropdown = function ($dropdown) {
- this.$dropdown = $dropdown;
- var $dropdownContainer = this.$container.find('.dropdown-wrapper');
- $dropdownContainer.append($dropdown);
- };
- Select2.prototype._placeResults = function ($results) {
- var $resultsContainer = this.$dropdown.find('.results');
- $resultsContainer.append($results);
- };
- Select2.prototype._bindAdapters = function () {
- this.data.bind(this, this.$container);
- this.selection.bind(this, this.$container);
- this.dropdown.bind(this, this.$container);
- this.results.bind(this, this.$container);
- };
- Select2.prototype._registerDomEvents = function () {
- var self = this;
- this.$element.on('change', function () {
- self.data.current(function (data) {
- self.trigger('selection:update', {
- data: data
- });
- });
- });
- };
- Select2.prototype._registerSelectionEvents = function () {
- var self = this;
- this.selection.on('open', function () {
- self.open();
- });
- this.selection.on('close', function () {
- self.close();
- });
- this.selection.on('toggle', function () {
- self.toggleDropdown();
- });
- this.selection.on('results:select', function () {
- self.trigger('results:select');
- });
- this.selection.on('results:previous', function () {
- self.trigger('results:previous');
- });
- this.selection.on('results:next', function () {
- self.trigger('results:next');
- });
- this.selection.on('unselected', function (params) {
- self.trigger('unselect', params);
- self.close();
- });
- this.selection.on('keypress', function (e) {
- self.trigger('keypress', e);
- });
- };
- Select2.prototype._registerDropdownEvents = function () {
- var self = this;
- this.dropdown.on('query', function (params) {
- self.trigger('query', params);
- });
- this.dropdown.on('keypress', function (e) {
- self.trigger('keypress', e);
- });
- };
- Select2.prototype._registerResultsEvents = function () {
- var self = this;
- this.results.on('selected', function (params) {
- self.trigger('select', params);
- self.close();
- });
- this.results.on('unselected', function (params) {
- self.trigger('unselect', params);
- self.close();
- });
- this.results.on('results:focus', function (params) {
- self.trigger('results:focus', params);
- });
- };
- Select2.prototype._registerEvents = function () {
- var self = this;
- this.on('open', function () {
- self.$container.addClass('open');
- });
- this.on('close', function () {
- self.$container.removeClass('open');
- });
- this.on('query', function (params) {
- this.data.query(params, function (data) {
- self.trigger('results:all', {
- data: data,
- query: params
- });
- });
- });
- this.on('keypress', function (evt) {
- var key = evt.which;
- if (self.isOpen()) {
- if (key === KEYS.ENTER) {
- self.trigger('results:select');
- evt.preventDefault();
- } else if (key === KEYS.UP) {
- self.trigger('results:previous');
- evt.preventDefault();
- } else if (key === KEYS.DOWN) {
- self.trigger('results:next');
- evt.preventDefault();
- } else if (key === KEYS.ESC || key === KEYS.TAB) {
- self.close();
- evt.preventDefault();
- }
- } else {
- if (key === KEYS.ENTER || key === KEYS.SPACE) {
- self.open();
- evt.preventDefault();
- }
- }
- });
- };
- Select2.prototype.toggleDropdown = function () {
- if (this.isOpen()) {
- this.close();
- } else {
- this.open();
- }
- };
- Select2.prototype.open = function () {
- if (this.isOpen()) {
- return;
- }
- this.trigger('query', {});
- this.trigger('open');
- };
- Select2.prototype.close = function () {
- if (!this.isOpen()) {
- return;
- }
- this.trigger('close');
- };
- Select2.prototype.isOpen = function () {
- return this.$container.hasClass('open');
- };
- Select2.prototype.render = function () {
- var $container = $(
- '<span class="select2 select2-container select2-theme-default">' +
- '<span class="selection"></span>' +
- '<span class="dropdown-wrapper" aria-hidden="true"></span>' +
- '</span>'
- );
- this.$container = $container;
- $container.data('element', this.$element);
- return $container;
- };
- return Select2;
- });
|