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);