|
@@ -1319,7 +1319,7 @@ S2.define('select2/selection/base',[
|
|
});
|
|
});
|
|
|
|
|
|
this.$selection.on('blur', function (evt) {
|
|
this.$selection.on('blur', function (evt) {
|
|
- self.trigger('blur', evt);
|
|
|
|
|
|
+ self._handleBlur(evt);
|
|
});
|
|
});
|
|
|
|
|
|
this.$selection.on('keydown', function (evt) {
|
|
this.$selection.on('keydown', function (evt) {
|
|
@@ -1366,6 +1366,24 @@ S2.define('select2/selection/base',[
|
|
});
|
|
});
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ BaseSelection.prototype._handleBlur = function (evt) {
|
|
|
|
+ var self = this;
|
|
|
|
+
|
|
|
|
+ // This needs to be delayed as the actve element is the body when the tab
|
|
|
|
+ // key is pressed, possibly along with others.
|
|
|
|
+ window.setTimeout(function () {
|
|
|
|
+ // Don't trigger `blur` if the focus is still in the selection
|
|
|
|
+ if (
|
|
|
|
+ (document.activeElement == self.$selection[0]) ||
|
|
|
|
+ ($.contains(self.$selection[0], document.activeElement))
|
|
|
|
+ ) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ self.trigger('blur', evt);
|
|
|
|
+ }, 1);
|
|
|
|
+ };
|
|
|
|
+
|
|
BaseSelection.prototype._attachCloseHandler = function (container) {
|
|
BaseSelection.prototype._attachCloseHandler = function (container) {
|
|
var self = this;
|
|
var self = this;
|
|
|
|
|
|
@@ -1475,11 +1493,11 @@ S2.define('select2/selection/single',[
|
|
this.$selection.find('.select2-selection__rendered').empty();
|
|
this.$selection.find('.select2-selection__rendered').empty();
|
|
};
|
|
};
|
|
|
|
|
|
- SingleSelection.prototype.display = function (data) {
|
|
|
|
|
|
+ SingleSelection.prototype.display = function (data, container) {
|
|
var template = this.options.get('templateSelection');
|
|
var template = this.options.get('templateSelection');
|
|
var escapeMarkup = this.options.get('escapeMarkup');
|
|
var escapeMarkup = this.options.get('escapeMarkup');
|
|
|
|
|
|
- return escapeMarkup(template(data));
|
|
|
|
|
|
+ return escapeMarkup(template(data, container));
|
|
};
|
|
};
|
|
|
|
|
|
SingleSelection.prototype.selectionContainer = function () {
|
|
SingleSelection.prototype.selectionContainer = function () {
|
|
@@ -1494,9 +1512,9 @@ S2.define('select2/selection/single',[
|
|
|
|
|
|
var selection = data[0];
|
|
var selection = data[0];
|
|
|
|
|
|
- var formatted = this.display(selection);
|
|
|
|
-
|
|
|
|
var $rendered = this.$selection.find('.select2-selection__rendered');
|
|
var $rendered = this.$selection.find('.select2-selection__rendered');
|
|
|
|
+ var formatted = this.display(selection, $rendered);
|
|
|
|
+
|
|
$rendered.empty().append(formatted);
|
|
$rendered.empty().append(formatted);
|
|
$rendered.prop('title', selection.title || selection.text);
|
|
$rendered.prop('title', selection.title || selection.text);
|
|
};
|
|
};
|
|
@@ -1556,11 +1574,11 @@ S2.define('select2/selection/multiple',[
|
|
this.$selection.find('.select2-selection__rendered').empty();
|
|
this.$selection.find('.select2-selection__rendered').empty();
|
|
};
|
|
};
|
|
|
|
|
|
- MultipleSelection.prototype.display = function (data) {
|
|
|
|
|
|
+ MultipleSelection.prototype.display = function (data, container) {
|
|
var template = this.options.get('templateSelection');
|
|
var template = this.options.get('templateSelection');
|
|
var escapeMarkup = this.options.get('escapeMarkup');
|
|
var escapeMarkup = this.options.get('escapeMarkup');
|
|
|
|
|
|
- return escapeMarkup(template(data));
|
|
|
|
|
|
+ return escapeMarkup(template(data, container));
|
|
};
|
|
};
|
|
|
|
|
|
MultipleSelection.prototype.selectionContainer = function () {
|
|
MultipleSelection.prototype.selectionContainer = function () {
|
|
@@ -1587,8 +1605,8 @@ S2.define('select2/selection/multiple',[
|
|
for (var d = 0; d < data.length; d++) {
|
|
for (var d = 0; d < data.length; d++) {
|
|
var selection = data[d];
|
|
var selection = data[d];
|
|
|
|
|
|
- var formatted = this.display(selection);
|
|
|
|
var $selection = this.selectionContainer();
|
|
var $selection = this.selectionContainer();
|
|
|
|
+ var formatted = this.display(selection, $selection);
|
|
|
|
|
|
$selection.append(formatted);
|
|
$selection.append(formatted);
|
|
$selection.prop('title', selection.title || selection.text);
|
|
$selection.prop('title', selection.title || selection.text);
|
|
@@ -1777,6 +1795,8 @@ S2.define('select2/selection/search',[
|
|
|
|
|
|
var $rendered = decorated.call(this);
|
|
var $rendered = decorated.call(this);
|
|
|
|
|
|
|
|
+ this._transferTabIndex();
|
|
|
|
+
|
|
return $rendered;
|
|
return $rendered;
|
|
};
|
|
};
|
|
|
|
|
|
@@ -1786,32 +1806,34 @@ S2.define('select2/selection/search',[
|
|
decorated.call(this, container, $container);
|
|
decorated.call(this, container, $container);
|
|
|
|
|
|
container.on('open', function () {
|
|
container.on('open', function () {
|
|
- self.$search.attr('tabindex', 0);
|
|
|
|
-
|
|
|
|
- self.$search.focus();
|
|
|
|
|
|
+ self.$search.trigger('focus');
|
|
});
|
|
});
|
|
|
|
|
|
container.on('close', function () {
|
|
container.on('close', function () {
|
|
- self.$search.attr('tabindex', -1);
|
|
|
|
-
|
|
|
|
self.$search.val('');
|
|
self.$search.val('');
|
|
- self.$search.focus();
|
|
|
|
|
|
+ self.$search.trigger('focus');
|
|
});
|
|
});
|
|
|
|
|
|
container.on('enable', function () {
|
|
container.on('enable', function () {
|
|
self.$search.prop('disabled', false);
|
|
self.$search.prop('disabled', false);
|
|
|
|
+
|
|
|
|
+ self._transferTabIndex();
|
|
});
|
|
});
|
|
|
|
|
|
container.on('disable', function () {
|
|
container.on('disable', function () {
|
|
self.$search.prop('disabled', true);
|
|
self.$search.prop('disabled', true);
|
|
});
|
|
});
|
|
|
|
|
|
|
|
+ container.on('focus', function (evt) {
|
|
|
|
+ self.$search.trigger('focus');
|
|
|
|
+ });
|
|
|
|
+
|
|
this.$selection.on('focusin', '.select2-search--inline', function (evt) {
|
|
this.$selection.on('focusin', '.select2-search--inline', function (evt) {
|
|
self.trigger('focus', evt);
|
|
self.trigger('focus', evt);
|
|
});
|
|
});
|
|
|
|
|
|
this.$selection.on('focusout', '.select2-search--inline', function (evt) {
|
|
this.$selection.on('focusout', '.select2-search--inline', function (evt) {
|
|
- self.trigger('blur', evt);
|
|
|
|
|
|
+ self._handleBlur(evt);
|
|
});
|
|
});
|
|
|
|
|
|
this.$selection.on('keydown', '.select2-search--inline', function (evt) {
|
|
this.$selection.on('keydown', '.select2-search--inline', function (evt) {
|
|
@@ -1847,10 +1869,34 @@ S2.define('select2/selection/search',[
|
|
|
|
|
|
this.$selection.on('keyup.search input', '.select2-search--inline',
|
|
this.$selection.on('keyup.search input', '.select2-search--inline',
|
|
function (evt) {
|
|
function (evt) {
|
|
|
|
+ var key = evt.which;
|
|
|
|
+
|
|
|
|
+ // We can freely ignore events from modifier keys
|
|
|
|
+ if (key == KEYS.SHIFT || key == KEYS.CTRL || key == KEYS.ALT) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // Tabbing will be handled during the `keydown` phase
|
|
|
|
+ if (key == KEYS.TAB) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
self.handleSearch(evt);
|
|
self.handleSearch(evt);
|
|
});
|
|
});
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
+ * This method will transfer the tabindex attribute from the rendered
|
|
|
|
+ * selection to the search box. This allows for the search box to be used as
|
|
|
|
+ * the primary focus instead of the selection container.
|
|
|
|
+ *
|
|
|
|
+ * @private
|
|
|
|
+ */
|
|
|
|
+ Search.prototype._transferTabIndex = function (decorated) {
|
|
|
|
+ this.$search.attr('tabindex', this.$selection.attr('tabindex'));
|
|
|
|
+ this.$selection.attr('tabindex', '-1');
|
|
|
|
+ };
|
|
|
|
+
|
|
Search.prototype.createPlaceholder = function (decorated, placeholder) {
|
|
Search.prototype.createPlaceholder = function (decorated, placeholder) {
|
|
this.$search.attr('placeholder', placeholder.text);
|
|
this.$search.attr('placeholder', placeholder.text);
|
|
};
|
|
};
|
|
@@ -3259,7 +3305,7 @@ S2.define('select2/data/ajax',[
|
|
this.processResults = this.ajaxOptions.processResults;
|
|
this.processResults = this.ajaxOptions.processResults;
|
|
}
|
|
}
|
|
|
|
|
|
- ArrayAdapter.__super__.constructor.call(this, $element, options);
|
|
|
|
|
|
+ AjaxAdapter.__super__.constructor.call(this, $element, options);
|
|
}
|
|
}
|
|
|
|
|
|
Utils.Extend(AjaxAdapter, ArrayAdapter);
|
|
Utils.Extend(AjaxAdapter, ArrayAdapter);
|
|
@@ -4868,8 +4914,8 @@ S2.define('select2/core',[
|
|
|
|
|
|
// Hide the original select
|
|
// Hide the original select
|
|
$element.addClass('select2-hidden-accessible');
|
|
$element.addClass('select2-hidden-accessible');
|
|
- $element.attr('aria-hidden', 'true');
|
|
|
|
-
|
|
|
|
|
|
+ $element.attr('aria-hidden', 'true');
|
|
|
|
+
|
|
// Synchronize any monitored attributes
|
|
// Synchronize any monitored attributes
|
|
this._syncAttributes();
|
|
this._syncAttributes();
|
|
|
|
|
|
@@ -5004,12 +5050,16 @@ S2.define('select2/core',[
|
|
|
|
|
|
Select2.prototype._registerSelectionEvents = function () {
|
|
Select2.prototype._registerSelectionEvents = function () {
|
|
var self = this;
|
|
var self = this;
|
|
- var nonRelayEvents = ['toggle'];
|
|
|
|
|
|
+ var nonRelayEvents = ['toggle', 'focus'];
|
|
|
|
|
|
this.selection.on('toggle', function () {
|
|
this.selection.on('toggle', function () {
|
|
self.toggleDropdown();
|
|
self.toggleDropdown();
|
|
});
|
|
});
|
|
|
|
|
|
|
|
+ this.selection.on('focus', function (params) {
|
|
|
|
+ self.focus(params);
|
|
|
|
+ });
|
|
|
|
+
|
|
this.selection.on('*', function (name, params) {
|
|
this.selection.on('*', function (name, params) {
|
|
if ($.inArray(name, nonRelayEvents) !== -1) {
|
|
if ($.inArray(name, nonRelayEvents) !== -1) {
|
|
return;
|
|
return;
|
|
@@ -5054,10 +5104,6 @@ S2.define('select2/core',[
|
|
self.$container.addClass('select2-container--disabled');
|
|
self.$container.addClass('select2-container--disabled');
|
|
});
|
|
});
|
|
|
|
|
|
- this.on('focus', function () {
|
|
|
|
- self.$container.addClass('select2-container--focus');
|
|
|
|
- });
|
|
|
|
-
|
|
|
|
this.on('blur', function () {
|
|
this.on('blur', function () {
|
|
self.$container.removeClass('select2-container--focus');
|
|
self.$container.removeClass('select2-container--focus');
|
|
});
|
|
});
|
|
@@ -5201,6 +5247,20 @@ S2.define('select2/core',[
|
|
return this.$container.hasClass('select2-container--open');
|
|
return this.$container.hasClass('select2-container--open');
|
|
};
|
|
};
|
|
|
|
|
|
|
|
+ Select2.prototype.hasFocus = function () {
|
|
|
|
+ return this.$container.hasClass('select2-container--focus');
|
|
|
|
+ };
|
|
|
|
+
|
|
|
|
+ Select2.prototype.focus = function (data) {
|
|
|
|
+ // No need to re-trigger focus events if we are already focused
|
|
|
|
+ if (this.hasFocus()) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ this.$container.addClass('select2-container--focus');
|
|
|
|
+ this.trigger('focus');
|
|
|
|
+ };
|
|
|
|
+
|
|
Select2.prototype.enable = function (args) {
|
|
Select2.prototype.enable = function (args) {
|
|
if (this.options.get('debug') && window.console && console.warn) {
|
|
if (this.options.get('debug') && window.console && console.warn) {
|
|
console.warn(
|
|
console.warn(
|
|
@@ -5281,7 +5341,7 @@ S2.define('select2/core',[
|
|
this.$element.attr('tabindex', this.$element.data('old-tabindex'));
|
|
this.$element.attr('tabindex', this.$element.data('old-tabindex'));
|
|
|
|
|
|
this.$element.removeClass('select2-hidden-accessible');
|
|
this.$element.removeClass('select2-hidden-accessible');
|
|
- this.$element.attr('aria-hidden', 'false');
|
|
|
|
|
|
+ this.$element.attr('aria-hidden', 'false');
|
|
this.$element.removeData('select2');
|
|
this.$element.removeData('select2');
|
|
|
|
|
|
this.dataAdapter.destroy();
|
|
this.dataAdapter.destroy();
|
|
@@ -5385,7 +5445,7 @@ S2.define('select2/compat/containerCss',[
|
|
containerCssAdapter = containerCssAdapter || _containerAdapter;
|
|
containerCssAdapter = containerCssAdapter || _containerAdapter;
|
|
|
|
|
|
if (containerCssClass.indexOf(':all:') !== -1) {
|
|
if (containerCssClass.indexOf(':all:') !== -1) {
|
|
- containerCssClass = containerCssClass.replace(':all', '');
|
|
|
|
|
|
+ containerCssClass = containerCssClass.replace(':all:', '');
|
|
|
|
|
|
var _cssAdapter = containerCssAdapter;
|
|
var _cssAdapter = containerCssAdapter;
|
|
|
|
|
|
@@ -5442,7 +5502,7 @@ S2.define('select2/compat/dropdownCss',[
|
|
dropdownCssAdapter = dropdownCssAdapter || _dropdownAdapter;
|
|
dropdownCssAdapter = dropdownCssAdapter || _dropdownAdapter;
|
|
|
|
|
|
if (dropdownCssClass.indexOf(':all:') !== -1) {
|
|
if (dropdownCssClass.indexOf(':all:') !== -1) {
|
|
- dropdownCssClass = dropdownCssClass.replace(':all', '');
|
|
|
|
|
|
+ dropdownCssClass = dropdownCssClass.replace(':all:', '');
|
|
|
|
|
|
var _cssAdapter = dropdownCssAdapter;
|
|
var _cssAdapter = dropdownCssAdapter;
|
|
|
|
|