select2-rails 0.0.7 → 0.0.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,5 +1,5 @@
1
1
  module Select2
2
2
  module Rails
3
- VERSION = "0.0.7"
3
+ VERSION = "0.0.9"
4
4
  end
5
5
  end
@@ -1,7 +1,7 @@
1
1
  /*
2
2
  Copyright 2012 Igor Vaynberg
3
-
4
- Version: @@ver@@ Timestamp: @@timestamp@@
3
+
4
+ Version: 2.1 Timestamp: Tue Jun 12 19:50:25 PDT 2012
5
5
 
6
6
  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this work except in
7
7
  compliance with the License. You may obtain a copy of the License in the LICENSE file, or at:
@@ -12,26 +12,6 @@
12
12
  distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
13
  See the License for the specific language governing permissions and limitations under the License.
14
14
  */
15
- (function ($) {
16
- if(typeof $.fn.each2 == "undefined"){
17
- $.fn.extend({
18
- /*
19
- * 4-10 times faster .each replacement
20
- * use it carefully, as it overrides jQuery context of element on each iteration
21
- */
22
- each2 : function (c) {
23
- var j = $([0]), i = -1, l = this.length;
24
- while (
25
- ++i < l
26
- && (j.context = j[0] = this[i])
27
- && c.call(j[0], i, j) !== false //"this"=DOM, i=index, j=jQuery object
28
- );
29
- return this;
30
- }
31
- });
32
- }
33
- })(jQuery);
34
-
35
15
  (function ($, undefined) {
36
16
  "use strict";
37
17
  /*global document, window, jQuery, console */
@@ -40,7 +20,7 @@
40
20
  return;
41
21
  }
42
22
 
43
- var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer;
23
+ var KEY, AbstractSelect2, SingleSelect2, MultiSelect2;
44
24
 
45
25
  KEY = {
46
26
  TAB: 9,
@@ -79,9 +59,6 @@
79
59
  case KEY.ALT:
80
60
  return true;
81
61
  }
82
-
83
- if (k.metaKey) return true;
84
-
85
62
  return false;
86
63
  },
87
64
  isFunctionKey: function (k) {
@@ -90,8 +67,6 @@
90
67
  }
91
68
  };
92
69
 
93
- nextUid=(function() { var counter=1; return function() { return counter++; }; }());
94
-
95
70
  function indexOf(value, array) {
96
71
  var i = 0, l = array.length, v;
97
72
 
@@ -115,7 +90,7 @@
115
90
  }
116
91
 
117
92
  /**
118
- * Compares equality of a and b taking into account that a and b may be strings, in which case localeCompare is used
93
+ * Compares equality of a and b taking into account that a and b may be strings, in which case localCompare is used
119
94
  * @param a
120
95
  * @param b
121
96
  */
@@ -157,18 +132,17 @@
157
132
  });
158
133
  }
159
134
 
160
- $(document).delegate("*", "mousemove", function (e) {
161
- $(document).data("select2-lastpos", {x: e.pageX, y: e.pageY});
162
- });
163
-
164
135
  /**
165
136
  * filters mouse events so an event is fired only if the mouse moved.
166
137
  *
167
138
  * filters out mouse events that occur when mouse is stationary but
168
139
  * the elements under the pointer are scrolled.
169
140
  */
141
+ $(document).delegate("*", "mousemove", function (e) {
142
+ $(document).data("select2-lastpos", {x: e.pageX, y: e.pageY});
143
+ });
170
144
  function installFilteredMouseMove(element) {
171
- element.bind("mousemove", function (e) {
145
+ element.bind("mousemove", function (e) {
172
146
  var lastpos = $(document).data("select2-lastpos");
173
147
  if (lastpos === undefined || lastpos.x !== e.pageX || lastpos.y !== e.pageY) {
174
148
  $(e.target).trigger("mousemove-filtered", e);
@@ -205,41 +179,25 @@
205
179
  }
206
180
 
207
181
  function measureTextWidth(e) {
208
- if (!sizer){
209
- var style = e[0].currentStyle || window.getComputedStyle(e[0], null);
210
- sizer = $("<div></div>").css({
211
- position: "absolute",
212
- left: "-1000px",
213
- top: "-1000px",
214
- display: "none",
215
- fontSize: style.fontSize,
216
- fontFamily: style.fontFamily,
217
- fontStyle: style.fontStyle,
218
- fontWeight: style.fontWeight,
219
- letterSpacing: style.letterSpacing,
220
- textTransform: style.textTransform,
221
- whiteSpace: "nowrap"
222
- });
223
- $("body").append(sizer);
224
- }
182
+ var sizer, width;
183
+ sizer = $("<div></div>").css({
184
+ position: "absolute",
185
+ left: "-1000px",
186
+ top: "-1000px",
187
+ display: "none",
188
+ fontSize: e.css("fontSize"),
189
+ fontFamily: e.css("fontFamily"),
190
+ fontStyle: e.css("fontStyle"),
191
+ fontWeight: e.css("fontWeight"),
192
+ letterSpacing: e.css("letterSpacing"),
193
+ textTransform: e.css("textTransform"),
194
+ whiteSpace: "nowrap"
195
+ });
225
196
  sizer.text(e.val());
226
- return sizer.width();
227
- }
228
-
229
- function markMatch(text, term, markup) {
230
- var match=text.toUpperCase().indexOf(term.toUpperCase()),
231
- tl=term.length;
232
-
233
- if (match<0) {
234
- markup.push(text);
235
- return;
236
- }
237
-
238
- markup.push(text.substring(0, match));
239
- markup.push("<span class='select2-match'>");
240
- markup.push(text.substring(match, match + tl));
241
- markup.push("</span>");
242
- markup.push(text.substring(match + tl, text.length));
197
+ $("body").append(sizer);
198
+ width = sizer.width();
199
+ sizer.remove();
200
+ return width;
243
201
  }
244
202
 
245
203
  /**
@@ -269,18 +227,17 @@
269
227
  requestSequence += 1; // increment the sequence
270
228
  var requestNumber = requestSequence, // this request's sequence number
271
229
  data = options.data, // ajax data function
272
- transport = options.transport || $.ajax,
273
- type = options.type || 'GET'; // set type of request (GET or POST)
230
+ transport = options.transport || $.ajax;
274
231
 
275
232
  data = data.call(this, query.term, query.page, query.context);
276
233
 
277
- if( null !== handler) { handler.abort(); }
278
-
234
+ if( null !== handler){
235
+ handler.abort();
236
+ }
279
237
  handler = transport.call(null, {
280
238
  url: options.url,
281
239
  dataType: options.dataType,
282
240
  data: data,
283
- type: type,
284
241
  success: function (data) {
285
242
  if (requestNumber < requestSequence) {
286
243
  return;
@@ -310,16 +267,12 @@
310
267
  */
311
268
  function local(options) {
312
269
  var data = options, // data elements
313
- dataText,
314
270
  text = function (item) { return ""+item.text; }; // function used to retrieve the text portion of a data item that is matched against the search
315
271
 
316
272
  if (!$.isArray(data)) {
317
273
  text = data.text;
318
274
  // if text is not a function we assume it to be a key name
319
- if (!$.isFunction(text)) {
320
- 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
321
- text = function (item) { return item[dataText]; };
322
- }
275
+ if (!$.isFunction(text)) text = function (item) { return item[data.text]; };
323
276
  data = data.results;
324
277
  }
325
278
 
@@ -365,23 +318,12 @@
365
318
  $(document).ready(function () {
366
319
  $(document).delegate("*", "mousedown focusin touchend", function (e) {
367
320
  var target = $(e.target).closest("div.select2-container").get(0);
368
- if (target) {
369
- $(document).find("div.select2-container-active").each(function () {
370
- if (this !== target) $(this).data("select2").blur();
371
- });
372
- } else {
373
- target = $(e.target).closest("div.select2-drop").get(0);
374
- $(document).find("div.select2-drop-active").each(function () {
375
- if (this !== target) $(this).data("select2").blur();
376
- });
377
- }
321
+ $(document).find("div.select2-container-active").each(function () {
322
+ if (this !== target) $(this).data("select2").blur();
323
+ });
378
324
  });
379
325
  });
380
326
 
381
- function evaluate(val) {
382
- return $.isFunction(val) ? val() : val;
383
- }
384
-
385
327
  /**
386
328
  * Creates a new class
387
329
  *
@@ -399,7 +341,6 @@
399
341
 
400
342
  AbstractSelect2 = clazz(Object, {
401
343
 
402
- // abstract
403
344
  bind: function (func) {
404
345
  var self = this;
405
346
  return function () {
@@ -407,7 +348,6 @@
407
348
  };
408
349
  },
409
350
 
410
- // abstract
411
351
  init: function (opts) {
412
352
  var results, search, resultsSelector = ".select2-results";
413
353
 
@@ -424,15 +364,11 @@
424
364
 
425
365
  this.enabled=true;
426
366
  this.container = this.createContainer();
427
- this.body = opts.element.closest("body"); // cache for future access
428
367
 
429
368
  if (opts.element.attr("class") !== undefined) {
430
369
  this.container.addClass(opts.element.attr("class"));
431
370
  }
432
371
 
433
- this.container.css(evaluate(opts.containerCss));
434
- this.container.addClass(evaluate(opts.containerCssClass));
435
-
436
372
  // swap container for the element
437
373
  this.opts.element
438
374
  .data("select2", this)
@@ -441,12 +377,8 @@
441
377
  this.container.data("select2", this);
442
378
 
443
379
  this.dropdown = this.container.find(".select2-drop");
444
- this.dropdown.css(evaluate(opts.dropdownCss));
445
- this.dropdown.addClass(evaluate(opts.dropdownCssClass));
446
- this.dropdown.data("select2", this);
447
-
448
380
  this.results = results = this.container.find(resultsSelector);
449
- this.search = search = this.container.find("input.select2-input");
381
+ this.search = search = this.container.find("input[type=text]");
450
382
 
451
383
  this.resultsPage = 0;
452
384
  this.context = null;
@@ -455,10 +387,10 @@
455
387
  this.initContainer();
456
388
 
457
389
  installFilteredMouseMove(this.results);
458
- this.dropdown.delegate(resultsSelector, "mousemove-filtered", this.bind(this.highlightUnderEvent));
390
+ this.container.delegate(resultsSelector, "mousemove-filtered", this.bind(this.highlightUnderEvent));
459
391
 
460
392
  installDebouncedScroll(80, this.results);
461
- this.dropdown.delegate(resultsSelector, "scroll-debounced", this.bind(this.loadMoreIfNeeded));
393
+ this.container.delegate(resultsSelector, "scroll-debounced", this.bind(this.loadMoreIfNeeded));
462
394
 
463
395
  // if jquery.mousewheel plugin is installed we can prevent out-of-bounds scrolling of results via mousewheel
464
396
  if ($.fn.mousewheel) {
@@ -476,11 +408,11 @@
476
408
 
477
409
  installKeyUpChangeEvent(search);
478
410
  search.bind("keyup-change", this.bind(this.updateResults));
479
- search.bind("focus", function () { search.addClass("select2-focused"); if (search.val() === " ") search.val(""); });
411
+ search.bind("focus", function () { search.addClass("select2-focused");});
480
412
  search.bind("blur", function () { search.removeClass("select2-focused");});
481
413
 
482
- this.dropdown.delegate(resultsSelector, "click", this.bind(function (e) {
483
- if ($(e.target).closest(".select2-result-selectable:not(.select2-disabled)").length > 0) {
414
+ this.container.delegate(resultsSelector, "click", this.bind(function (e) {
415
+ if ($(e.target).closest(".select2-result:not(.select2-disabled)").length > 0) {
484
416
  this.highlightUnderEvent(e);
485
417
  this.selectHighlighted(e);
486
418
  } else {
@@ -501,12 +433,10 @@
501
433
  if (opts.element.is(":disabled")) this.disable();
502
434
  },
503
435
 
504
- // abstract
505
436
  destroy: function () {
506
437
  var select2 = this.opts.element.data("select2");
507
438
  if (select2 !== undefined) {
508
439
  select2.container.remove();
509
- select2.dropdown.remove();
510
440
  select2.opts.element
511
441
  .removeData("select2")
512
442
  .unbind(".select2")
@@ -514,7 +444,6 @@
514
444
  }
515
445
  },
516
446
 
517
- // abstract
518
447
  prepareOpts: function (opts) {
519
448
  var element, select, idKey;
520
449
 
@@ -534,69 +463,10 @@
534
463
  }
535
464
 
536
465
  opts = $.extend({}, {
537
- containerCss: {},
538
- dropdownCss: {},
539
- containerCssClass: "",
540
- dropdownCssClass: "",
541
- populateResults: function(container, results, query) {
542
- var uidToData={}, populate, markup=[], uid, data, result, children, formatted, id=this.opts.id;
543
-
544
- populate=function(results, depth) {
545
-
546
- var i, l, uid, result, selectable, compound;
547
- for (i = 0, l = results.length; i < l; i = i + 1) {
548
-
549
- result=results[i];
550
- selectable=id(result) !== undefined;
551
- compound=("children" in result) && result.children.length > 0;
552
-
553
- markup.push("<li class='select2-result-depth-" + depth);
554
- markup.push(" select2-result");
555
- markup.push(selectable ? " select2-result-selectable" : " select2-result-unselectable");
556
- if (compound) { markup.push(" select2-result-with-children"); }
557
-
558
- markup.push("'");
559
-
560
- uid=nextUid();
561
- markup.push(" id='select2-result-"+uid+"'");
562
- uidToData[uid]=result;
563
-
564
- markup.push("><div class='select2-result-label'>");
565
- formatted=opts.formatResult(result, query, markup);
566
- // for backwards compat with <3.0 versions
567
- if (formatted!==undefined) {
568
- markup.push(formatted);
569
- }
570
- markup.push("</div>");
571
-
572
- if (compound) {
573
- markup.push("<ul class='select2-result-sub'>");
574
- populate(result.children, depth + 1);
575
- markup.push("</ul>");
576
- }
577
-
578
- markup.push("</li>");
579
- }
580
- };
581
-
582
- populate(results, 0);
583
-
584
- container.append(markup.join(""));
585
-
586
- for (uid in uidToData) {
587
- $("#select2-result-"+uid, container).data("select2-data", uidToData[uid]);
588
- }
589
-
590
- },
591
- formatResult: function(result, query, markup) {
592
- markMatch(result.text, query.term, markup);
593
- },
594
- formatSelection: function (data) {
595
- return data.fullText || data.text;
596
- },
466
+ formatResult: function (data) { return data.text; },
467
+ formatSelection: function (data) { return data.text; },
597
468
  formatNoMatches: function () { return "No matches found"; },
598
469
  formatInputTooShort: function (input, min) { return "Please enter " + (min - input.length) + " more characters"; },
599
- formatLoadMore: function (pageNumber) { return "Loading more results..."; },
600
470
  minimumResultsForSearch: 0,
601
471
  minimumInputLength: 0,
602
472
  id: function (e) { return e.id; },
@@ -612,37 +482,19 @@
612
482
 
613
483
  if (select) {
614
484
  opts.query = this.bind(function (query) {
615
- var data = { results: [], more: false },
485
+ var data = {results: [], more: false},
616
486
  term = query.term,
617
- children, firstChild, process;
618
-
619
- process=function(element, collection) {
620
- var group;
621
- if (element.is("option")) {
622
- if (query.matcher(term, element.text())) {
623
- collection.push({id:element.attr("value"), text:element.text(), element: element.get()});
624
- }
625
- } else if (element.is("optgroup")) {
626
- group={text:element.attr("label"), children:[], element: element.get()};
627
- element.children().each2(function(i, elm) { process(elm, group.children); });
628
- if (group.children.length>0) {
629
- collection.push(group);
630
- }
631
- }
632
- };
487
+ placeholder = this.getPlaceholder();
488
+ element.find("option").each(function (i) {
489
+ var e = $(this),
490
+ text = e.text();
633
491
 
634
- children=element.children();
492
+ if (i === 0 && placeholder !== undefined && text === "") return true;
635
493
 
636
- // ignore the placeholder option if there is one
637
- if (this.getPlaceholder() !== undefined && children.length > 0) {
638
- firstChild = children[0];
639
- if ($(firstChild).text() === "") {
640
- children=children.not(firstChild);
494
+ if (query.matcher(term, text)) {
495
+ data.results.push({id: e.attr("value"), text: text});
641
496
  }
642
- }
643
-
644
- children.each2(function(i, elm) { process(elm, data.results); });
645
-
497
+ });
646
498
  query.callback(data);
647
499
  });
648
500
  // this is needed because inside val() we construct choices from options and there id is hardcoded
@@ -656,13 +508,12 @@
656
508
  } else if ("tags" in opts) {
657
509
  opts.query = tags(opts.tags);
658
510
  opts.createSearchChoice = function (term) { return {id: term, text: term}; };
659
- opts.initSelection = function (element, callback) {
511
+ opts.initSelection = function (element) {
660
512
  var data = [];
661
513
  $(splitVal(element.val(), ",")).each(function () {
662
514
  data.push({id: this, text: this});
663
515
  });
664
-
665
- callback(data);
516
+ return data;
666
517
  };
667
518
  }
668
519
  }
@@ -677,7 +528,6 @@
677
528
  /**
678
529
  * Monitor the original element for changes and update select2 accordingly
679
530
  */
680
- // abstract
681
531
  monitorSource: function () {
682
532
  this.opts.element.bind("change.select2", this.bind(function (e) {
683
533
  if (this.opts.element.data("select2-change-triggered") !== true) {
@@ -689,19 +539,14 @@
689
539
  /**
690
540
  * Triggers the change event on the source element
691
541
  */
692
- // abstract
693
- triggerChange: function (details) {
694
-
695
- details = details || {};
696
- details= $.extend({}, details, { type: "change", val: this.val() });
697
- // prevents recursive triggering
542
+ triggerChange: function () {
543
+ // Prevents recursive triggering
698
544
  this.opts.element.data("select2-change-triggered", true);
699
- this.opts.element.trigger(details);
545
+ this.opts.element.trigger("change");
700
546
  this.opts.element.data("select2-change-triggered", false);
701
547
  },
702
548
 
703
549
 
704
- // abstract
705
550
  enable: function() {
706
551
  if (this.enabled) return;
707
552
 
@@ -709,7 +554,6 @@
709
554
  this.container.removeClass("select2-container-disabled");
710
555
  },
711
556
 
712
- // abstract
713
557
  disable: function() {
714
558
  if (!this.enabled) return;
715
559
 
@@ -719,67 +563,21 @@
719
563
  this.container.addClass("select2-container-disabled");
720
564
  },
721
565
 
722
- // abstract
723
566
  opened: function () {
724
567
  return this.container.hasClass("select2-dropdown-open");
725
568
  },
726
569
 
727
- // abstract
728
- positionDropdown: function() {
729
- var offset = this.container.offset();
730
- var height = this.container.outerHeight();
731
- var width = this.container.outerWidth();
732
- var css = {
733
- top: offset.top + height,
734
- left: offset.left,
735
- width: width
736
- }
737
- this.dropdown.css(css);
738
- },
739
-
740
- // abstract
741
- shouldOpen: function() {
742
- var event;
743
-
744
- if (this.opened()) return false;
745
-
746
- event = jQuery.Event("open");
747
- this.opts.element.trigger(event);
748
- return !event.isDefaultPrevented();
749
- },
750
-
751
- /**
752
- * Opens the dropdown
753
- *
754
- * @return {Boolean} whether or not dropdown was opened. This method will return false if, for example,
755
- * the dropdown is already open, or if the 'open' event listener on the element called preventDefault().
756
- */
757
- // abstract
758
570
  open: function () {
759
-
760
- if (!this.shouldOpen()) return false;
761
-
762
- if (this.search.val() === " ") { this.search.val(""); }
571
+ if (this.opened()) return;
763
572
 
764
573
  this.container.addClass("select2-dropdown-open").addClass("select2-container-active");
765
- if(this.dropdown[0] !== this.body.children().last()[0]) {
766
- // ensure the dropdown is the last child of body, so the z-index is always respected correctly
767
- this.dropdown.detach().appendTo(this.body);
768
- }
769
-
770
- this.dropdown.addClass("select2-drop-active");
771
-
772
- this.positionDropdown();
773
574
 
774
575
  this.updateResults(true);
775
576
  this.dropdown.show();
776
577
  this.ensureHighlightVisible();
777
578
  this.focusSearch();
778
-
779
- return true;
780
579
  },
781
580
 
782
- // abstract
783
581
  close: function () {
784
582
  if (!this.opened()) return;
785
583
 
@@ -789,31 +587,18 @@
789
587
  this.clearSearch();
790
588
  },
791
589
 
792
- // abstract
793
590
  clearSearch: function () {
794
591
 
795
592
  },
796
593
 
797
- // abstract
798
594
  ensureHighlightVisible: function () {
799
595
  var results = this.results, children, index, child, hb, rb, y, more;
800
596
 
597
+ children = results.children(".select2-result");
801
598
  index = this.highlight();
802
599
 
803
600
  if (index < 0) return;
804
601
 
805
- if (index == 0) {
806
-
807
- // if the first element is highlighted scroll all the way to the top,
808
- // that way any unselectable headers above it will also be scrolled
809
- // into view
810
-
811
- results.scrollTop(0);
812
- return;
813
- }
814
-
815
- children = results.find(".select2-result-selectable");
816
-
817
602
  child = $(children[index]);
818
603
 
819
604
  hb = child.offset().top + child.outerHeight();
@@ -838,84 +623,84 @@
838
623
  }
839
624
  },
840
625
 
841
- // abstract
842
626
  moveHighlight: function (delta) {
843
- var choices = this.results.find(".select2-result-selectable"),
627
+ var choices = this.results.children(".select2-result"),
844
628
  index = this.highlight();
845
629
 
846
630
  while (index > -1 && index < choices.length) {
847
631
  index += delta;
848
- var choice = $(choices[index]);
849
- if (choice.hasClass("select2-result-selectable") && !choice.hasClass("select2-disabled")) {
632
+ if (!$(choices[index]).hasClass("select2-disabled")) {
850
633
  this.highlight(index);
851
634
  break;
852
635
  }
853
636
  }
854
637
  },
855
638
 
856
- // abstract
857
639
  highlight: function (index) {
858
- var choices = this.results.find(".select2-result-selectable");
640
+ var choices = this.results.children(".select2-result");
859
641
 
860
642
  if (arguments.length === 0) {
861
643
  return indexOf(choices.filter(".select2-highlighted")[0], choices.get());
862
644
  }
863
645
 
646
+ choices.removeClass("select2-highlighted");
647
+
864
648
  if (index >= choices.length) index = choices.length - 1;
865
649
  if (index < 0) index = 0;
866
650
 
867
- choices.removeClass("select2-highlighted");
868
-
869
651
  $(choices[index]).addClass("select2-highlighted");
870
652
  this.ensureHighlightVisible();
871
653
 
872
- //if (this.opened()) this.focusSearch();
654
+ if (this.opened()) this.focusSearch();
873
655
  },
874
656
 
875
- // abstract
876
657
  highlightUnderEvent: function (event) {
877
- var el = $(event.target).closest(".select2-result-selectable");
878
- if (el.length > 0 && !el.is(".select2-highlighted")) {
879
- var choices = this.results.find('.select2-result-selectable');
880
- this.highlight(choices.index(el));
881
- } else if (el.length == 0) {
882
- // if we are over an unselectable item remove al highlights
883
- this.results.find(".select2-highlighted").removeClass("select2-highlighted");
658
+ var el = $(event.target).closest(".select2-result");
659
+ if (el.length > 0) {
660
+ this.highlight(el.index());
884
661
  }
885
662
  },
886
663
 
887
- // abstract
888
664
  loadMoreIfNeeded: function () {
889
665
  var results = this.results,
890
666
  more = results.find("li.select2-more-results"),
891
667
  below, // pixels the element is below the scroll fold, below==0 is when the element is starting to be visible
892
668
  offset = -1, // index of first element without data
893
- page = this.resultsPage + 1,
894
- self=this,
895
- term=this.search.val(),
896
- context=this.context;
669
+ page = this.resultsPage + 1;
897
670
 
898
671
  if (more.length === 0) return;
672
+
899
673
  below = more.offset().top - results.offset().top - results.height();
900
674
 
901
675
  if (below <= 0) {
902
676
  more.addClass("select2-active");
903
677
  this.opts.query({
904
- term: term,
678
+ term: this.search.val(),
905
679
  page: page,
906
- context: context,
680
+ context: this.context,
907
681
  matcher: this.opts.matcher,
908
682
  callback: this.bind(function (data) {
909
-
910
- self.opts.populateResults.call(this, results, data.results, {term: term, page: page, context:context});
911
-
912
- if (data.more===true) {
913
- more.detach().appendTo(results.children(":last")).text(self.opts.formatLoadMore(page+1));
914
- window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10);
683
+ var parts = [], self = this;
684
+ $(data.results).each(function () {
685
+ parts.push("<li class='select2-result'>");
686
+ parts.push(self.opts.formatResult(this));
687
+ parts.push("</li>");
688
+ });
689
+ more.before(parts.join(""));
690
+ results.find(".select2-result").each(function (i) {
691
+ var e = $(this);
692
+ if (e.data("select2-data") !== undefined) {
693
+ offset = i;
694
+ } else {
695
+ e.data("select2-data", data.results[i - offset - 1]);
696
+ }
697
+ });
698
+ if (data.more) {
699
+ more.removeClass("select2-active");
915
700
  } else {
916
701
  more.remove();
917
702
  }
918
- self.resultsPage = page;
703
+ this.resultsPage = page;
919
704
  })});
920
705
  }
921
706
  },
@@ -923,7 +708,6 @@
923
708
  /**
924
709
  * @param initial whether or not this is the call to this method right after the dropdown has been opened
925
710
  */
926
- // abstract
927
711
  updateResults: function (initial) {
928
712
  var search = this.search, results = this.results, opts = this.opts, self=this;
929
713
 
@@ -934,14 +718,10 @@
934
718
 
935
719
  search.addClass("select2-active");
936
720
 
937
- function postRender() {
938
- results.scrollTop(0);
939
- search.removeClass("select2-active");
940
- }
941
-
942
721
  function render(html) {
943
722
  results.html(html);
944
- postRender();
723
+ results.scrollTop(0);
724
+ search.removeClass("select2-active");
945
725
  }
946
726
 
947
727
  if (search.val().length < opts.minimumInputLength) {
@@ -956,7 +736,8 @@
956
736
  context: null,
957
737
  matcher: opts.matcher,
958
738
  callback: this.bind(function (data) {
959
- var def; // default choice
739
+ var parts = [], // html parts
740
+ def; // default choice
960
741
 
961
742
  // save context, if any
962
743
  this.context = (data.context===undefined) ? null : data.context;
@@ -979,36 +760,41 @@
979
760
  return;
980
761
  }
981
762
 
982
- results.empty();
983
- self.opts.populateResults.call(this, results, data.results, {term: search.val(), page: this.resultsPage, context:null});
984
- postRender();
763
+ $(data.results).each(function () {
764
+ parts.push("<li class='select2-result'>");
765
+ parts.push(opts.formatResult(this));
766
+ parts.push("</li>");
767
+ });
985
768
 
986
769
  if (data.more === true) {
987
- results.children().filter(":last").append("<li class='select2-more-results'>" + opts.formatLoadMore(this.resultsPage) + "</li>");
988
- window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10);
770
+ parts.push("<li class='select2-more-results'>Loading more results...</li>");
989
771
  }
990
772
 
773
+ render(parts.join(""));
774
+ results.children(".select2-result").each(function (i) {
775
+ var d = data.results[i];
776
+ $(this).data("select2-data", d);
777
+ });
991
778
  this.postprocessResults(data, initial);
992
779
  })});
993
780
  },
994
781
 
995
- // abstract
996
782
  cancel: function () {
997
783
  this.close();
998
784
  },
999
785
 
1000
- // abstract
1001
786
  blur: function () {
1002
- this.close();
1003
- this.container.removeClass("select2-container-active");
1004
- this.dropdown.removeClass("select2-drop-active");
1005
- // synonymous to .is(':focus'), which is available in jquery >= 1.6
1006
- if (this.search[0] === document.activeElement) { this.search.blur(); }
1007
- this.clearSearch();
1008
- this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
787
+ /* we do this in a timeout so that current event processing can complete before this code is executed.
788
+ this allows tab index to be preserved even if this code blurs the textfield */
789
+ window.setTimeout(this.bind(function () {
790
+ this.close();
791
+ this.container.removeClass("select2-container-active");
792
+ this.clearSearch();
793
+ this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
794
+ this.search.blur();
795
+ }), 10);
1009
796
  },
1010
797
 
1011
- // abstract
1012
798
  focusSearch: function () {
1013
799
  /* we do this in a timeout so that current event processing can complete before this code is executed.
1014
800
  this makes sure the search field is focussed even if the current event would blur it */
@@ -1017,20 +803,15 @@
1017
803
  }), 10);
1018
804
  },
1019
805
 
1020
- // abstract
1021
806
  selectHighlighted: function () {
1022
- var data = this.results.find(".select2-highlighted").not(".select2-disabled").closest('.select2-result-selectable').data("select2-data");
807
+ var data = this.results.find(".select2-highlighted:not(.select2-disabled)").data("select2-data");
1023
808
  if (data) {
1024
809
  this.onSelect(data);
1025
810
  }
1026
811
  },
1027
812
 
1028
- // abstract
1029
813
  getPlaceholder: function () {
1030
- return this.opts.element.attr("placeholder") ||
1031
- this.opts.element.attr("data-placeholder") || // jquery 1.4 compat
1032
- this.opts.element.data("placeholder") ||
1033
- this.opts.placeholder;
814
+ return this.opts.element.attr("placeholder") || this.opts.element.data("placeholder") || this.opts.placeholder;
1034
815
  },
1035
816
 
1036
817
  /**
@@ -1041,7 +822,6 @@
1041
822
  *
1042
823
  * @returns The width string (with units) for the container.
1043
824
  */
1044
- // abstract
1045
825
  getContainerWidth: function () {
1046
826
  var style, attrs, matches, i, l;
1047
827
  if (this.opts.width !== undefined)
@@ -1057,64 +837,61 @@
1057
837
  return matches[1];
1058
838
  }
1059
839
  }
1060
- return (this.opts.element.width() === 0 ? 'auto' : this.opts.element.width() + 'px');
840
+ return this.opts.element.width() + 'px';
1061
841
  }
1062
842
  });
1063
843
 
1064
844
  SingleSelect2 = clazz(AbstractSelect2, {
1065
845
 
1066
- // single
1067
846
  createContainer: function () {
1068
847
  return $("<div></div>", {
1069
848
  "class": "select2-container",
1070
849
  "style": "width: " + this.getContainerWidth()
1071
850
  }).html([
1072
- " <a href='javascript:void(0)' class='select2-choice'><input type='text' class='select2-offscreen select2-focusser'/>",
851
+ " <a href='javascript:void(0)' class='select2-choice'>",
1073
852
  " <span></span><abbr class='select2-search-choice-close' style='display:none;'></abbr>",
1074
853
  " <div><b></b></div>" ,
1075
854
  "</a>",
1076
855
  " <div class='select2-drop' style='display:none;'>" ,
1077
856
  " <div class='select2-search'>" ,
1078
- " <input type='text' autocomplete='off' class='select2-input'/>" ,
857
+ " <input type='text' autocomplete='off'/>" ,
1079
858
  " </div>" ,
1080
859
  " <ul class='select2-results'>" ,
1081
860
  " </ul>" ,
1082
861
  "</div>"].join(""));
1083
862
  },
1084
863
 
1085
- // single
864
+ open: function () {
865
+
866
+ if (this.opened()) return;
867
+
868
+ this.parent.open.apply(this, arguments);
869
+
870
+ },
871
+
1086
872
  close: function () {
1087
873
  if (!this.opened()) return;
1088
874
  this.parent.close.apply(this, arguments);
1089
875
  },
1090
876
 
1091
- // single
1092
877
  focus: function () {
1093
878
  this.close();
1094
879
  this.selection.focus();
1095
880
  },
1096
881
 
1097
- // single
1098
882
  isFocused: function () {
1099
- return this.selection[0] === document.activeElement;
883
+ return this.selection.is(":focus");
1100
884
  },
1101
885
 
1102
- // single
1103
886
  cancel: function () {
1104
887
  this.parent.cancel.apply(this, arguments);
1105
888
  this.selection.focus();
1106
889
  },
1107
890
 
1108
- // single
1109
891
  initContainer: function () {
1110
892
 
1111
- var selection,
1112
- container = this.container,
1113
- dropdown = this.dropdown,
1114
- containers = $([this.container.get(0), this.dropdown.get(0)]),
1115
- clickingInside = false,
1116
- selector = ".select2-choice",
1117
- focusser=container.find("input.select2-focusser");
893
+ var selection, container = this.container, clickingInside = false,
894
+ selector = ".select2-choice";
1118
895
 
1119
896
  this.selection = selection = container.find(selector);
1120
897
 
@@ -1132,12 +909,12 @@
1132
909
  return;
1133
910
  case KEY.ESC:
1134
911
  this.cancel(e);
1135
- killEvent(e);
912
+ e.preventDefault();
1136
913
  return;
1137
914
  }
1138
915
  }));
1139
916
 
1140
- containers.delegate(selector, "click", this.bind(function (e) {
917
+ container.delegate(selector, "click", this.bind(function (e) {
1141
918
  clickingInside = true;
1142
919
 
1143
920
  if (this.opened()) {
@@ -1150,7 +927,7 @@
1150
927
 
1151
928
  clickingInside = false;
1152
929
  }));
1153
- containers.delegate(selector, "keydown", this.bind(function (e) {
930
+ container.delegate(selector, "keydown", this.bind(function (e) {
1154
931
  if (!this.enabled || e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) {
1155
932
  return;
1156
933
  }
@@ -1164,80 +941,56 @@
1164
941
  killEvent(e);
1165
942
  }
1166
943
  }));
1167
- containers.delegate(selector, "focus", function () { if (this.enabled) { containers.addClass("select2-container-active"); dropdown.addClass("select2-drop-active"); }});
1168
- containers.delegate(selector, "blur", this.bind(function (e) {
944
+ container.delegate(selector, "focus", function () { if (this.enabled) container.addClass("select2-container-active"); });
945
+ container.delegate(selector, "blur", this.bind(function () {
1169
946
  if (clickingInside) return;
1170
- if (e.target===focusser.get(0)) return; // ignore blurs from focusser
1171
- if (!this.opened()) { this.blur(); }
947
+ if (!this.opened()) this.blur();
1172
948
  }));
1173
949
 
1174
950
  selection.delegate("abbr", "click", this.bind(function (e) {
1175
951
  if (!this.enabled) return;
1176
- this.clear();
952
+ this.val("");
1177
953
  killEvent(e);
1178
954
  this.close();
1179
955
  this.triggerChange();
1180
- selection.focus();
1181
956
  }));
1182
957
 
1183
958
  this.setPlaceholder();
1184
-
1185
- focusser.bind("focus", function() { selection.focus(); });
1186
- selection.bind("focus", this.bind(function() {
1187
- focusser.hide();
1188
- this.container.addClass("select2-container-active");
1189
- }));
1190
- selection.bind("blur", function() { focusser.show(); });
1191
- this.opts.element.bind("open", function() { focusser.hide(); });
1192
- },
1193
-
1194
- clear: function() {
1195
- this.opts.element.val("");
1196
- this.selection.find("span").empty();
1197
- this.selection.removeData("select2-data");
1198
- this.setPlaceholder();
1199
959
  },
1200
960
 
1201
961
  /**
1202
962
  * Sets selection based on source element's value
1203
963
  */
1204
- // single
1205
964
  initSelection: function () {
1206
965
  var selected;
1207
966
  if (this.opts.element.val() === "") {
1208
967
  this.updateSelection({id: "", text: ""});
1209
- this.close();
1210
- this.setPlaceholder();
1211
968
  } else {
1212
- var self = this;
1213
- this.opts.initSelection.call(null, this.opts.element, function(selected){
1214
- if (selected !== undefined && selected !== null) {
1215
- self.updateSelection(selected);
1216
- self.close();
1217
- self.setPlaceholder();
1218
- }
1219
- });
969
+ selected = this.opts.initSelection.call(null, this.opts.element);
970
+ if (selected !== undefined && selected !== null) {
971
+ this.updateSelection(selected);
972
+ }
1220
973
  }
974
+
975
+ this.close();
976
+ this.setPlaceholder();
1221
977
  },
1222
978
 
1223
- // single
1224
979
  prepareOpts: function () {
1225
980
  var opts = this.parent.prepareOpts.apply(this, arguments);
1226
981
 
1227
982
  if (opts.element.get(0).tagName.toLowerCase() === "select") {
1228
- // install the selection initializer
1229
- opts.initSelection = function (element, callback) {
983
+ // install sthe selection initializer
984
+ opts.initSelection = function (element) {
1230
985
  var selected = element.find(":selected");
1231
986
  // a single select box always has a value, no need to null check 'selected'
1232
- if ($.isFunction(callback))
1233
- callback({id: selected.attr("value"), text: selected.text()});
987
+ return {id: selected.attr("value"), text: selected.text()};
1234
988
  };
1235
989
  }
1236
990
 
1237
991
  return opts;
1238
992
  },
1239
993
 
1240
- // single
1241
994
  setPlaceholder: function () {
1242
995
  var placeholder = this.getPlaceholder();
1243
996
 
@@ -1257,14 +1010,13 @@
1257
1010
  }
1258
1011
  },
1259
1012
 
1260
- // single
1261
1013
  postprocessResults: function (data, initial) {
1262
1014
  var selected = 0, self = this, showSearchInput = true;
1263
1015
 
1264
1016
  // find the selected element in the result list
1265
1017
 
1266
- this.results.find(".select2-result-selectable").each2(function (i, elm) {
1267
- if (equal(self.id(elm.data("select2-data")), self.opts.element.val())) {
1018
+ this.results.find(".select2-result").each(function (i) {
1019
+ if (equal(self.id($(this).data("select2-data")), self.opts.element.val())) {
1268
1020
  selected = i;
1269
1021
  return false;
1270
1022
  }
@@ -1277,18 +1029,15 @@
1277
1029
  // hide the search box if this is the first we got the results and there are a few of them
1278
1030
 
1279
1031
  if (initial === true) {
1280
- // TODO below we use data.results.length, but what we really need is something recursive to calc the length
1281
- // TODO in case there are optgroups
1282
1032
  showSearchInput = this.showSearchInput = data.results.length >= this.opts.minimumResultsForSearch;
1283
- this.dropdown.find(".select2-search")[showSearchInput ? "removeClass" : "addClass"]("select2-search-hidden");
1033
+ this.container.find(".select2-search")[showSearchInput ? "removeClass" : "addClass"]("select2-search-hidden");
1284
1034
 
1285
1035
  //add "select2-with-searchbox" to the container if search box is shown
1286
- $(this.dropdown, this.container)[showSearchInput ? "addClass" : "removeClass"]("select2-with-searchbox");
1036
+ this.container[showSearchInput ? "addClass" : "removeClass"]("select2-with-searchbox");
1287
1037
  }
1288
1038
 
1289
1039
  },
1290
1040
 
1291
- // single
1292
1041
  onSelect: function (data) {
1293
1042
  var old = this.opts.element.val();
1294
1043
 
@@ -1300,11 +1049,7 @@
1300
1049
  if (!equal(old, this.id(data))) { this.triggerChange(); }
1301
1050
  },
1302
1051
 
1303
- // single
1304
1052
  updateSelection: function (data) {
1305
-
1306
- this.selection.data("select2-data", data);
1307
-
1308
1053
  this.selection
1309
1054
  .find("span")
1310
1055
  .html(this.opts.formatSelection(data));
@@ -1316,7 +1061,6 @@
1316
1061
  }
1317
1062
  },
1318
1063
 
1319
- // single
1320
1064
  val: function () {
1321
1065
  var val, data = null;
1322
1066
 
@@ -1330,8 +1074,8 @@
1330
1074
  // val is an id
1331
1075
  this.select
1332
1076
  .val(val)
1333
- .find(":selected").each2(function (i, elm) {
1334
- data = {id: elm.attr("value"), text: elm.text()};
1077
+ .find(":selected").each(function () {
1078
+ data = {id: $(this).attr("value"), text: $(this).text()};
1335
1079
  return false;
1336
1080
  });
1337
1081
  this.updateSelection(data);
@@ -1344,29 +1088,13 @@
1344
1088
 
1345
1089
  },
1346
1090
 
1347
- // single
1348
1091
  clearSearch: function () {
1349
1092
  this.search.val("");
1350
- },
1351
-
1352
- // single
1353
- data: function(value) {
1354
- if (arguments.length === 0) {
1355
- return this.selection.data("select2-data");
1356
- } else {
1357
- if (!value || value === "") {
1358
- this.clear();
1359
- } else {
1360
- this.opts.element.val(!value ? "" : this.id(value));
1361
- this.updateSelection(value);
1362
- }
1363
- }
1364
1093
  }
1365
1094
  });
1366
1095
 
1367
1096
  MultiSelect2 = clazz(AbstractSelect2, {
1368
1097
 
1369
- // multi
1370
1098
  createContainer: function () {
1371
1099
  return $("<div></div>", {
1372
1100
  "class": "select2-container select2-container-multi",
@@ -1375,16 +1103,15 @@
1375
1103
  " <ul class='select2-choices'>",
1376
1104
  //"<li class='select2-search-choice'><span>California</span><a href="javascript:void(0)" class="select2-search-choice-close"></a></li>" ,
1377
1105
  " <li class='select2-search-field'>" ,
1378
- " <input type='text' autocomplete='off' style='width: 25px;' class='select2-input'>" ,
1106
+ " <input type='text' autocomplete='off' style='width: 25px;'>" ,
1379
1107
  " </li>" ,
1380
1108
  "</ul>" ,
1381
- "<div class='select2-drop select2-drop-multi' style='display:none;'>" ,
1109
+ "<div class='select2-drop' style='display:none;'>" ,
1382
1110
  " <ul class='select2-results'>" ,
1383
1111
  " </ul>" ,
1384
1112
  "</div>"].join(""));
1385
1113
  },
1386
1114
 
1387
- // multi
1388
1115
  prepareOpts: function () {
1389
1116
  var opts = this.parent.prepareOpts.apply(this, arguments);
1390
1117
 
@@ -1396,22 +1123,18 @@
1396
1123
 
1397
1124
  if (opts.element.get(0).tagName.toLowerCase() === "select") {
1398
1125
  // install sthe selection initializer
1399
- opts.initSelection = function (element,callback) {
1400
-
1126
+ opts.initSelection = function (element) {
1401
1127
  var data = [];
1402
- element.find(":selected").each2(function (i, elm) {
1403
- data.push({id: elm.attr("value"), text: elm.text()});
1128
+ element.find(":selected").each(function () {
1129
+ data.push({id: $(this).attr("value"), text: $(this).text()});
1404
1130
  });
1405
-
1406
- if ($.isFunction(callback))
1407
- callback(data);
1131
+ return data;
1408
1132
  };
1409
1133
  }
1410
1134
 
1411
1135
  return opts;
1412
1136
  },
1413
1137
 
1414
- // multi
1415
1138
  initContainer: function () {
1416
1139
 
1417
1140
  var selector = ".select2-choices", selection;
@@ -1456,7 +1179,7 @@
1456
1179
  return;
1457
1180
  case KEY.ESC:
1458
1181
  this.cancel(e);
1459
- killEvent(e);
1182
+ e.preventDefault();
1460
1183
  return;
1461
1184
  }
1462
1185
  }
@@ -1485,7 +1208,6 @@
1485
1208
  this.container.delegate(selector, "focus", this.bind(function () {
1486
1209
  if (!this.enabled) return;
1487
1210
  this.container.addClass("select2-container-active");
1488
- this.dropdown.addClass("select2-drop-active");
1489
1211
  this.clearPlaceholder();
1490
1212
  }));
1491
1213
 
@@ -1493,7 +1215,6 @@
1493
1215
  this.clearSearch();
1494
1216
  },
1495
1217
 
1496
- // multi
1497
1218
  enable: function() {
1498
1219
  if (this.enabled) return;
1499
1220
 
@@ -1502,7 +1223,6 @@
1502
1223
  this.search.show();
1503
1224
  },
1504
1225
 
1505
- // multi
1506
1226
  disable: function() {
1507
1227
  if (!this.enabled) return;
1508
1228
 
@@ -1511,77 +1231,66 @@
1511
1231
  this.search.hide();
1512
1232
  },
1513
1233
 
1514
- // multi
1515
1234
  initSelection: function () {
1516
1235
  var data;
1517
1236
  if (this.opts.element.val() === "") {
1518
1237
  this.updateSelection([]);
1519
- this.close();
1520
- // set the placeholder if necessary
1521
- this.clearSearch();
1522
1238
  }
1523
1239
  if (this.select || this.opts.element.val() !== "") {
1524
- var self = this;
1525
- this.opts.initSelection.call(null, this.opts.element, function(data){
1526
- if (data !== undefined && data !== null) {
1527
- self.updateSelection(data);
1528
- self.close();
1529
- // set the placeholder if necessary
1530
- self.clearSearch();
1531
- }
1532
- });
1240
+ data = this.opts.initSelection.call(null, this.opts.element);
1241
+ if (data !== undefined && data !== null) {
1242
+ this.updateSelection(data);
1243
+ }
1533
1244
  }
1245
+
1246
+ this.close();
1247
+
1248
+ // set the placeholder if necessary
1249
+ this.clearSearch();
1534
1250
  },
1535
1251
 
1536
- // multi
1537
1252
  clearSearch: function () {
1538
1253
  var placeholder = this.getPlaceholder();
1539
1254
 
1540
- if (placeholder !== undefined && this.getVal().length === 0 && this.search.hasClass("select2-focused") === false) {
1255
+ if (placeholder !== undefined
1256
+ && this.getVal().length === 0
1257
+ && this.search.hasClass("select2-focused") === false) {
1258
+
1541
1259
  this.search.val(placeholder).addClass("select2-default");
1542
1260
  // stretch the search box to full width of the container so as much of the placeholder is visible as possible
1543
1261
  this.search.width(this.getContainerWidth());
1544
1262
  } else {
1545
- // we set this to " " instead of "" and later clear it on focus() because there is a firefox bug
1546
- // that does not properly render the caret when the field starts out blank
1547
- this.search.val(" ").width(10);
1263
+ this.search.val("").width(10);
1548
1264
  }
1549
1265
  },
1550
1266
 
1551
- // multi
1552
1267
  clearPlaceholder: function () {
1553
1268
  if (this.search.hasClass("select2-default")) {
1554
1269
  this.search.val("").removeClass("select2-default");
1555
1270
  }
1556
1271
  },
1557
1272
 
1558
- // multi
1559
1273
  open: function () {
1560
- if (this.parent.open.apply(this, arguments) === false) return false;
1561
- this.clearPlaceholder();
1562
- this.resizeSearch();
1274
+ if (this.opened()) return;
1275
+ this.parent.open.apply(this, arguments);
1276
+ this.resizeSearch();
1563
1277
  this.focusSearch();
1564
- return true;
1565
1278
  },
1566
1279
 
1567
- // multi
1568
1280
  close: function () {
1569
1281
  if (!this.opened()) return;
1570
1282
  this.parent.close.apply(this, arguments);
1571
1283
  },
1572
1284
 
1573
- // multi
1574
1285
  focus: function () {
1575
1286
  this.close();
1576
1287
  this.search.focus();
1577
1288
  },
1578
1289
 
1579
- // multi
1580
1290
  isFocused: function () {
1581
1291
  return this.search.hasClass("select2-focused");
1582
1292
  },
1583
1293
 
1584
- // multi
1585
1294
  updateSelection: function (data) {
1586
1295
  var ids = [], filtered = [], self = this;
1587
1296
 
@@ -1601,7 +1310,6 @@
1601
1310
  self.postprocessResults();
1602
1311
  },
1603
1312
 
1604
- // multi
1605
1313
  onSelect: function (data) {
1606
1314
  this.addSelectedChoice(data);
1607
1315
  if (this.select) { this.postprocessResults(); }
@@ -1616,18 +1324,16 @@
1616
1324
 
1617
1325
  // since its not possible to select an element that has already been
1618
1326
  // added we do not need to check if this is a new element before firing change
1619
- this.triggerChange({ added: data });
1327
+ this.triggerChange();
1620
1328
 
1621
1329
  this.focusSearch();
1622
1330
  },
1623
1331
 
1624
- // multi
1625
1332
  cancel: function () {
1626
1333
  this.close();
1627
1334
  this.focusSearch();
1628
1335
  },
1629
1336
 
1630
- // multi
1631
1337
  addSelectedChoice: function (data) {
1632
1338
  var choice,
1633
1339
  id = this.id(data),
@@ -1653,7 +1359,6 @@
1653
1359
  })).bind("focus", this.bind(function () {
1654
1360
  if (!this.enabled) return;
1655
1361
  this.container.addClass("select2-container-active");
1656
- this.dropdown.addClass("select2-drop-active");
1657
1362
  }));
1658
1363
 
1659
1364
  choice.data("select2-data", data);
@@ -1663,10 +1368,8 @@
1663
1368
  this.setVal(val);
1664
1369
  },
1665
1370
 
1666
- // multi
1667
1371
  unselect: function (selected) {
1668
1372
  var val = this.getVal(),
1669
- data,
1670
1373
  index;
1671
1374
 
1672
1375
  selected = selected.closest(".select2-search-choice");
@@ -1675,9 +1378,7 @@
1675
1378
  throw "Invalid argument: " + selected + ". Must be .select2-search-choice";
1676
1379
  }
1677
1380
 
1678
- data = selected.data("select2-data");
1679
-
1680
- index = indexOf(this.id(data), val);
1381
+ index = indexOf(this.id(selected.data("select2-data")), val);
1681
1382
 
1682
1383
  if (index >= 0) {
1683
1384
  val.splice(index, 1);
@@ -1685,17 +1386,16 @@
1685
1386
  if (this.select) this.postprocessResults();
1686
1387
  }
1687
1388
  selected.remove();
1688
- this.triggerChange({ removed: data });
1389
+ this.triggerChange();
1689
1390
  },
1690
1391
 
1691
- // multi
1692
1392
  postprocessResults: function () {
1693
1393
  var val = this.getVal(),
1694
- choices = this.results.find(".select2-result-selectable"),
1394
+ choices = this.results.find(".select2-result"),
1695
1395
  self = this;
1696
1396
 
1697
- choices.each2(function (i, choice) {
1698
- var id = self.id(choice.data("select2-data"));
1397
+ choices.each(function () {
1398
+ var choice = $(this), id = self.id(choice.data("select2-data"));
1699
1399
  if (indexOf(id, val) >= 0) {
1700
1400
  choice.addClass("select2-disabled");
1701
1401
  } else {
@@ -1703,8 +1403,8 @@
1703
1403
  }
1704
1404
  });
1705
1405
 
1706
- choices.each2(function (i, choice) {
1707
- if (!choice.hasClass("select2-disabled")) {
1406
+ choices.each(function (i) {
1407
+ if (!$(this).hasClass("select2-disabled")) {
1708
1408
  self.highlight(i);
1709
1409
  return false;
1710
1410
  }
@@ -1712,11 +1412,9 @@
1712
1412
 
1713
1413
  },
1714
1414
 
1715
- // multi
1716
1415
  resizeSearch: function () {
1717
1416
 
1718
- var minimumWidth, left, maxWidth, containerLeft, searchWidth,
1719
- sideBorderPadding = getSideBorderPadding(this.search);
1417
+ var minimumWidth, left, maxWidth, containerLeft, searchWidth;
1720
1418
 
1721
1419
  minimumWidth = measureTextWidth(this.search) + 10;
1722
1420
 
@@ -1725,19 +1423,18 @@
1725
1423
  maxWidth = this.selection.width();
1726
1424
  containerLeft = this.selection.offset().left;
1727
1425
 
1728
- searchWidth = maxWidth - (left - containerLeft) - sideBorderPadding;
1426
+ searchWidth = maxWidth - (left - containerLeft) - getSideBorderPadding(this.search);
1729
1427
 
1730
1428
  if (searchWidth < minimumWidth) {
1731
- searchWidth = maxWidth - sideBorderPadding;
1429
+ searchWidth = maxWidth - getSideBorderPadding(this.search);
1732
1430
  }
1733
1431
 
1734
1432
  if (searchWidth < 40) {
1735
- searchWidth = maxWidth - sideBorderPadding;
1433
+ searchWidth = maxWidth - getSideBorderPadding(this.search);
1736
1434
  }
1737
1435
  this.search.width(searchWidth);
1738
1436
  },
1739
1437
 
1740
- // multi
1741
1438
  getVal: function () {
1742
1439
  var val;
1743
1440
  if (this.select) {
@@ -1749,7 +1446,6 @@
1749
1446
  }
1750
1447
  },
1751
1448
 
1752
- // multi
1753
1449
  setVal: function (val) {
1754
1450
  var unique;
1755
1451
  if (this.select) {
@@ -1764,7 +1460,6 @@
1764
1460
  }
1765
1461
  },
1766
1462
 
1767
- // multi
1768
1463
  val: function () {
1769
1464
  var val, data = [], self=this;
1770
1465
 
@@ -1783,6 +1478,7 @@
1783
1478
  this.updateSelection(data);
1784
1479
  } else {
1785
1480
  val = (val === null) ? [] : val;
1481
+ this.setVal(val);
1786
1482
  // val is a list of objects
1787
1483
  $(val).each(function () { data.push(self.id(this)); });
1788
1484
  this.setVal(data);
@@ -1791,8 +1487,6 @@
1791
1487
 
1792
1488
  this.clearSearch();
1793
1489
  },
1794
-
1795
- // multi
1796
1490
  onSortStart: function() {
1797
1491
  if (this.select) {
1798
1492
  throw new Error("Sorting of elements is not supported when attached to <select>. Attach to <input type='hidden'/> instead.");
@@ -1803,8 +1497,6 @@
1803
1497
  // hide the container
1804
1498
  this.searchContainer.hide();
1805
1499
  },
1806
-
1807
- // multi
1808
1500
  onSortEnd:function() {
1809
1501
 
1810
1502
  var val=[], self=this;
@@ -1813,7 +1505,7 @@
1813
1505
  this.searchContainer.show();
1814
1506
  // make sure the search container is the last item in the list
1815
1507
  this.searchContainer.appendTo(this.searchContainer.parent());
1816
- // since we collapsed the width in dragStarted, we resize it here
1508
+ // since we collapsed the width in dragStarteed, we resize it here
1817
1509
  this.resizeSearch();
1818
1510
 
1819
1511
  // update selection
@@ -1823,22 +1515,6 @@
1823
1515
  });
1824
1516
  this.setVal(val);
1825
1517
  this.triggerChange();
1826
- },
1827
-
1828
- // multi
1829
- data: function(values) {
1830
- var self=this, ids;
1831
- if (arguments.length === 0) {
1832
- return this.selection
1833
- .find(".select2-search-choice")
1834
- .map(function() { return $(this).data("select2-data"); })
1835
- .get();
1836
- } else {
1837
- ids = $.map(values, function(e) { return self.opts.id(e)});
1838
- this.setVal(ids);
1839
- this.updateSelection(values);
1840
- this.clearSearch();
1841
- }
1842
1518
  }
1843
1519
  });
1844
1520
 
@@ -1847,7 +1523,7 @@
1847
1523
  var args = Array.prototype.slice.call(arguments, 0),
1848
1524
  opts,
1849
1525
  select2,
1850
- value, multiple, allowedMethods = ["val", "destroy", "open", "close", "focus", "isFocused", "container", "onSortStart", "onSortEnd", "enable", "disable", "positionDropdown", "data"];
1526
+ value, multiple, allowedMethods = ["val", "destroy", "open", "close", "focus", "isFocused", "container", "onSortStart", "onSortEnd", "enable", "disable"];
1851
1527
 
1852
1528
  this.each(function () {
1853
1529
  if (args.length === 0 || typeof(args[0]) === "object") {
@@ -1892,8 +1568,7 @@
1892
1568
  local: local,
1893
1569
  tags: tags
1894
1570
  }, util: {
1895
- debounce: debounce,
1896
- markMatch: markMatch
1571
+ debounce: debounce
1897
1572
  }, "class": {
1898
1573
  "abstract": AbstractSelect2,
1899
1574
  "single": SingleSelect2,