From b2c6ced65ff4b2cc89f33a587aee5333d6b1a32a Mon Sep 17 00:00:00 2001 From: Justin DuJardin Date: Tue, 27 Mar 2012 16:04:35 -0700 Subject: [PATCH] Rework select2 and styles to support styled width's (rather than just fixed pixel widths) - Will not work with styles specified in remote CSS, because there's no easy way to retrieve the original css value. - Will work with styles specified inline on the element (regex parse out width value with specified units intact, from the element style attribute) Tested in Firefox,Chrome,Safari,Opera --- select2.css | 61 ++++++++++++++++++++++-------- select2.js | 105 ++++++++++++++++++++++++++++++---------------------- 2 files changed, 105 insertions(+), 61 deletions(-) diff --git a/select2.css b/select2.css index 34034b1f..9b3b864e 100755 --- a/select2.css +++ b/select2.css @@ -7,12 +7,29 @@ } +.select2-container, +.select2-drop, +.select2-search, +.select2-container .select2-search input{ + /* + Force border-box so that % widths fit the parent + container without overlap because of margin/padding. + + More Info : http://www.quirksmode.org/css/box.html + */ + -moz-box-sizing: border-box; /* firefox */ + -ms-box-sizing: border-box; /* ie */ + -webkit-box-sizing: border-box; /* webkit */ + -khtml-box-sizing: border-box; /* konqueror */ + box-sizing: border-box; /* css3 */ +} + .select2-container .select2-choice { background-color: #fff; background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eeeeee), color-stop(0.5, white)); background-image: -webkit-linear-gradient(center bottom, #eeeeee 0%, white 50%); background-image: -moz-linear-gradient(center bottom, #eeeeee 0%, white 50%); - background-image: -o-linear-gradient(top, #eeeeee 0%, #ffffff 50%); + background-image: -o-linear-gradient(bottom, #eeeeee 0%, #ffffff 50%); background-image: -ms-linear-gradient(top, #eeeeee 0%, #ffffff 50%); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#ffffff', GradientType = 0); background-image: linear-gradient(top, #eeeeee 0%, #ffffff 50%); @@ -69,19 +86,17 @@ border-top: 0; position: absolute; top: 29px; - left: 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); z-index: 999; + width:100%; + margin-top:-1px; -webkit-border-radius: 0 0 4px 4px; -moz-border-radius: 0 0 4px 4px; border-radius: 0 0 4px 4px; - -moz-background-clip: padding; - -webkit-background-clip: padding-box; - background-clip: padding-box; } .select2-container .select2-choice div { @@ -116,11 +131,12 @@ } .select2-container .select2-search { - padding: 3px 4px; - position: relative; margin: 0; white-space: nowrap; z-index: 1010; + position: absolute; + left:4px; + right:4px; } .select2-container .select2-search input { @@ -131,12 +147,12 @@ background: url('select2.png') no-repeat 100% -22px, -o-linear-gradient(bottom, white 85%, #eeeeee 99%); background: url('select2.png') no-repeat 100% -22px, -ms-linear-gradient(top, #ffffff 85%, #eeeeee 99%); background: url('select2.png') no-repeat 100% -22px, linear-gradient(top, #ffffff 85%, #eeeeee 99%); - margin: 1px 0; padding: 4px 20px 4px 5px; outline: 0; border: 1px solid #aaa; font-family: sans-serif; font-size: 1em; + width:100%; } .select2-container .select2-search input.select2-active { @@ -158,17 +174,17 @@ .select2-container-active .select2-choice, .select2-container-active .select2-choices { - -webkit-box-shadow: none; - -moz-box-shadow: none; - box-shadow: none; - outline: thin dotted #333; - outline: 5px auto -webkit-focus-ring-color; - outline-offset: -2px; - + -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3); + -moz-box-shadow : 0 0 5px rgba(0,0,0,.3); + -o-box-shadow : 0 0 5px rgba(0,0,0,.3); + box-shadow : 0 0 5px rgba(0,0,0,.3); + border: 1px solid #5897fb; + outline: none; } .select2-dropdown-open .select2-choice { border: 1px solid #aaa; + border-bottom: none; -webkit-box-shadow: 0 1px 0 #fff inset; -moz-box-shadow : 0 1px 0 #fff inset; -o-box-shadow : 0 1px 0 #fff inset; @@ -199,7 +215,7 @@ /* results */ .select2-container .select2-results { - margin: 0 4px 4px 0; + margin: 30px 4px 4px 0; padding: 0 0 0 4px; position: relative; overflow-x: hidden; @@ -272,6 +288,19 @@ height: 1%; position: relative; } + +.select2-container-multi .select2-drop { + margin-top:0; +} + +.select2-container-multi.select2-container-active .select2-choices { + -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3); + -moz-box-shadow : 0 0 5px rgba(0,0,0,.3); + -o-box-shadow : 0 0 5px rgba(0,0,0,.3); + box-shadow : 0 0 5px rgba(0,0,0,.3); + border: 1px solid #5897fb; + outline: none; +} .select2-container-multi .select2-choices li { float: left; list-style: none; diff --git a/select2.js b/select2.js index 60fe446d..91e726d4 100755 --- a/select2.js +++ b/select2.js @@ -301,36 +301,36 @@ } else { if (!("query" in opts)) { if ("ajax" in opts) { - opts.query = (function () { - var timeout, // current scheduled but not yet executed request - requestSequence = 0, // sequence used to drop out-of-order responses - quietMillis = opts.ajax.quietMillis || 100; + opts.query = (function () { + var timeout, // current scheduled but not yet executed request + requestSequence = 0, // sequence used to drop out-of-order responses + quietMillis = opts.ajax.quietMillis || 100; - return function (query) { - window.clearTimeout(timeout); - timeout = window.setTimeout(function () { - requestSequence += 1; // increment the sequence - var requestNumber = requestSequence, // this request's sequence number - options = opts.ajax, // ajax parameters - data = options.data; // ajax data function + return function (query) { + window.clearTimeout(timeout); + timeout = window.setTimeout(function () { + requestSequence += 1; // increment the sequence + var requestNumber = requestSequence, // this request's sequence number + options = opts.ajax, // ajax parameters + data = options.data; // ajax data function - data = data.call(this, query.term, query.page); + data = data.call(this, query.term, query.page); - $.ajax({ - url: options.url, - dataType: options.dataType, - data: data - }).success( - function (data) { - if (requestNumber < requestSequence) { - return; - } - query.callback(options.results(data, query.page)); + $.ajax({ + url: options.url, + dataType: options.dataType, + data: data + }).success( + function (data) { + if (requestNumber < requestSequence) { + return; } - ); - }, quietMillis); - }; - }()); + query.callback(options.results(data, query.page)); + } + ); + }, quietMillis); + }; + }()); } else if ("data" in opts) { opts.query = (function () { var data = opts.data, // data elements @@ -355,9 +355,9 @@ query.callback(filtered); }; }()); - } } } + } if (typeof(opts.query) !== "function") { throw "query function not defined for Select2 " + opts.element.attr("id"); } @@ -371,14 +371,11 @@ AbstractSelect2.prototype.alignDropdown = function () { this.dropdown.css({ - top: this.container.height(), - width: this.container.outerWidth() - getSideBorderPadding(this.dropdown) + top: this.container.height() }); }; AbstractSelect2.prototype.open = function () { - var width; - if (this.opened()) return; this.container.addClass("select2-dropdown-open").addClass("select2-container-active"); @@ -394,7 +391,7 @@ this.dropdown.hide(); this.container.removeClass("select2-dropdown-open"); - this.results.empty(); + this.results.empty(); this.clearSearch(); }; @@ -595,6 +592,32 @@ return this.opts.placeholder; }; + /** + * Get the desired width for the container element. This is + * derived first from option `width` passed to select2, then + * the inline 'style' on the original element, and finally + * falls back to the jQuery calculated element width. + * + * @returns The width string (with units) for the container. + */ + AbstractSelect2.prototype.getContainerWidth = function() { + if (this.opts.width !== undefined) + return this.opts.width; + + var style = this.opts.element.attr('style'); + var attrs = style.split(';'); + for (var i = 0; i < attrs.length; i++) { + var attr = attrs[i].trim(); + var matches = attr.match(/width:(([0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/); + if(matches == null || matches.length < 1) + continue; + return matches[1]; + } + + return this.opts.element.width(); + } + + function SingleSelect2() { } @@ -605,7 +628,7 @@ SingleSelect2.prototype.createContainer = function () { return $("
", { "class": "select2-container", - "style": "width: " + this.opts.element.outerWidth() + "px" + "style": "width: " + this.getContainerWidth() }).html([ " ", " ", @@ -622,18 +645,10 @@ SingleSelect2.prototype.open = function () { - var width; - if (this.opened()) return; this.parent.open.apply(this, arguments); - // size the search field - - width = this.dropdown.width(); - width -= getSideBorderPadding(this.container.find(".select2-search")); - width -= getSideBorderPadding(this.search); - this.search.css({width: width}); }; SingleSelect2.prototype.close = function () { @@ -795,9 +810,9 @@ this.select .val(val) .find(":selected").each(function () { - data = {id: $(this).attr("value"), text: $(this).text()}; - return false; - }); + data = {id: $(this).attr("value"), text: $(this).text()}; + return false; + }); this.updateSelection(data); } else { // val is an object @@ -823,7 +838,7 @@ MultiSelect2.prototype.createContainer = function () { return $("
", { "class": "select2-container select2-container-multi", - "style": "width: " + this.opts.element.outerWidth() + "px" + "style": "width: " + this.getContainerWidth() }).html([ "