Browse Source

dropdown can now open above or below control depending on available screens pace. fixes #120. based on #197

Igor Vaynberg 13 years ago
parent
commit
482cc409ea
2 changed files with 81 additions and 6 deletions
  1. 34 0
      select2.css
  2. 47 6
      select2.js

+ 34 - 0
select2.css

@@ -54,6 +54,21 @@ Version: @@ver@@ Timestamp: @@timestamp@@
     text-decoration: none;
 }
 
+.select2-container.select2-drop-above .select2-choice
+{
+    border-bottom-color: #aaa;
+    -webkit-border-radius:0px 0px 4px 4px;
+    -moz-border-radius:0px 0px 4px 4px;
+    border-radius:0px 0px 4px 4px;
+    background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.9, white));
+    background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 90%);
+    background-image: -moz-linear-gradient(center bottom, #eeeeee 0%, white 90%);
+    background-image: -o-linear-gradient(bottom, #eeeeee 0%, white 90%);
+    background-image: -ms-linear-gradient(top, #eeeeee 0%,#ffffff 90%);
+    filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff',GradientType=0 );
+    background-image: linear-gradient(top, #eeeeee 0%,#ffffff 90%);
+}
+
 .select2-container .select2-choice span {
     margin-right: 26px;
     display: block;
@@ -102,6 +117,20 @@ Version: @@ver@@ Timestamp: @@timestamp@@
   border-radius: 0 0 4px 4px;
 }
 
+.select2-drop.select2-drop-above {
+    -webkit-border-radius: 4px 4px 0px 0px;
+    -moz-border-radius: 4px 4px 0px 0px;
+    border-radius: 4px 4px 0px 0px;
+    margin-top:1px;
+    border-top: 1px solid #aaa;
+    border-bottom: 0;
+
+    -webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
+    -moz-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
+    -o-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
+    box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
+}
+
 .select2-container .select2-choice div {
     -webkit-border-radius: 0 4px 4px 0;
     -moz-border-radius: 0 4px 4px 0;
@@ -175,6 +204,11 @@ Version: @@ver@@ Timestamp: @@timestamp@@
     -webkit-border-radius: 0;
 }
 
+.select2-drop.select2-drop-above .select2-search input
+{
+    margin-top:4px;
+}
+
 .select2-search input.select2-active {
     background: #fff url('spinner.gif') no-repeat 100%;
     background: url('spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, white), color-stop(0.99, #eeeeee));

+ 47 - 6
select2.js

@@ -728,11 +728,40 @@
         positionDropdown: function() {
             var offset = this.container.offset(),
                 height = this.container.outerHeight(),
-                width  = this.container.outerWidth(),
-                css = {
-                top: offset.top + height,
-                left: offset.left,
-                width: width
+                width = this.container.outerWidth(),
+                dropHeight = this.dropdown.outerHeight(),
+                viewportBottom = document.body.scrollTop + document.documentElement.clientHeight,
+                dropTop = offset.top + height,
+                enoughRoomBelow = dropTop + dropHeight <= viewportBottom,
+                enoughRoomAbove = (offset.top - dropHeight) >= document.body.scrollTop,
+                aboveNow = this.dropdown.hasClass("select2-drop-above"),
+                above,
+                css;
+
+            // always prefer the current above/below alignment, unless there is not enough room
+
+            if (aboveNow) {
+                above = true;
+                if (!enoughRoomAbove && enoughRoomBelow) above = false;
+            } else {
+                above = false;
+                if (!enoughRoomBelow && enoughRoomAbove) above = true;
+            }
+
+            if (above) {
+                dropTop = offset.top - dropHeight;
+                this.container.addClass("select2-drop-above");
+                this.dropdown.addClass("select2-drop-above");
+            }
+            else {
+                this.container.removeClass("select2-drop-above");
+                this.dropdown.removeClass("select2-drop-above");
+            }
+
+            css = {
+                top:dropTop,
+                left:offset.left,
+                width:width
             };
 
             this.dropdown.css(css);
@@ -749,6 +778,13 @@
             return !event.isDefaultPrevented();
         },
 
+        // abstract
+        clearDropdownAlignmentPreference: function() {
+            // clear the classes used to figure out the preference of where the dropdown should be opened
+            this.container.removeClass("select2-drop-above");
+            this.dropdown.removeClass("select2-drop-above");
+        },
+
         /**
          * Opens the dropdown
          *
@@ -760,6 +796,8 @@
 
             if (!this.shouldOpen()) return false;
 
+            this.clearDropdownAlignmentPreference();
+
             if (this.search.val() === " ") { this.search.val(""); }
 
             this.container.addClass("select2-dropdown-open").addClass("select2-container-active");
@@ -784,6 +822,8 @@
         close: function () {
             if (!this.opened()) return;
 
+            this.clearDropdownAlignmentPreference();
+
             this.dropdown.hide();
             this.container.removeClass("select2-dropdown-open");
             this.results.empty();
@@ -1575,7 +1615,8 @@
         // multi
         open: function () {
             if (this.parent.open.apply(this, arguments) === false) return false;
-			this.clearPlaceholder();
+
+            this.clearPlaceholder();
 			this.resizeSearch();
             this.focusSearch();
             return true;