select2-rails 3.2.1 → 3.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +3 -3
- data/lib/select2-rails/version.rb +1 -1
- data/select2-rails.gemspec +1 -0
- data/vendor/assets/images/select2-spinner.gif +0 -0
- data/vendor/assets/images/select2.png +0 -0
- data/vendor/assets/images/select2x2.png +0 -0
- data/vendor/assets/javascripts/select2.js +460 -271
- data/vendor/assets/stylesheets/select2.css.scss +324 -259
- metadata +95 -80
data/README.md
CHANGED
@@ -26,13 +26,13 @@ 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.
|
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`.
|
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
|
|
33
33
|
## Contributions
|
34
34
|
|
35
|
-
If you
|
35
|
+
If you want to contribute, please:
|
36
36
|
|
37
37
|
* Fork the project.
|
38
38
|
* Make your feature addition or bug fix.
|
@@ -40,4 +40,4 @@ If you wont to contribute, please:
|
|
40
40
|
|
41
41
|
## Copyright
|
42
42
|
|
43
|
-
Copyright (c) 2012 Rogerio Medeiros. See [LICENSE](https://github.com/argerim/select2-rails/blob/master/LICENSE) for details.
|
43
|
+
Copyright (c) 2012 Rogerio Medeiros. See [LICENSE](https://github.com/argerim/select2-rails/blob/master/LICENSE) for details.
|
data/select2-rails.gemspec
CHANGED
@@ -16,6 +16,7 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.require_paths = ["lib"]
|
17
17
|
|
18
18
|
s.add_dependency "thor", "~> 0.14"
|
19
|
+
s.add_runtime_dependency "sass-rails", "~> 3.2"
|
19
20
|
s.add_development_dependency "bundler", "~> 1.0"
|
20
21
|
s.add_development_dependency "rails", "~> 3.0"
|
21
22
|
s.add_development_dependency "httpclient", "~> 2.2"
|
Binary file
|
File without changes
|
File without changes
|
@@ -1,17 +1,23 @@
|
|
1
1
|
/*
|
2
|
-
|
2
|
+
Copyright 2012 Igor Vaynberg
|
3
3
|
|
4
|
-
|
4
|
+
Version: 3.3.0 Timestamp: Tue Feb 5 18:33:54 PST 2013
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
|
7
|
+
General Public License version 2 (the "GPL License"). You may choose either license to govern your
|
8
|
+
use of this software only upon the condition that you accept all of the terms of either the Apache
|
9
|
+
License or the GPL License.
|
8
10
|
|
9
|
-
|
11
|
+
You may obtain a copy of the Apache License and the GPL License at:
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
13
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
14
|
+
http://www.gnu.org/licenses/gpl-2.0.html
|
15
|
+
|
16
|
+
Unless required by applicable law or agreed to in writing, software distributed under the
|
17
|
+
Apache License or the GPL Licesnse is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
18
|
+
CONDITIONS OF ANY KIND, either express or implied. See the Apache License and the GPL License for
|
19
|
+
the specific language governing permissions and limitations under the Apache License and the GPL License.
|
20
|
+
*/
|
15
21
|
(function ($) {
|
16
22
|
if(typeof $.fn.each2 == "undefined"){
|
17
23
|
$.fn.extend({
|
@@ -40,7 +46,8 @@
|
|
40
46
|
return;
|
41
47
|
}
|
42
48
|
|
43
|
-
var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer
|
49
|
+
var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer,
|
50
|
+
lastMousePosition, $document;
|
44
51
|
|
45
52
|
KEY = {
|
46
53
|
TAB: 9,
|
@@ -90,42 +97,23 @@
|
|
90
97
|
}
|
91
98
|
};
|
92
99
|
|
100
|
+
$document = $(document);
|
101
|
+
|
93
102
|
nextUid=(function() { var counter=1; return function() { return counter++; }; }());
|
94
103
|
|
95
104
|
function indexOf(value, array) {
|
96
|
-
var i = 0, l = array.length
|
97
|
-
|
98
|
-
if (typeof value === "undefined") {
|
99
|
-
return -1;
|
100
|
-
}
|
101
|
-
|
102
|
-
if (value.constructor === String) {
|
103
|
-
for (; i < l; i = i + 1) if (value.localeCompare(array[i]) === 0) return i;
|
104
|
-
} else {
|
105
|
-
for (; i < l; i = i + 1) {
|
106
|
-
v = array[i];
|
107
|
-
if (v.constructor === String) {
|
108
|
-
if (v.localeCompare(value) === 0) return i;
|
109
|
-
} else {
|
110
|
-
if (v === value) return i;
|
111
|
-
}
|
112
|
-
}
|
113
|
-
}
|
105
|
+
var i = 0, l = array.length;
|
106
|
+
for (; i < l; i = i + 1) if (value === array[i]) return i;
|
114
107
|
return -1;
|
115
108
|
}
|
116
109
|
|
117
110
|
/**
|
118
|
-
* Compares equality of a and b
|
111
|
+
* Compares equality of a and b
|
119
112
|
* @param a
|
120
113
|
* @param b
|
121
114
|
*/
|
122
115
|
function equal(a, b) {
|
123
|
-
|
124
|
-
if (a === undefined || b === undefined) return false;
|
125
|
-
if (a === null || b === null) return false;
|
126
|
-
if (a.constructor === String) return a.localeCompare(b) === 0;
|
127
|
-
if (b.constructor === String) return b.localeCompare(a) === 0;
|
128
|
-
return false;
|
116
|
+
return a===b;
|
129
117
|
}
|
130
118
|
|
131
119
|
/**
|
@@ -143,7 +131,7 @@
|
|
143
131
|
}
|
144
132
|
|
145
133
|
function getSideBorderPadding(element) {
|
146
|
-
return element.outerWidth() - element.width();
|
134
|
+
return element.outerWidth(false) - element.width();
|
147
135
|
}
|
148
136
|
|
149
137
|
function installKeyUpChangeEvent(element) {
|
@@ -162,8 +150,8 @@
|
|
162
150
|
});
|
163
151
|
}
|
164
152
|
|
165
|
-
$
|
166
|
-
|
153
|
+
$document.bind("mousemove", function (e) {
|
154
|
+
lastMousePosition = {x: e.pageX, y: e.pageY};
|
167
155
|
});
|
168
156
|
|
169
157
|
/**
|
@@ -174,7 +162,7 @@
|
|
174
162
|
*/
|
175
163
|
function installFilteredMouseMove(element) {
|
176
164
|
element.bind("mousemove", function (e) {
|
177
|
-
var lastpos =
|
165
|
+
var lastpos = lastMousePosition;
|
178
166
|
if (lastpos === undefined || lastpos.x !== e.pageX || lastpos.y !== e.pageY) {
|
179
167
|
$(e.target).trigger("mousemove-filtered", e);
|
180
168
|
}
|
@@ -227,11 +215,15 @@
|
|
227
215
|
event.preventDefault();
|
228
216
|
event.stopPropagation();
|
229
217
|
}
|
218
|
+
function killEventImmediately(event) {
|
219
|
+
event.preventDefault();
|
220
|
+
event.stopImmediatePropagation();
|
221
|
+
}
|
230
222
|
|
231
223
|
function measureTextWidth(e) {
|
232
224
|
if (!sizer){
|
233
225
|
var style = e[0].currentStyle || window.getComputedStyle(e[0], null);
|
234
|
-
sizer = $("
|
226
|
+
sizer = $(document.createElement("div")).css({
|
235
227
|
position: "absolute",
|
236
228
|
left: "-10000px",
|
237
229
|
top: "-10000px",
|
@@ -244,26 +236,27 @@
|
|
244
236
|
textTransform: style.textTransform,
|
245
237
|
whiteSpace: "nowrap"
|
246
238
|
});
|
239
|
+
sizer.attr("class","select2-sizer");
|
247
240
|
$("body").append(sizer);
|
248
241
|
}
|
249
242
|
sizer.text(e.val());
|
250
243
|
return sizer.width();
|
251
244
|
}
|
252
245
|
|
253
|
-
function markMatch(text, term, markup) {
|
246
|
+
function markMatch(text, term, markup, escapeMarkup) {
|
254
247
|
var match=text.toUpperCase().indexOf(term.toUpperCase()),
|
255
248
|
tl=term.length;
|
256
249
|
|
257
250
|
if (match<0) {
|
258
|
-
markup.push(text);
|
251
|
+
markup.push(escapeMarkup(text));
|
259
252
|
return;
|
260
253
|
}
|
261
254
|
|
262
|
-
markup.push(text.substring(0, match));
|
255
|
+
markup.push(escapeMarkup(text.substring(0, match)));
|
263
256
|
markup.push("<span class='select2-match'>");
|
264
|
-
markup.push(text.substring(match, match + tl));
|
257
|
+
markup.push(escapeMarkup(text.substring(match, match + tl)));
|
265
258
|
markup.push("</span>");
|
266
|
-
markup.push(text.substring(match + tl, text.length));
|
259
|
+
markup.push(escapeMarkup(text.substring(match + tl, text.length)));
|
267
260
|
}
|
268
261
|
|
269
262
|
/**
|
@@ -294,16 +287,18 @@
|
|
294
287
|
requestSequence += 1; // increment the sequence
|
295
288
|
var requestNumber = requestSequence, // this request's sequence number
|
296
289
|
data = options.data, // ajax data function
|
290
|
+
url = options.url, // ajax url string or function
|
297
291
|
transport = options.transport || $.ajax,
|
298
292
|
traditional = options.traditional || false,
|
299
293
|
type = options.type || 'GET'; // set type of request (GET or POST)
|
300
294
|
|
301
|
-
data = data.call(this, query.term, query.page, query.context);
|
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;
|
302
297
|
|
303
298
|
if( null !== handler) { handler.abort(); }
|
304
299
|
|
305
300
|
handler = transport.call(null, {
|
306
|
-
url:
|
301
|
+
url: url,
|
307
302
|
dataType: options.dataType,
|
308
303
|
data: data,
|
309
304
|
type: type,
|
@@ -367,11 +362,11 @@
|
|
367
362
|
}
|
368
363
|
group.children=[];
|
369
364
|
$(datum.children).each2(function(i, childDatum) { process(childDatum, group.children); });
|
370
|
-
if (group.children.length) {
|
365
|
+
if (group.children.length || query.matcher(t, text(group), datum)) {
|
371
366
|
collection.push(group);
|
372
367
|
}
|
373
368
|
} else {
|
374
|
-
if (query.matcher(t, text(datum))) {
|
369
|
+
if (query.matcher(t, text(datum), datum)) {
|
375
370
|
collection.push(datum);
|
376
371
|
}
|
377
372
|
}
|
@@ -384,17 +379,10 @@
|
|
384
379
|
|
385
380
|
// TODO javadoc
|
386
381
|
function tags(data) {
|
387
|
-
|
388
|
-
// the function for arrays. otherwise only functions that return objects are supported.
|
389
|
-
if ($.isFunction(data)) {
|
390
|
-
return data;
|
391
|
-
}
|
392
|
-
|
393
|
-
// if not a function we assume it to be an array
|
394
|
-
|
382
|
+
var isFunc = $.isFunction(data);
|
395
383
|
return function (query) {
|
396
384
|
var t = query.term, filtered = {results: []};
|
397
|
-
$(data).each(function () {
|
385
|
+
$(isFunc ? data() : data).each(function () {
|
398
386
|
var isObject = this.text !== undefined,
|
399
387
|
text = isObject ? this.text : this;
|
400
388
|
if (t === "" || query.matcher(t, text)) {
|
@@ -485,38 +473,9 @@
|
|
485
473
|
}
|
486
474
|
}
|
487
475
|
|
488
|
-
if (original
|
476
|
+
if (original!==input) return input;
|
489
477
|
}
|
490
478
|
|
491
|
-
/**
|
492
|
-
* blurs any Select2 container that has focus when an element outside them was clicked or received focus
|
493
|
-
*
|
494
|
-
* also takes care of clicks on label tags that point to the source element
|
495
|
-
*/
|
496
|
-
$(document).ready(function () {
|
497
|
-
$(document).delegate("body", "mousedown touchend", function (e) {
|
498
|
-
var target = $(e.target).closest("div.select2-container").get(0), attr;
|
499
|
-
if (target) {
|
500
|
-
$(document).find("div.select2-container-active").each(function () {
|
501
|
-
if (this !== target) $(this).data("select2").blur();
|
502
|
-
});
|
503
|
-
} else {
|
504
|
-
target = $(e.target).closest("div.select2-drop").get(0);
|
505
|
-
$(document).find("div.select2-drop-active").each(function () {
|
506
|
-
if (this !== target) $(this).data("select2").blur();
|
507
|
-
});
|
508
|
-
}
|
509
|
-
|
510
|
-
target=$(e.target);
|
511
|
-
attr = target.attr("for");
|
512
|
-
if ("LABEL" === e.target.tagName && attr && attr.length > 0) {
|
513
|
-
target = $("#"+attr);
|
514
|
-
target = target.data("select2");
|
515
|
-
if (target !== undefined) { target.focus(); e.preventDefault();}
|
516
|
-
}
|
517
|
-
});
|
518
|
-
});
|
519
|
-
|
520
479
|
/**
|
521
480
|
* Creates a new class
|
522
481
|
*
|
@@ -544,7 +503,7 @@
|
|
544
503
|
|
545
504
|
// abstract
|
546
505
|
init: function (opts) {
|
547
|
-
var results, search, resultsSelector = ".select2-results";
|
506
|
+
var results, search, resultsSelector = ".select2-results", mask;
|
548
507
|
|
549
508
|
// prepare options
|
550
509
|
this.opts = opts = this.prepareOpts(opts);
|
@@ -567,6 +526,25 @@
|
|
567
526
|
// cache the body so future lookups are cheap
|
568
527
|
this.body = thunk(function() { return opts.element.closest("body"); });
|
569
528
|
|
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
|
+
|
570
548
|
if (opts.element.attr("class") !== undefined) {
|
571
549
|
this.container.addClass(opts.element.attr("class").replace(/validate\[[\S ]+] ?/, ''));
|
572
550
|
}
|
@@ -574,10 +552,14 @@
|
|
574
552
|
this.container.css(evaluate(opts.containerCss));
|
575
553
|
this.container.addClass(evaluate(opts.containerCssClass));
|
576
554
|
|
555
|
+
this.elementTabIndex = this.opts.element.attr("tabIndex");
|
556
|
+
|
577
557
|
// swap container for the element
|
578
558
|
this.opts.element
|
579
559
|
.data("select2", this)
|
580
|
-
.
|
560
|
+
.addClass("select2-offscreen")
|
561
|
+
.bind("focus.select2", function() { $(this).select2("focus")})
|
562
|
+
.attr("tabIndex", "-1")
|
581
563
|
.before(this.container);
|
582
564
|
this.container.data("select2", this);
|
583
565
|
|
@@ -588,7 +570,7 @@
|
|
588
570
|
this.results = results = this.container.find(resultsSelector);
|
589
571
|
this.search = search = this.container.find("input.select2-input");
|
590
572
|
|
591
|
-
search.attr("tabIndex", this.
|
573
|
+
search.attr("tabIndex", this.elementTabIndex);
|
592
574
|
|
593
575
|
this.resultsPage = 0;
|
594
576
|
this.context = null;
|
@@ -623,7 +605,7 @@
|
|
623
605
|
search.bind("blur", function () { search.removeClass("select2-focused");});
|
624
606
|
|
625
607
|
this.dropdown.delegate(resultsSelector, "mouseup", this.bind(function (e) {
|
626
|
-
if ($(e.target).closest(".select2-result-selectable
|
608
|
+
if ($(e.target).closest(".select2-result-selectable").length > 0) {
|
627
609
|
this.highlightUnderEvent(e);
|
628
610
|
this.selectHighlighted(e);
|
629
611
|
} else {
|
@@ -652,12 +634,17 @@
|
|
652
634
|
// abstract
|
653
635
|
destroy: function () {
|
654
636
|
var select2 = this.opts.element.data("select2");
|
637
|
+
|
638
|
+
if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; }
|
639
|
+
|
655
640
|
if (select2 !== undefined) {
|
641
|
+
|
656
642
|
select2.container.remove();
|
657
643
|
select2.dropdown.remove();
|
658
644
|
select2.opts.element
|
659
645
|
.removeData("select2")
|
660
646
|
.unbind(".select2")
|
647
|
+
.attr("tabIndex", this.elementTabIndex)
|
661
648
|
.show();
|
662
649
|
}
|
663
650
|
},
|
@@ -687,26 +674,33 @@
|
|
687
674
|
|
688
675
|
populate=function(results, container, depth) {
|
689
676
|
|
690
|
-
var i, l, result, selectable, compound, node, label, innerContainer, formatted;
|
677
|
+
var i, l, result, selectable, disabled, compound, node, label, innerContainer, formatted;
|
678
|
+
|
679
|
+
results = opts.sortResults(results, container, query);
|
680
|
+
|
691
681
|
for (i = 0, l = results.length; i < l; i = i + 1) {
|
692
682
|
|
693
683
|
result=results[i];
|
694
|
-
|
684
|
+
|
685
|
+
disabled = (result.disabled === true);
|
686
|
+
selectable = (!disabled) && (id(result) !== undefined);
|
687
|
+
|
695
688
|
compound=result.children && result.children.length > 0;
|
696
689
|
|
697
690
|
node=$("<li></li>");
|
698
691
|
node.addClass("select2-results-dept-"+depth);
|
699
692
|
node.addClass("select2-result");
|
700
693
|
node.addClass(selectable ? "select2-result-selectable" : "select2-result-unselectable");
|
694
|
+
if (disabled) { node.addClass("select2-disabled"); }
|
701
695
|
if (compound) { node.addClass("select2-result-with-children"); }
|
702
696
|
node.addClass(self.opts.formatResultCssClass(result));
|
703
697
|
|
704
|
-
label=$("
|
698
|
+
label=$(document.createElement("div"));
|
705
699
|
label.addClass("select2-result-label");
|
706
700
|
|
707
|
-
formatted=opts.formatResult(result, label, query);
|
701
|
+
formatted=opts.formatResult(result, label, query, self.opts.escapeMarkup);
|
708
702
|
if (formatted!==undefined) {
|
709
|
-
label.html(
|
703
|
+
label.html(formatted);
|
710
704
|
}
|
711
705
|
|
712
706
|
node.append(label);
|
@@ -733,6 +727,13 @@
|
|
733
727
|
opts.id = function (e) { return e[idKey]; };
|
734
728
|
}
|
735
729
|
|
730
|
+
if ($.isArray(opts.element.data("select2Tags"))) {
|
731
|
+
if ("tags" in opts) {
|
732
|
+
throw "tags specified as both an attribute 'data-select2-tags' and in options of Select2 " + opts.element.attr("id");
|
733
|
+
}
|
734
|
+
opts.tags=opts.element.attr("data-select2-tags");
|
735
|
+
}
|
736
|
+
|
736
737
|
if (select) {
|
737
738
|
opts.query = this.bind(function (query) {
|
738
739
|
var data = { results: [], more: false },
|
@@ -743,7 +744,7 @@
|
|
743
744
|
var group;
|
744
745
|
if (element.is("option")) {
|
745
746
|
if (query.matcher(term, element.text(), element)) {
|
746
|
-
collection.push({id:element.attr("value"), text:element.text(), element: element.get(), css: element.attr("class")});
|
747
|
+
collection.push({id:element.attr("value"), text:element.text(), element: element.get(), css: element.attr("class"), disabled: equal(element.attr("disabled"), "disabled") });
|
747
748
|
}
|
748
749
|
} else if (element.is("optgroup")) {
|
749
750
|
group={text:element.attr("label"), children:[], element: element.get(), css: element.attr("class")};
|
@@ -773,6 +774,7 @@
|
|
773
774
|
opts.formatResultCssClass = function(data) { return data.css; }
|
774
775
|
} else {
|
775
776
|
if (!("query" in opts)) {
|
777
|
+
|
776
778
|
if ("ajax" in opts) {
|
777
779
|
ajaxUrl = opts.element.data("ajax-url");
|
778
780
|
if (ajaxUrl && ajaxUrl.length > 0) {
|
@@ -783,7 +785,9 @@
|
|
783
785
|
opts.query = local(opts.data);
|
784
786
|
} else if ("tags" in opts) {
|
785
787
|
opts.query = tags(opts.tags);
|
786
|
-
opts.createSearchChoice
|
788
|
+
if (opts.createSearchChoice === undefined) {
|
789
|
+
opts.createSearchChoice = function (term) { return {id: term, text: term}; };
|
790
|
+
}
|
787
791
|
opts.initSelection = function (element, callback) {
|
788
792
|
var data = [];
|
789
793
|
$(splitVal(element.val(), opts.separator)).each(function () {
|
@@ -810,11 +814,39 @@
|
|
810
814
|
*/
|
811
815
|
// abstract
|
812
816
|
monitorSource: function () {
|
813
|
-
this.opts.element
|
817
|
+
var el = this.opts.element, sync;
|
818
|
+
|
819
|
+
el.bind("change.select2", this.bind(function (e) {
|
814
820
|
if (this.opts.element.data("select2-change-triggered") !== true) {
|
815
821
|
this.initSelection();
|
816
822
|
}
|
817
823
|
}));
|
824
|
+
|
825
|
+
sync = this.bind(function () {
|
826
|
+
var enabled = this.opts.element.attr("disabled") !== "disabled";
|
827
|
+
var readonly = this.opts.element.attr("readonly") === "readonly";
|
828
|
+
|
829
|
+
enabled = enabled && !readonly;
|
830
|
+
|
831
|
+
if (this.enabled !== enabled) {
|
832
|
+
if (enabled) {
|
833
|
+
this.enable();
|
834
|
+
} else {
|
835
|
+
this.disable();
|
836
|
+
}
|
837
|
+
}
|
838
|
+
});
|
839
|
+
|
840
|
+
// mozilla and IE
|
841
|
+
el.bind("propertychange.select2 DOMAttrModified.select2", sync);
|
842
|
+
// safari and chrome
|
843
|
+
if (typeof WebKitMutationObserver !== "undefined") {
|
844
|
+
if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; }
|
845
|
+
this.propertyObserver = new WebKitMutationObserver(function (mutations) {
|
846
|
+
mutations.forEach(sync);
|
847
|
+
});
|
848
|
+
this.propertyObserver.observe(el.get(0), { attributes:true, subtree:false });
|
849
|
+
}
|
818
850
|
},
|
819
851
|
|
820
852
|
/**
|
@@ -840,13 +872,13 @@
|
|
840
872
|
this.opts.element.blur();
|
841
873
|
},
|
842
874
|
|
843
|
-
|
844
875
|
// abstract
|
845
876
|
enable: function() {
|
846
877
|
if (this.enabled) return;
|
847
878
|
|
848
879
|
this.enabled=true;
|
849
880
|
this.container.removeClass("select2-container-disabled");
|
881
|
+
this.opts.element.removeAttr("disabled");
|
850
882
|
},
|
851
883
|
|
852
884
|
// abstract
|
@@ -857,6 +889,7 @@
|
|
857
889
|
|
858
890
|
this.enabled=false;
|
859
891
|
this.container.addClass("select2-container-disabled");
|
892
|
+
this.opts.element.attr("disabled", "disabled");
|
860
893
|
},
|
861
894
|
|
862
895
|
// abstract
|
@@ -867,14 +900,17 @@
|
|
867
900
|
// abstract
|
868
901
|
positionDropdown: function() {
|
869
902
|
var offset = this.container.offset(),
|
870
|
-
height = this.container.outerHeight(),
|
871
|
-
width = this.container.outerWidth(),
|
872
|
-
dropHeight = this.dropdown.outerHeight(),
|
903
|
+
height = this.container.outerHeight(false),
|
904
|
+
width = this.container.outerWidth(false),
|
905
|
+
dropHeight = this.dropdown.outerHeight(false),
|
906
|
+
viewPortRight = $(window).scrollLeft() + document.documentElement.clientWidth,
|
873
907
|
viewportBottom = $(window).scrollTop() + document.documentElement.clientHeight,
|
874
908
|
dropTop = offset.top + height,
|
875
909
|
dropLeft = offset.left,
|
876
910
|
enoughRoomBelow = dropTop + dropHeight <= viewportBottom,
|
877
911
|
enoughRoomAbove = (offset.top - dropHeight) >= this.body().scrollTop(),
|
912
|
+
dropWidth = this.dropdown.outerWidth(false),
|
913
|
+
enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight,
|
878
914
|
aboveNow = this.dropdown.hasClass("select2-drop-above"),
|
879
915
|
bodyOffset,
|
880
916
|
above,
|
@@ -901,6 +937,10 @@
|
|
901
937
|
if (!enoughRoomBelow && enoughRoomAbove) above = true;
|
902
938
|
}
|
903
939
|
|
940
|
+
if (!enoughRoomOnRight) {
|
941
|
+
dropLeft = offset.left + width - dropWidth;
|
942
|
+
}
|
943
|
+
|
904
944
|
if (above) {
|
905
945
|
dropTop = offset.top - dropHeight;
|
906
946
|
this.container.addClass("select2-drop-above");
|
@@ -959,26 +999,11 @@
|
|
959
999
|
*/
|
960
1000
|
// abstract
|
961
1001
|
opening: function() {
|
962
|
-
var cid = this.containerId,
|
963
|
-
scroll = "scroll." + cid,
|
964
|
-
|
965
|
-
|
966
|
-
|
967
|
-
var s2 = $(selector);
|
968
|
-
if (s2.length == 0) {
|
969
|
-
$(this).unbind(scroll);
|
970
|
-
}
|
971
|
-
s2.select2("close");
|
972
|
-
});
|
973
|
-
});
|
974
|
-
|
975
|
-
$(window).bind(resize, function() {
|
976
|
-
var s2 = $(selector);
|
977
|
-
if (s2.length == 0) {
|
978
|
-
$(window).unbind(resize);
|
979
|
-
}
|
980
|
-
s2.select2("close");
|
981
|
-
});
|
1002
|
+
var cid = this.containerId,
|
1003
|
+
scroll = "scroll." + cid,
|
1004
|
+
resize = "resize."+cid,
|
1005
|
+
orient = "orientationchange."+cid,
|
1006
|
+
mask;
|
982
1007
|
|
983
1008
|
this.clearDropdownAlignmentPreference();
|
984
1009
|
|
@@ -986,19 +1011,46 @@
|
|
986
1011
|
|
987
1012
|
this.container.addClass("select2-dropdown-open").addClass("select2-container-active");
|
988
1013
|
|
989
|
-
this.updateResults(true);
|
990
1014
|
|
991
1015
|
if(this.dropdown[0] !== this.body().children().last()[0]) {
|
992
1016
|
this.dropdown.detach().appendTo(this.body());
|
993
1017
|
}
|
994
1018
|
|
995
|
-
this.
|
1019
|
+
this.updateResults(true);
|
1020
|
+
|
1021
|
+
mask = $("#select2-drop-mask");
|
996
1022
|
|
1023
|
+
// ensure the mask is always right before the dropdown
|
1024
|
+
if (this.dropdown.prev()[0] !== mask[0]) {
|
1025
|
+
this.dropdown.before(mask);
|
1026
|
+
}
|
1027
|
+
|
1028
|
+
// move the global id to the correct dropdown
|
1029
|
+
$("#select2-drop").removeAttr("id");
|
1030
|
+
this.dropdown.attr("id", "select2-drop");
|
1031
|
+
|
1032
|
+
// show the elements
|
1033
|
+
mask.css({
|
1034
|
+
width: document.documentElement.scrollWidth,
|
1035
|
+
height: document.documentElement.scrollHeight});
|
1036
|
+
mask.show();
|
1037
|
+
this.dropdown.show();
|
997
1038
|
this.positionDropdown();
|
998
|
-
this.dropdown.addClass("select2-drop-active");
|
999
1039
|
|
1040
|
+
this.dropdown.addClass("select2-drop-active");
|
1000
1041
|
this.ensureHighlightVisible();
|
1001
1042
|
|
1043
|
+
// attach listeners to events that can change the position of the container and thus require
|
1044
|
+
// the position of the dropdown to be updated as well so it does not come unglued from the container
|
1045
|
+
this.container.parents().add(window).each(function () {
|
1046
|
+
$(this).bind(resize+" "+scroll+" "+orient, function (e) {
|
1047
|
+
$("#select2-drop-mask").css({
|
1048
|
+
width:document.documentElement.scrollWidth,
|
1049
|
+
height:document.documentElement.scrollHeight});
|
1050
|
+
$("#select2-drop").data("select2").positionDropdown();
|
1051
|
+
});
|
1052
|
+
});
|
1053
|
+
|
1002
1054
|
this.focusSearch();
|
1003
1055
|
},
|
1004
1056
|
|
@@ -1006,15 +1058,18 @@
|
|
1006
1058
|
close: function () {
|
1007
1059
|
if (!this.opened()) return;
|
1008
1060
|
|
1009
|
-
var
|
1061
|
+
var cid = this.containerId,
|
1062
|
+
scroll = "scroll." + cid,
|
1063
|
+
resize = "resize."+cid,
|
1064
|
+
orient = "orientationchange."+cid;
|
1010
1065
|
|
1011
|
-
|
1012
|
-
|
1013
|
-
});
|
1014
|
-
$(window).unbind("resize." + this.containerId);
|
1066
|
+
// unbind event listeners
|
1067
|
+
this.container.parents().add(window).each(function () { $(this).unbind(scroll).unbind(resize).unbind(orient); });
|
1015
1068
|
|
1016
1069
|
this.clearDropdownAlignmentPreference();
|
1017
1070
|
|
1071
|
+
$("#select2-drop-mask").hide();
|
1072
|
+
this.dropdown.removeAttr("id"); // only the active dropdown has the select2-drop id
|
1018
1073
|
this.dropdown.hide();
|
1019
1074
|
this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active");
|
1020
1075
|
this.results.empty();
|
@@ -1046,41 +1101,47 @@
|
|
1046
1101
|
return;
|
1047
1102
|
}
|
1048
1103
|
|
1049
|
-
children =
|
1104
|
+
children = this.findHighlightableChoices();
|
1050
1105
|
|
1051
1106
|
child = $(children[index]);
|
1052
1107
|
|
1053
|
-
hb = child.offset().top + child.outerHeight();
|
1108
|
+
hb = child.offset().top + child.outerHeight(true);
|
1054
1109
|
|
1055
1110
|
// if this is the last child lets also make sure select2-more-results is visible
|
1056
1111
|
if (index === children.length - 1) {
|
1057
1112
|
more = results.find("li.select2-more-results");
|
1058
1113
|
if (more.length > 0) {
|
1059
|
-
hb = more.offset().top + more.outerHeight();
|
1114
|
+
hb = more.offset().top + more.outerHeight(true);
|
1060
1115
|
}
|
1061
1116
|
}
|
1062
1117
|
|
1063
|
-
rb = results.offset().top + results.outerHeight();
|
1118
|
+
rb = results.offset().top + results.outerHeight(true);
|
1064
1119
|
if (hb > rb) {
|
1065
1120
|
results.scrollTop(results.scrollTop() + (hb - rb));
|
1066
1121
|
}
|
1067
1122
|
y = child.offset().top - results.offset().top;
|
1068
1123
|
|
1069
1124
|
// make sure the top of the element is visible
|
1070
|
-
if (y < 0) {
|
1125
|
+
if (y < 0 && child.css('display') != 'none' ) {
|
1071
1126
|
results.scrollTop(results.scrollTop() + y); // y is negative
|
1072
1127
|
}
|
1073
1128
|
},
|
1074
1129
|
|
1130
|
+
// abstract
|
1131
|
+
findHighlightableChoices: function() {
|
1132
|
+
var h=this.results.find(".select2-result-selectable:not(.select2-selected):not(.select2-disabled)");
|
1133
|
+
return this.results.find(".select2-result-selectable:not(.select2-selected):not(.select2-disabled)");
|
1134
|
+
},
|
1135
|
+
|
1075
1136
|
// abstract
|
1076
1137
|
moveHighlight: function (delta) {
|
1077
|
-
var choices = this.
|
1138
|
+
var choices = this.findHighlightableChoices(),
|
1078
1139
|
index = this.highlight();
|
1079
1140
|
|
1080
1141
|
while (index > -1 && index < choices.length) {
|
1081
1142
|
index += delta;
|
1082
1143
|
var choice = $(choices[index]);
|
1083
|
-
if (choice.hasClass("select2-result-selectable") && !choice.hasClass("select2-disabled")) {
|
1144
|
+
if (choice.hasClass("select2-result-selectable") && !choice.hasClass("select2-disabled") && !choice.hasClass("select2-selected")) {
|
1084
1145
|
this.highlight(index);
|
1085
1146
|
break;
|
1086
1147
|
}
|
@@ -1089,7 +1150,7 @@
|
|
1089
1150
|
|
1090
1151
|
// abstract
|
1091
1152
|
highlight: function (index) {
|
1092
|
-
var choices = this.
|
1153
|
+
var choices = this.findHighlightableChoices();
|
1093
1154
|
|
1094
1155
|
if (arguments.length === 0) {
|
1095
1156
|
return indexOf(choices.filter(".select2-highlighted")[0], choices.get());
|
@@ -1098,23 +1159,22 @@
|
|
1098
1159
|
if (index >= choices.length) index = choices.length - 1;
|
1099
1160
|
if (index < 0) index = 0;
|
1100
1161
|
|
1101
|
-
|
1162
|
+
this.results.find(".select2-highlighted").removeClass("select2-highlighted");
|
1102
1163
|
|
1103
1164
|
$(choices[index]).addClass("select2-highlighted");
|
1104
1165
|
this.ensureHighlightVisible();
|
1105
|
-
|
1106
1166
|
},
|
1107
1167
|
|
1108
1168
|
// abstract
|
1109
1169
|
countSelectableResults: function() {
|
1110
|
-
return this.
|
1170
|
+
return this.findHighlightableChoices().length;
|
1111
1171
|
},
|
1112
1172
|
|
1113
1173
|
// abstract
|
1114
1174
|
highlightUnderEvent: function (event) {
|
1115
1175
|
var el = $(event.target).closest(".select2-result-selectable");
|
1116
1176
|
if (el.length > 0 && !el.is(".select2-highlighted")) {
|
1117
|
-
var choices = this.
|
1177
|
+
var choices = this.findHighlightableChoices();
|
1118
1178
|
this.highlight(choices.index(el));
|
1119
1179
|
} else if (el.length == 0) {
|
1120
1180
|
// if we are over an unselectable item remove al highlights
|
@@ -1136,7 +1196,7 @@
|
|
1136
1196
|
if (more.length === 0) return;
|
1137
1197
|
below = more.offset().top - results.offset().top - results.height();
|
1138
1198
|
|
1139
|
-
if (below <=
|
1199
|
+
if (below <= this.opts.loadMorePadding) {
|
1140
1200
|
more.addClass("select2-active");
|
1141
1201
|
this.opts.query({
|
1142
1202
|
term: term,
|
@@ -1191,26 +1251,40 @@
|
|
1191
1251
|
}
|
1192
1252
|
|
1193
1253
|
function render(html) {
|
1194
|
-
results.html(
|
1254
|
+
results.html(html);
|
1195
1255
|
postRender();
|
1196
1256
|
}
|
1197
1257
|
|
1198
|
-
|
1258
|
+
var maxSelSize = $.isFunction(opts.maximumSelectionSize) ? opts.maximumSelectionSize() : opts.maximumSelectionSize;
|
1259
|
+
if (maxSelSize >=1) {
|
1199
1260
|
data = this.data();
|
1200
|
-
if ($.isArray(data) && data.length >=
|
1201
|
-
render("<li class='select2-selection-limit'>" + opts.formatSelectionTooBig(
|
1261
|
+
if ($.isArray(data) && data.length >= maxSelSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) {
|
1262
|
+
render("<li class='select2-selection-limit'>" + opts.formatSelectionTooBig(maxSelSize) + "</li>");
|
1202
1263
|
return;
|
1203
1264
|
}
|
1204
1265
|
}
|
1205
1266
|
|
1206
|
-
if (search.val().length < opts.minimumInputLength
|
1207
|
-
|
1267
|
+
if (search.val().length < opts.minimumInputLength) {
|
1268
|
+
if (checkFormatter(opts.formatInputTooShort, "formatInputTooShort")) {
|
1269
|
+
render("<li class='select2-no-results'>" + opts.formatInputTooShort(search.val(), opts.minimumInputLength) + "</li>");
|
1270
|
+
} else {
|
1271
|
+
render("");
|
1272
|
+
}
|
1208
1273
|
return;
|
1209
1274
|
}
|
1210
|
-
else {
|
1275
|
+
else if (opts.formatSearching() && initial===true) {
|
1211
1276
|
render("<li class='select2-searching'>" + opts.formatSearching() + "</li>");
|
1212
1277
|
}
|
1213
1278
|
|
1279
|
+
if (opts.maximumInputLength && search.val().length > opts.maximumInputLength) {
|
1280
|
+
if (checkFormatter(opts.formatInputTooLong, "formatInputTooLong")) {
|
1281
|
+
render("<li class='select2-no-results'>" + opts.formatInputTooLong(search.val(), opts.maximumInputLength) + "</li>");
|
1282
|
+
} else {
|
1283
|
+
render("");
|
1284
|
+
}
|
1285
|
+
return;
|
1286
|
+
}
|
1287
|
+
|
1214
1288
|
// give the tokenizer a chance to pre-process the input
|
1215
1289
|
input = this.tokenize();
|
1216
1290
|
if (input != undefined && input != null) {
|
@@ -1271,6 +1345,10 @@
|
|
1271
1345
|
|
1272
1346
|
// abstract
|
1273
1347
|
blur: function () {
|
1348
|
+
// if selectOnBlur == true, select the currently highlighted option
|
1349
|
+
if (this.opts.selectOnBlur)
|
1350
|
+
this.selectHighlighted({noFocus: true});
|
1351
|
+
|
1274
1352
|
this.close();
|
1275
1353
|
this.container.removeClass("select2-container-active");
|
1276
1354
|
this.dropdown.removeClass("select2-drop-active");
|
@@ -1278,6 +1356,7 @@
|
|
1278
1356
|
if (this.search[0] === document.activeElement) { this.search.blur(); }
|
1279
1357
|
this.clearSearch();
|
1280
1358
|
this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
|
1359
|
+
this.opts.element.triggerHandler("blur");
|
1281
1360
|
},
|
1282
1361
|
|
1283
1362
|
// abstract
|
@@ -1297,19 +1376,27 @@
|
|
1297
1376
|
},
|
1298
1377
|
|
1299
1378
|
// abstract
|
1300
|
-
selectHighlighted: function () {
|
1379
|
+
selectHighlighted: function (options) {
|
1301
1380
|
var index=this.highlight(),
|
1302
|
-
highlighted=this.results.find(".select2-highlighted")
|
1303
|
-
data = highlighted.closest('.select2-result
|
1381
|
+
highlighted=this.results.find(".select2-highlighted"),
|
1382
|
+
data = highlighted.closest('.select2-result').data("select2-data");
|
1383
|
+
|
1304
1384
|
if (data) {
|
1305
|
-
highlighted.addClass("select2-disabled");
|
1306
1385
|
this.highlight(index);
|
1307
|
-
this.onSelect(data);
|
1386
|
+
this.onSelect(data, options);
|
1308
1387
|
}
|
1309
1388
|
},
|
1310
1389
|
|
1311
1390
|
// abstract
|
1312
1391
|
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
|
+
|
1313
1400
|
return this.opts.element.attr("placeholder") ||
|
1314
1401
|
this.opts.element.attr("data-placeholder") || // jquery 1.4 compat
|
1315
1402
|
this.opts.element.data("placeholder") ||
|
@@ -1330,7 +1417,7 @@
|
|
1330
1417
|
if (this.opts.width === "off") {
|
1331
1418
|
return null;
|
1332
1419
|
} else if (this.opts.width === "element"){
|
1333
|
-
return this.opts.element.outerWidth() === 0 ? 'auto' : this.opts.element.outerWidth() + 'px';
|
1420
|
+
return this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px';
|
1334
1421
|
} else if (this.opts.width === "copy" || this.opts.width === "resolve") {
|
1335
1422
|
// check if there is inline style on the element that contains width
|
1336
1423
|
style = this.opts.element.attr('style');
|
@@ -1351,7 +1438,7 @@
|
|
1351
1438
|
if (style.indexOf("%") > 0) return style;
|
1352
1439
|
|
1353
1440
|
// finally, fallback on the calculated width of the element
|
1354
|
-
return (this.opts.element.outerWidth() === 0 ? 'auto' : this.opts.element.outerWidth() + 'px');
|
1441
|
+
return (this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px');
|
1355
1442
|
}
|
1356
1443
|
|
1357
1444
|
return null;
|
@@ -1374,10 +1461,10 @@
|
|
1374
1461
|
// single
|
1375
1462
|
|
1376
1463
|
createContainer: function () {
|
1377
|
-
var container = $("
|
1464
|
+
var container = $(document.createElement("div")).attr({
|
1378
1465
|
"class": "select2-container"
|
1379
1466
|
}).html([
|
1380
|
-
" <a href='
|
1467
|
+
" <a href='javascript:void(0)' onclick='return false;' class='select2-choice'>",
|
1381
1468
|
" <span></span><abbr class='select2-search-choice-close' style='display:none;'></abbr>",
|
1382
1469
|
" <div><b></b></div>" ,
|
1383
1470
|
"</a>",
|
@@ -1391,6 +1478,31 @@
|
|
1391
1478
|
return container;
|
1392
1479
|
},
|
1393
1480
|
|
1481
|
+
// single
|
1482
|
+
disable: function() {
|
1483
|
+
if (!this.enabled) return;
|
1484
|
+
|
1485
|
+
this.parent.disable.apply(this, arguments);
|
1486
|
+
|
1487
|
+
this.selection.attr("tabIndex", "-1");
|
1488
|
+
this.search.attr("tabIndex", "-1");
|
1489
|
+
},
|
1490
|
+
|
1491
|
+
// single
|
1492
|
+
enable: function() {
|
1493
|
+
if (this.enabled) return;
|
1494
|
+
|
1495
|
+
this.parent.enable.apply(this, arguments);
|
1496
|
+
|
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");
|
1504
|
+
},
|
1505
|
+
|
1394
1506
|
// single
|
1395
1507
|
opening: function () {
|
1396
1508
|
this.search.show();
|
@@ -1409,6 +1521,7 @@
|
|
1409
1521
|
focus: function () {
|
1410
1522
|
this.close();
|
1411
1523
|
this.selection.focus();
|
1524
|
+
this.opts.element.triggerHandler("focus");
|
1412
1525
|
},
|
1413
1526
|
|
1414
1527
|
// single
|
@@ -1482,7 +1595,24 @@
|
|
1482
1595
|
}));
|
1483
1596
|
this.search.bind("blur", this.bind(function() {
|
1484
1597
|
if (!this.opened()) this.container.removeClass("select2-container-active");
|
1485
|
-
window.setTimeout(this.bind(function() {
|
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);
|
1607
|
+
}));
|
1608
|
+
|
1609
|
+
selection.delegate("abbr", "mousedown", this.bind(function (e) {
|
1610
|
+
if (!this.enabled) return;
|
1611
|
+
this.clear();
|
1612
|
+
killEventImmediately(e);
|
1613
|
+
this.close();
|
1614
|
+
this.triggerChange();
|
1615
|
+
this.selection.focus();
|
1486
1616
|
}));
|
1487
1617
|
|
1488
1618
|
selection.bind("mousedown", this.bind(function (e) {
|
@@ -1501,6 +1631,8 @@
|
|
1501
1631
|
dropdown.bind("mousedown", this.bind(function() { this.search.focus(); }));
|
1502
1632
|
|
1503
1633
|
selection.bind("focus", this.bind(function() {
|
1634
|
+
if (!this.enabled) return;
|
1635
|
+
|
1504
1636
|
this.container.addClass("select2-container-active");
|
1505
1637
|
// hide the search so the tab key does not focus on it
|
1506
1638
|
this.search.attr("tabIndex", "-1");
|
@@ -1510,70 +1642,34 @@
|
|
1510
1642
|
if (!this.opened()) {
|
1511
1643
|
this.container.removeClass("select2-container-active");
|
1512
1644
|
}
|
1513
|
-
window.setTimeout(this.bind(function() { this.search.attr("tabIndex", this.
|
1645
|
+
window.setTimeout(this.bind(function() { this.search.attr("tabIndex", this.elementTabIndex || 0); }), 10);
|
1514
1646
|
}));
|
1515
1647
|
|
1516
1648
|
selection.bind("keydown", this.bind(function(e) {
|
1517
1649
|
if (!this.enabled) return;
|
1518
1650
|
|
1519
|
-
if (e.which
|
1520
|
-
|
1651
|
+
if (e.which == KEY.DOWN || e.which == KEY.UP
|
1652
|
+
|| (e.which == KEY.ENTER && this.opts.openOnEnter)) {
|
1653
|
+
this.open();
|
1521
1654
|
killEvent(e);
|
1522
1655
|
return;
|
1523
1656
|
}
|
1524
1657
|
|
1525
|
-
if (e.which
|
1526
|
-
|| e.which === KEY.ESC) {
|
1527
|
-
return;
|
1528
|
-
}
|
1529
|
-
|
1530
|
-
if (this.opts.openOnEnter === false && e.which === KEY.ENTER) {
|
1531
|
-
return;
|
1532
|
-
}
|
1533
|
-
|
1534
|
-
if (e.which == KEY.DELETE) {
|
1658
|
+
if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE) {
|
1535
1659
|
if (this.opts.allowClear) {
|
1536
1660
|
this.clear();
|
1537
1661
|
}
|
1538
|
-
return;
|
1539
|
-
}
|
1540
|
-
|
1541
|
-
this.open();
|
1542
|
-
|
1543
|
-
if (e.which === KEY.ENTER) {
|
1544
|
-
// do not propagate the event otherwise we open, and propagate enter which closes
|
1545
|
-
killEvent(e);
|
1546
|
-
return;
|
1547
|
-
}
|
1548
|
-
|
1549
|
-
// do not set the search input value for non-alpha-numeric keys
|
1550
|
-
// otherwise pressing down results in a '(' being set in the search field
|
1551
|
-
if (e.which < 48 ) { // '0' == 48
|
1552
1662
|
killEvent(e);
|
1553
1663
|
return;
|
1554
1664
|
}
|
1555
|
-
|
1556
|
-
var keyWritten = String.fromCharCode(e.which).toLowerCase();
|
1557
|
-
|
1558
|
-
if (e.shiftKey) {
|
1559
|
-
keyWritten = keyWritten.toUpperCase();
|
1560
|
-
}
|
1561
|
-
|
1562
|
-
// focus the field before calling val so the cursor ends up after the value instead of before
|
1563
|
-
this.search.focus();
|
1564
|
-
this.search.val(keyWritten);
|
1565
|
-
|
1566
|
-
// prevent event propagation so it doesnt replay on the now focussed search field and result in double key entry
|
1567
|
-
killEvent(e);
|
1568
1665
|
}));
|
1569
|
-
|
1570
|
-
|
1571
|
-
|
1572
|
-
|
1573
|
-
|
1574
|
-
this.
|
1575
|
-
this.
|
1576
|
-
this.selection.focus();
|
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();
|
1577
1673
|
}));
|
1578
1674
|
|
1579
1675
|
this.setPlaceholder();
|
@@ -1597,7 +1693,7 @@
|
|
1597
1693
|
// single
|
1598
1694
|
initSelection: function () {
|
1599
1695
|
var selected;
|
1600
|
-
if (this.opts.element.val() === "") {
|
1696
|
+
if (this.opts.element.val() === "" && this.opts.element.text() === "") {
|
1601
1697
|
this.close();
|
1602
1698
|
this.setPlaceholder();
|
1603
1699
|
} else {
|
@@ -1622,7 +1718,21 @@
|
|
1622
1718
|
var selected = element.find(":selected");
|
1623
1719
|
// a single select box always has a value, no need to null check 'selected'
|
1624
1720
|
if ($.isFunction(callback))
|
1625
|
-
callback({id: selected.attr("value"), text: selected.text()});
|
1721
|
+
callback({id: selected.attr("value"), text: selected.text(), element:selected});
|
1722
|
+
};
|
1723
|
+
} else if ("data" in opts) {
|
1724
|
+
// install default initSelection when applied to hidden input and data is local
|
1725
|
+
opts.initSelection = opts.initSelection || function (element, callback) {
|
1726
|
+
var id = element.val();
|
1727
|
+
//search in data by id
|
1728
|
+
opts.query({
|
1729
|
+
matcher: function(term, text, el){
|
1730
|
+
return equal(id, opts.id(el));
|
1731
|
+
},
|
1732
|
+
callback: !$.isFunction(callback) ? $.noop : function(filtered) {
|
1733
|
+
callback(filtered.results.length ? filtered.results[0] : null);
|
1734
|
+
}
|
1735
|
+
});
|
1626
1736
|
};
|
1627
1737
|
}
|
1628
1738
|
|
@@ -1652,7 +1762,7 @@
|
|
1652
1762
|
|
1653
1763
|
// find the selected element in the result list
|
1654
1764
|
|
1655
|
-
this.
|
1765
|
+
this.findHighlightableChoices().each2(function (i, elm) {
|
1656
1766
|
if (equal(self.id(elm.data("select2-data")), self.opts.element.val())) {
|
1657
1767
|
selected = i;
|
1658
1768
|
return false;
|
@@ -1676,13 +1786,15 @@
|
|
1676
1786
|
},
|
1677
1787
|
|
1678
1788
|
// single
|
1679
|
-
onSelect: function (data) {
|
1789
|
+
onSelect: function (data, options) {
|
1680
1790
|
var old = this.opts.element.val();
|
1681
1791
|
|
1682
1792
|
this.opts.element.val(this.id(data));
|
1683
1793
|
this.updateSelection(data);
|
1684
1794
|
this.close();
|
1685
|
-
|
1795
|
+
|
1796
|
+
if (!options || !options.noFocus)
|
1797
|
+
this.selection.focus();
|
1686
1798
|
|
1687
1799
|
if (!equal(old, this.id(data))) { this.triggerChange(); }
|
1688
1800
|
},
|
@@ -1709,7 +1821,7 @@
|
|
1709
1821
|
|
1710
1822
|
// single
|
1711
1823
|
val: function () {
|
1712
|
-
var val, data = null, self = this;
|
1824
|
+
var val, triggerChange = false, data = null, self = this;
|
1713
1825
|
|
1714
1826
|
if (arguments.length === 0) {
|
1715
1827
|
return this.opts.element.val();
|
@@ -1717,6 +1829,10 @@
|
|
1717
1829
|
|
1718
1830
|
val = arguments[0];
|
1719
1831
|
|
1832
|
+
if (arguments.length > 1) {
|
1833
|
+
triggerChange = arguments[1];
|
1834
|
+
}
|
1835
|
+
|
1720
1836
|
if (this.select) {
|
1721
1837
|
this.select
|
1722
1838
|
.val(val)
|
@@ -1726,13 +1842,19 @@
|
|
1726
1842
|
});
|
1727
1843
|
this.updateSelection(data);
|
1728
1844
|
this.setPlaceholder();
|
1845
|
+
if (triggerChange) {
|
1846
|
+
this.triggerChange();
|
1847
|
+
}
|
1729
1848
|
} else {
|
1730
1849
|
if (this.opts.initSelection === undefined) {
|
1731
1850
|
throw new Error("cannot call val() if initSelection() is not defined");
|
1732
1851
|
}
|
1733
|
-
// val is an id. !val is true for [undefined,null,'']
|
1734
|
-
if (!val) {
|
1852
|
+
// val is an id. !val is true for [undefined,null,'',0] - 0 is legal
|
1853
|
+
if (!val && val !== 0) {
|
1735
1854
|
this.clear();
|
1855
|
+
if (triggerChange) {
|
1856
|
+
this.triggerChange();
|
1857
|
+
}
|
1736
1858
|
return;
|
1737
1859
|
}
|
1738
1860
|
this.opts.element.val(val);
|
@@ -1740,6 +1862,7 @@
|
|
1740
1862
|
self.opts.element.val(!data ? "" : self.id(data));
|
1741
1863
|
self.updateSelection(data);
|
1742
1864
|
self.setPlaceholder();
|
1865
|
+
self.triggerChange();
|
1743
1866
|
});
|
1744
1867
|
}
|
1745
1868
|
},
|
@@ -1772,7 +1895,7 @@
|
|
1772
1895
|
|
1773
1896
|
// multi
|
1774
1897
|
createContainer: function () {
|
1775
|
-
var container = $("
|
1898
|
+
var container = $(document.createElement("div")).attr({
|
1776
1899
|
"class": "select2-container select2-container-multi"
|
1777
1900
|
}).html([
|
1778
1901
|
" <ul class='select2-choices'>",
|
@@ -1800,12 +1923,28 @@
|
|
1800
1923
|
|
1801
1924
|
var data = [];
|
1802
1925
|
element.find(":selected").each2(function (i, elm) {
|
1803
|
-
data.push({id: elm.attr("value"), text: elm.text()});
|
1926
|
+
data.push({id: elm.attr("value"), text: elm.text(), element: elm});
|
1804
1927
|
});
|
1805
1928
|
|
1806
1929
|
if ($.isFunction(callback))
|
1807
1930
|
callback(data);
|
1808
1931
|
};
|
1932
|
+
} else if ("data" in opts) {
|
1933
|
+
// install default initSelection when applied to hidden input and data is local
|
1934
|
+
opts.initSelection = opts.initSelection || function (element, callback) {
|
1935
|
+
var ids = splitVal(element.val(), opts.separator);
|
1936
|
+
//search in data by array of ids
|
1937
|
+
opts.query({
|
1938
|
+
matcher: function(term, text, el){
|
1939
|
+
return $.grep(ids, function(id) {
|
1940
|
+
return equal(id, opts.id(el));
|
1941
|
+
}).length;
|
1942
|
+
},
|
1943
|
+
callback: !$.isFunction(callback) ? $.noop : function(filtered) {
|
1944
|
+
callback(filtered.results);
|
1945
|
+
}
|
1946
|
+
});
|
1947
|
+
};
|
1809
1948
|
}
|
1810
1949
|
|
1811
1950
|
return opts;
|
@@ -1834,7 +1973,7 @@
|
|
1834
1973
|
return;
|
1835
1974
|
}
|
1836
1975
|
|
1837
|
-
choices = selection.find(".select2-search-choice");
|
1976
|
+
choices = selection.find(".select2-search-choice:not(.select2-locked)");
|
1838
1977
|
if (choices.length > 0) {
|
1839
1978
|
choices.last().addClass("select2-search-choice-focus");
|
1840
1979
|
}
|
@@ -1883,7 +2022,7 @@
|
|
1883
2022
|
this.search.bind("blur", this.bind(function(e) {
|
1884
2023
|
this.container.removeClass("select2-container-active");
|
1885
2024
|
this.search.removeClass("select2-focused");
|
1886
|
-
this.clearSearch();
|
2025
|
+
if (!this.opened()) this.clearSearch();
|
1887
2026
|
e.stopImmediatePropagation();
|
1888
2027
|
}));
|
1889
2028
|
|
@@ -1931,7 +2070,7 @@
|
|
1931
2070
|
// multi
|
1932
2071
|
initSelection: function () {
|
1933
2072
|
var data;
|
1934
|
-
if (this.opts.element.val() === "") {
|
2073
|
+
if (this.opts.element.val() === "" && this.opts.element.text() === "") {
|
1935
2074
|
this.updateSelection([]);
|
1936
2075
|
this.close();
|
1937
2076
|
// set the placeholder if necessary
|
@@ -1994,6 +2133,7 @@
|
|
1994
2133
|
focus: function () {
|
1995
2134
|
this.close();
|
1996
2135
|
this.search.focus();
|
2136
|
+
this.opts.element.triggerHandler("focus");
|
1997
2137
|
},
|
1998
2138
|
|
1999
2139
|
// multi
|
@@ -2034,9 +2174,9 @@
|
|
2034
2174
|
},
|
2035
2175
|
|
2036
2176
|
// multi
|
2037
|
-
onSelect: function (data) {
|
2177
|
+
onSelect: function (data, options) {
|
2038
2178
|
this.addSelectedChoice(data);
|
2039
|
-
if (this.select
|
2179
|
+
if (this.select || !this.opts.closeOnSelect) this.postprocessResults();
|
2040
2180
|
|
2041
2181
|
if (this.opts.closeOnSelect) {
|
2042
2182
|
this.close();
|
@@ -2056,7 +2196,8 @@
|
|
2056
2196
|
// added we do not need to check if this is a new element before firing change
|
2057
2197
|
this.triggerChange({ added: data });
|
2058
2198
|
|
2059
|
-
|
2199
|
+
if (!options || !options.noFocus)
|
2200
|
+
this.focusSearch();
|
2060
2201
|
},
|
2061
2202
|
|
2062
2203
|
// multi
|
@@ -2065,36 +2206,46 @@
|
|
2065
2206
|
this.focusSearch();
|
2066
2207
|
},
|
2067
2208
|
|
2068
|
-
// multi
|
2069
2209
|
addSelectedChoice: function (data) {
|
2070
|
-
var
|
2210
|
+
var enableChoice = !data.locked,
|
2211
|
+
enabledItem = $(
|
2071
2212
|
"<li class='select2-search-choice'>" +
|
2072
2213
|
" <div></div>" +
|
2073
2214
|
" <a href='#' onclick='return false;' class='select2-search-choice-close' tabindex='-1'></a>" +
|
2074
2215
|
"</li>"),
|
2216
|
+
disabledItem = $(
|
2217
|
+
"<li class='select2-search-choice select2-locked'>" +
|
2218
|
+
"<div></div>" +
|
2219
|
+
"</li>");
|
2220
|
+
var choice = enableChoice ? enabledItem : disabledItem,
|
2075
2221
|
id = this.id(data),
|
2076
2222
|
val = this.getVal(),
|
2077
2223
|
formatted;
|
2078
2224
|
|
2079
|
-
formatted=this.opts.formatSelection(data, choice);
|
2080
|
-
|
2081
|
-
|
2082
|
-
|
2083
|
-
.bind("click dblclick", this.bind(function (e) {
|
2084
|
-
if (!this.enabled) return;
|
2225
|
+
formatted=this.opts.formatSelection(data, choice.find("div"));
|
2226
|
+
if (formatted != undefined) {
|
2227
|
+
choice.find("div").replaceWith("<div>"+this.opts.escapeMarkup(formatted)+"</div>");
|
2228
|
+
}
|
2085
2229
|
|
2086
|
-
|
2087
|
-
|
2088
|
-
|
2089
|
-
|
2090
|
-
|
2091
|
-
|
2092
|
-
|
2093
|
-
|
2094
|
-
|
2095
|
-
|
2096
|
-
|
2097
|
-
|
2230
|
+
if(enableChoice){
|
2231
|
+
choice.find(".select2-search-choice-close")
|
2232
|
+
.bind("mousedown", killEvent)
|
2233
|
+
.bind("click dblclick", this.bind(function (e) {
|
2234
|
+
if (!this.enabled) return;
|
2235
|
+
|
2236
|
+
$(e.target).closest(".select2-search-choice").fadeOut('fast', this.bind(function(){
|
2237
|
+
this.unselect($(e.target));
|
2238
|
+
this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
|
2239
|
+
this.close();
|
2240
|
+
this.focusSearch();
|
2241
|
+
})).dequeue();
|
2242
|
+
killEvent(e);
|
2243
|
+
})).bind("focus", this.bind(function () {
|
2244
|
+
if (!this.enabled) return;
|
2245
|
+
this.container.addClass("select2-container-active");
|
2246
|
+
this.dropdown.addClass("select2-drop-active");
|
2247
|
+
}));
|
2248
|
+
}
|
2098
2249
|
|
2099
2250
|
choice.data("select2-data", data);
|
2100
2251
|
choice.insertBefore(this.searchContainer);
|
@@ -2117,6 +2268,12 @@
|
|
2117
2268
|
|
2118
2269
|
data = selected.data("select2-data");
|
2119
2270
|
|
2271
|
+
if (!data) {
|
2272
|
+
// prevent a race condition when the 'x' is clicked really fast repeatedly the event can be queued
|
2273
|
+
// and invoked on an element already removed
|
2274
|
+
return;
|
2275
|
+
}
|
2276
|
+
|
2120
2277
|
index = indexOf(this.id(data), val);
|
2121
2278
|
|
2122
2279
|
if (index >= 0) {
|
@@ -2131,33 +2288,30 @@
|
|
2131
2288
|
// multi
|
2132
2289
|
postprocessResults: function () {
|
2133
2290
|
var val = this.getVal(),
|
2134
|
-
choices = this.results.find(".select2-result
|
2291
|
+
choices = this.results.find(".select2-result"),
|
2135
2292
|
compound = this.results.find(".select2-result-with-children"),
|
2136
2293
|
self = this;
|
2137
2294
|
|
2138
2295
|
choices.each2(function (i, choice) {
|
2139
2296
|
var id = self.id(choice.data("select2-data"));
|
2140
2297
|
if (indexOf(id, val) >= 0) {
|
2141
|
-
choice.addClass("select2-
|
2142
|
-
|
2143
|
-
choice.
|
2298
|
+
choice.addClass("select2-selected");
|
2299
|
+
// mark all children of the selected parent as selected
|
2300
|
+
choice.find(".select2-result-selectable").addClass("select2-selected");
|
2144
2301
|
}
|
2145
2302
|
});
|
2146
2303
|
|
2147
|
-
compound.each2(function(i,
|
2148
|
-
if
|
2149
|
-
|
2150
|
-
|
2151
|
-
|
2304
|
+
compound.each2(function(i, choice) {
|
2305
|
+
// hide an optgroup if it doesnt have any selectable children
|
2306
|
+
if (!choice.is('.select2-result-selectable')
|
2307
|
+
&& choice.find(".select2-result-selectable:not(.select2-selected)").length === 0) {
|
2308
|
+
choice.addClass("select2-selected");
|
2152
2309
|
}
|
2153
2310
|
});
|
2154
2311
|
|
2155
|
-
|
2156
|
-
|
2157
|
-
|
2158
|
-
return false;
|
2159
|
-
}
|
2160
|
-
});
|
2312
|
+
if (this.highlight() == -1){
|
2313
|
+
self.highlight(0);
|
2314
|
+
}
|
2161
2315
|
|
2162
2316
|
},
|
2163
2317
|
|
@@ -2182,6 +2336,11 @@
|
|
2182
2336
|
if (searchWidth < 40) {
|
2183
2337
|
searchWidth = maxWidth - sideBorderPadding;
|
2184
2338
|
}
|
2339
|
+
|
2340
|
+
if (searchWidth <= 0) {
|
2341
|
+
searchWidth = minimumWidth
|
2342
|
+
}
|
2343
|
+
|
2185
2344
|
this.search.width(searchWidth);
|
2186
2345
|
},
|
2187
2346
|
|
@@ -2214,7 +2373,7 @@
|
|
2214
2373
|
|
2215
2374
|
// multi
|
2216
2375
|
val: function () {
|
2217
|
-
var val, data = [], self=this;
|
2376
|
+
var val, triggerChange = false, data = [], self=this;
|
2218
2377
|
|
2219
2378
|
if (arguments.length === 0) {
|
2220
2379
|
return this.getVal();
|
@@ -2222,10 +2381,18 @@
|
|
2222
2381
|
|
2223
2382
|
val = arguments[0];
|
2224
2383
|
|
2225
|
-
if (
|
2384
|
+
if (arguments.length > 1) {
|
2385
|
+
triggerChange = arguments[1];
|
2386
|
+
}
|
2387
|
+
|
2388
|
+
// val is an id. !val is true for [undefined,null,'',0] - 0 is legal
|
2389
|
+
if (!val && val !== 0) {
|
2226
2390
|
this.opts.element.val("");
|
2227
2391
|
this.updateSelection([]);
|
2228
2392
|
this.clearSearch();
|
2393
|
+
if (triggerChange) {
|
2394
|
+
this.triggerChange();
|
2395
|
+
}
|
2229
2396
|
return;
|
2230
2397
|
}
|
2231
2398
|
|
@@ -2237,6 +2404,9 @@
|
|
2237
2404
|
data.push({id: $(this).attr("value"), text: $(this).text()});
|
2238
2405
|
});
|
2239
2406
|
this.updateSelection(data);
|
2407
|
+
if (triggerChange) {
|
2408
|
+
this.triggerChange();
|
2409
|
+
}
|
2240
2410
|
} else {
|
2241
2411
|
if (this.opts.initSelection === undefined) {
|
2242
2412
|
throw new Error("val() cannot be called if initSelection() is not defined")
|
@@ -2247,6 +2417,9 @@
|
|
2247
2417
|
self.setVal(ids);
|
2248
2418
|
self.updateSelection(data);
|
2249
2419
|
self.clearSearch();
|
2420
|
+
if (triggerChange) {
|
2421
|
+
self.triggerChange();
|
2422
|
+
}
|
2250
2423
|
});
|
2251
2424
|
}
|
2252
2425
|
this.clearSearch();
|
@@ -2349,28 +2522,34 @@
|
|
2349
2522
|
// plugin defaults, accessible to users
|
2350
2523
|
$.fn.select2.defaults = {
|
2351
2524
|
width: "copy",
|
2525
|
+
loadMorePadding: 0,
|
2352
2526
|
closeOnSelect: true,
|
2353
2527
|
openOnEnter: true,
|
2354
2528
|
containerCss: {},
|
2355
2529
|
dropdownCss: {},
|
2356
2530
|
containerCssClass: "",
|
2357
2531
|
dropdownCssClass: "",
|
2358
|
-
formatResult: function(result, container, query) {
|
2532
|
+
formatResult: function(result, container, query, escapeMarkup) {
|
2359
2533
|
var markup=[];
|
2360
|
-
markMatch(result.text, query.term, markup);
|
2534
|
+
markMatch(result.text, query.term, markup, escapeMarkup);
|
2361
2535
|
return markup.join("");
|
2362
2536
|
},
|
2363
2537
|
formatSelection: function (data, container) {
|
2364
2538
|
return data ? data.text : undefined;
|
2365
2539
|
},
|
2540
|
+
sortResults: function (results, container, query) {
|
2541
|
+
return results;
|
2542
|
+
},
|
2366
2543
|
formatResultCssClass: function(data) {return undefined;},
|
2367
2544
|
formatNoMatches: function () { return "No matches found"; },
|
2368
|
-
formatInputTooShort: function (input, min) { return "Please enter " +
|
2545
|
+
formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " more character" + (n == 1? "" : "s"); },
|
2546
|
+
formatInputTooLong: function (input, max) { var n = input.length - max; return "Please enter " + n + " less character" + (n == 1? "" : "s"); },
|
2369
2547
|
formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); },
|
2370
2548
|
formatLoadMore: function (pageNumber) { return "Loading more results..."; },
|
2371
2549
|
formatSearching: function () { return "Searching..."; },
|
2372
2550
|
minimumResultsForSearch: 0,
|
2373
2551
|
minimumInputLength: 0,
|
2552
|
+
maximumInputLength: null,
|
2374
2553
|
maximumSelectionSize: 0,
|
2375
2554
|
id: function (e) { return e.id; },
|
2376
2555
|
matcher: function(term, text) {
|
@@ -2380,12 +2559,22 @@
|
|
2380
2559
|
tokenSeparators: [],
|
2381
2560
|
tokenizer: defaultTokenizer,
|
2382
2561
|
escapeMarkup: function (markup) {
|
2383
|
-
|
2384
|
-
|
2385
|
-
|
2386
|
-
|
2562
|
+
var replace_map = {
|
2563
|
+
'\\': '\',
|
2564
|
+
'&': '&',
|
2565
|
+
'<': '<',
|
2566
|
+
'>': '>',
|
2567
|
+
'"': '"',
|
2568
|
+
"'": ''',
|
2569
|
+
"/": '/'
|
2570
|
+
};
|
2571
|
+
|
2572
|
+
return String(markup).replace(/[&<>"'/\\]/g, function (match) {
|
2573
|
+
return replace_map[match[0]];
|
2574
|
+
});
|
2387
2575
|
},
|
2388
|
-
blurOnChange: false
|
2576
|
+
blurOnChange: false,
|
2577
|
+
selectOnBlur: false
|
2389
2578
|
};
|
2390
2579
|
|
2391
2580
|
// exports
|