2 Chosen, a Select Box Enhancer for jQuery and Prototype
3 by Patrick Filler for Harvest, http://getharvest.com
6 Full source at https://github.com/harvesthq/chosen
7 Copyright (c) 2011-2017 Harvest http://getharvest.com
9 MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
10 This file is generated by `grunt build`, do not edit it by hand.
14 var $, AbstractChosen
, Chosen
, SelectParser
,
15 bind = function(fn
, me
){ return function(){ return fn
.apply(me
, arguments
); }; },
16 extend = function(child
, parent
) { for (var key
in parent
) { if (hasProp
.call(parent
, key
)) child
[key
] = parent
[key
]; } function ctor() { this.constructor = child
; } ctor
.prototype = parent
.prototype; child
.prototype = new ctor(); child
.__super__
= parent
.prototype; return child
; },
17 hasProp
= {}.hasOwnProperty
;
19 SelectParser
= (function() {
20 function SelectParser() {
21 this.options_index
= 0;
25 SelectParser
.prototype.add_node = function(child
) {
26 if (child
.nodeName
.toUpperCase() === "OPTGROUP") {
27 return this.add_group(child
);
29 return this.add_option(child
);
33 SelectParser
.prototype.add_group = function(group
) {
34 var group_position
, i
, len
, option
, ref
, results1
;
35 group_position
= this.parsed
.length
;
37 array_index
: group_position
,
40 title
: group
.title
? group
.title
: void 0,
42 disabled
: group
.disabled
,
43 classes
: group
.className
45 ref
= group
.childNodes
;
47 for (i
= 0, len
= ref
.length
; i
< len
; i
++) {
49 results1
.push(this.add_option(option
, group_position
, group
.disabled
));
54 SelectParser
.prototype.add_option = function(option
, group_position
, group_disabled
) {
55 if (option
.nodeName
.toUpperCase() === "OPTION") {
56 if (option
.text
!== "") {
57 if (group_position
!= null) {
58 this.parsed
[group_position
].children
+= 1;
61 array_index
: this.parsed
.length
,
62 options_index
: this.options_index
,
65 html
: option
.innerHTML
,
66 title
: option
.title
? option
.title
: void 0,
67 selected
: option
.selected
,
68 disabled
: group_disabled
=== true ? group_disabled
: option
.disabled
,
69 group_array_index
: group_position
,
70 group_label
: group_position
!= null ? this.parsed
[group_position
].label
: null,
71 classes
: option
.className
,
72 style
: option
.style
.cssText
76 array_index
: this.parsed
.length
,
77 options_index
: this.options_index
,
81 return this.options_index
+= 1;
89 SelectParser
.select_to_array = function(select
) {
90 var child
, i
, len
, parser
, ref
;
91 parser
= new SelectParser();
92 ref
= select
.childNodes
;
93 for (i
= 0, len
= ref
.length
; i
< len
; i
++) {
95 parser
.add_node(child
);
100 AbstractChosen
= (function() {
101 function AbstractChosen(form_field
, options1
) {
102 this.form_field
= form_field
;
103 this.options
= options1
!= null ? options1
: {};
104 this.label_click_handler
= bind(this.label_click_handler
, this);
105 if (!AbstractChosen
.browser_is_supported()) {
108 this.is_multiple
= this.form_field
.multiple
;
109 this.set_default_text();
110 this.set_default_values();
113 this.register_observers();
117 AbstractChosen
.prototype.set_default_values = function() {
118 this.click_test_action
= (function(_this
) {
119 return function(evt
) {
120 return _this
.test_active_click(evt
);
123 this.activate_action
= (function(_this
) {
124 return function(evt
) {
125 return _this
.activate_field(evt
);
128 this.active_field
= false;
129 this.mouse_on_container
= false;
130 this.results_showing
= false;
131 this.result_highlighted
= null;
132 this.is_rtl
= this.options
.rtl
|| /\bchosen-rtl\b/.test(this.form_field
.className
);
133 this.allow_single_deselect
= (this.options
.allow_single_deselect
!= null) && (this.form_field
.options
[0] != null) && this.form_field
.options
[0].text
=== "" ? this.options
.allow_single_deselect
: false;
134 this.disable_search_threshold
= this.options
.disable_search_threshold
|| 0;
135 this.disable_search
= this.options
.disable_search
|| false;
136 this.enable_split_word_search
= this.options
.enable_split_word_search
!= null ? this.options
.enable_split_word_search
: true;
137 this.group_search
= this.options
.group_search
!= null ? this.options
.group_search
: true;
138 this.search_contains
= this.options
.search_contains
|| false;
139 this.single_backstroke_delete
= this.options
.single_backstroke_delete
!= null ? this.options
.single_backstroke_delete
: true;
140 this.max_selected_options
= this.options
.max_selected_options
|| Infinity
;
141 this.inherit_select_classes
= this.options
.inherit_select_classes
|| false;
142 this.display_selected_options
= this.options
.display_selected_options
!= null ? this.options
.display_selected_options
: true;
143 this.display_disabled_options
= this.options
.display_disabled_options
!= null ? this.options
.display_disabled_options
: true;
144 this.include_group_label_in_selected
= this.options
.include_group_label_in_selected
|| false;
145 this.max_shown_results
= this.options
.max_shown_results
|| Number
.POSITIVE_INFINITY
;
146 this.case_sensitive_search
= this.options
.case_sensitive_search
|| false;
147 return this.hide_results_on_select
= this.options
.hide_results_on_select
!= null ? this.options
.hide_results_on_select
: true;
150 AbstractChosen
.prototype.set_default_text = function() {
151 if (this.form_field
.getAttribute("data-placeholder")) {
152 this.default_text
= this.form_field
.getAttribute("data-placeholder");
153 } else if (this.is_multiple
) {
154 this.default_text
= this.options
.placeholder_text_multiple
|| this.options
.placeholder_text
|| AbstractChosen
.default_multiple_text
;
156 this.default_text
= this.options
.placeholder_text_single
|| this.options
.placeholder_text
|| AbstractChosen
.default_single_text
;
158 this.default_text
= this.escape_html(this.default_text
);
159 return this.results_none_found
= this.form_field
.getAttribute("data-no_results_text") || this.options
.no_results_text
|| AbstractChosen
.default_no_result_text
;
162 AbstractChosen
.prototype.choice_label = function(item
) {
163 if (this.include_group_label_in_selected
&& (item
.group_label
!= null)) {
164 return "<b class='group-name'>" + item
.group_label
+ "</b>" + item
.html
;
170 AbstractChosen
.prototype.mouse_enter = function() {
171 return this.mouse_on_container
= true;
174 AbstractChosen
.prototype.mouse_leave = function() {
175 return this.mouse_on_container
= false;
178 AbstractChosen
.prototype.input_focus = function(evt
) {
179 if (this.is_multiple
) {
180 if (!this.active_field
) {
181 return setTimeout(((function(_this
) {
183 return _this
.container_mousedown();
188 if (!this.active_field
) {
189 return this.activate_field();
194 AbstractChosen
.prototype.input_blur = function(evt
) {
195 if (!this.mouse_on_container
) {
196 this.active_field
= false;
197 return setTimeout(((function(_this
) {
199 return _this
.blur_test();
205 AbstractChosen
.prototype.label_click_handler = function(evt
) {
206 if (this.is_multiple
) {
207 return this.container_mousedown(evt
);
209 return this.activate_field();
213 AbstractChosen
.prototype.results_option_build = function(options
) {
214 var content
, data
, data_content
, i
, len
, ref
, shown_results
;
217 ref
= this.results_data
;
218 for (i
= 0, len
= ref
.length
; i
< len
; i
++) {
222 data_content
= this.result_add_group(data
);
224 data_content
= this.result_add_option(data
);
226 if (data_content
!== '') {
228 content
+= data_content
;
230 if (options
!= null ? options
.first
: void 0) {
231 if (data
.selected
&& this.is_multiple
) {
232 this.choice_build(data
);
233 } else if (data
.selected
&& !this.is_multiple
) {
234 this.single_set_selected_text(this.choice_label(data
));
237 if (shown_results
>= this.max_shown_results
) {
244 AbstractChosen
.prototype.result_add_option = function(option
) {
245 var classes
, option_el
;
246 if (!option
.search_match
) {
249 if (!this.include_option_in_results(option
)) {
253 if (!option
.disabled
&& !(option
.selected
&& this.is_multiple
)) {
254 classes
.push("active-result");
256 if (option
.disabled
&& !(option
.selected
&& this.is_multiple
)) {
257 classes
.push("disabled-result");
259 if (option
.selected
) {
260 classes
.push("result-selected");
262 if (option
.group_array_index
!= null) {
263 classes
.push("group-option");
265 if (option
.classes
!== "") {
266 classes
.push(option
.classes
);
268 option_el
= document
.createElement("li");
269 option_el
.className
= classes
.join(" ");
270 option_el
.style
.cssText
= option
.style
;
271 option_el
.setAttribute("data-option-array-index", option
.array_index
);
272 option_el
.innerHTML
= option
.highlighted_html
|| option
.html
;
274 option_el
.title
= option
.title
;
276 return this.outerHTML(option_el
);
279 AbstractChosen
.prototype.result_add_group = function(group
) {
280 var classes
, group_el
;
281 if (!(group
.search_match
|| group
.group_match
)) {
284 if (!(group
.active_options
> 0)) {
288 classes
.push("group-result");
290 classes
.push(group
.classes
);
292 group_el
= document
.createElement("li");
293 group_el
.className
= classes
.join(" ");
294 group_el
.innerHTML
= group
.highlighted_html
|| this.escape_html(group
.label
);
296 group_el
.title
= group
.title
;
298 return this.outerHTML(group_el
);
301 AbstractChosen
.prototype.results_update_field = function() {
302 this.set_default_text();
303 if (!this.is_multiple
) {
304 this.results_reset_cleanup();
306 this.result_clear_highlight();
307 this.results_build();
308 if (this.results_showing
) {
309 return this.winnow_results();
313 AbstractChosen
.prototype.reset_single_select_options = function() {
314 var i
, len
, ref
, result
, results1
;
315 ref
= this.results_data
;
317 for (i
= 0, len
= ref
.length
; i
< len
; i
++) {
319 if (result
.selected
) {
320 results1
.push(result
.selected
= false);
322 results1
.push(void 0);
328 AbstractChosen
.prototype.results_toggle = function() {
329 if (this.results_showing
) {
330 return this.results_hide();
332 return this.results_show();
336 AbstractChosen
.prototype.results_search = function(evt
) {
337 if (this.results_showing
) {
338 return this.winnow_results();
340 return this.results_show();
344 AbstractChosen
.prototype.winnow_results = function() {
345 var escapedQuery
, fix
, i
, len
, option
, prefix
, query
, ref
, regex
, results
, results_group
, search_match
, startpos
, suffix
, text
;
346 this.no_results_clear();
348 query
= this.get_search_text();
349 escapedQuery
= query
.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
350 regex
= this.get_search_regex(escapedQuery
);
351 ref
= this.results_data
;
352 for (i
= 0, len
= ref
.length
; i
< len
; i
++) {
354 option
.search_match
= false;
355 results_group
= null;
357 option
.highlighted_html
= '';
358 if (this.include_option_in_results(option
)) {
360 option
.group_match
= false;
361 option
.active_options
= 0;
363 if ((option
.group_array_index
!= null) && this.results_data
[option
.group_array_index
]) {
364 results_group
= this.results_data
[option
.group_array_index
];
365 if (results_group
.active_options
=== 0 && results_group
.search_match
) {
368 results_group
.active_options
+= 1;
370 text
= option
.group
? option
.label
: option
.text
;
371 if (!(option
.group
&& !this.group_search
)) {
372 search_match
= this.search_string_match(text
, regex
);
373 option
.search_match
= search_match
!= null;
374 if (option
.search_match
&& !option
.group
) {
377 if (option
.search_match
) {
379 startpos
= search_match
.index
;
380 prefix
= text
.slice(0, startpos
);
381 fix
= text
.slice(startpos
, startpos
+ query
.length
);
382 suffix
= text
.slice(startpos
+ query
.length
);
383 option
.highlighted_html
= (this.escape_html(prefix
)) + "<em>" + (this.escape_html(fix
)) + "</em>" + (this.escape_html(suffix
));
385 if (results_group
!= null) {
386 results_group
.group_match
= true;
388 } else if ((option
.group_array_index
!= null) && this.results_data
[option
.group_array_index
].search_match
) {
389 option
.search_match
= true;
394 this.result_clear_highlight();
395 if (results
< 1 && query
.length
) {
396 this.update_results_content("");
397 return this.no_results(query
);
399 this.update_results_content(this.results_option_build());
400 return this.winnow_results_set_highlight();
404 AbstractChosen
.prototype.get_search_regex = function(escaped_search_string
) {
405 var regex_flag
, regex_string
;
406 regex_string
= this.search_contains
? escaped_search_string
: "(^|\\s|\\b)" + escaped_search_string
+ "[^\\s]*";
407 if (!(this.enable_split_word_search
|| this.search_contains
)) {
408 regex_string
= "^" + regex_string
;
410 regex_flag
= this.case_sensitive_search
? "" : "i";
411 return new RegExp(regex_string
, regex_flag
);
414 AbstractChosen
.prototype.search_string_match = function(search_string
, regex
) {
416 match
= regex
.exec(search_string
);
417 if (!this.search_contains
&& (match
!= null ? match
[1] : void 0)) {
423 AbstractChosen
.prototype.choices_count = function() {
424 var i
, len
, option
, ref
;
425 if (this.selected_option_count
!= null) {
426 return this.selected_option_count
;
428 this.selected_option_count
= 0;
429 ref
= this.form_field
.options
;
430 for (i
= 0, len
= ref
.length
; i
< len
; i
++) {
432 if (option
.selected
) {
433 this.selected_option_count
+= 1;
436 return this.selected_option_count
;
439 AbstractChosen
.prototype.choices_click = function(evt
) {
440 evt
.preventDefault();
441 this.activate_field();
442 if (!(this.results_showing
|| this.is_disabled
)) {
443 return this.results_show();
447 AbstractChosen
.prototype.keydown_checker = function(evt
) {
449 stroke
= (ref
= evt
.which
) != null ? ref
: evt
.keyCode
;
450 this.search_field_scale();
451 if (stroke
!== 8 && this.pending_backstroke
) {
452 this.clear_backstroke();
456 this.backstroke_length
= this.get_search_field_value().length
;
459 if (this.results_showing
&& !this.is_multiple
) {
460 this.result_select(evt
);
462 this.mouse_on_container
= false;
465 if (this.results_showing
) {
466 evt
.preventDefault();
470 if (this.results_showing
) {
471 evt
.preventDefault();
475 if (this.disable_search
) {
476 evt
.preventDefault();
480 evt
.preventDefault();
484 evt
.preventDefault();
485 this.keydown_arrow();
490 AbstractChosen
.prototype.keyup_checker = function(evt
) {
492 stroke
= (ref
= evt
.which
) != null ? ref
: evt
.keyCode
;
493 this.search_field_scale();
496 if (this.is_multiple
&& this.backstroke_length
< 1 && this.choices_count() > 0) {
497 this.keydown_backstroke();
498 } else if (!this.pending_backstroke
) {
499 this.result_clear_highlight();
500 this.results_search();
504 evt
.preventDefault();
505 if (this.results_showing
) {
506 this.result_select(evt
);
510 if (this.results_showing
) {
523 this.results_search();
528 AbstractChosen
.prototype.clipboard_event_checker = function(evt
) {
529 if (this.is_disabled
) {
532 return setTimeout(((function(_this
) {
534 return _this
.results_search();
539 AbstractChosen
.prototype.container_width = function() {
540 if (this.options
.width
!= null) {
541 return this.options
.width
;
543 return this.form_field
.offsetWidth
+ "px";
547 AbstractChosen
.prototype.include_option_in_results = function(option
) {
548 if (this.is_multiple
&& (!this.display_selected_options
&& option
.selected
)) {
551 if (!this.display_disabled_options
&& option
.disabled
) {
560 AbstractChosen
.prototype.search_results_touchstart = function(evt
) {
561 this.touch_started
= true;
562 return this.search_results_mouseover(evt
);
565 AbstractChosen
.prototype.search_results_touchmove = function(evt
) {
566 this.touch_started
= false;
567 return this.search_results_mouseout(evt
);
570 AbstractChosen
.prototype.search_results_touchend = function(evt
) {
571 if (this.touch_started
) {
572 return this.search_results_mouseup(evt
);
576 AbstractChosen
.prototype.outerHTML = function(element
) {
578 if (element
.outerHTML
) {
579 return element
.outerHTML
;
581 tmp
= document
.createElement("div");
582 tmp
.appendChild(element
);
583 return tmp
.innerHTML
;
586 AbstractChosen
.prototype.get_single_html = function() {
587 return "<a class=\"chosen-single chosen-default\">\n <span>" + this.default_text
+ "</span>\n <div><b></b></div>\n</a>\n<div class=\"chosen-drop\">\n <div class=\"chosen-search\">\n <input class=\"chosen-search-input\" type=\"text\" autocomplete=\"off\" />\n </div>\n <ul class=\"chosen-results\"></ul>\n</div>";
590 AbstractChosen
.prototype.get_multi_html = function() {
591 return "<ul class=\"chosen-choices\">\n <li class=\"search-field\">\n <input class=\"chosen-search-input\" type=\"text\" autocomplete=\"off\" value=\"" + this.default_text
+ "\" />\n </li>\n</ul>\n<div class=\"chosen-drop\">\n <ul class=\"chosen-results\"></ul>\n</div>";
594 AbstractChosen
.prototype.get_no_results_html = function(terms
) {
595 return "<li class=\"no-results\">\n " + this.results_none_found
+ " <span>" + (this.escape_html(terms
)) + "</span>\n</li>";
598 AbstractChosen
.browser_is_supported = function() {
599 if ("Microsoft Internet Explorer" === window
.navigator
.appName
) {
600 return document
.documentMode
>= 8;
602 if (/iP(od|hone)/i.test(window
.navigator
.userAgent
) || /IEMobile/i.test(window
.navigator
.userAgent
) || /Windows Phone/i.test(window
.navigator
.userAgent
) || /BlackBerry/i.test(window
.navigator
.userAgent
) || /BB10/i.test(window
.navigator
.userAgent
) || /Android.*Mobile/i.test(window
.navigator
.userAgent
)) {
608 AbstractChosen
.default_multiple_text
= "Select Some Options";
610 AbstractChosen
.default_single_text
= "Select an Option";
612 AbstractChosen
.default_no_result_text
= "No results match";
614 return AbstractChosen
;
621 chosen: function(options
) {
622 if (!AbstractChosen
.browser_is_supported()) {
625 return this.each(function(input_field
) {
628 chosen
= $this.data('chosen');
629 if (options
=== 'destroy') {
630 if (chosen
instanceof Chosen
) {
635 if (!(chosen
instanceof Chosen
)) {
636 $this.data('chosen', new Chosen(this, options
));
642 Chosen
= (function(superClass
) {
643 extend(Chosen
, superClass
);
646 return Chosen
.__super__
.constructor.apply(this, arguments
);
649 Chosen
.prototype.setup = function() {
650 this.form_field_jq
= $(this.form_field
);
651 return this.current_selectedIndex
= this.form_field
.selectedIndex
;
654 Chosen
.prototype.set_up_html = function() {
655 var container_classes
, container_props
;
656 container_classes
= ["chosen-container"];
657 container_classes
.push("chosen-container-" + (this.is_multiple
? "multi" : "single"));
658 if (this.inherit_select_classes
&& this.form_field
.className
) {
659 container_classes
.push(this.form_field
.className
);
662 container_classes
.push("chosen-rtl");
665 'class': container_classes
.join(' '),
666 'title': this.form_field
.title
668 if (this.form_field
.id
.length
) {
669 container_props
.id
= this.form_field
.id
.replace(/[^\w]/g, '_') + "_chosen";
671 this.container
= $("<div />", container_props
);
672 this.container
.width(this.container_width());
673 if (this.is_multiple
) {
674 this.container
.html(this.get_multi_html());
676 this.container
.html(this.get_single_html());
678 this.form_field_jq
.hide().after(this.container
);
679 this.dropdown
= this.container
.find('div.chosen-drop').first();
680 this.search_field
= this.container
.find('input').first();
681 this.search_results
= this.container
.find('ul.chosen-results').first();
682 this.search_field_scale();
683 this.search_no_results
= this.container
.find('li.no-results').first();
684 if (this.is_multiple
) {
685 this.search_choices
= this.container
.find('ul.chosen-choices').first();
686 this.search_container
= this.container
.find('li.search-field').first();
688 this.search_container
= this.container
.find('div.chosen-search').first();
689 this.selected_item
= this.container
.find('.chosen-single').first();
691 this.results_build();
692 this.set_tab_index();
693 return this.set_label_behavior();
696 Chosen
.prototype.on_ready = function() {
697 return this.form_field_jq
.trigger("chosen:ready", {
702 Chosen
.prototype.register_observers = function() {
703 this.container
.on('touchstart.chosen', (function(_this
) {
704 return function(evt
) {
705 _this
.container_mousedown(evt
);
708 this.container
.on('touchend.chosen', (function(_this
) {
709 return function(evt
) {
710 _this
.container_mouseup(evt
);
713 this.container
.on('mousedown.chosen', (function(_this
) {
714 return function(evt
) {
715 _this
.container_mousedown(evt
);
718 this.container
.on('mouseup.chosen', (function(_this
) {
719 return function(evt
) {
720 _this
.container_mouseup(evt
);
723 this.container
.on('mouseenter.chosen', (function(_this
) {
724 return function(evt
) {
725 _this
.mouse_enter(evt
);
728 this.container
.on('mouseleave.chosen', (function(_this
) {
729 return function(evt
) {
730 _this
.mouse_leave(evt
);
733 this.search_results
.on('mouseup.chosen', (function(_this
) {
734 return function(evt
) {
735 _this
.search_results_mouseup(evt
);
738 this.search_results
.on('mouseover.chosen', (function(_this
) {
739 return function(evt
) {
740 _this
.search_results_mouseover(evt
);
743 this.search_results
.on('mouseout.chosen', (function(_this
) {
744 return function(evt
) {
745 _this
.search_results_mouseout(evt
);
748 this.search_results
.on('mousewheel.chosen DOMMouseScroll.chosen', (function(_this
) {
749 return function(evt
) {
750 _this
.search_results_mousewheel(evt
);
753 this.search_results
.on('touchstart.chosen', (function(_this
) {
754 return function(evt
) {
755 _this
.search_results_touchstart(evt
);
758 this.search_results
.on('touchmove.chosen', (function(_this
) {
759 return function(evt
) {
760 _this
.search_results_touchmove(evt
);
763 this.search_results
.on('touchend.chosen', (function(_this
) {
764 return function(evt
) {
765 _this
.search_results_touchend(evt
);
768 this.form_field_jq
.on("chosen:updated.chosen", (function(_this
) {
769 return function(evt
) {
770 _this
.results_update_field(evt
);
773 this.form_field_jq
.on("chosen:activate.chosen", (function(_this
) {
774 return function(evt
) {
775 _this
.activate_field(evt
);
778 this.form_field_jq
.on("chosen:open.chosen", (function(_this
) {
779 return function(evt
) {
780 _this
.container_mousedown(evt
);
783 this.form_field_jq
.on("chosen:close.chosen", (function(_this
) {
784 return function(evt
) {
785 _this
.close_field(evt
);
788 this.search_field
.on('blur.chosen', (function(_this
) {
789 return function(evt
) {
790 _this
.input_blur(evt
);
793 this.search_field
.on('keyup.chosen', (function(_this
) {
794 return function(evt
) {
795 _this
.keyup_checker(evt
);
798 this.search_field
.on('keydown.chosen', (function(_this
) {
799 return function(evt
) {
800 _this
.keydown_checker(evt
);
803 this.search_field
.on('focus.chosen', (function(_this
) {
804 return function(evt
) {
805 _this
.input_focus(evt
);
808 this.search_field
.on('cut.chosen', (function(_this
) {
809 return function(evt
) {
810 _this
.clipboard_event_checker(evt
);
813 this.search_field
.on('paste.chosen', (function(_this
) {
814 return function(evt
) {
815 _this
.clipboard_event_checker(evt
);
818 if (this.is_multiple
) {
819 return this.search_choices
.on('click.chosen', (function(_this
) {
820 return function(evt
) {
821 _this
.choices_click(evt
);
825 return this.container
.on('click.chosen', function(evt
) {
826 evt
.preventDefault();
831 Chosen
.prototype.destroy = function() {
832 $(this.container
[0].ownerDocument
).off('click.chosen', this.click_test_action
);
833 if (this.form_field_label
.length
> 0) {
834 this.form_field_label
.off('click.chosen');
836 if (this.search_field
[0].tabIndex
) {
837 this.form_field_jq
[0].tabIndex
= this.search_field
[0].tabIndex
;
839 this.container
.remove();
840 this.form_field_jq
.removeData('chosen');
841 return this.form_field_jq
.show();
844 Chosen
.prototype.search_field_disabled = function() {
845 this.is_disabled
= this.form_field
.disabled
|| this.form_field_jq
.parents('fieldset').is(':disabled');
846 this.container
.toggleClass('chosen-disabled', this.is_disabled
);
847 this.search_field
[0].disabled
= this.is_disabled
;
848 if (!this.is_multiple
) {
849 this.selected_item
.off('focus.chosen', this.activate_field
);
851 if (this.is_disabled
) {
852 return this.close_field();
853 } else if (!this.is_multiple
) {
854 return this.selected_item
.on('focus.chosen', this.activate_field
);
858 Chosen
.prototype.container_mousedown = function(evt
) {
860 if (this.is_disabled
) {
863 if (evt
&& ((ref
= evt
.type
) === 'mousedown' || ref
=== 'touchstart') && !this.results_showing
) {
864 evt
.preventDefault();
866 if (!((evt
!= null) && ($(evt
.target
)).hasClass("search-choice-close"))) {
867 if (!this.active_field
) {
868 if (this.is_multiple
) {
869 this.search_field
.val("");
871 $(this.container
[0].ownerDocument
).on('click.chosen', this.click_test_action
);
873 } else if (!this.is_multiple
&& evt
&& (($(evt
.target
)[0] === this.selected_item
[0]) || $(evt
.target
).parents("a.chosen-single").length
)) {
874 evt
.preventDefault();
875 this.results_toggle();
877 return this.activate_field();
881 Chosen
.prototype.container_mouseup = function(evt
) {
882 if (evt
.target
.nodeName
=== "ABBR" && !this.is_disabled
) {
883 return this.results_reset(evt
);
887 Chosen
.prototype.search_results_mousewheel = function(evt
) {
889 if (evt
.originalEvent
) {
890 delta
= evt
.originalEvent
.deltaY
|| -evt
.originalEvent
.wheelDelta
|| evt
.originalEvent
.detail
;
893 evt
.preventDefault();
894 if (evt
.type
=== 'DOMMouseScroll') {
897 return this.search_results
.scrollTop(delta
+ this.search_results
.scrollTop());
901 Chosen
.prototype.blur_test = function(evt
) {
902 if (!this.active_field
&& this.container
.hasClass("chosen-container-active")) {
903 return this.close_field();
907 Chosen
.prototype.close_field = function() {
908 $(this.container
[0].ownerDocument
).off("click.chosen", this.click_test_action
);
909 this.active_field
= false;
911 this.container
.removeClass("chosen-container-active");
912 this.clear_backstroke();
913 this.show_search_field_default();
914 this.search_field_scale();
915 return this.search_field
.blur();
918 Chosen
.prototype.activate_field = function() {
919 if (this.is_disabled
) {
922 this.container
.addClass("chosen-container-active");
923 this.active_field
= true;
924 this.search_field
.val(this.search_field
.val());
925 return this.search_field
.focus();
928 Chosen
.prototype.test_active_click = function(evt
) {
929 var active_container
;
930 active_container
= $(evt
.target
).closest('.chosen-container');
931 if (active_container
.length
&& this.container
[0] === active_container
[0]) {
932 return this.active_field
= true;
934 return this.close_field();
938 Chosen
.prototype.results_build = function() {
940 this.selected_option_count
= null;
941 this.results_data
= SelectParser
.select_to_array(this.form_field
);
942 if (this.is_multiple
) {
943 this.search_choices
.find("li.search-choice").remove();
944 } else if (!this.is_multiple
) {
945 this.single_set_selected_text();
946 if (this.disable_search
|| this.form_field
.options
.length
<= this.disable_search_threshold
) {
947 this.search_field
[0].readOnly
= true;
948 this.container
.addClass("chosen-container-single-nosearch");
950 this.search_field
[0].readOnly
= false;
951 this.container
.removeClass("chosen-container-single-nosearch");
954 this.update_results_content(this.results_option_build({
957 this.search_field_disabled();
958 this.show_search_field_default();
959 this.search_field_scale();
960 return this.parsing
= false;
963 Chosen
.prototype.result_do_highlight = function(el
) {
964 var high_bottom
, high_top
, maxHeight
, visible_bottom
, visible_top
;
966 this.result_clear_highlight();
967 this.result_highlight
= el
;
968 this.result_highlight
.addClass("highlighted");
969 maxHeight
= parseInt(this.search_results
.css("maxHeight"), 10);
970 visible_top
= this.search_results
.scrollTop();
971 visible_bottom
= maxHeight
+ visible_top
;
972 high_top
= this.result_highlight
.position().top
+ this.search_results
.scrollTop();
973 high_bottom
= high_top
+ this.result_highlight
.outerHeight();
974 if (high_bottom
>= visible_bottom
) {
975 return this.search_results
.scrollTop((high_bottom
- maxHeight
) > 0 ? high_bottom
- maxHeight
: 0);
976 } else if (high_top
< visible_top
) {
977 return this.search_results
.scrollTop(high_top
);
982 Chosen
.prototype.result_clear_highlight = function() {
983 if (this.result_highlight
) {
984 this.result_highlight
.removeClass("highlighted");
986 return this.result_highlight
= null;
989 Chosen
.prototype.results_show = function() {
990 if (this.is_multiple
&& this.max_selected_options
<= this.choices_count()) {
991 this.form_field_jq
.trigger("chosen:maxselected", {
996 this.container
.addClass("chosen-with-drop");
997 this.results_showing
= true;
998 this.search_field
.focus();
999 this.search_field
.val(this.get_search_field_value());
1000 this.winnow_results();
1001 return this.form_field_jq
.trigger("chosen:showing_dropdown", {
1006 Chosen
.prototype.update_results_content = function(content
) {
1007 return this.search_results
.html(content
);
1010 Chosen
.prototype.results_hide = function() {
1011 if (this.results_showing
) {
1012 this.result_clear_highlight();
1013 this.container
.removeClass("chosen-with-drop");
1014 this.form_field_jq
.trigger("chosen:hiding_dropdown", {
1018 return this.results_showing
= false;
1021 Chosen
.prototype.set_tab_index = function(el
) {
1023 if (this.form_field
.tabIndex
) {
1024 ti
= this.form_field
.tabIndex
;
1025 this.form_field
.tabIndex
= -1;
1026 return this.search_field
[0].tabIndex
= ti
;
1030 Chosen
.prototype.set_label_behavior = function() {
1031 this.form_field_label
= this.form_field_jq
.parents("label");
1032 if (!this.form_field_label
.length
&& this.form_field
.id
.length
) {
1033 this.form_field_label
= $("label[for='" + this.form_field
.id
+ "']");
1035 if (this.form_field_label
.length
> 0) {
1036 return this.form_field_label
.on('click.chosen', this.label_click_handler
);
1040 Chosen
.prototype.show_search_field_default = function() {
1041 if (this.is_multiple
&& this.choices_count() < 1 && !this.active_field
) {
1042 this.search_field
.val(this.default_text
);
1043 return this.search_field
.addClass("default");
1045 this.search_field
.val("");
1046 return this.search_field
.removeClass("default");
1050 Chosen
.prototype.search_results_mouseup = function(evt
) {
1052 target
= $(evt
.target
).hasClass("active-result") ? $(evt
.target
) : $(evt
.target
).parents(".active-result").first();
1053 if (target
.length
) {
1054 this.result_highlight
= target
;
1055 this.result_select(evt
);
1056 return this.search_field
.focus();
1060 Chosen
.prototype.search_results_mouseover = function(evt
) {
1062 target
= $(evt
.target
).hasClass("active-result") ? $(evt
.target
) : $(evt
.target
).parents(".active-result").first();
1064 return this.result_do_highlight(target
);
1068 Chosen
.prototype.search_results_mouseout = function(evt
) {
1069 if ($(evt
.target
).hasClass("active-result") || $(evt
.target
).parents('.active-result').first()) {
1070 return this.result_clear_highlight();
1074 Chosen
.prototype.choice_build = function(item
) {
1075 var choice
, close_link
;
1076 choice
= $('<li />', {
1077 "class": "search-choice"
1078 }).html("<span>" + (this.choice_label(item
)) + "</span>");
1079 if (item
.disabled
) {
1080 choice
.addClass('search-choice-disabled');
1082 close_link
= $('<a />', {
1083 "class": 'search-choice-close',
1084 'data-option-array-index': item
.array_index
1086 close_link
.on('click.chosen', (function(_this
) {
1087 return function(evt
) {
1088 return _this
.choice_destroy_link_click(evt
);
1091 choice
.append(close_link
);
1093 return this.search_container
.before(choice
);
1096 Chosen
.prototype.choice_destroy_link_click = function(evt
) {
1097 evt
.preventDefault();
1098 evt
.stopPropagation();
1099 if (!this.is_disabled
) {
1100 return this.choice_destroy($(evt
.target
));
1104 Chosen
.prototype.choice_destroy = function(link
) {
1105 if (this.result_deselect(link
[0].getAttribute("data-option-array-index"))) {
1106 if (this.active_field
) {
1107 this.search_field
.focus();
1109 this.show_search_field_default();
1111 if (this.is_multiple
&& this.choices_count() > 0 && this.get_search_field_value().length
< 1) {
1112 this.results_hide();
1114 link
.parents('li').first().remove();
1115 return this.search_field_scale();
1119 Chosen
.prototype.results_reset = function() {
1120 this.reset_single_select_options();
1121 this.form_field
.options
[0].selected
= true;
1122 this.single_set_selected_text();
1123 this.show_search_field_default();
1124 this.results_reset_cleanup();
1125 this.trigger_form_field_change();
1126 if (this.active_field
) {
1127 return this.results_hide();
1131 Chosen
.prototype.results_reset_cleanup = function() {
1132 this.current_selectedIndex
= this.form_field
.selectedIndex
;
1133 return this.selected_item
.find("abbr").remove();
1136 Chosen
.prototype.result_select = function(evt
) {
1138 if (this.result_highlight
) {
1139 high
= this.result_highlight
;
1140 this.result_clear_highlight();
1141 if (this.is_multiple
&& this.max_selected_options
<= this.choices_count()) {
1142 this.form_field_jq
.trigger("chosen:maxselected", {
1147 if (this.is_multiple
) {
1148 high
.removeClass("active-result");
1150 this.reset_single_select_options();
1152 high
.addClass("result-selected");
1153 item
= this.results_data
[high
[0].getAttribute("data-option-array-index")];
1154 item
.selected
= true;
1155 this.form_field
.options
[item
.options_index
].selected
= true;
1156 this.selected_option_count
= null;
1157 this.search_field
.val("");
1158 if (this.is_multiple
) {
1159 this.choice_build(item
);
1161 this.single_set_selected_text(this.choice_label(item
));
1163 if (this.is_multiple
&& (!this.hide_results_on_select
|| (evt
.metaKey
|| evt
.ctrlKey
))) {
1164 this.winnow_results();
1166 this.results_hide();
1167 this.show_search_field_default();
1169 if (this.is_multiple
|| this.form_field
.selectedIndex
!== this.current_selectedIndex
) {
1170 this.trigger_form_field_change({
1171 selected
: this.form_field
.options
[item
.options_index
].value
1174 this.current_selectedIndex
= this.form_field
.selectedIndex
;
1175 evt
.preventDefault();
1176 return this.search_field_scale();
1180 Chosen
.prototype.single_set_selected_text = function(text
) {
1182 text
= this.default_text
;
1184 if (text
=== this.default_text
) {
1185 this.selected_item
.addClass("chosen-default");
1187 this.single_deselect_control_build();
1188 this.selected_item
.removeClass("chosen-default");
1190 return this.selected_item
.find("span").html(text
);
1193 Chosen
.prototype.result_deselect = function(pos
) {
1195 result_data
= this.results_data
[pos
];
1196 if (!this.form_field
.options
[result_data
.options_index
].disabled
) {
1197 result_data
.selected
= false;
1198 this.form_field
.options
[result_data
.options_index
].selected
= false;
1199 this.selected_option_count
= null;
1200 this.result_clear_highlight();
1201 if (this.results_showing
) {
1202 this.winnow_results();
1204 this.trigger_form_field_change({
1205 deselected
: this.form_field
.options
[result_data
.options_index
].value
1207 this.search_field_scale();
1214 Chosen
.prototype.single_deselect_control_build = function() {
1215 if (!this.allow_single_deselect
) {
1218 if (!this.selected_item
.find("abbr").length
) {
1219 this.selected_item
.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
1221 return this.selected_item
.addClass("chosen-single-with-deselect");
1224 Chosen
.prototype.get_search_field_value = function() {
1225 return this.search_field
.val();
1228 Chosen
.prototype.get_search_text = function() {
1229 return $.trim(this.get_search_field_value());
1232 Chosen
.prototype.escape_html = function(text
) {
1233 return $('<div/>').text(text
).html();
1236 Chosen
.prototype.winnow_results_set_highlight = function() {
1237 var do_high
, selected_results
;
1238 selected_results
= !this.is_multiple
? this.search_results
.find(".result-selected.active-result") : [];
1239 do_high
= selected_results
.length
? selected_results
.first() : this.search_results
.find(".active-result").first();
1240 if (do_high
!= null) {
1241 return this.result_do_highlight(do_high
);
1245 Chosen
.prototype.no_results = function(terms
) {
1246 var no_results_html
;
1247 no_results_html
= this.get_no_results_html(terms
);
1248 this.search_results
.append(no_results_html
);
1249 return this.form_field_jq
.trigger("chosen:no_results", {
1254 Chosen
.prototype.no_results_clear = function() {
1255 return this.search_results
.find(".no-results").remove();
1258 Chosen
.prototype.keydown_arrow = function() {
1260 if (this.results_showing
&& this.result_highlight
) {
1261 next_sib
= this.result_highlight
.nextAll("li.active-result").first();
1263 return this.result_do_highlight(next_sib
);
1266 return this.results_show();
1270 Chosen
.prototype.keyup_arrow = function() {
1272 if (!this.results_showing
&& !this.is_multiple
) {
1273 return this.results_show();
1274 } else if (this.result_highlight
) {
1275 prev_sibs
= this.result_highlight
.prevAll("li.active-result");
1276 if (prev_sibs
.length
) {
1277 return this.result_do_highlight(prev_sibs
.first());
1279 if (this.choices_count() > 0) {
1280 this.results_hide();
1282 return this.result_clear_highlight();
1287 Chosen
.prototype.keydown_backstroke = function() {
1288 var next_available_destroy
;
1289 if (this.pending_backstroke
) {
1290 this.choice_destroy(this.pending_backstroke
.find("a").first());
1291 return this.clear_backstroke();
1293 next_available_destroy
= this.search_container
.siblings("li.search-choice").last();
1294 if (next_available_destroy
.length
&& !next_available_destroy
.hasClass("search-choice-disabled")) {
1295 this.pending_backstroke
= next_available_destroy
;
1296 if (this.single_backstroke_delete
) {
1297 return this.keydown_backstroke();
1299 return this.pending_backstroke
.addClass("search-choice-focus");
1305 Chosen
.prototype.clear_backstroke = function() {
1306 if (this.pending_backstroke
) {
1307 this.pending_backstroke
.removeClass("search-choice-focus");
1309 return this.pending_backstroke
= null;
1312 Chosen
.prototype.search_field_scale = function() {
1313 var div
, i
, len
, style
, style_block
, styles
, width
;
1314 if (!this.is_multiple
) {
1318 position
: 'absolute',
1324 styles
= ['fontSize', 'fontStyle', 'fontWeight', 'fontFamily', 'lineHeight', 'textTransform', 'letterSpacing'];
1325 for (i
= 0, len
= styles
.length
; i
< len
; i
++) {
1327 style_block
[style
] = this.search_field
.css(style
);
1329 div
= $('<div />').css(style_block
);
1330 div
.text(this.get_search_field_value());
1331 $('body').append(div
);
1332 width
= div
.width() + 25;
1334 if (this.container
.is(':visible')) {
1335 width
= Math
.min(this.container
.outerWidth() - 10, width
);
1337 return this.search_field
.width(width
);
1340 Chosen
.prototype.trigger_form_field_change = function(extra
) {
1341 this.form_field_jq
.trigger("input", extra
);
1342 return this.form_field_jq
.trigger("change", extra
);