Add a module for attaching the dropdown to the body
In Select2 3.x, the dropdown is attached to the body element and it is floated above all other elements. In Select2 4.x, the dropdown is attached directly to the Select2 container, which allows us to skip any special placing logic. This happens to be how Chosen currently does it, and it prevents us from having the dropdown display up, as well as a few other strange issues that can't be prevented. This new module will most likely become the default, as it matches the functionality of Select2 3.x and has quite a few advantages. The other positioning code will need to be broken out into a separate module in the future.
This commit is contained in:
parent
31c09315c8
commit
6a0c002f94
87
dist/js/select2.amd.full.js
vendored
87
dist/js/select2.amd.full.js
vendored
@ -230,8 +230,8 @@ define('select2/results',[
|
||||
this.$results.append($options);
|
||||
};
|
||||
|
||||
Results.prototype.position = function ($results, $container) {
|
||||
var $resultsContainer = $container.find('.select2-results');
|
||||
Results.prototype.position = function ($results, $dropdown) {
|
||||
var $resultsContainer = $dropdown.find('.select2-results');
|
||||
$resultsContainer.append($results);
|
||||
};
|
||||
|
||||
@ -2812,6 +2812,79 @@ define('select2/dropdown/infiniteScroll',[
|
||||
return InfiniteScroll;
|
||||
});
|
||||
|
||||
define('select2/dropdown/attachBody',[
|
||||
|
||||
], function () {
|
||||
function AttachBody (decorated, $element, options) {
|
||||
decorated.call(this, $element, options);
|
||||
}
|
||||
|
||||
AttachBody.prototype.bind = function (decorated, container, $container) {
|
||||
var self = this;
|
||||
|
||||
decorated.call(this, container, $container);
|
||||
|
||||
container.on('open', function () {
|
||||
self._showDropdown();
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
self._hideDropdown();
|
||||
});
|
||||
|
||||
this.$dropdownContainer.on('mousedown', function (evt) {
|
||||
evt.stopPropagation();
|
||||
});
|
||||
};
|
||||
|
||||
AttachBody.prototype.position = function (decorated, $dropdown, $container) {
|
||||
// Clone all of the container classes
|
||||
$dropdown.attr('class', $container.attr('class'));
|
||||
|
||||
$dropdown.removeClass('select2');
|
||||
$dropdown.addClass('select2-container--open');
|
||||
|
||||
$dropdown.css({
|
||||
position: 'absolute'
|
||||
});
|
||||
|
||||
$dropdown.width($container.outerWidth(false));
|
||||
|
||||
this.$container = $container;
|
||||
};
|
||||
|
||||
AttachBody.prototype.render = function (decorated) {
|
||||
var $container = $('<span></span>');
|
||||
|
||||
var $dropdown = decorated.call(this);
|
||||
$container.append($dropdown);
|
||||
|
||||
this.$dropdownContainer = $container;
|
||||
|
||||
return $container;
|
||||
};
|
||||
|
||||
AttachBody.prototype._hideDropdown = function (decorated) {
|
||||
this.$dropdownContainer.detach();
|
||||
};
|
||||
|
||||
AttachBody.prototype._positionDropdown = function () {
|
||||
var css = this.$container.offset();
|
||||
|
||||
css.top += this.$container.outerHeight(true);
|
||||
|
||||
this.$dropdownContainer.css(css);
|
||||
};
|
||||
|
||||
AttachBody.prototype._showDropdown = function (decorated) {
|
||||
this.$dropdownContainer.appendTo(document.body);
|
||||
|
||||
this._positionDropdown();
|
||||
};
|
||||
|
||||
return AttachBody;
|
||||
});
|
||||
|
||||
define('select2/i18n/en',[],function () {
|
||||
return {
|
||||
errorLoading: function () {
|
||||
@ -2884,6 +2957,7 @@ define('select2/defaults',[
|
||||
'./dropdown/search',
|
||||
'./dropdown/hidePlaceholder',
|
||||
'./dropdown/infiniteScroll',
|
||||
'./dropdown/attachBody',
|
||||
|
||||
'./i18n/en'
|
||||
], function ($, ResultsList,
|
||||
@ -2892,6 +2966,7 @@ define('select2/defaults',[
|
||||
Utils, Translation, DIACRITICS,
|
||||
SelectData, ArrayData, AjaxData, Tags, MinimumInputLength,
|
||||
Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,
|
||||
AttachBody,
|
||||
EnglishTranslation) {
|
||||
function Defaults () {
|
||||
this.reset();
|
||||
@ -2948,6 +3023,11 @@ define('select2/defaults',[
|
||||
|
||||
options.dropdownAdapter = SearchableDropdown;
|
||||
}
|
||||
|
||||
options.dropdownAdapter = Utils.Decorate(
|
||||
options.dropdownAdapter,
|
||||
AttachBody
|
||||
);
|
||||
}
|
||||
|
||||
if (options.selectionAdapter == null) {
|
||||
@ -3162,10 +3242,9 @@ define('select2/core',[
|
||||
|
||||
var ResultsAdapter = this.options.get('resultsAdapter');
|
||||
this.results = new ResultsAdapter($element, this.options, this.data);
|
||||
|
||||
this.$results = this.results.render();
|
||||
|
||||
this.results.position(this.$results, $container);
|
||||
this.results.position(this.$results, this.$dropdown);
|
||||
|
||||
// Bind events
|
||||
|
||||
|
87
dist/js/select2.amd.js
vendored
87
dist/js/select2.amd.js
vendored
@ -230,8 +230,8 @@ define('select2/results',[
|
||||
this.$results.append($options);
|
||||
};
|
||||
|
||||
Results.prototype.position = function ($results, $container) {
|
||||
var $resultsContainer = $container.find('.select2-results');
|
||||
Results.prototype.position = function ($results, $dropdown) {
|
||||
var $resultsContainer = $dropdown.find('.select2-results');
|
||||
$resultsContainer.append($results);
|
||||
};
|
||||
|
||||
@ -2812,6 +2812,79 @@ define('select2/dropdown/infiniteScroll',[
|
||||
return InfiniteScroll;
|
||||
});
|
||||
|
||||
define('select2/dropdown/attachBody',[
|
||||
|
||||
], function () {
|
||||
function AttachBody (decorated, $element, options) {
|
||||
decorated.call(this, $element, options);
|
||||
}
|
||||
|
||||
AttachBody.prototype.bind = function (decorated, container, $container) {
|
||||
var self = this;
|
||||
|
||||
decorated.call(this, container, $container);
|
||||
|
||||
container.on('open', function () {
|
||||
self._showDropdown();
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
self._hideDropdown();
|
||||
});
|
||||
|
||||
this.$dropdownContainer.on('mousedown', function (evt) {
|
||||
evt.stopPropagation();
|
||||
});
|
||||
};
|
||||
|
||||
AttachBody.prototype.position = function (decorated, $dropdown, $container) {
|
||||
// Clone all of the container classes
|
||||
$dropdown.attr('class', $container.attr('class'));
|
||||
|
||||
$dropdown.removeClass('select2');
|
||||
$dropdown.addClass('select2-container--open');
|
||||
|
||||
$dropdown.css({
|
||||
position: 'absolute'
|
||||
});
|
||||
|
||||
$dropdown.width($container.outerWidth(false));
|
||||
|
||||
this.$container = $container;
|
||||
};
|
||||
|
||||
AttachBody.prototype.render = function (decorated) {
|
||||
var $container = $('<span></span>');
|
||||
|
||||
var $dropdown = decorated.call(this);
|
||||
$container.append($dropdown);
|
||||
|
||||
this.$dropdownContainer = $container;
|
||||
|
||||
return $container;
|
||||
};
|
||||
|
||||
AttachBody.prototype._hideDropdown = function (decorated) {
|
||||
this.$dropdownContainer.detach();
|
||||
};
|
||||
|
||||
AttachBody.prototype._positionDropdown = function () {
|
||||
var css = this.$container.offset();
|
||||
|
||||
css.top += this.$container.outerHeight(true);
|
||||
|
||||
this.$dropdownContainer.css(css);
|
||||
};
|
||||
|
||||
AttachBody.prototype._showDropdown = function (decorated) {
|
||||
this.$dropdownContainer.appendTo(document.body);
|
||||
|
||||
this._positionDropdown();
|
||||
};
|
||||
|
||||
return AttachBody;
|
||||
});
|
||||
|
||||
define('select2/i18n/en',[],function () {
|
||||
return {
|
||||
errorLoading: function () {
|
||||
@ -2884,6 +2957,7 @@ define('select2/defaults',[
|
||||
'./dropdown/search',
|
||||
'./dropdown/hidePlaceholder',
|
||||
'./dropdown/infiniteScroll',
|
||||
'./dropdown/attachBody',
|
||||
|
||||
'./i18n/en'
|
||||
], function ($, ResultsList,
|
||||
@ -2892,6 +2966,7 @@ define('select2/defaults',[
|
||||
Utils, Translation, DIACRITICS,
|
||||
SelectData, ArrayData, AjaxData, Tags, MinimumInputLength,
|
||||
Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,
|
||||
AttachBody,
|
||||
EnglishTranslation) {
|
||||
function Defaults () {
|
||||
this.reset();
|
||||
@ -2948,6 +3023,11 @@ define('select2/defaults',[
|
||||
|
||||
options.dropdownAdapter = SearchableDropdown;
|
||||
}
|
||||
|
||||
options.dropdownAdapter = Utils.Decorate(
|
||||
options.dropdownAdapter,
|
||||
AttachBody
|
||||
);
|
||||
}
|
||||
|
||||
if (options.selectionAdapter == null) {
|
||||
@ -3162,10 +3242,9 @@ define('select2/core',[
|
||||
|
||||
var ResultsAdapter = this.options.get('resultsAdapter');
|
||||
this.results = new ResultsAdapter($element, this.options, this.data);
|
||||
|
||||
this.$results = this.results.render();
|
||||
|
||||
this.results.position(this.$results, $container);
|
||||
this.results.position(this.$results, this.$dropdown);
|
||||
|
||||
// Bind events
|
||||
|
||||
|
87
dist/js/select2.full.js
vendored
87
dist/js/select2.full.js
vendored
@ -9765,8 +9765,8 @@ define('select2/results',[
|
||||
this.$results.append($options);
|
||||
};
|
||||
|
||||
Results.prototype.position = function ($results, $container) {
|
||||
var $resultsContainer = $container.find('.select2-results');
|
||||
Results.prototype.position = function ($results, $dropdown) {
|
||||
var $resultsContainer = $dropdown.find('.select2-results');
|
||||
$resultsContainer.append($results);
|
||||
};
|
||||
|
||||
@ -12347,6 +12347,79 @@ define('select2/dropdown/infiniteScroll',[
|
||||
return InfiniteScroll;
|
||||
});
|
||||
|
||||
define('select2/dropdown/attachBody',[
|
||||
|
||||
], function () {
|
||||
function AttachBody (decorated, $element, options) {
|
||||
decorated.call(this, $element, options);
|
||||
}
|
||||
|
||||
AttachBody.prototype.bind = function (decorated, container, $container) {
|
||||
var self = this;
|
||||
|
||||
decorated.call(this, container, $container);
|
||||
|
||||
container.on('open', function () {
|
||||
self._showDropdown();
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
self._hideDropdown();
|
||||
});
|
||||
|
||||
this.$dropdownContainer.on('mousedown', function (evt) {
|
||||
evt.stopPropagation();
|
||||
});
|
||||
};
|
||||
|
||||
AttachBody.prototype.position = function (decorated, $dropdown, $container) {
|
||||
// Clone all of the container classes
|
||||
$dropdown.attr('class', $container.attr('class'));
|
||||
|
||||
$dropdown.removeClass('select2');
|
||||
$dropdown.addClass('select2-container--open');
|
||||
|
||||
$dropdown.css({
|
||||
position: 'absolute'
|
||||
});
|
||||
|
||||
$dropdown.width($container.outerWidth(false));
|
||||
|
||||
this.$container = $container;
|
||||
};
|
||||
|
||||
AttachBody.prototype.render = function (decorated) {
|
||||
var $container = $('<span></span>');
|
||||
|
||||
var $dropdown = decorated.call(this);
|
||||
$container.append($dropdown);
|
||||
|
||||
this.$dropdownContainer = $container;
|
||||
|
||||
return $container;
|
||||
};
|
||||
|
||||
AttachBody.prototype._hideDropdown = function (decorated) {
|
||||
this.$dropdownContainer.detach();
|
||||
};
|
||||
|
||||
AttachBody.prototype._positionDropdown = function () {
|
||||
var css = this.$container.offset();
|
||||
|
||||
css.top += this.$container.outerHeight(true);
|
||||
|
||||
this.$dropdownContainer.css(css);
|
||||
};
|
||||
|
||||
AttachBody.prototype._showDropdown = function (decorated) {
|
||||
this.$dropdownContainer.appendTo(document.body);
|
||||
|
||||
this._positionDropdown();
|
||||
};
|
||||
|
||||
return AttachBody;
|
||||
});
|
||||
|
||||
define('select2/i18n/en',[],function () {
|
||||
return {
|
||||
errorLoading: function () {
|
||||
@ -12419,6 +12492,7 @@ define('select2/defaults',[
|
||||
'./dropdown/search',
|
||||
'./dropdown/hidePlaceholder',
|
||||
'./dropdown/infiniteScroll',
|
||||
'./dropdown/attachBody',
|
||||
|
||||
'./i18n/en'
|
||||
], function ($, ResultsList,
|
||||
@ -12427,6 +12501,7 @@ define('select2/defaults',[
|
||||
Utils, Translation, DIACRITICS,
|
||||
SelectData, ArrayData, AjaxData, Tags, MinimumInputLength,
|
||||
Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,
|
||||
AttachBody,
|
||||
EnglishTranslation) {
|
||||
function Defaults () {
|
||||
this.reset();
|
||||
@ -12483,6 +12558,11 @@ define('select2/defaults',[
|
||||
|
||||
options.dropdownAdapter = SearchableDropdown;
|
||||
}
|
||||
|
||||
options.dropdownAdapter = Utils.Decorate(
|
||||
options.dropdownAdapter,
|
||||
AttachBody
|
||||
);
|
||||
}
|
||||
|
||||
if (options.selectionAdapter == null) {
|
||||
@ -12697,10 +12777,9 @@ define('select2/core',[
|
||||
|
||||
var ResultsAdapter = this.options.get('resultsAdapter');
|
||||
this.results = new ResultsAdapter($element, this.options, this.data);
|
||||
|
||||
this.$results = this.results.render();
|
||||
|
||||
this.results.position(this.$results, $container);
|
||||
this.results.position(this.$results, this.$dropdown);
|
||||
|
||||
// Bind events
|
||||
|
||||
|
2
dist/js/select2.full.min.js
vendored
2
dist/js/select2.full.min.js
vendored
File diff suppressed because one or more lines are too long
87
dist/js/select2.js
vendored
87
dist/js/select2.js
vendored
@ -658,8 +658,8 @@ define('select2/results',[
|
||||
this.$results.append($options);
|
||||
};
|
||||
|
||||
Results.prototype.position = function ($results, $container) {
|
||||
var $resultsContainer = $container.find('.select2-results');
|
||||
Results.prototype.position = function ($results, $dropdown) {
|
||||
var $resultsContainer = $dropdown.find('.select2-results');
|
||||
$resultsContainer.append($results);
|
||||
};
|
||||
|
||||
@ -3240,6 +3240,79 @@ define('select2/dropdown/infiniteScroll',[
|
||||
return InfiniteScroll;
|
||||
});
|
||||
|
||||
define('select2/dropdown/attachBody',[
|
||||
|
||||
], function () {
|
||||
function AttachBody (decorated, $element, options) {
|
||||
decorated.call(this, $element, options);
|
||||
}
|
||||
|
||||
AttachBody.prototype.bind = function (decorated, container, $container) {
|
||||
var self = this;
|
||||
|
||||
decorated.call(this, container, $container);
|
||||
|
||||
container.on('open', function () {
|
||||
self._showDropdown();
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
self._hideDropdown();
|
||||
});
|
||||
|
||||
this.$dropdownContainer.on('mousedown', function (evt) {
|
||||
evt.stopPropagation();
|
||||
});
|
||||
};
|
||||
|
||||
AttachBody.prototype.position = function (decorated, $dropdown, $container) {
|
||||
// Clone all of the container classes
|
||||
$dropdown.attr('class', $container.attr('class'));
|
||||
|
||||
$dropdown.removeClass('select2');
|
||||
$dropdown.addClass('select2-container--open');
|
||||
|
||||
$dropdown.css({
|
||||
position: 'absolute'
|
||||
});
|
||||
|
||||
$dropdown.width($container.outerWidth(false));
|
||||
|
||||
this.$container = $container;
|
||||
};
|
||||
|
||||
AttachBody.prototype.render = function (decorated) {
|
||||
var $container = $('<span></span>');
|
||||
|
||||
var $dropdown = decorated.call(this);
|
||||
$container.append($dropdown);
|
||||
|
||||
this.$dropdownContainer = $container;
|
||||
|
||||
return $container;
|
||||
};
|
||||
|
||||
AttachBody.prototype._hideDropdown = function (decorated) {
|
||||
this.$dropdownContainer.detach();
|
||||
};
|
||||
|
||||
AttachBody.prototype._positionDropdown = function () {
|
||||
var css = this.$container.offset();
|
||||
|
||||
css.top += this.$container.outerHeight(true);
|
||||
|
||||
this.$dropdownContainer.css(css);
|
||||
};
|
||||
|
||||
AttachBody.prototype._showDropdown = function (decorated) {
|
||||
this.$dropdownContainer.appendTo(document.body);
|
||||
|
||||
this._positionDropdown();
|
||||
};
|
||||
|
||||
return AttachBody;
|
||||
});
|
||||
|
||||
define('select2/i18n/en',[],function () {
|
||||
return {
|
||||
errorLoading: function () {
|
||||
@ -3312,6 +3385,7 @@ define('select2/defaults',[
|
||||
'./dropdown/search',
|
||||
'./dropdown/hidePlaceholder',
|
||||
'./dropdown/infiniteScroll',
|
||||
'./dropdown/attachBody',
|
||||
|
||||
'./i18n/en'
|
||||
], function ($, ResultsList,
|
||||
@ -3320,6 +3394,7 @@ define('select2/defaults',[
|
||||
Utils, Translation, DIACRITICS,
|
||||
SelectData, ArrayData, AjaxData, Tags, MinimumInputLength,
|
||||
Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,
|
||||
AttachBody,
|
||||
EnglishTranslation) {
|
||||
function Defaults () {
|
||||
this.reset();
|
||||
@ -3376,6 +3451,11 @@ define('select2/defaults',[
|
||||
|
||||
options.dropdownAdapter = SearchableDropdown;
|
||||
}
|
||||
|
||||
options.dropdownAdapter = Utils.Decorate(
|
||||
options.dropdownAdapter,
|
||||
AttachBody
|
||||
);
|
||||
}
|
||||
|
||||
if (options.selectionAdapter == null) {
|
||||
@ -3590,10 +3670,9 @@ define('select2/core',[
|
||||
|
||||
var ResultsAdapter = this.options.get('resultsAdapter');
|
||||
this.results = new ResultsAdapter($element, this.options, this.data);
|
||||
|
||||
this.$results = this.results.render();
|
||||
|
||||
this.results.position(this.$results, $container);
|
||||
this.results.position(this.$results, this.$dropdown);
|
||||
|
||||
// Bind events
|
||||
|
||||
|
2
dist/js/select2.min.js
vendored
2
dist/js/select2.min.js
vendored
File diff suppressed because one or more lines are too long
2
src/js/select2/core.js
vendored
2
src/js/select2/core.js
vendored
@ -44,7 +44,7 @@ define([
|
||||
this.results = new ResultsAdapter($element, this.options, this.data);
|
||||
this.$results = this.results.render();
|
||||
|
||||
this.results.position(this.$results, $container);
|
||||
this.results.position(this.$results, this.$dropdown);
|
||||
|
||||
// Bind events
|
||||
|
||||
|
7
src/js/select2/defaults.js
vendored
7
src/js/select2/defaults.js
vendored
@ -22,6 +22,7 @@ define([
|
||||
'./dropdown/search',
|
||||
'./dropdown/hidePlaceholder',
|
||||
'./dropdown/infiniteScroll',
|
||||
'./dropdown/attachBody',
|
||||
|
||||
'./i18n/en'
|
||||
], function ($, ResultsList,
|
||||
@ -30,6 +31,7 @@ define([
|
||||
Utils, Translation, DIACRITICS,
|
||||
SelectData, ArrayData, AjaxData, Tags, MinimumInputLength,
|
||||
Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,
|
||||
AttachBody,
|
||||
EnglishTranslation) {
|
||||
function Defaults () {
|
||||
this.reset();
|
||||
@ -86,6 +88,11 @@ define([
|
||||
|
||||
options.dropdownAdapter = SearchableDropdown;
|
||||
}
|
||||
|
||||
options.dropdownAdapter = Utils.Decorate(
|
||||
options.dropdownAdapter,
|
||||
AttachBody
|
||||
);
|
||||
}
|
||||
|
||||
if (options.selectionAdapter == null) {
|
||||
|
72
src/js/select2/dropdown/attachBody.js
vendored
Normal file
72
src/js/select2/dropdown/attachBody.js
vendored
Normal file
@ -0,0 +1,72 @@
|
||||
define([
|
||||
|
||||
], function () {
|
||||
function AttachBody (decorated, $element, options) {
|
||||
decorated.call(this, $element, options);
|
||||
}
|
||||
|
||||
AttachBody.prototype.bind = function (decorated, container, $container) {
|
||||
var self = this;
|
||||
|
||||
decorated.call(this, container, $container);
|
||||
|
||||
container.on('open', function () {
|
||||
self._showDropdown();
|
||||
});
|
||||
|
||||
container.on('close', function () {
|
||||
self._hideDropdown();
|
||||
});
|
||||
|
||||
this.$dropdownContainer.on('mousedown', function (evt) {
|
||||
evt.stopPropagation();
|
||||
});
|
||||
};
|
||||
|
||||
AttachBody.prototype.position = function (decorated, $dropdown, $container) {
|
||||
// Clone all of the container classes
|
||||
$dropdown.attr('class', $container.attr('class'));
|
||||
|
||||
$dropdown.removeClass('select2');
|
||||
$dropdown.addClass('select2-container--open');
|
||||
|
||||
$dropdown.css({
|
||||
position: 'absolute'
|
||||
});
|
||||
|
||||
$dropdown.width($container.outerWidth(false));
|
||||
|
||||
this.$container = $container;
|
||||
};
|
||||
|
||||
AttachBody.prototype.render = function (decorated) {
|
||||
var $container = $('<span></span>');
|
||||
|
||||
var $dropdown = decorated.call(this);
|
||||
$container.append($dropdown);
|
||||
|
||||
this.$dropdownContainer = $container;
|
||||
|
||||
return $container;
|
||||
};
|
||||
|
||||
AttachBody.prototype._hideDropdown = function (decorated) {
|
||||
this.$dropdownContainer.detach();
|
||||
};
|
||||
|
||||
AttachBody.prototype._positionDropdown = function () {
|
||||
var css = this.$container.offset();
|
||||
|
||||
css.top += this.$container.outerHeight(true);
|
||||
|
||||
this.$dropdownContainer.css(css);
|
||||
};
|
||||
|
||||
AttachBody.prototype._showDropdown = function (decorated) {
|
||||
this.$dropdownContainer.appendTo(document.body);
|
||||
|
||||
this._positionDropdown();
|
||||
};
|
||||
|
||||
return AttachBody;
|
||||
});
|
4
src/js/select2/results.js
vendored
4
src/js/select2/results.js
vendored
@ -72,8 +72,8 @@ define([
|
||||
this.$results.append($options);
|
||||
};
|
||||
|
||||
Results.prototype.position = function ($results, $container) {
|
||||
var $resultsContainer = $container.find('.select2-results');
|
||||
Results.prototype.position = function ($results, $dropdown) {
|
||||
var $resultsContainer = $dropdown.find('.select2-results');
|
||||
$resultsContainer.append($results);
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user