As per title, is there a way to force select2 to always create a dropdown instead of a drop-up?
There also appears to be some javascript that is either causing the flip when you scroll above the dropdown, adding a new CSS class "select2-drop-above", or both.
EDIT: I should've specified that I'm pulling the library in via select2-rails. I'm hoping there is a way around this that doesn't involve pulling the whole select2 lib in myself and editing the select2.js file directly.
HTML. Create a <select class="select2_el" > element to initialize select2 on page load and create <div id="elements" > container to store <select > element on button click using jQuery AJAX.
Select2 gives you a customizable select box with support for searching, tagging, remote data sets, infinite scrolling, and many other highly used options.
// Set up the Select2 control $('#mySelect2').select2({ ajax: { url: '/api/students' } }); // Fetch the preselected item, and add to the control var studentSelect = $('#mySelect2'); $.ajax({ type: 'GET', url: '/api/students/s/' + studentId }).then(function (data) { // create the option and append to Select2 var option ...
By default, Select2 will attach the dropdown to the end of the body and will absolutely position it to appear above or below the selection container. Select2 will display the dropdown above the container if there is not enough space below the container, but there is enough space above it.
Since modifying the source code is not an option and adding a hook to the select2:open
event is not very elegant, especially when you have multiple select2 instances in the same page, I have written a small extension for the Select2
plugin.
My implementation is inspired by a PR from the plugin's repository (https://github.com/select2/select2/pull/4618) that is not yet merged.
Basically, the following code overrides the original plugin function that handles the dropdown positioning and adds a new option (dropdownPosition
) to force the dropdown positioning above/below.
The new dropdownPosition
option can take the following values: - below
- the dropdown is always displayed at the bottom of the input; - above
- the dropdown is always displayed at the top of the input; - auto
(default) - it uses the old behavior.
Just insert the following code after select2.js
file:
(function($) { var Defaults = $.fn.select2.amd.require('select2/defaults'); $.extend(Defaults.defaults, { dropdownPosition: 'auto' }); var AttachBody = $.fn.select2.amd.require('select2/dropdown/attachBody'); var _positionDropdown = AttachBody.prototype._positionDropdown; AttachBody.prototype._positionDropdown = function() { var $window = $(window); var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above'); var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below'); var newDirection = null; var offset = this.$container.offset(); offset.bottom = offset.top + this.$container.outerHeight(false); var container = { height: this.$container.outerHeight(false) }; container.top = offset.top; container.bottom = offset.top + container.height; var dropdown = { height: this.$dropdown.outerHeight(false) }; var viewport = { top: $window.scrollTop(), bottom: $window.scrollTop() + $window.height() }; var enoughRoomAbove = viewport.top < (offset.top - dropdown.height); var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height); var css = { left: offset.left, top: container.bottom }; // Determine what the parent element is to use for calciulating the offset var $offsetParent = this.$dropdownParent; // For statically positoned elements, we need to get the element // that is determining the offset if ($offsetParent.css('position') === 'static') { $offsetParent = $offsetParent.offsetParent(); } var parentOffset = $offsetParent.offset(); css.top -= parentOffset.top css.left -= parentOffset.left; var dropdownPositionOption = this.options.get('dropdownPosition'); if (dropdownPositionOption === 'above' || dropdownPositionOption === 'below') { newDirection = dropdownPositionOption; } else { if (!isCurrentlyAbove && !isCurrentlyBelow) { newDirection = 'below'; } if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) { newDirection = 'above'; } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) { newDirection = 'below'; } } if (newDirection == 'above' || (isCurrentlyAbove && newDirection !== 'below')) { css.top = container.top - parentOffset.top - dropdown.height; } if (newDirection != null) { this.$dropdown .removeClass('select2-dropdown--below select2-dropdown--above') .addClass('select2-dropdown--' + newDirection); this.$container .removeClass('select2-container--below select2-container--above') .addClass('select2-container--' + newDirection); } this.$dropdownContainer.css(css); }; })(window.jQuery);
The initialize the plugin with as follows:
$(document).ready(function() { $(".select-el").select2({ dropdownPosition: 'below' }); });
Fiddle here: https://jsfiddle.net/byxj73ov/
Github repository: https://github.com/andreivictor/select2-dropdownPosition
UPDATE December 30, 2019
Fiddle with the latest Select2 Version (v4.0.12): https://jsfiddle.net/g4maj9ox/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With