select2-rails 3.3.0 → 3.3.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -26,7 +26,7 @@ Add to your `app/assets/stylesheets/application.css`:
26
26
  *= require select2
27
27
 
28
28
  ## Version
29
- From `v2.1.0` on, `select2-rails`'s version will match the version of `Select2` it uses. Currently, `select2-rails` uses `Select2 v3.2`.
29
+ From `v2.1.0` on, `select2-rails`'s version will match the version of `Select2` it uses.
30
30
 
31
31
  The last number of the version is the patch version specific to the gem. For example, for a version of the form `2.x.y`, `2.x` is the release of `Select2` we should be compatible with, and y is the patch version specific to the gem (ie. to resolve any gem-specific issues that crop up).
32
32
 
File without changes
File without changes
File without changes
File without changes
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  Copyright 2012 Igor Vaynberg
3
3
 
4
- Version: 3.3.0 Timestamp: Tue Feb 5 18:33:54 PST 2013
4
+ Version: 3.3.1 Timestamp: Wed Feb 20 09:57:22 PST 2013
5
5
 
6
6
  This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
7
7
  General Public License version 2 (the "GPL License"). You may choose either license to govern your
@@ -103,7 +103,9 @@ the specific language governing permissions and limitations under the Apache Lic
103
103
 
104
104
  function indexOf(value, array) {
105
105
  var i = 0, l = array.length;
106
- for (; i < l; i = i + 1) if (value === array[i]) return i;
106
+ for (; i < l; i = i + 1) {
107
+ if (equal(value, array[i])) return i;
108
+ }
107
109
  return -1;
108
110
  }
109
111
 
@@ -113,7 +115,12 @@ the specific language governing permissions and limitations under the Apache Lic
113
115
  * @param b
114
116
  */
115
117
  function equal(a, b) {
116
- return a===b;
118
+ if (a === b) return true;
119
+ if (a === undefined || b === undefined) return false;
120
+ if (a === null || b === null) return false;
121
+ if (a.constructor === String) return a === b+'';
122
+ if (b.constructor === String) return b === a+'';
123
+ return false;
117
124
  }
118
125
 
119
126
  /**
@@ -211,6 +218,34 @@ the specific language governing permissions and limitations under the Apache Lic
211
218
  });
212
219
  }
213
220
 
221
+ function focus($el) {
222
+ if ($el[0] === document.activeElement) return;
223
+
224
+ /* set the focus in a 0 timeout - that way the focus is set after the processing
225
+ of the current event has finished - which seems like the only reliable way
226
+ to set focus */
227
+ window.setTimeout(function() {
228
+ var el=$el[0], pos=$el.val().length, range;
229
+
230
+ $el.focus();
231
+
232
+ /* after the focus is set move the caret to the end, necessary when we val()
233
+ just before setting focus */
234
+ if(el.setSelectionRange)
235
+ {
236
+ el.setSelectionRange(pos, pos);
237
+ }
238
+ else if (el.createTextRange) {
239
+ range = el.createTextRange();
240
+ range.collapse(true);
241
+ range.moveEnd('character', pos);
242
+ range.moveStart('character', pos);
243
+ range.select();
244
+ }
245
+
246
+ }, 0);
247
+ }
248
+
214
249
  function killEvent(event) {
215
250
  event.preventDefault();
216
251
  event.stopPropagation();
@@ -243,6 +278,32 @@ the specific language governing permissions and limitations under the Apache Lic
243
278
  return sizer.width();
244
279
  }
245
280
 
281
+ function syncCssClasses(dest, src, adapter) {
282
+ var classes, replacements = [], adapted;
283
+
284
+ classes = dest.attr("class");
285
+ if (typeof classes === "string") {
286
+ $(classes.split(" ")).each2(function() {
287
+ if (this.indexOf("select2-") === 0) {
288
+ replacements.push(this);
289
+ }
290
+ });
291
+ }
292
+ classes = src.attr("class");
293
+ if (typeof classes === "string") {
294
+ $(classes.split(" ")).each2(function() {
295
+ if (this.indexOf("select2-") !== 0) {
296
+ adapted = adapter(this);
297
+ if (typeof adapted === "string" && adapted.length > 0) {
298
+ replacements.push(this);
299
+ }
300
+ }
301
+ });
302
+ }
303
+ dest.attr("class", replacements.join(" "));
304
+ }
305
+
306
+
246
307
  function markMatch(text, term, markup, escapeMarkup) {
247
308
  var match=text.toUpperCase().indexOf(term.toUpperCase()),
248
309
  tl=term.length;
@@ -279,7 +340,9 @@ the specific language governing permissions and limitations under the Apache Lic
279
340
  var timeout, // current scheduled but not yet executed request
280
341
  requestSequence = 0, // sequence used to drop out-of-order responses
281
342
  handler = null,
282
- quietMillis = options.quietMillis || 100;
343
+ quietMillis = options.quietMillis || 100,
344
+ ajaxUrl = options.url,
345
+ self = this;
283
346
 
284
347
  return function (query) {
285
348
  window.clearTimeout(timeout);
@@ -287,31 +350,40 @@ the specific language governing permissions and limitations under the Apache Lic
287
350
  requestSequence += 1; // increment the sequence
288
351
  var requestNumber = requestSequence, // this request's sequence number
289
352
  data = options.data, // ajax data function
290
- url = options.url, // ajax url string or function
353
+ url = ajaxUrl, // ajax url string or function
291
354
  transport = options.transport || $.ajax,
292
- traditional = options.traditional || false,
293
- type = options.type || 'GET'; // set type of request (GET or POST)
355
+ type = options.type || 'GET', // set type of request (GET or POST)
356
+ params = {};
294
357
 
295
- data = data ? data.call(this, query.term, query.page, query.context) : null;
296
- url = (typeof url === 'function') ? url.call(this, query.term, query.page, query.context) : url;
358
+ data = data ? data.call(self, query.term, query.page, query.context) : null;
359
+ url = (typeof url === 'function') ? url.call(self, query.term, query.page, query.context) : url;
297
360
 
298
361
  if( null !== handler) { handler.abort(); }
299
362
 
300
- handler = transport.call(null, {
363
+ if (options.params) {
364
+ if ($.isFunction(options.params)) {
365
+ $.extend(params, options.params.call(self));
366
+ } else {
367
+ $.extend(params, options.params);
368
+ }
369
+ }
370
+
371
+ $.extend(params, {
301
372
  url: url,
302
373
  dataType: options.dataType,
303
374
  data: data,
304
375
  type: type,
305
- traditional: traditional,
376
+ cache: false,
306
377
  success: function (data) {
307
378
  if (requestNumber < requestSequence) {
308
379
  return;
309
380
  }
310
- // TODO 3.0 - replace query.page with query so users have access to term, page, etc.
381
+ // TODO - replace query.page with query so users have access to term, page, etc.
311
382
  var results = options.results(data, query.page);
312
383
  query.callback(results);
313
384
  }
314
385
  });
386
+ handler = transport.call(self, params);
315
387
  }, quietMillis);
316
388
  };
317
389
  }
@@ -333,22 +405,33 @@ the specific language governing permissions and limitations under the Apache Lic
333
405
  function local(options) {
334
406
  var data = options, // data elements
335
407
  dataText,
408
+ tmp,
336
409
  text = function (item) { return ""+item.text; }; // function used to retrieve the text portion of a data item that is matched against the search
337
410
 
338
- if (!$.isArray(data)) {
339
- text = data.text;
411
+ if ($.isArray(data)) {
412
+ tmp = data;
413
+ data = { results: tmp };
414
+ }
415
+
416
+ if ($.isFunction(data) === false) {
417
+ tmp = data;
418
+ data = function() { return tmp; };
419
+ }
420
+
421
+ var dataItem = data();
422
+ if (dataItem.text) {
423
+ text = dataItem.text;
340
424
  // if text is not a function we assume it to be a key name
341
425
  if (!$.isFunction(text)) {
342
- dataText = data.text; // we need to store this in a separate variable because in the next step data gets reset and data.text is no longer available
343
- text = function (item) { return item[dataText]; };
426
+ dataText = data.text; // we need to store this in a separate variable because in the next step data gets reset and data.text is no longer available
427
+ text = function (item) { return item[dataText]; };
344
428
  }
345
- data = data.results;
346
429
  }
347
430
 
348
431
  return function (query) {
349
432
  var t = query.term, filtered = { results: [] }, process;
350
433
  if (t === "") {
351
- query.callback({results: data});
434
+ query.callback(data());
352
435
  return;
353
436
  }
354
437
 
@@ -372,7 +455,7 @@ the specific language governing permissions and limitations under the Apache Lic
372
455
  }
373
456
  };
374
457
 
375
- $(data).each2(function(i, datum) { process(datum, filtered.results); });
458
+ $(data().results).each2(function(i, datum) { process(datum, filtered.results); });
376
459
  query.callback(filtered);
377
460
  };
378
461
  }
@@ -526,28 +609,7 @@ the specific language governing permissions and limitations under the Apache Lic
526
609
  // cache the body so future lookups are cheap
527
610
  this.body = thunk(function() { return opts.element.closest("body"); });
528
611
 
529
- // create the dropdown mask if doesnt already exist
530
- mask = $("#select2-drop-mask");
531
- if (mask.length == 0) {
532
- mask = $(document.createElement("div"));
533
- mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask");
534
- mask.hide();
535
- mask.appendTo(this.body());
536
- mask.bind("mousedown touchstart", function (e) {
537
- var dropdown = $("#select2-drop"), self;
538
- if (dropdown.length > 0) {
539
- self=dropdown.data("select2");
540
- if (self.opts.selectOnBlur) {
541
- self.selectHighlighted({noFocus: true});
542
- }
543
- self.close();
544
- }
545
- });
546
- }
547
-
548
- if (opts.element.attr("class") !== undefined) {
549
- this.container.addClass(opts.element.attr("class").replace(/validate\[[\S ]+] ?/, ''));
550
- }
612
+ syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
551
613
 
552
614
  this.container.css(evaluate(opts.containerCss));
553
615
  this.container.addClass(evaluate(opts.containerCssClass));
@@ -558,7 +620,7 @@ the specific language governing permissions and limitations under the Apache Lic
558
620
  this.opts.element
559
621
  .data("select2", this)
560
622
  .addClass("select2-offscreen")
561
- .bind("focus.select2", function() { $(this).select2("focus")})
623
+ .bind("focus.select2", function() { $(this).select2("focus"); })
562
624
  .attr("tabIndex", "-1")
563
625
  .before(this.container);
564
626
  this.container.data("select2", this);
@@ -577,10 +639,9 @@ the specific language governing permissions and limitations under the Apache Lic
577
639
 
578
640
  // initialize the container
579
641
  this.initContainer();
580
- this.initContainerWidth();
581
642
 
582
643
  installFilteredMouseMove(this.results);
583
- this.dropdown.delegate(resultsSelector, "mousemove-filtered", this.bind(this.highlightUnderEvent));
644
+ this.dropdown.delegate(resultsSelector, "mousemove-filtered touchstart touchmove touchend", this.bind(this.highlightUnderEvent));
584
645
 
585
646
  installDebouncedScroll(80, this.results);
586
647
  this.dropdown.delegate(resultsSelector, "scroll-debounced", this.bind(this.loadMoreIfNeeded));
@@ -600,18 +661,15 @@ the specific language governing permissions and limitations under the Apache Lic
600
661
  }
601
662
 
602
663
  installKeyUpChangeEvent(search);
603
- search.bind("keyup-change", this.bind(this.updateResults));
604
- search.bind("focus", function () { search.addClass("select2-focused"); if (search.val() === " ") search.val(""); });
664
+ search.bind("keyup-change input paste", this.bind(this.updateResults));
665
+ search.bind("focus", function () { search.addClass("select2-focused"); });
605
666
  search.bind("blur", function () { search.removeClass("select2-focused");});
606
667
 
607
668
  this.dropdown.delegate(resultsSelector, "mouseup", this.bind(function (e) {
608
669
  if ($(e.target).closest(".select2-result-selectable").length > 0) {
609
670
  this.highlightUnderEvent(e);
610
671
  this.selectHighlighted(e);
611
- } else {
612
- this.focusSearch();
613
672
  }
614
- killEvent(e);
615
673
  }));
616
674
 
617
675
  // trap all mouse events from leaving the dropdown. sometimes there may be a modal that is listening
@@ -642,9 +700,10 @@ the specific language governing permissions and limitations under the Apache Lic
642
700
  select2.container.remove();
643
701
  select2.dropdown.remove();
644
702
  select2.opts.element
703
+ .removeClass("select2-offscreen")
645
704
  .removeData("select2")
646
705
  .unbind(".select2")
647
- .attr("tabIndex", this.elementTabIndex)
706
+ .attr({"tabIndex": this.elementTabIndex})
648
707
  .show();
649
708
  }
650
709
  },
@@ -771,7 +830,7 @@ the specific language governing permissions and limitations under the Apache Lic
771
830
  });
772
831
  // this is needed because inside val() we construct choices from options and there id is hardcoded
773
832
  opts.id=function(e) { return e.id; };
774
- opts.formatResultCssClass = function(data) { return data.css; }
833
+ opts.formatResultCssClass = function(data) { return data.css; };
775
834
  } else {
776
835
  if (!("query" in opts)) {
777
836
 
@@ -780,7 +839,7 @@ the specific language governing permissions and limitations under the Apache Lic
780
839
  if (ajaxUrl && ajaxUrl.length > 0) {
781
840
  opts.ajax.url = ajaxUrl;
782
841
  }
783
- opts.query = ajax(opts.ajax);
842
+ opts.query = ajax.call(opts.element, opts.ajax);
784
843
  } else if ("data" in opts) {
785
844
  opts.query = local(opts.data);
786
845
  } else if ("tags" in opts) {
@@ -788,17 +847,19 @@ the specific language governing permissions and limitations under the Apache Lic
788
847
  if (opts.createSearchChoice === undefined) {
789
848
  opts.createSearchChoice = function (term) { return {id: term, text: term}; };
790
849
  }
791
- opts.initSelection = function (element, callback) {
792
- var data = [];
793
- $(splitVal(element.val(), opts.separator)).each(function () {
794
- var id = this, text = this, tags=opts.tags;
795
- if ($.isFunction(tags)) tags=tags();
796
- $(tags).each(function() { if (equal(this.id, id)) { text = this.text; return false; } });
797
- data.push({id: id, text: text});
798
- });
799
-
800
- callback(data);
801
- };
850
+ if (opts.initSelection === undefined) {
851
+ opts.initSelection = function (element, callback) {
852
+ var data = [];
853
+ $(splitVal(element.val(), opts.separator)).each(function () {
854
+ var id = this, text = this, tags=opts.tags;
855
+ if ($.isFunction(tags)) tags=tags();
856
+ $(tags).each(function() { if (equal(this.id, id)) { text = this.text; return false; } });
857
+ data.push({id: id, text: text});
858
+ });
859
+
860
+ callback(data);
861
+ };
862
+ }
802
863
  }
803
864
  }
804
865
  }
@@ -823,8 +884,13 @@ the specific language governing permissions and limitations under the Apache Lic
823
884
  }));
824
885
 
825
886
  sync = this.bind(function () {
826
- var enabled = this.opts.element.attr("disabled") !== "disabled";
827
- var readonly = this.opts.element.attr("readonly") === "readonly";
887
+
888
+ var enabled, readonly, self = this;
889
+
890
+ // sync enabled state
891
+
892
+ enabled = this.opts.element.attr("disabled") !== "disabled";
893
+ readonly = this.opts.element.attr("readonly") === "readonly";
828
894
 
829
895
  enabled = enabled && !readonly;
830
896
 
@@ -835,6 +901,14 @@ the specific language governing permissions and limitations under the Apache Lic
835
901
  this.disable();
836
902
  }
837
903
  }
904
+
905
+
906
+ syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
907
+ this.container.addClass(evaluate(this.opts.containerCssClass));
908
+
909
+ syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass);
910
+ this.dropdown.addClass(evaluate(this.opts.dropdownCssClass));
911
+
838
912
  });
839
913
 
840
914
  // mozilla and IE
@@ -903,21 +977,21 @@ the specific language governing permissions and limitations under the Apache Lic
903
977
  height = this.container.outerHeight(false),
904
978
  width = this.container.outerWidth(false),
905
979
  dropHeight = this.dropdown.outerHeight(false),
906
- viewPortRight = $(window).scrollLeft() + document.documentElement.clientWidth,
907
- viewportBottom = $(window).scrollTop() + document.documentElement.clientHeight,
980
+ viewPortRight = $(window).scrollLeft() + $(window).width(),
981
+ viewportBottom = $(window).scrollTop() + $(window).height(),
908
982
  dropTop = offset.top + height,
909
983
  dropLeft = offset.left,
910
984
  enoughRoomBelow = dropTop + dropHeight <= viewportBottom,
911
985
  enoughRoomAbove = (offset.top - dropHeight) >= this.body().scrollTop(),
912
- dropWidth = this.dropdown.outerWidth(false),
913
- enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight,
986
+ dropWidth = this.dropdown.outerWidth(false),
987
+ enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight,
914
988
  aboveNow = this.dropdown.hasClass("select2-drop-above"),
915
989
  bodyOffset,
916
990
  above,
917
991
  css;
918
992
 
919
- // console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow);
920
- // console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body().scrollTop(), "enough?", enoughRoomAbove);
993
+ //console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow);
994
+ //console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body().scrollTop(), "enough?", enoughRoomAbove);
921
995
 
922
996
  // fix positioning when body has an offset and is not position: static
923
997
 
@@ -937,9 +1011,9 @@ the specific language governing permissions and limitations under the Apache Lic
937
1011
  if (!enoughRoomBelow && enoughRoomAbove) above = true;
938
1012
  }
939
1013
 
940
- if (!enoughRoomOnRight) {
941
- dropLeft = offset.left + width - dropWidth;
942
- }
1014
+ if (!enoughRoomOnRight) {
1015
+ dropLeft = offset.left + width - dropWidth;
1016
+ }
943
1017
 
944
1018
  if (above) {
945
1019
  dropTop = offset.top - dropHeight;
@@ -966,7 +1040,7 @@ the specific language governing permissions and limitations under the Apache Lic
966
1040
 
967
1041
  if (this.opened()) return false;
968
1042
 
969
- event = $.Event("open");
1043
+ event = $.Event("opening");
970
1044
  this.opts.element.trigger(event);
971
1045
  return !event.isDefaultPrevented();
972
1046
  },
@@ -1007,8 +1081,6 @@ the specific language governing permissions and limitations under the Apache Lic
1007
1081
 
1008
1082
  this.clearDropdownAlignmentPreference();
1009
1083
 
1010
- if (this.search.val() === " ") { this.search.val(""); }
1011
-
1012
1084
  this.container.addClass("select2-dropdown-open").addClass("select2-container-active");
1013
1085
 
1014
1086
 
@@ -1018,7 +1090,24 @@ the specific language governing permissions and limitations under the Apache Lic
1018
1090
 
1019
1091
  this.updateResults(true);
1020
1092
 
1093
+ // create the dropdown mask if doesnt already exist
1021
1094
  mask = $("#select2-drop-mask");
1095
+ if (mask.length == 0) {
1096
+ mask = $(document.createElement("div"));
1097
+ mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask");
1098
+ mask.hide();
1099
+ mask.appendTo(this.body());
1100
+ mask.bind("mousedown touchstart", function (e) {
1101
+ var dropdown = $("#select2-drop"), self;
1102
+ if (dropdown.length > 0) {
1103
+ self=dropdown.data("select2");
1104
+ if (self.opts.selectOnBlur) {
1105
+ self.selectHighlighted({noFocus: true});
1106
+ }
1107
+ self.close();
1108
+ }
1109
+ });
1110
+ }
1022
1111
 
1023
1112
  // ensure the mask is always right before the dropdown
1024
1113
  if (this.dropdown.prev()[0] !== mask[0]) {
@@ -1042,12 +1131,13 @@ the specific language governing permissions and limitations under the Apache Lic
1042
1131
 
1043
1132
  // attach listeners to events that can change the position of the container and thus require
1044
1133
  // the position of the dropdown to be updated as well so it does not come unglued from the container
1134
+ var that = this;
1045
1135
  this.container.parents().add(window).each(function () {
1046
1136
  $(this).bind(resize+" "+scroll+" "+orient, function (e) {
1047
1137
  $("#select2-drop-mask").css({
1048
1138
  width:document.documentElement.scrollWidth,
1049
1139
  height:document.documentElement.scrollHeight});
1050
- $("#select2-drop").data("select2").positionDropdown();
1140
+ that.positionDropdown();
1051
1141
  });
1052
1142
  });
1053
1143
 
@@ -1071,7 +1161,7 @@ the specific language governing permissions and limitations under the Apache Lic
1071
1161
  $("#select2-drop-mask").hide();
1072
1162
  this.dropdown.removeAttr("id"); // only the active dropdown has the select2-drop id
1073
1163
  this.dropdown.hide();
1074
- this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active");
1164
+ this.container.removeClass("select2-dropdown-open");
1075
1165
  this.results.empty();
1076
1166
  this.clearSearch();
1077
1167
 
@@ -1083,6 +1173,11 @@ the specific language governing permissions and limitations under the Apache Lic
1083
1173
 
1084
1174
  },
1085
1175
 
1176
+ //abstract
1177
+ getMaximumSelectionSize: function() {
1178
+ return evaluate(this.opts.maximumSelectionSize);
1179
+ },
1180
+
1086
1181
  // abstract
1087
1182
  ensureHighlightVisible: function () {
1088
1183
  var results = this.results, children, index, child, hb, rb, y, more;
@@ -1150,7 +1245,9 @@ the specific language governing permissions and limitations under the Apache Lic
1150
1245
 
1151
1246
  // abstract
1152
1247
  highlight: function (index) {
1153
- var choices = this.findHighlightableChoices();
1248
+ var choices = this.findHighlightableChoices(),
1249
+ choice,
1250
+ data;
1154
1251
 
1155
1252
  if (arguments.length === 0) {
1156
1253
  return indexOf(choices.filter(".select2-highlighted")[0], choices.get());
@@ -1161,8 +1258,15 @@ the specific language governing permissions and limitations under the Apache Lic
1161
1258
 
1162
1259
  this.results.find(".select2-highlighted").removeClass("select2-highlighted");
1163
1260
 
1164
- $(choices[index]).addClass("select2-highlighted");
1261
+ choice = $(choices[index]);
1262
+ choice.addClass("select2-highlighted");
1263
+
1165
1264
  this.ensureHighlightVisible();
1265
+
1266
+ data = choice.data("select2-data");
1267
+ if (data) {
1268
+ this.opts.element.trigger({ type: "highlight", val: this.id(data), choice: data });
1269
+ }
1166
1270
  },
1167
1271
 
1168
1272
  // abstract
@@ -1199,6 +1303,7 @@ the specific language governing permissions and limitations under the Apache Lic
1199
1303
  if (below <= this.opts.loadMorePadding) {
1200
1304
  more.addClass("select2-active");
1201
1305
  this.opts.query({
1306
+ element: this.opts.element,
1202
1307
  term: term,
1203
1308
  page: page,
1204
1309
  context: context,
@@ -1219,6 +1324,7 @@ the specific language governing permissions and limitations under the Apache Lic
1219
1324
  }
1220
1325
  self.positionDropdown();
1221
1326
  self.resultsPage = page;
1327
+ self.context = data.context;
1222
1328
  })});
1223
1329
  }
1224
1330
  },
@@ -1255,7 +1361,7 @@ the specific language governing permissions and limitations under the Apache Lic
1255
1361
  postRender();
1256
1362
  }
1257
1363
 
1258
- var maxSelSize = $.isFunction(opts.maximumSelectionSize) ? opts.maximumSelectionSize() : opts.maximumSelectionSize;
1364
+ var maxSelSize = this.getMaximumSelectionSize();
1259
1365
  if (maxSelSize >=1) {
1260
1366
  data = this.data();
1261
1367
  if ($.isArray(data) && data.length >= maxSelSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) {
@@ -1292,7 +1398,9 @@ the specific language governing permissions and limitations under the Apache Lic
1292
1398
  }
1293
1399
 
1294
1400
  this.resultsPage = 1;
1401
+
1295
1402
  opts.query({
1403
+ element: opts.element,
1296
1404
  term: search.val(),
1297
1405
  page: this.resultsPage,
1298
1406
  context: null,
@@ -1305,7 +1413,6 @@ the specific language governing permissions and limitations under the Apache Lic
1305
1413
 
1306
1414
  // save context, if any
1307
1415
  this.context = (data.context===undefined) ? null : data.context;
1308
-
1309
1416
  // create a default choice and prepend it to the list
1310
1417
  if (this.opts.createSearchChoice && search.val() !== "") {
1311
1418
  def = this.opts.createSearchChoice.call(null, search.val(), data.results);
@@ -1351,28 +1458,15 @@ the specific language governing permissions and limitations under the Apache Lic
1351
1458
 
1352
1459
  this.close();
1353
1460
  this.container.removeClass("select2-container-active");
1354
- this.dropdown.removeClass("select2-drop-active");
1355
1461
  // synonymous to .is(':focus'), which is available in jquery >= 1.6
1356
1462
  if (this.search[0] === document.activeElement) { this.search.blur(); }
1357
1463
  this.clearSearch();
1358
1464
  this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
1359
- this.opts.element.triggerHandler("blur");
1360
1465
  },
1361
1466
 
1362
1467
  // abstract
1363
1468
  focusSearch: function () {
1364
- // need to do it here as well as in timeout so it works in IE
1365
- this.search.show();
1366
- this.search.focus();
1367
-
1368
- /* we do this in a timeout so that current event processing can complete before this code is executed.
1369
- this makes sure the search field is focussed even if the current event would blur it */
1370
- window.setTimeout(this.bind(function () {
1371
- // reset the value so IE places the cursor at the end of the input box
1372
- this.search.show();
1373
- this.search.focus();
1374
- this.search.val(this.search.val());
1375
- }), 10);
1469
+ focus(this.search);
1376
1470
  },
1377
1471
 
1378
1472
  // abstract
@@ -1389,14 +1483,6 @@ the specific language governing permissions and limitations under the Apache Lic
1389
1483
 
1390
1484
  // abstract
1391
1485
  getPlaceholder: function () {
1392
-
1393
- // if a placeholder is specified on a select without the first empty option ignore it
1394
- if (this.select) {
1395
- if (this.select.find("option").first().text() !== "") {
1396
- return undefined;
1397
- }
1398
- }
1399
-
1400
1486
  return this.opts.element.attr("placeholder") ||
1401
1487
  this.opts.element.attr("data-placeholder") || // jquery 1.4 compat
1402
1488
  this.opts.element.data("placeholder") ||
@@ -1451,7 +1537,7 @@ the specific language governing permissions and limitations under the Apache Lic
1451
1537
 
1452
1538
  var width = resolveContainerWidth.call(this);
1453
1539
  if (width !== null) {
1454
- this.container.attr("style", "width: "+width);
1540
+ this.container.css("width", width);
1455
1541
  }
1456
1542
  }
1457
1543
  });
@@ -1464,11 +1550,12 @@ the specific language governing permissions and limitations under the Apache Lic
1464
1550
  var container = $(document.createElement("div")).attr({
1465
1551
  "class": "select2-container"
1466
1552
  }).html([
1467
- " <a href='javascript:void(0)' onclick='return false;' class='select2-choice'>",
1553
+ "<a href='javascript:void(0)' onclick='return false;' class='select2-choice' tabindex='-1'>",
1468
1554
  " <span></span><abbr class='select2-search-choice-close' style='display:none;'></abbr>",
1469
1555
  " <div><b></b></div>" ,
1470
1556
  "</a>",
1471
- " <div class='select2-drop select2-offscreen'>" ,
1557
+ "<input class='select2-focusser select2-offscreen' type='text'/>",
1558
+ "<div class='select2-drop' style='display:none'>" ,
1472
1559
  " <div class='select2-search'>" ,
1473
1560
  " <input type='text' autocomplete='off' class='select2-input'/>" ,
1474
1561
  " </div>" ,
@@ -1484,8 +1571,7 @@ the specific language governing permissions and limitations under the Apache Lic
1484
1571
 
1485
1572
  this.parent.disable.apply(this, arguments);
1486
1573
 
1487
- this.selection.attr("tabIndex", "-1");
1488
- this.search.attr("tabIndex", "-1");
1574
+ this.focusser.attr("disabled", "disabled");
1489
1575
  },
1490
1576
 
1491
1577
  // single
@@ -1494,45 +1580,45 @@ the specific language governing permissions and limitations under the Apache Lic
1494
1580
 
1495
1581
  this.parent.enable.apply(this, arguments);
1496
1582
 
1497
- if (this.elementTabIndex) {
1498
- this.selection.attr("tabIndex", this.elementTabIndex)
1499
- } else {
1500
- this.selection.removeAttr("tabIndex");
1501
- }
1502
-
1503
- this.search.removeAttr("tabIndex");
1583
+ this.focusser.removeAttr("disabled");
1504
1584
  },
1505
1585
 
1506
1586
  // single
1507
1587
  opening: function () {
1508
- this.search.show();
1509
1588
  this.parent.opening.apply(this, arguments);
1510
- this.dropdown.removeClass("select2-offscreen");
1589
+ this.focusser.attr("disabled", "disabled");
1590
+
1591
+ this.opts.element.trigger($.Event("open"));
1511
1592
  },
1512
1593
 
1513
1594
  // single
1514
1595
  close: function () {
1515
1596
  if (!this.opened()) return;
1516
1597
  this.parent.close.apply(this, arguments);
1517
- this.dropdown.removeAttr("style").addClass("select2-offscreen").insertAfter(this.selection).show();
1598
+ this.focusser.removeAttr("disabled");
1599
+ focus(this.focusser);
1518
1600
  },
1519
1601
 
1520
1602
  // single
1521
1603
  focus: function () {
1522
- this.close();
1523
- this.selection.focus();
1524
- this.opts.element.triggerHandler("focus");
1604
+ if (this.opened()) {
1605
+ this.close();
1606
+ } else {
1607
+ this.focusser.removeAttr("disabled");
1608
+ this.focusser.focus();
1609
+ }
1525
1610
  },
1526
1611
 
1527
1612
  // single
1528
1613
  isFocused: function () {
1529
- return this.selection[0] === document.activeElement;
1614
+ return this.container.hasClass("select2-container-active");
1530
1615
  },
1531
1616
 
1532
1617
  // single
1533
1618
  cancel: function () {
1534
1619
  this.parent.cancel.apply(this, arguments);
1535
- this.selection.focus();
1620
+ this.focusser.removeAttr("disabled");
1621
+ this.focusser.focus();
1536
1622
  },
1537
1623
 
1538
1624
  // single
@@ -1543,8 +1629,12 @@ the specific language governing permissions and limitations under the Apache Lic
1543
1629
  dropdown = this.dropdown,
1544
1630
  clickingInside = false;
1545
1631
 
1632
+ this.showSearch(this.opts.minimumResultsForSearch >= 0);
1633
+
1546
1634
  this.selection = selection = container.find(".select2-choice");
1547
1635
 
1636
+ this.focusser = container.find(".select2-focusser");
1637
+
1548
1638
  this.search.bind("keydown", this.bind(function (e) {
1549
1639
  if (!this.enabled) return;
1550
1640
 
@@ -1554,56 +1644,62 @@ the specific language governing permissions and limitations under the Apache Lic
1554
1644
  return;
1555
1645
  }
1556
1646
 
1557
- if (this.opened()) {
1558
- switch (e.which) {
1559
- case KEY.UP:
1560
- case KEY.DOWN:
1561
- this.moveHighlight((e.which === KEY.UP) ? -1 : 1);
1562
- killEvent(e);
1563
- return;
1564
- case KEY.TAB:
1565
- case KEY.ENTER:
1566
- this.selectHighlighted();
1567
- killEvent(e);
1568
- return;
1569
- case KEY.ESC:
1570
- this.cancel(e);
1571
- killEvent(e);
1572
- return;
1573
- }
1574
- } else {
1575
-
1576
- if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) {
1647
+ switch (e.which) {
1648
+ case KEY.UP:
1649
+ case KEY.DOWN:
1650
+ this.moveHighlight((e.which === KEY.UP) ? -1 : 1);
1651
+ killEvent(e);
1577
1652
  return;
1578
- }
1579
-
1580
- if (this.opts.openOnEnter === false && e.which === KEY.ENTER) {
1653
+ case KEY.TAB:
1654
+ case KEY.ENTER:
1655
+ this.selectHighlighted();
1656
+ killEvent(e);
1581
1657
  return;
1582
- }
1658
+ case KEY.ESC:
1659
+ this.cancel(e);
1660
+ killEvent(e);
1661
+ return;
1662
+ }
1663
+ }));
1664
+
1665
+ this.focusser.bind("keydown", this.bind(function (e) {
1666
+ if (!this.enabled) return;
1667
+
1668
+ if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) {
1669
+ return;
1670
+ }
1671
+
1672
+ if (this.opts.openOnEnter === false && e.which === KEY.ENTER) {
1673
+ killEvent(e);
1674
+ return;
1675
+ }
1583
1676
 
1677
+ if (e.which == KEY.DOWN || e.which == KEY.UP
1678
+ || (e.which == KEY.ENTER && this.opts.openOnEnter)) {
1584
1679
  this.open();
1680
+ killEvent(e);
1681
+ return;
1682
+ }
1585
1683
 
1586
- if (e.which === KEY.ENTER) {
1587
- // do not propagate the event otherwise we open, and propagate enter which closes
1588
- return;
1684
+ if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE) {
1685
+ if (this.opts.allowClear) {
1686
+ this.clear();
1589
1687
  }
1688
+ killEvent(e);
1689
+ return;
1590
1690
  }
1591
1691
  }));
1592
1692
 
1593
- this.search.bind("focus", this.bind(function() {
1594
- this.selection.attr("tabIndex", "-1");
1595
- }));
1596
- this.search.bind("blur", this.bind(function() {
1597
- if (!this.opened()) this.container.removeClass("select2-container-active");
1598
- window.setTimeout(this.bind(function() {
1599
- // restore original tab index
1600
- var ti=this.elementTabIndex || 0;
1601
- if (ti) {
1602
- this.selection.attr("tabIndex", ti);
1603
- } else {
1604
- this.selection.removeAttr("tabIndex");
1605
- }
1606
- }), 10);
1693
+
1694
+ installKeyUpChangeEvent(this.focusser);
1695
+ this.focusser.bind("keyup-change input", this.bind(function(e) {
1696
+ if (this.opened()) return;
1697
+ this.open();
1698
+ if (this.showSearchInput !== false) {
1699
+ this.search.val(this.focusser.val());
1700
+ }
1701
+ this.focusser.val("");
1702
+ killEvent(e);
1607
1703
  }));
1608
1704
 
1609
1705
  selection.delegate("abbr", "mousedown", this.bind(function (e) {
@@ -1611,7 +1707,6 @@ the specific language governing permissions and limitations under the Apache Lic
1611
1707
  this.clear();
1612
1708
  killEventImmediately(e);
1613
1709
  this.close();
1614
- this.triggerChange();
1615
1710
  this.selection.focus();
1616
1711
  }));
1617
1712
 
@@ -1620,71 +1715,47 @@ the specific language governing permissions and limitations under the Apache Lic
1620
1715
 
1621
1716
  if (this.opened()) {
1622
1717
  this.close();
1623
- this.selection.focus();
1624
1718
  } else if (this.enabled) {
1625
1719
  this.open();
1626
1720
  }
1627
1721
 
1722
+ killEvent(e);
1723
+
1628
1724
  clickingInside = false;
1629
1725
  }));
1630
1726
 
1631
1727
  dropdown.bind("mousedown", this.bind(function() { this.search.focus(); }));
1632
1728
 
1633
- selection.bind("focus", this.bind(function() {
1634
- if (!this.enabled) return;
1635
-
1636
- this.container.addClass("select2-container-active");
1637
- // hide the search so the tab key does not focus on it
1638
- this.search.attr("tabIndex", "-1");
1729
+ selection.bind("focus", this.bind(function(e) {
1730
+ killEvent(e);
1639
1731
  }));
1640
1732
 
1641
- selection.bind("blur", this.bind(function() {
1733
+ this.focusser.bind("focus", this.bind(function(){
1734
+ this.container.addClass("select2-container-active");
1735
+ })).bind("blur", this.bind(function() {
1642
1736
  if (!this.opened()) {
1643
1737
  this.container.removeClass("select2-container-active");
1644
1738
  }
1645
- window.setTimeout(this.bind(function() { this.search.attr("tabIndex", this.elementTabIndex || 0); }), 10);
1646
- }));
1647
-
1648
- selection.bind("keydown", this.bind(function(e) {
1649
- if (!this.enabled) return;
1650
-
1651
- if (e.which == KEY.DOWN || e.which == KEY.UP
1652
- || (e.which == KEY.ENTER && this.opts.openOnEnter)) {
1653
- this.open();
1654
- killEvent(e);
1655
- return;
1656
- }
1657
-
1658
- if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE) {
1659
- if (this.opts.allowClear) {
1660
- this.clear();
1661
- }
1662
- killEvent(e);
1663
- return;
1664
- }
1665
- }));
1666
- selection.bind("keypress", this.bind(function(e) {
1667
- if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE || e.which == KEY.TAB || e.which == KEY.ENTER || e.which == 0) {
1668
- return
1669
- }
1670
- var key = String.fromCharCode(e.which);
1671
- this.search.val(key);
1672
- this.open();
1673
1739
  }));
1740
+ this.search.bind("focus", this.bind(function(){
1741
+ this.container.addClass("select2-container-active");
1742
+ }))
1674
1743
 
1744
+ this.initContainerWidth();
1675
1745
  this.setPlaceholder();
1676
1746
 
1677
- this.search.bind("focus", this.bind(function() {
1678
- this.container.addClass("select2-container-active");
1679
- }));
1680
1747
  },
1681
1748
 
1682
1749
  // single
1683
1750
  clear: function() {
1751
+ var data=this.selection.data("select2-data");
1684
1752
  this.opts.element.val("");
1685
1753
  this.selection.find("span").empty();
1686
1754
  this.selection.removeData("select2-data");
1687
1755
  this.setPlaceholder();
1756
+
1757
+ this.opts.element.trigger({ type: "removed", val: this.id(data), choice: data });
1758
+ this.triggerChange({removed:data});
1688
1759
  },
1689
1760
 
1690
1761
  /**
@@ -1739,6 +1810,18 @@ the specific language governing permissions and limitations under the Apache Lic
1739
1810
  return opts;
1740
1811
  },
1741
1812
 
1813
+ // single
1814
+ getPlaceholder: function() {
1815
+ // if a placeholder is specified on a single select without the first empty option ignore it
1816
+ if (this.select) {
1817
+ if (this.select.find("option").first().text() !== "") {
1818
+ return undefined;
1819
+ }
1820
+ }
1821
+
1822
+ return this.parent.getPlaceholder.apply(this, arguments);
1823
+ },
1824
+
1742
1825
  // single
1743
1826
  setPlaceholder: function () {
1744
1827
  var placeholder = this.getPlaceholder();
@@ -1776,21 +1859,31 @@ the specific language governing permissions and limitations under the Apache Lic
1776
1859
  // hide the search box if this is the first we got the results and there are a few of them
1777
1860
 
1778
1861
  if (initial === true) {
1779
- showSearchInput = this.showSearchInput = countResults(data.results) >= this.opts.minimumResultsForSearch;
1780
- this.dropdown.find(".select2-search")[showSearchInput ? "removeClass" : "addClass"]("select2-search-hidden");
1781
-
1782
- //add "select2-with-searchbox" to the container if search box is shown
1783
- $(this.dropdown, this.container)[showSearchInput ? "addClass" : "removeClass"]("select2-with-searchbox");
1862
+ var min=this.opts.minimumResultsForSearch;
1863
+ showSearchInput = min < 0 ? false : countResults(data.results) >= min;
1864
+ this.showSearch(showSearchInput);
1784
1865
  }
1785
1866
 
1786
1867
  },
1787
1868
 
1869
+ // single
1870
+ showSearch: function(showSearchInput) {
1871
+ this.showSearchInput = showSearchInput;
1872
+
1873
+ this.dropdown.find(".select2-search")[showSearchInput ? "removeClass" : "addClass"]("select2-search-hidden");
1874
+ //add "select2-with-searchbox" to the container if search box is shown
1875
+ $(this.dropdown, this.container)[showSearchInput ? "addClass" : "removeClass"]("select2-with-searchbox");
1876
+ },
1877
+
1788
1878
  // single
1789
1879
  onSelect: function (data, options) {
1790
1880
  var old = this.opts.element.val();
1791
1881
 
1792
1882
  this.opts.element.val(this.id(data));
1793
1883
  this.updateSelection(data);
1884
+
1885
+ this.opts.element.trigger({ type: "selected", val: this.id(data), choice: data });
1886
+
1794
1887
  this.close();
1795
1888
 
1796
1889
  if (!options || !options.noFocus)
@@ -1862,7 +1955,9 @@ the specific language governing permissions and limitations under the Apache Lic
1862
1955
  self.opts.element.val(!data ? "" : self.id(data));
1863
1956
  self.updateSelection(data);
1864
1957
  self.setPlaceholder();
1865
- self.triggerChange();
1958
+ if (triggerChange) {
1959
+ self.triggerChange();
1960
+ }
1866
1961
  });
1867
1962
  }
1868
1963
  },
@@ -1870,6 +1965,7 @@ the specific language governing permissions and limitations under the Apache Lic
1870
1965
  // single
1871
1966
  clearSearch: function () {
1872
1967
  this.search.val("");
1968
+ this.focusser.val("");
1873
1969
  },
1874
1970
 
1875
1971
  // single
@@ -1919,15 +2015,14 @@ the specific language governing permissions and limitations under the Apache Lic
1919
2015
 
1920
2016
  if (opts.element.get(0).tagName.toLowerCase() === "select") {
1921
2017
  // install sthe selection initializer
1922
- opts.initSelection = function (element,callback) {
2018
+ opts.initSelection = function (element, callback) {
1923
2019
 
1924
2020
  var data = [];
2021
+
1925
2022
  element.find(":selected").each2(function (i, elm) {
1926
- data.push({id: elm.attr("value"), text: elm.text(), element: elm});
2023
+ data.push({id: elm.attr("value"), text: elm.text(), element: elm[0]});
1927
2024
  });
1928
-
1929
- if ($.isFunction(callback))
1930
- callback(data);
2025
+ callback(data);
1931
2026
  };
1932
2027
  } else if ("data" in opts) {
1933
2028
  // install default initSelection when applied to hidden input and data is local
@@ -1958,6 +2053,13 @@ the specific language governing permissions and limitations under the Apache Lic
1958
2053
  this.searchContainer = this.container.find(".select2-search-field");
1959
2054
  this.selection = selection = this.container.find(selector);
1960
2055
 
2056
+ this.search.bind("input paste", this.bind(function() {
2057
+ if (!this.enabled) return;
2058
+ if (!this.opened()) {
2059
+ this.open();
2060
+ }
2061
+ }));
2062
+
1961
2063
  this.search.bind("keydown", this.bind(function (e) {
1962
2064
  if (!this.enabled) return;
1963
2065
 
@@ -2005,8 +2107,12 @@ the specific language governing permissions and limitations under the Apache Lic
2005
2107
  return;
2006
2108
  }
2007
2109
 
2008
- if (this.opts.openOnEnter === false && e.which === KEY.ENTER) {
2009
- return;
2110
+ if (e.which === KEY.ENTER) {
2111
+ if (this.opts.openOnEnter === false) {
2112
+ return;
2113
+ } else if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
2114
+ return;
2115
+ }
2010
2116
  }
2011
2117
 
2012
2118
  this.open();
@@ -2045,6 +2151,8 @@ the specific language governing permissions and limitations under the Apache Lic
2045
2151
  this.clearPlaceholder();
2046
2152
  }));
2047
2153
 
2154
+ this.initContainerWidth();
2155
+
2048
2156
  // set the placeholder if necessary
2049
2157
  this.clearSearch();
2050
2158
  },
@@ -2098,9 +2206,7 @@ the specific language governing permissions and limitations under the Apache Lic
2098
2206
  // stretch the search box to full width of the container so as much of the placeholder is visible as possible
2099
2207
  this.resizeSearch();
2100
2208
  } else {
2101
- // we set this to " " instead of "" and later clear it on focus() because there is a firefox bug
2102
- // that does not properly render the caret when the field starts out blank
2103
- this.search.val(" ").width(10);
2209
+ this.search.val("").width(10);
2104
2210
  }
2105
2211
  },
2106
2212
 
@@ -2108,9 +2214,6 @@ the specific language governing permissions and limitations under the Apache Lic
2108
2214
  clearPlaceholder: function () {
2109
2215
  if (this.search.hasClass("select2-default")) {
2110
2216
  this.search.val("").removeClass("select2-default");
2111
- } else {
2112
- // work around for the space character we set to avoid firefox caret bug
2113
- if (this.search.val() === " ") this.search.val("");
2114
2217
  }
2115
2218
  },
2116
2219
 
@@ -2121,6 +2224,8 @@ the specific language governing permissions and limitations under the Apache Lic
2121
2224
  this.clearPlaceholder();
2122
2225
  this.resizeSearch();
2123
2226
  this.focusSearch();
2227
+
2228
+ this.opts.element.trigger($.Event("open"));
2124
2229
  },
2125
2230
 
2126
2231
  // multi
@@ -2176,6 +2281,9 @@ the specific language governing permissions and limitations under the Apache Lic
2176
2281
  // multi
2177
2282
  onSelect: function (data, options) {
2178
2283
  this.addSelectedChoice(data);
2284
+
2285
+ this.opts.element.trigger({ type: "selected", val: this.id(data), choice: data });
2286
+
2179
2287
  if (this.select || !this.opts.closeOnSelect) this.postprocessResults();
2180
2288
 
2181
2289
  if (this.opts.closeOnSelect) {
@@ -2185,10 +2293,16 @@ the specific language governing permissions and limitations under the Apache Lic
2185
2293
  if (this.countSelectableResults()>0) {
2186
2294
  this.search.width(10);
2187
2295
  this.resizeSearch();
2296
+ if (this.val().length >= this.getMaximumSelectionSize()) {
2297
+ // if we reached max selection size repaint the results so choices
2298
+ // are replaced with the max selection reached message
2299
+ this.updateResults(true);
2300
+ }
2188
2301
  this.positionDropdown();
2189
2302
  } else {
2190
2303
  // if nothing left to select close
2191
2304
  this.close();
2305
+ this.search.width(10);
2192
2306
  }
2193
2307
  }
2194
2308
 
@@ -2282,6 +2396,8 @@ the specific language governing permissions and limitations under the Apache Lic
2282
2396
  if (this.select) this.postprocessResults();
2283
2397
  }
2284
2398
  selected.remove();
2399
+
2400
+ this.opts.element.trigger({ type: "removed", val: this.id(data), choice: data });
2285
2401
  this.triggerChange({ removed: data });
2286
2402
  },
2287
2403
 
@@ -2317,7 +2433,6 @@ the specific language governing permissions and limitations under the Apache Lic
2317
2433
 
2318
2434
  // multi
2319
2435
  resizeSearch: function () {
2320
-
2321
2436
  var minimumWidth, left, maxWidth, containerLeft, searchWidth,
2322
2437
  sideBorderPadding = getSideBorderPadding(this.search);
2323
2438
 
@@ -2329,6 +2444,7 @@ the specific language governing permissions and limitations under the Apache Lic
2329
2444
  containerLeft = this.selection.offset().left;
2330
2445
 
2331
2446
  searchWidth = maxWidth - (left - containerLeft) - sideBorderPadding;
2447
+
2332
2448
  if (searchWidth < minimumWidth) {
2333
2449
  searchWidth = maxWidth - sideBorderPadding;
2334
2450
  }
@@ -2338,7 +2454,7 @@ the specific language governing permissions and limitations under the Apache Lic
2338
2454
  }
2339
2455
 
2340
2456
  if (searchWidth <= 0) {
2341
- searchWidth = minimumWidth
2457
+ searchWidth = minimumWidth;
2342
2458
  }
2343
2459
 
2344
2460
  this.search.width(searchWidth);
@@ -2400,16 +2516,13 @@ the specific language governing permissions and limitations under the Apache Lic
2400
2516
  this.setVal(val);
2401
2517
 
2402
2518
  if (this.select) {
2403
- this.select.find(":selected").each(function () {
2404
- data.push({id: $(this).attr("value"), text: $(this).text()});
2405
- });
2406
- this.updateSelection(data);
2519
+ this.opts.initSelection(this.select, this.bind(this.updateSelection));
2407
2520
  if (triggerChange) {
2408
2521
  this.triggerChange();
2409
2522
  }
2410
2523
  } else {
2411
2524
  if (this.opts.initSelection === undefined) {
2412
- throw new Error("val() cannot be called if initSelection() is not defined")
2525
+ throw new Error("val() cannot be called if initSelection() is not defined");
2413
2526
  }
2414
2527
 
2415
2528
  this.opts.initSelection(this.opts.element, function(data){
@@ -2468,7 +2581,7 @@ the specific language governing permissions and limitations under the Apache Lic
2468
2581
  .get();
2469
2582
  } else {
2470
2583
  if (!values) { values = []; }
2471
- ids = $.map(values, function(e) { return self.opts.id(e)});
2584
+ ids = $.map(values, function(e) { return self.opts.id(e); });
2472
2585
  this.setVal(ids);
2473
2586
  this.updateSelection(values);
2474
2587
  this.clearSearch();
@@ -2574,7 +2687,9 @@ the specific language governing permissions and limitations under the Apache Lic
2574
2687
  });
2575
2688
  },
2576
2689
  blurOnChange: false,
2577
- selectOnBlur: false
2690
+ selectOnBlur: false,
2691
+ adaptContainerCssClass: function(c) { return c; },
2692
+ adaptDropdownCssClass: function(c) { return null; }
2578
2693
  };
2579
2694
 
2580
2695
  // exports