From 7956d7aee349eb391a2c1c3d1dfe46770dd9a44a Mon Sep 17 00:00:00 2001 From: jfoster Date: Mon, 18 Mar 2013 18:39:10 -0400 Subject: [PATCH] Add option to automatically size dropdown width --- select2.css | 9 +++++++++ select2.js | 52 ++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 51 insertions(+), 10 deletions(-) diff --git a/select2.css b/select2.css index 8abc1962..a77f4669 100644 --- a/select2.css +++ b/select2.css @@ -147,6 +147,15 @@ Version: @@ver@@ Timestamp: @@timestamp@@ box-shadow: 0 4px 5px rgba(0, 0, 0, .15); } +.select2-drop-auto-width { + border-top: 1px solid #aaa; + width: auto; +} + +.select2-drop-auto-width .select2-search { + padding-top: 4px; +} + .select2-drop.select2-drop-above { margin-top: 1px; border-top: 1px solid #aaa; diff --git a/select2.js b/select2.js index 8d295c7b..ea57573f 100644 --- a/select2.js +++ b/select2.js @@ -47,7 +47,7 @@ the specific language governing permissions and limitations under the Apache Lic } var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer, - lastMousePosition, $document; + lastMousePosition, $document, scrollBarDimensions, KEY = { TAB: 9, @@ -95,7 +95,8 @@ the specific language governing permissions and limitations under the Apache Lic k = k.which ? k.which : k; return k >= 112 && k <= 123; } - }; + }, + MEASURE_SCROLLBAR_TEMPLATE = "
"; $document = $(document); @@ -109,6 +110,19 @@ the specific language governing permissions and limitations under the Apache Lic return -1; } + function measureScrollbar () { + var $template = $( MEASURE_SCROLLBAR_TEMPLATE ); + $template.appendTo('body'); + + var dim = { + width: $template.width() - $template[0].clientWidth, + height: $template.height() - $template[0].clientHeight + }; + $template.remove(); + + return dim; + } + /** * Compares equality of a and b * @param a @@ -691,6 +705,9 @@ the specific language governing permissions and limitations under the Apache Lic } if (opts.element.is(":disabled") || opts.element.is("[readonly='readonly']")) this.disable(); + + // Calculate size of scrollbar + scrollBarDimensions = scrollBarDimensions || measureScrollbar(); }, // abstract @@ -977,22 +994,37 @@ the specific language governing permissions and limitations under the Apache Lic // abstract positionDropdown: function() { - var offset = this.container.offset(), + var $dropdown = this.dropdown, + offset = this.container.offset(), height = this.container.outerHeight(false), width = this.container.outerWidth(false), - dropHeight = this.dropdown.outerHeight(false), + dropHeight = $dropdown.outerHeight(false), viewPortRight = $(window).scrollLeft() + $(window).width(), viewportBottom = $(window).scrollTop() + $(window).height(), dropTop = offset.top + height, dropLeft = offset.left, enoughRoomBelow = dropTop + dropHeight <= viewportBottom, enoughRoomAbove = (offset.top - dropHeight) >= this.body().scrollTop(), - dropWidth = this.dropdown.outerWidth(false), + dropWidth = $dropdown.outerWidth(false), enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight, - aboveNow = this.dropdown.hasClass("select2-drop-above"), + aboveNow = $dropdown.hasClass("select2-drop-above"), bodyOffset, above, - css; + css, + resultsListNode; + + if (this.opts.dropdownAutoWidth) { + resultsListNode = $('.select2-results', $dropdown)[0]; + $dropdown.addClass('select2-drop-auto-width'); + $dropdown.css('width', ''); + // Add scrollbar width to dropdown if vertical scrollbar is present + dropWidth = $dropdown.outerWidth(false) + (resultsListNode.scrollHeight === resultsListNode.clientHeight ? 0 : scrollBarDimensions.width); + dropWidth > width ? width = dropWidth : dropWidth = width; + enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight; + } + else { + this.container.removeClass('select2-drop-auto-width'); + } //console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow); //console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body().scrollTop(), "enough?", enoughRoomAbove); @@ -1022,11 +1054,11 @@ the specific language governing permissions and limitations under the Apache Lic if (above) { dropTop = offset.top - dropHeight; this.container.addClass("select2-drop-above"); - this.dropdown.addClass("select2-drop-above"); + $dropdown.addClass("select2-drop-above"); } else { this.container.removeClass("select2-drop-above"); - this.dropdown.removeClass("select2-drop-above"); + $dropdown.removeClass("select2-drop-above"); } css = $.extend({ @@ -1035,7 +1067,7 @@ the specific language governing permissions and limitations under the Apache Lic width: width }, evaluate(this.opts.dropdownCss)); - this.dropdown.css(css); + $dropdown.css(css); }, // abstract