').append(this.$clear)))},value2html:function(c,d){var e=a.datepicker.formatDate(this.options.viewformat,c);b.superclass.value2html.call(this,e,d)},html2value:function(b){if("string"!=typeof b)return b;var c;try{c=a.datepicker.parseDate(this.options.viewformat,b)}catch(d){}return c},value2str:function(b){return a.datepicker.formatDate(this.options.format,b)},str2value:function(b){if("string"!=typeof b)return b;var c;try{c=a.datepicker.parseDate(this.options.format,b)}catch(d){}return c},value2submit:function(a){return this.value2str(a)},value2input:function(a){this.$input.datepicker("setDate",a)},input2value:function(){return this.$input.datepicker("getDate")},activate:function(){},clear:function(){this.$input.datepicker("setDate",null),this.isAutosubmit&&this.submit()},autosubmit:function(){this.isAutosubmit=!0,this.$input.on("mouseup","table.ui-datepicker-calendar a.ui-state-default",a.proxy(this.submit,this))},submit:function(){var a=this.$input.closest("form");setTimeout(function(){a.submit()},200)}}),b.defaults=a.extend({},a.fn.editabletypes.abstractinput.defaults,{tpl:'
',inputclass:null,format:"yyyy-mm-dd",viewformat:null,datepicker:{firstDay:0,changeYear:!0,changeMonth:!0,showOtherMonths:!0},clear:"× clear"}),a.fn.editabletypes.dateui=b}(window.jQuery),function(a){"use strict";var b=function(a){this.init("dateuifield",a,b.defaults),this.initPicker(a,b.defaults)};a.fn.editableutils.inherit(b,a.fn.editabletypes.dateui),a.extend(b.prototype,{render:function(){this.$input.datepicker(this.options.datepicker),a.fn.editabletypes.text.prototype.renderClear.call(this)},value2input:function(b){this.$input.val(a.datepicker.formatDate(this.options.viewformat,b))},input2value:function(){return this.html2value(this.$input.val())},activate:function(){a.fn.editabletypes.text.prototype.activate.call(this)},toggleClear:function(){a.fn.editabletypes.text.prototype.toggleClear.call(this)},autosubmit:function(){}}),b.defaults=a.extend({},a.fn.editabletypes.dateui.defaults,{tpl:'
',inputclass:null,datepicker:{showOn:"button",buttonImage:"http://jqueryui.com/resources/demos/datepicker/images/calendar.gif",buttonImageOnly:!0,firstDay:0,changeYear:!0,changeMonth:!0,showOtherMonths:!0},clear:!1}),a.fn.editabletypes.dateuifield=b}(window.jQuery);
\ No newline at end of file
diff --git a/src/containers/editable-container.js b/src/containers/editable-container.js
index 5691f771..7887ccc5 100644
--- a/src/containers/editable-container.js
+++ b/src/containers/editable-container.js
@@ -59,7 +59,8 @@ Applied as jQuery method.
//(mousedown could be better than click, it closes everything also on drag drop)
$(document).on('click.editable', function(e) {
var $target = $(e.target), i,
- exclude_classes = ['.editable-container',
+ exclude_classes = ['.editable-container',
+ '.select2-container',
'.ui-datepicker-header',
'.datepicker', //in inline mode datepicker is rendered into body
'.modal-backdrop',
diff --git a/src/inputs/select2/lib/select2-bootstrap.css b/src/inputs/select2/lib/select2-bootstrap.css
deleted file mode 100644
index 90997107..00000000
--- a/src/inputs/select2/lib/select2-bootstrap.css
+++ /dev/null
@@ -1,87 +0,0 @@
-.form-control .select2-choice {
- border: 0;
- border-radius: 2px;
-}
-
-.form-control .select2-choice .select2-arrow {
- border-radius: 0 2px 2px 0;
-}
-
-.form-control.select2-container {
- height: auto !important;
- padding: 0px;
-}
-
-.form-control.select2-container.select2-dropdown-open {
- border-color: #5897FB;
- border-radius: 3px 3px 0 0;
-}
-
-.form-control .select2-container.select2-dropdown-open .select2-choices {
- border-radius: 3px 3px 0 0;
-}
-
-.form-control.select2-container .select2-choices {
- border: 0 !important;
- border-radius: 3px;
-}
-
-.control-group.warning .select2-container .select2-choice,
-.control-group.warning .select2-container .select2-choices,
-.control-group.warning .select2-container-active .select2-choice,
-.control-group.warning .select2-container-active .select2-choices,
-.control-group.warning .select2-dropdown-open.select2-drop-above .select2-choice,
-.control-group.warning .select2-dropdown-open.select2-drop-above .select2-choices,
-.control-group.warning .select2-container-multi.select2-container-active .select2-choices {
- border: 1px solid #C09853 !important;
-}
-
-.control-group.warning .select2-container .select2-choice div {
- border-left: 1px solid #C09853 !important;
- background: #FCF8E3 !important;
-}
-
-.control-group.error .select2-container .select2-choice,
-.control-group.error .select2-container .select2-choices,
-.control-group.error .select2-container-active .select2-choice,
-.control-group.error .select2-container-active .select2-choices,
-.control-group.error .select2-dropdown-open.select2-drop-above .select2-choice,
-.control-group.error .select2-dropdown-open.select2-drop-above .select2-choices,
-.control-group.error .select2-container-multi.select2-container-active .select2-choices {
- border: 1px solid #B94A48 !important;
-}
-
-.control-group.error .select2-container .select2-choice div {
- border-left: 1px solid #B94A48 !important;
- background: #F2DEDE !important;
-}
-
-.control-group.info .select2-container .select2-choice,
-.control-group.info .select2-container .select2-choices,
-.control-group.info .select2-container-active .select2-choice,
-.control-group.info .select2-container-active .select2-choices,
-.control-group.info .select2-dropdown-open.select2-drop-above .select2-choice,
-.control-group.info .select2-dropdown-open.select2-drop-above .select2-choices,
-.control-group.info .select2-container-multi.select2-container-active .select2-choices {
- border: 1px solid #3A87AD !important;
-}
-
-.control-group.info .select2-container .select2-choice div {
- border-left: 1px solid #3A87AD !important;
- background: #D9EDF7 !important;
-}
-
-.control-group.success .select2-container .select2-choice,
-.control-group.success .select2-container .select2-choices,
-.control-group.success .select2-container-active .select2-choice,
-.control-group.success .select2-container-active .select2-choices,
-.control-group.success .select2-dropdown-open.select2-drop-above .select2-choice,
-.control-group.success .select2-dropdown-open.select2-drop-above .select2-choices,
-.control-group.success .select2-container-multi.select2-container-active .select2-choices {
- border: 1px solid #468847 !important;
-}
-
-.control-group.success .select2-container .select2-choice div {
- border-left: 1px solid #468847 !important;
- background: #DFF0D8 !important;
-}
diff --git a/src/inputs/select2/lib/select2-spinner.gif b/src/inputs/select2/lib/select2-spinner.gif
deleted file mode 100644
index 5b33f7e5..00000000
Binary files a/src/inputs/select2/lib/select2-spinner.gif and /dev/null differ
diff --git a/src/inputs/select2/lib/select2.css b/src/inputs/select2/lib/select2.css
index d0d7ae3d..d365213c 100644
--- a/src/inputs/select2/lib/select2.css
+++ b/src/inputs/select2/lib/select2.css
@@ -1,615 +1,431 @@
-/*
-Version: 3.4.4 Timestamp: Thu Oct 24 13:23:11 PDT 2013
-*/
.select2-container {
- margin: 0;
- position: relative;
- display: inline-block;
- /* inline-block for ie7 */
- zoom: 1;
- *display: inline;
- vertical-align: middle;
-}
-
-.select2-container,
-.select2-drop,
-.select2-search,
-.select2-search input {
- /*
- Force border-box so that % widths fit the parent
- container without overlap because of margin/padding.
-
- More Info : http://www.quirksmode.org/css/box.html
- */
- -webkit-box-sizing: border-box; /* webkit */
- -moz-box-sizing: border-box; /* firefox */
- box-sizing: border-box; /* css3 */
-}
-
-.select2-container .select2-choice {
- display: block;
- height: 26px;
- padding: 0 0 0 8px;
- overflow: hidden;
- position: relative;
-
- border: 1px solid #aaa;
- white-space: nowrap;
- line-height: 26px;
- color: #444;
- text-decoration: none;
-
- border-radius: 4px;
-
- background-clip: padding-box;
-
- -webkit-touch-callout: none;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-
- background-color: #fff;
- background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.5, #fff));
- background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 50%);
- background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 50%);
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#ffffff', endColorstr = '#eeeeee', GradientType = 0);
- background-image: linear-gradient(top, #fff 0%, #eee 50%);
-}
-
-.select2-container.select2-drop-above .select2-choice {
- border-bottom-color: #aaa;
-
- border-radius: 0 0 4px 4px;
-
- background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #eee), color-stop(0.9, #fff));
- background-image: -webkit-linear-gradient(center bottom, #eee 0%, #fff 90%);
- background-image: -moz-linear-gradient(center bottom, #eee 0%, #fff 90%);
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0);
- background-image: linear-gradient(top, #eee 0%, #fff 90%);
-}
-
-.select2-container.select2-allowclear .select2-choice .select2-chosen {
- margin-right: 42px;
-}
-
-.select2-container .select2-choice > .select2-chosen {
- margin-right: 26px;
- display: block;
- overflow: hidden;
-
- white-space: nowrap;
-
- text-overflow: ellipsis;
-}
-
-.select2-container .select2-choice abbr {
- display: none;
- width: 12px;
- height: 12px;
- position: absolute;
- right: 24px;
- top: 8px;
-
- font-size: 1px;
- text-decoration: none;
-
- border: 0;
- background: url('select2.png') right top no-repeat;
+ box-sizing: border-box;
+ display: inline-block;
+ margin: 0;
+ position: relative;
+ vertical-align: middle; }
+ .select2-container .select2-selection--single {
+ box-sizing: border-box;
cursor: pointer;
- outline: 0;
-}
-
-.select2-container.select2-allowclear .select2-choice abbr {
- display: inline-block;
-}
-
-.select2-container .select2-choice abbr:hover {
- background-position: right -11px;
+ display: block;
+ height: 28px;
+ user-select: none;
+ -webkit-user-select: none; }
+ .select2-container .select2-selection--single .select2-selection__rendered {
+ display: block;
+ padding-left: 8px;
+ padding-right: 20px;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap; }
+ .select2-container[dir="rtl"] .select2-selection--single .select2-selection__rendered {
+ padding-right: 8px;
+ padding-left: 20px; }
+ .select2-container .select2-selection--multiple {
+ box-sizing: border-box;
cursor: pointer;
-}
-
-.select2-drop-mask {
- border: 0;
- margin: 0;
- padding: 0;
- position: fixed;
- left: 0;
- top: 0;
- min-height: 100%;
- min-width: 100%;
- height: auto;
- width: auto;
- opacity: 0;
- z-index: 9998;
- /* styles required for IE to work */
- background-color: #fff;
- filter: alpha(opacity=0);
-}
-
-.select2-drop {
- width: 100%;
- margin-top: -1px;
- position: absolute;
- z-index: 9999;
- top: 100%;
-
- background: #fff;
- color: #000;
- border: 1px solid #aaa;
- border-top: 0;
-
- border-radius: 0 0 4px 4px;
-
- -webkit-box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
- box-shadow: 0 4px 5px rgba(0, 0, 0, .15);
-}
-
-.select2-drop-auto-width {
- border-top: 1px solid #aaa;
- width: auto;
-}
-
-.select2-drop-auto-width .select2-search {
- padding-top: 4px;
-}
-
-.select2-drop.select2-drop-above {
- margin-top: 1px;
- border-top: 1px solid #aaa;
- border-bottom: 0;
-
- border-radius: 4px 4px 0 0;
-
- -webkit-box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
- box-shadow: 0 -4px 5px rgba(0, 0, 0, .15);
-}
-
-.select2-drop-active {
- border: 1px solid #5897fb;
- border-top: none;
-}
-
-.select2-drop.select2-drop-above.select2-drop-active {
- border-top: 1px solid #5897fb;
-}
-
-.select2-container .select2-choice .select2-arrow {
- display: inline-block;
- width: 18px;
- height: 100%;
- position: absolute;
- right: 0;
- top: 0;
-
- border-left: 1px solid #aaa;
- border-radius: 0 4px 4px 0;
-
- background-clip: padding-box;
-
- background: #ccc;
- background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #ccc), color-stop(0.6, #eee));
- background-image: -webkit-linear-gradient(center bottom, #ccc 0%, #eee 60%);
- background-image: -moz-linear-gradient(center bottom, #ccc 0%, #eee 60%);
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr = '#eeeeee', endColorstr = '#cccccc', GradientType = 0);
- background-image: linear-gradient(top, #ccc 0%, #eee 60%);
-}
-
-.select2-container .select2-choice .select2-arrow b {
display: block;
- width: 100%;
- height: 100%;
- background: url('select2.png') no-repeat 0 1px;
-}
-
-.select2-search {
- display: inline-block;
- width: 100%;
- min-height: 26px;
- margin: 0;
- padding-left: 4px;
- padding-right: 4px;
-
- position: relative;
- z-index: 10000;
-
- white-space: nowrap;
-}
-
-.select2-search input {
- width: 100%;
- height: auto !important;
- min-height: 26px;
- padding: 4px 20px 4px 5px;
- margin: 0;
-
- outline: 0;
- font-family: sans-serif;
- font-size: 1em;
+ min-height: 32px;
+ user-select: none;
+ -webkit-user-select: none; }
+ .select2-container .select2-selection--multiple .select2-selection__rendered {
+ display: inline-block;
+ overflow: hidden;
+ padding-left: 8px;
+ text-overflow: ellipsis;
+ white-space: nowrap; }
+ .select2-container .select2-search--inline {
+ float: left; }
+ .select2-container .select2-search--inline .select2-search__field {
+ box-sizing: border-box;
+ border: none;
+ font-size: 100%;
+ margin-top: 5px; }
+ .select2-container .select2-search--inline .select2-search__field::-webkit-search-cancel-button {
+ -webkit-appearance: none; }
+
+.select2-dropdown {
+ background-color: white;
+ border: 1px solid #aaa;
+ border-radius: 4px;
+ box-sizing: border-box;
+ display: block;
+ position: absolute;
+ left: -100000px;
+ width: 100%;
+ z-index: 1051; }
- border: 1px solid #aaa;
- border-radius: 0;
-
- -webkit-box-shadow: none;
- box-shadow: none;
-
- background: #fff url('select2.png') no-repeat 100% -22px;
- background: url('select2.png') no-repeat 100% -22px, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));
- background: url('select2.png') no-repeat 100% -22px, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);
- background: url('select2.png') no-repeat 100% -22px, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);
- background: url('select2.png') no-repeat 100% -22px, linear-gradient(top, #fff 85%, #eee 99%);
-}
-
-.select2-drop.select2-drop-above .select2-search input {
- margin-top: 4px;
-}
-
-.select2-search input.select2-active {
- background: #fff url('select2-spinner.gif') no-repeat 100%;
- background: url('select2-spinner.gif') no-repeat 100%, -webkit-gradient(linear, left bottom, left top, color-stop(0.85, #fff), color-stop(0.99, #eee));
- background: url('select2-spinner.gif') no-repeat 100%, -webkit-linear-gradient(center bottom, #fff 85%, #eee 99%);
- background: url('select2-spinner.gif') no-repeat 100%, -moz-linear-gradient(center bottom, #fff 85%, #eee 99%);
- background: url('select2-spinner.gif') no-repeat 100%, linear-gradient(top, #fff 85%, #eee 99%);
-}
-
-.select2-container-active .select2-choice,
-.select2-container-active .select2-choices {
- border: 1px solid #5897fb;
- outline: none;
-
- -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);
- box-shadow: 0 0 5px rgba(0, 0, 0, .3);
-}
-
-.select2-dropdown-open .select2-choice {
- border-bottom-color: transparent;
- -webkit-box-shadow: 0 1px 0 #fff inset;
- box-shadow: 0 1px 0 #fff inset;
-
- border-bottom-left-radius: 0;
- border-bottom-right-radius: 0;
-
- background-color: #eee;
- background-image: -webkit-gradient(linear, left bottom, left top, color-stop(0, #fff), color-stop(0.5, #eee));
- background-image: -webkit-linear-gradient(center bottom, #fff 0%, #eee 50%);
- background-image: -moz-linear-gradient(center bottom, #fff 0%, #eee 50%);
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);
- background-image: linear-gradient(top, #fff 0%, #eee 50%);
-}
-
-.select2-dropdown-open.select2-drop-above .select2-choice,
-.select2-dropdown-open.select2-drop-above .select2-choices {
- border: 1px solid #5897fb;
- border-top-color: transparent;
-
- background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0, #fff), color-stop(0.5, #eee));
- background-image: -webkit-linear-gradient(center top, #fff 0%, #eee 50%);
- background-image: -moz-linear-gradient(center top, #fff 0%, #eee 50%);
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0);
- background-image: linear-gradient(bottom, #fff 0%, #eee 50%);
-}
-
-.select2-dropdown-open .select2-choice .select2-arrow {
- background: transparent;
- border-left: none;
- filter: none;
-}
-.select2-dropdown-open .select2-choice .select2-arrow b {
- background-position: -18px 1px;
-}
-
-/* results */
.select2-results {
- max-height: 200px;
- padding: 0 0 0 4px;
- margin: 4px 4px 4px 0;
- position: relative;
- overflow-x: hidden;
- overflow-y: auto;
- -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
-}
-
-.select2-results ul.select2-result-sub {
- margin: 0;
- padding-left: 0;
-}
-
-.select2-results ul.select2-result-sub > li .select2-result-label { padding-left: 20px }
-.select2-results ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 40px }
-.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 60px }
-.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 80px }
-.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 100px }
-.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 110px }
-.select2-results ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub ul.select2-result-sub > li .select2-result-label { padding-left: 120px }
-
-.select2-results li {
+ display: block; }
+
+.select2-results__options {
+ list-style: none;
+ margin: 0;
+ padding: 0; }
+
+.select2-results__option {
+ padding: 6px;
+ user-select: none;
+ -webkit-user-select: none; }
+ .select2-results__option[aria-selected] {
+ cursor: pointer; }
+
+.select2-container--open .select2-dropdown {
+ left: 0; }
+
+.select2-container--open .select2-dropdown--above {
+ border-bottom: none;
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0; }
+
+.select2-container--open .select2-dropdown--below {
+ border-top: none;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0; }
+
+.select2-search--dropdown {
+ display: block;
+ padding: 4px; }
+ .select2-search--dropdown .select2-search__field {
+ padding: 4px;
+ width: 100%;
+ box-sizing: border-box; }
+ .select2-search--dropdown .select2-search__field::-webkit-search-cancel-button {
+ -webkit-appearance: none; }
+ .select2-search--dropdown.select2-search--hide {
+ display: none; }
+
+.select2-close-mask {
+ border: 0;
+ margin: 0;
+ padding: 0;
+ display: block;
+ position: fixed;
+ left: 0;
+ top: 0;
+ min-height: 100%;
+ min-width: 100%;
+ height: auto;
+ width: auto;
+ opacity: 0;
+ z-index: 99;
+ background-color: #fff;
+ filter: alpha(opacity=0); }
+
+.select2-hidden-accessible {
+ border: 0;
+ clip: rect(0 0 0 0);
+ height: 1px;
+ margin: -1px;
+ overflow: hidden;
+ padding: 0;
+ position: absolute;
+ width: 1px; }
+
+.select2-container--default .select2-selection--single {
+ background-color: #fff;
+ border: 1px solid #aaa;
+ border-radius: 4px; }
+ .select2-container--default .select2-selection--single .select2-selection__rendered {
+ color: #444;
+ line-height: 28px; }
+ .select2-container--default .select2-selection--single .select2-selection__clear {
+ cursor: pointer;
+ float: right;
+ font-weight: bold; }
+ .select2-container--default .select2-selection--single .select2-selection__placeholder {
+ color: #999; }
+ .select2-container--default .select2-selection--single .select2-selection__arrow {
+ height: 26px;
+ position: absolute;
+ top: 1px;
+ right: 1px;
+ width: 20px; }
+ .select2-container--default .select2-selection--single .select2-selection__arrow b {
+ border-color: #888 transparent transparent transparent;
+ border-style: solid;
+ border-width: 5px 4px 0 4px;
+ height: 0;
+ left: 50%;
+ margin-left: -4px;
+ margin-top: -2px;
+ position: absolute;
+ top: 50%;
+ width: 0; }
+.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__clear {
+ float: left; }
+.select2-container--default[dir="rtl"] .select2-selection--single .select2-selection__arrow {
+ left: 1px;
+ right: auto; }
+.select2-container--default.select2-container--disabled .select2-selection--single {
+ background-color: #eee;
+ cursor: default; }
+ .select2-container--default.select2-container--disabled .select2-selection--single .select2-selection__clear {
+ display: none; }
+.select2-container--default.select2-container--open .select2-selection--single .select2-selection__arrow b {
+ border-color: transparent transparent #888 transparent;
+ border-width: 0 4px 5px 4px; }
+.select2-container--default .select2-selection--multiple {
+ background-color: white;
+ border: 1px solid #aaa;
+ border-radius: 4px;
+ cursor: text; }
+ .select2-container--default .select2-selection--multiple .select2-selection__rendered {
+ box-sizing: border-box;
list-style: none;
- display: list-item;
- background-image: none;
-}
-
-.select2-results li.select2-result-with-children > .select2-result-label {
- font-weight: bold;
-}
-
-.select2-results .select2-result-label {
- padding: 3px 7px 4px;
margin: 0;
+ padding: 0 5px;
+ width: 100%; }
+ .select2-container--default .select2-selection--multiple .select2-selection__placeholder {
+ color: #999;
+ margin-top: 5px;
+ float: left; }
+ .select2-container--default .select2-selection--multiple .select2-selection__clear {
cursor: pointer;
-
- min-height: 1em;
-
- -webkit-touch-callout: none;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-}
-
-.select2-results .select2-highlighted {
- background: #3875d7;
- color: #fff;
-}
-
-.select2-results li em {
- background: #feffde;
- font-style: normal;
-}
-
-.select2-results .select2-highlighted em {
- background: transparent;
-}
-
-.select2-results .select2-highlighted ul {
- background: #fff;
- color: #000;
-}
-
-
-.select2-results .select2-no-results,
-.select2-results .select2-searching,
-.select2-results .select2-selection-limit {
- background: #f4f4f4;
- display: list-item;
-}
-
-/*
-disabled look for disabled choices in the results dropdown
-*/
-.select2-results .select2-disabled.select2-highlighted {
- color: #666;
- background: #f4f4f4;
- display: list-item;
- cursor: default;
-}
-.select2-results .select2-disabled {
- background: #f4f4f4;
- display: list-item;
- cursor: default;
-}
-
-.select2-results .select2-selected {
- display: none;
-}
-
-.select2-more-results.select2-active {
- background: #f4f4f4 url('select2-spinner.gif') no-repeat 100%;
-}
-
-.select2-more-results {
- background: #f4f4f4;
- display: list-item;
-}
-
-/* disabled styles */
-
-.select2-container.select2-container-disabled .select2-choice {
- background-color: #f4f4f4;
- background-image: none;
- border: 1px solid #ddd;
- cursor: default;
-}
-
-.select2-container.select2-container-disabled .select2-choice .select2-arrow {
- background-color: #f4f4f4;
- background-image: none;
- border-left: 0;
-}
-
-.select2-container.select2-container-disabled .select2-choice abbr {
- display: none;
-}
-
-
-/* multiselect */
-
-.select2-container-multi .select2-choices {
- height: auto !important;
- height: 1%;
- margin: 0;
- padding: 0;
- position: relative;
-
+ float: right;
+ font-weight: bold;
+ margin-top: 5px;
+ margin-right: 10px; }
+ .select2-container--default .select2-selection--multiple .select2-selection__choice {
+ background-color: #e4e4e4;
border: 1px solid #aaa;
- cursor: text;
- overflow: hidden;
-
- background-color: #fff;
- background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(1%, #eee), color-stop(15%, #fff));
- background-image: -webkit-linear-gradient(top, #eee 1%, #fff 15%);
- background-image: -moz-linear-gradient(top, #eee 1%, #fff 15%);
- background-image: linear-gradient(top, #eee 1%, #fff 15%);
-}
-
-.select2-locked {
- padding: 3px 5px 3px 5px !important;
-}
-
-.select2-container-multi .select2-choices {
- min-height: 26px;
-}
-
-.select2-container-multi.select2-container-active .select2-choices {
- border: 1px solid #5897fb;
- outline: none;
-
- -webkit-box-shadow: 0 0 5px rgba(0, 0, 0, .3);
- box-shadow: 0 0 5px rgba(0, 0, 0, .3);
-}
-.select2-container-multi .select2-choices li {
+ border-radius: 4px;
+ cursor: default;
float: left;
+ margin-right: 5px;
+ margin-top: 5px;
+ padding: 0 5px; }
+ .select2-container--default .select2-selection--multiple .select2-selection__choice__remove {
+ color: #999;
+ cursor: pointer;
+ display: inline-block;
+ font-weight: bold;
+ margin-right: 2px; }
+ .select2-container--default .select2-selection--multiple .select2-selection__choice__remove:hover {
+ color: #333; }
+.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice, .select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__placeholder {
+ float: right; }
+.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
+ margin-left: 5px;
+ margin-right: auto; }
+.select2-container--default[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
+ margin-left: 2px;
+ margin-right: auto; }
+.select2-container--default.select2-container--focus .select2-selection--multiple {
+ border: solid black 1px;
+ outline: 0; }
+.select2-container--default.select2-container--disabled .select2-selection--multiple {
+ background-color: #eee;
+ cursor: default; }
+.select2-container--default.select2-container--disabled .select2-selection__choice__remove {
+ display: none; }
+.select2-container--default.select2-container--open.select2-container--above .select2-selection--single, .select2-container--default.select2-container--open.select2-container--above .select2-selection--multiple {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0; }
+.select2-container--default.select2-container--open.select2-container--below .select2-selection--single, .select2-container--default.select2-container--open.select2-container--below .select2-selection--multiple {
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0; }
+.select2-container--default .select2-search--dropdown .select2-search__field {
+ border: 1px solid #aaa; }
+.select2-container--default .select2-search--inline .select2-search__field {
+ background: transparent;
+ border: none;
+ outline: 0; }
+.select2-container--default .select2-results > .select2-results__options {
+ max-height: 200px;
+ overflow-y: auto; }
+.select2-container--default .select2-results__option[role=group] {
+ padding: 0; }
+.select2-container--default .select2-results__option[aria-disabled=true] {
+ color: #999; }
+.select2-container--default .select2-results__option[aria-selected=true] {
+ background-color: #ddd; }
+.select2-container--default .select2-results__option .select2-results__option {
+ padding-left: 1em; }
+ .select2-container--default .select2-results__option .select2-results__option .select2-results__group {
+ padding-left: 0; }
+ .select2-container--default .select2-results__option .select2-results__option .select2-results__option {
+ margin-left: -1em;
+ padding-left: 2em; }
+ .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
+ margin-left: -2em;
+ padding-left: 3em; }
+ .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
+ margin-left: -3em;
+ padding-left: 4em; }
+ .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
+ margin-left: -4em;
+ padding-left: 5em; }
+ .select2-container--default .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option .select2-results__option {
+ margin-left: -5em;
+ padding-left: 6em; }
+.select2-container--default .select2-results__option--highlighted[aria-selected] {
+ background-color: #5897fb;
+ color: white; }
+.select2-container--default .select2-results__group {
+ cursor: default;
+ display: block;
+ padding: 6px; }
+
+.select2-container--classic .select2-selection--single {
+ background-color: #f6f6f6;
+ border: 1px solid #aaa;
+ border-radius: 4px;
+ outline: 0;
+ background-image: -webkit-linear-gradient(top, #ffffff 50%, #eeeeee 100%);
+ background-image: -o-linear-gradient(top, #ffffff 50%, #eeeeee 100%);
+ background-image: linear-gradient(to bottom, #ffffff 50%, #eeeeee 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); }
+ .select2-container--classic .select2-selection--single:focus {
+ border: 1px solid #5897fb; }
+ .select2-container--classic .select2-selection--single .select2-selection__rendered {
+ color: #444;
+ line-height: 28px; }
+ .select2-container--classic .select2-selection--single .select2-selection__clear {
+ cursor: pointer;
+ float: right;
+ font-weight: bold;
+ margin-right: 10px; }
+ .select2-container--classic .select2-selection--single .select2-selection__placeholder {
+ color: #999; }
+ .select2-container--classic .select2-selection--single .select2-selection__arrow {
+ background-color: #ddd;
+ border: none;
+ border-left: 1px solid #aaa;
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+ height: 26px;
+ position: absolute;
+ top: 1px;
+ right: 1px;
+ width: 20px;
+ background-image: -webkit-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
+ background-image: -o-linear-gradient(top, #eeeeee 50%, #cccccc 100%);
+ background-image: linear-gradient(to bottom, #eeeeee 50%, #cccccc 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#cccccc', GradientType=0); }
+ .select2-container--classic .select2-selection--single .select2-selection__arrow b {
+ border-color: #888 transparent transparent transparent;
+ border-style: solid;
+ border-width: 5px 4px 0 4px;
+ height: 0;
+ left: 50%;
+ margin-left: -4px;
+ margin-top: -2px;
+ position: absolute;
+ top: 50%;
+ width: 0; }
+.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__clear {
+ float: left; }
+.select2-container--classic[dir="rtl"] .select2-selection--single .select2-selection__arrow {
+ border: none;
+ border-right: 1px solid #aaa;
+ border-radius: 0;
+ border-top-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+ left: 1px;
+ right: auto; }
+.select2-container--classic.select2-container--open .select2-selection--single {
+ border: 1px solid #5897fb; }
+ .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow {
+ background: transparent;
+ border: none; }
+ .select2-container--classic.select2-container--open .select2-selection--single .select2-selection__arrow b {
+ border-color: transparent transparent #888 transparent;
+ border-width: 0 4px 5px 4px; }
+.select2-container--classic.select2-container--open.select2-container--above .select2-selection--single {
+ border-top: none;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ background-image: -webkit-linear-gradient(top, #ffffff 0%, #eeeeee 50%);
+ background-image: -o-linear-gradient(top, #ffffff 0%, #eeeeee 50%);
+ background-image: linear-gradient(to bottom, #ffffff 0%, #eeeeee 50%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0); }
+.select2-container--classic.select2-container--open.select2-container--below .select2-selection--single {
+ border-bottom: none;
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ background-image: -webkit-linear-gradient(top, #eeeeee 50%, #ffffff 100%);
+ background-image: -o-linear-gradient(top, #eeeeee 50%, #ffffff 100%);
+ background-image: linear-gradient(to bottom, #eeeeee 50%, #ffffff 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0); }
+.select2-container--classic .select2-selection--multiple {
+ background-color: white;
+ border: 1px solid #aaa;
+ border-radius: 4px;
+ cursor: text;
+ outline: 0; }
+ .select2-container--classic .select2-selection--multiple:focus {
+ border: 1px solid #5897fb; }
+ .select2-container--classic .select2-selection--multiple .select2-selection__rendered {
list-style: none;
-}
-.select2-container-multi .select2-choices .select2-search-field {
margin: 0;
- padding: 0;
- white-space: nowrap;
-}
-
-.select2-container-multi .select2-choices .select2-search-field input {
- padding: 5px;
- margin: 1px 0;
-
- font-family: sans-serif;
- font-size: 100%;
- color: #666;
- outline: 0;
- border: 0;
- -webkit-box-shadow: none;
- box-shadow: none;
- background: transparent !important;
-}
-
-.select2-container-multi .select2-choices .select2-search-field input.select2-active {
- background: #fff url('select2-spinner.gif') no-repeat 100% !important;
-}
-
-.select2-default {
- color: #999 !important;
-}
-
-.select2-container-multi .select2-choices .select2-search-choice {
- padding: 3px 5px 3px 18px;
- margin: 3px 0 3px 5px;
- position: relative;
-
- line-height: 13px;
- color: #333;
- cursor: default;
- border: 1px solid #aaaaaa;
-
- border-radius: 3px;
-
- -webkit-box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);
- box-shadow: 0 0 2px #fff inset, 0 1px 0 rgba(0, 0, 0, 0.05);
-
- background-clip: padding-box;
-
- -webkit-touch-callout: none;
- -webkit-user-select: none;
- -moz-user-select: none;
- -ms-user-select: none;
- user-select: none;
-
+ padding: 0 5px; }
+ .select2-container--classic .select2-selection--multiple .select2-selection__clear {
+ display: none; }
+ .select2-container--classic .select2-selection--multiple .select2-selection__choice {
background-color: #e4e4e4;
- filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#eeeeee', endColorstr='#f4f4f4', GradientType=0);
- background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eee));
- background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
- background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
- background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eee 100%);
-}
-.select2-container-multi .select2-choices .select2-search-choice .select2-chosen {
- cursor: default;
-}
-.select2-container-multi .select2-choices .select2-search-choice-focus {
- background: #d4d4d4;
-}
-
-.select2-search-choice-close {
- display: block;
- width: 12px;
- height: 13px;
- position: absolute;
- right: 3px;
- top: 4px;
-
- font-size: 1px;
- outline: none;
- background: url('select2.png') right top no-repeat;
-}
-
-.select2-container-multi .select2-search-choice-close {
- left: 3px;
-}
-
-.select2-container-multi .select2-choices .select2-search-choice .select2-search-choice-close:hover {
- background-position: right -11px;
-}
-.select2-container-multi .select2-choices .select2-search-choice-focus .select2-search-choice-close {
- background-position: right -11px;
-}
-
-/* disabled styles */
-.select2-container-multi.select2-container-disabled .select2-choices {
- background-color: #f4f4f4;
- background-image: none;
- border: 1px solid #ddd;
+ border: 1px solid #aaa;
+ border-radius: 4px;
cursor: default;
-}
-
-.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice {
- padding: 3px 5px 3px 5px;
- border: 1px solid #ddd;
- background-image: none;
- background-color: #f4f4f4;
-}
-
-.select2-container-multi.select2-container-disabled .select2-choices .select2-search-choice .select2-search-choice-close { display: none;
- background: none;
-}
-/* end multiselect */
-
-
-.select2-result-selectable .select2-match,
-.select2-result-unselectable .select2-match {
- text-decoration: underline;
-}
-
-.select2-offscreen, .select2-offscreen:focus {
- clip: rect(0 0 0 0) !important;
- width: 1px !important;
- height: 1px !important;
- border: 0 !important;
- margin: 0 !important;
- padding: 0 !important;
- overflow: hidden !important;
- position: absolute !important;
- outline: 0 !important;
- left: 0px !important;
- top: 0px !important;
-}
-
-.select2-display-none {
- display: none;
-}
-
-.select2-measure-scrollbar {
- position: absolute;
- top: -10000px;
- left: -10000px;
- width: 100px;
- height: 100px;
- overflow: scroll;
-}
-/* Retina-ize icons */
-
-@media only screen and (-webkit-min-device-pixel-ratio: 1.5), only screen and (min-resolution: 144dpi) {
- .select2-search input, .select2-search-choice-close, .select2-container .select2-choice abbr, .select2-container .select2-choice .select2-arrow b {
- background-image: url('select2x2.png') !important;
- background-repeat: no-repeat !important;
- background-size: 60px 40px !important;
- }
- .select2-search input {
- background-position: 100% -21px !important;
- }
-}
+ float: left;
+ margin-right: 5px;
+ margin-top: 5px;
+ padding: 0 5px; }
+ .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove {
+ color: #888;
+ cursor: pointer;
+ display: inline-block;
+ font-weight: bold;
+ margin-right: 2px; }
+ .select2-container--classic .select2-selection--multiple .select2-selection__choice__remove:hover {
+ color: #555; }
+.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
+ float: right; }
+.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice {
+ margin-left: 5px;
+ margin-right: auto; }
+.select2-container--classic[dir="rtl"] .select2-selection--multiple .select2-selection__choice__remove {
+ margin-left: 2px;
+ margin-right: auto; }
+.select2-container--classic.select2-container--open .select2-selection--multiple {
+ border: 1px solid #5897fb; }
+.select2-container--classic.select2-container--open.select2-container--above .select2-selection--multiple {
+ border-top: none;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0; }
+.select2-container--classic.select2-container--open.select2-container--below .select2-selection--multiple {
+ border-bottom: none;
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0; }
+.select2-container--classic .select2-search--dropdown .select2-search__field {
+ border: 1px solid #aaa;
+ outline: 0; }
+.select2-container--classic .select2-search--inline .select2-search__field {
+ outline: 0; }
+.select2-container--classic .select2-dropdown {
+ background-color: white;
+ border: 1px solid transparent; }
+.select2-container--classic .select2-dropdown--above {
+ border-bottom: none; }
+.select2-container--classic .select2-dropdown--below {
+ border-top: none; }
+.select2-container--classic .select2-results > .select2-results__options {
+ max-height: 200px;
+ overflow-y: auto; }
+.select2-container--classic .select2-results__option[role=group] {
+ padding: 0; }
+.select2-container--classic .select2-results__option[aria-disabled=true] {
+ color: grey; }
+.select2-container--classic .select2-results__option--highlighted[aria-selected] {
+ background-color: #3875d7;
+ color: white; }
+.select2-container--classic .select2-results__group {
+ cursor: default;
+ display: block;
+ padding: 6px; }
+.select2-container--classic.select2-container--open .select2-dropdown {
+ border-color: #5897fb; }
diff --git a/src/inputs/select2/lib/select2.js b/src/inputs/select2/lib/select2.js
index 0fd6a865..b569c9e4 100644
--- a/src/inputs/select2/lib/select2.js
+++ b/src/inputs/select2/lib/select2.js
@@ -1,3251 +1,5403 @@
-/*
-Copyright 2012 Igor Vaynberg
-
-Version: 3.4.4 Timestamp: Thu Oct 24 13:23:11 PDT 2013
-
-This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
-General Public License version 2 (the "GPL License"). You may choose either license to govern your
-use of this software only upon the condition that you accept all of the terms of either the Apache
-License or the GPL License.
-
-You may obtain a copy of the Apache License and the GPL License at:
-
- http://www.apache.org/licenses/LICENSE-2.0
- http://www.gnu.org/licenses/gpl-2.0.html
-
-Unless required by applicable law or agreed to in writing, software distributed under the
-Apache License or the GPL Licesnse is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
-CONDITIONS OF ANY KIND, either express or implied. See the Apache License and the GPL License for
-the specific language governing permissions and limitations under the Apache License and the GPL License.
-*/
-(function ($) {
- if(typeof $.fn.each2 == "undefined") {
- $.extend($.fn, {
- /*
- * 4-10 times faster .each replacement
- * use it carefully, as it overrides jQuery context of element on each iteration
- */
- each2 : function (c) {
- var j = $([0]), i = -1, l = this.length;
- while (
- ++i < l
- && (j.context = j[0] = this[i])
- && c.call(j[0], i, j) !== false //"this"=DOM, i=index, j=jQuery object
- );
- return this;
- }
- });
+/*!
+ * Select2 4.0.0
+ * https://select2.github.io
+ *
+ * Released under the MIT license
+ * https://github.com/select2/select2/blob/master/LICENSE.md
+ */
+(function (factory) {
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(['jquery'], factory);
+ } else if (typeof exports === 'object') {
+ // Node/CommonJS
+ factory(require('jquery'));
+ } else {
+ // Browser globals
+ factory(jQuery);
+ }
+}(function (jQuery) {
+ // This is needed so we can catch the AMD loader configuration and use it
+ // The inner file should be wrapped (by `banner.start.js`) in a function that
+ // returns the AMD loader references.
+ var S2 =
+(function () {
+ // Restore the Select2 AMD loader so it can be used
+ // Needed mostly in the language files, where the loader is not inserted
+ if (jQuery && jQuery.fn && jQuery.fn.select2 && jQuery.fn.select2.amd) {
+ var S2 = jQuery.fn.select2.amd;
+ }
+var S2;(function () { if (!S2 || !S2.requirejs) {
+if (!S2) { S2 = {}; } else { require = S2; }
+/**
+ * @license almond 0.2.9 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
+ * Available via the MIT or new BSD license.
+ * see: http://github.com/jrburke/almond for details
+ */
+//Going sloppy to avoid 'use strict' string cost, but strict practices should
+//be followed.
+/*jslint sloppy: true */
+/*global setTimeout: false */
+
+var requirejs, require, define;
+(function (undef) {
+ var main, req, makeMap, handlers,
+ defined = {},
+ waiting = {},
+ config = {},
+ defining = {},
+ hasOwn = Object.prototype.hasOwnProperty,
+ aps = [].slice,
+ jsSuffixRegExp = /\.js$/;
+
+ function hasProp(obj, prop) {
+ return hasOwn.call(obj, prop);
}
-})(jQuery);
-(function ($, undefined) {
- "use strict";
- /*global document, window, jQuery, console */
+ /**
+ * Given a relative module name, like ./something, normalize it to
+ * a real name that can be mapped to a path.
+ * @param {String} name the relative name
+ * @param {String} baseName a real name that the name arg is relative
+ * to.
+ * @returns {String} normalized name
+ */
+ function normalize(name, baseName) {
+ var nameParts, nameSegment, mapValue, foundMap, lastIndex,
+ foundI, foundStarMap, starI, i, j, part,
+ baseParts = baseName && baseName.split("/"),
+ map = config.map,
+ starMap = (map && map['*']) || {};
+
+ //Adjust any relative paths.
+ if (name && name.charAt(0) === ".") {
+ //If have a base name, try to normalize against it,
+ //otherwise, assume it is a top-level require that will
+ //be relative to baseUrl in the end.
+ if (baseName) {
+ //Convert baseName to array, and lop off the last part,
+ //so that . matches that "directory" and not name of the baseName's
+ //module. For instance, baseName of "one/two/three", maps to
+ //"one/two/three.js", but we want the directory, "one/two" for
+ //this normalization.
+ baseParts = baseParts.slice(0, baseParts.length - 1);
+ name = name.split('/');
+ lastIndex = name.length - 1;
+
+ // Node .js allowance:
+ if (config.nodeIdCompat && jsSuffixRegExp.test(name[lastIndex])) {
+ name[lastIndex] = name[lastIndex].replace(jsSuffixRegExp, '');
+ }
- if (window.Select2 !== undefined) {
- return;
- }
+ name = baseParts.concat(name);
+
+ //start trimDots
+ for (i = 0; i < name.length; i += 1) {
+ part = name[i];
+ if (part === ".") {
+ name.splice(i, 1);
+ i -= 1;
+ } else if (part === "..") {
+ if (i === 1 && (name[2] === '..' || name[0] === '..')) {
+ //End of the line. Keep at least one non-dot
+ //path segment at the front so it can be mapped
+ //correctly to disk. Otherwise, there is likely
+ //no path mapping for a path starting with '..'.
+ //This can still fail, but catches the most reasonable
+ //uses of ..
+ break;
+ } else if (i > 0) {
+ name.splice(i - 1, 2);
+ i -= 2;
+ }
+ }
+ }
+ //end trimDots
- var KEY, AbstractSelect2, SingleSelect2, MultiSelect2, nextUid, sizer,
- lastMousePosition={x:0,y:0}, $document, scrollBarDimensions,
-
- KEY = {
- TAB: 9,
- ENTER: 13,
- ESC: 27,
- SPACE: 32,
- LEFT: 37,
- UP: 38,
- RIGHT: 39,
- DOWN: 40,
- SHIFT: 16,
- CTRL: 17,
- ALT: 18,
- PAGE_UP: 33,
- PAGE_DOWN: 34,
- HOME: 36,
- END: 35,
- BACKSPACE: 8,
- DELETE: 46,
- isArrow: function (k) {
- k = k.which ? k.which : k;
- switch (k) {
- case KEY.LEFT:
- case KEY.RIGHT:
- case KEY.UP:
- case KEY.DOWN:
- return true;
- }
- return false;
- },
- isControl: function (e) {
- var k = e.which;
- switch (k) {
- case KEY.SHIFT:
- case KEY.CTRL:
- case KEY.ALT:
- return true;
+ name = name.join("/");
+ } else if (name.indexOf('./') === 0) {
+ // No baseName, so this is ID is resolved relative
+ // to baseUrl, pull off the leading dot.
+ name = name.substring(2);
}
-
- if (e.metaKey) return true;
-
- return false;
- },
- isFunctionKey: function (k) {
- k = k.which ? k.which : k;
- return k >= 112 && k <= 123;
}
- },
- MEASURE_SCROLLBAR_TEMPLATE = "
",
-
- DIACRITICS = {"\u24B6":"A","\uFF21":"A","\u00C0":"A","\u00C1":"A","\u00C2":"A","\u1EA6":"A","\u1EA4":"A","\u1EAA":"A","\u1EA8":"A","\u00C3":"A","\u0100":"A","\u0102":"A","\u1EB0":"A","\u1EAE":"A","\u1EB4":"A","\u1EB2":"A","\u0226":"A","\u01E0":"A","\u00C4":"A","\u01DE":"A","\u1EA2":"A","\u00C5":"A","\u01FA":"A","\u01CD":"A","\u0200":"A","\u0202":"A","\u1EA0":"A","\u1EAC":"A","\u1EB6":"A","\u1E00":"A","\u0104":"A","\u023A":"A","\u2C6F":"A","\uA732":"AA","\u00C6":"AE","\u01FC":"AE","\u01E2":"AE","\uA734":"AO","\uA736":"AU","\uA738":"AV","\uA73A":"AV","\uA73C":"AY","\u24B7":"B","\uFF22":"B","\u1E02":"B","\u1E04":"B","\u1E06":"B","\u0243":"B","\u0182":"B","\u0181":"B","\u24B8":"C","\uFF23":"C","\u0106":"C","\u0108":"C","\u010A":"C","\u010C":"C","\u00C7":"C","\u1E08":"C","\u0187":"C","\u023B":"C","\uA73E":"C","\u24B9":"D","\uFF24":"D","\u1E0A":"D","\u010E":"D","\u1E0C":"D","\u1E10":"D","\u1E12":"D","\u1E0E":"D","\u0110":"D","\u018B":"D","\u018A":"D","\u0189":"D","\uA779":"D","\u01F1":"DZ","\u01C4":"DZ","\u01F2":"Dz","\u01C5":"Dz","\u24BA":"E","\uFF25":"E","\u00C8":"E","\u00C9":"E","\u00CA":"E","\u1EC0":"E","\u1EBE":"E","\u1EC4":"E","\u1EC2":"E","\u1EBC":"E","\u0112":"E","\u1E14":"E","\u1E16":"E","\u0114":"E","\u0116":"E","\u00CB":"E","\u1EBA":"E","\u011A":"E","\u0204":"E","\u0206":"E","\u1EB8":"E","\u1EC6":"E","\u0228":"E","\u1E1C":"E","\u0118":"E","\u1E18":"E","\u1E1A":"E","\u0190":"E","\u018E":"E","\u24BB":"F","\uFF26":"F","\u1E1E":"F","\u0191":"F","\uA77B":"F","\u24BC":"G","\uFF27":"G","\u01F4":"G","\u011C":"G","\u1E20":"G","\u011E":"G","\u0120":"G","\u01E6":"G","\u0122":"G","\u01E4":"G","\u0193":"G","\uA7A0":"G","\uA77D":"G","\uA77E":"G","\u24BD":"H","\uFF28":"H","\u0124":"H","\u1E22":"H","\u1E26":"H","\u021E":"H","\u1E24":"H","\u1E28":"H","\u1E2A":"H","\u0126":"H","\u2C67":"H","\u2C75":"H","\uA78D":"H","\u24BE":"I","\uFF29":"I","\u00CC":"I","\u00CD":"I","\u00CE":"I","\u0128":"I","\u012A":"I","\u012C":"I","\u0130":"I","\u00CF":"I","\u1E2E":"I","\u1EC8":"I","\u01CF":"I","\u0208":"I","\u020A":"I","\u1ECA":"I","\u012E":"I","\u1E2C":"I","\u0197":"I","\u24BF":"J","\uFF2A":"J","\u0134":"J","\u0248":"J","\u24C0":"K","\uFF2B":"K","\u1E30":"K","\u01E8":"K","\u1E32":"K","\u0136":"K","\u1E34":"K","\u0198":"K","\u2C69":"K","\uA740":"K","\uA742":"K","\uA744":"K","\uA7A2":"K","\u24C1":"L","\uFF2C":"L","\u013F":"L","\u0139":"L","\u013D":"L","\u1E36":"L","\u1E38":"L","\u013B":"L","\u1E3C":"L","\u1E3A":"L","\u0141":"L","\u023D":"L","\u2C62":"L","\u2C60":"L","\uA748":"L","\uA746":"L","\uA780":"L","\u01C7":"LJ","\u01C8":"Lj","\u24C2":"M","\uFF2D":"M","\u1E3E":"M","\u1E40":"M","\u1E42":"M","\u2C6E":"M","\u019C":"M","\u24C3":"N","\uFF2E":"N","\u01F8":"N","\u0143":"N","\u00D1":"N","\u1E44":"N","\u0147":"N","\u1E46":"N","\u0145":"N","\u1E4A":"N","\u1E48":"N","\u0220":"N","\u019D":"N","\uA790":"N","\uA7A4":"N","\u01CA":"NJ","\u01CB":"Nj","\u24C4":"O","\uFF2F":"O","\u00D2":"O","\u00D3":"O","\u00D4":"O","\u1ED2":"O","\u1ED0":"O","\u1ED6":"O","\u1ED4":"O","\u00D5":"O","\u1E4C":"O","\u022C":"O","\u1E4E":"O","\u014C":"O","\u1E50":"O","\u1E52":"O","\u014E":"O","\u022E":"O","\u0230":"O","\u00D6":"O","\u022A":"O","\u1ECE":"O","\u0150":"O","\u01D1":"O","\u020C":"O","\u020E":"O","\u01A0":"O","\u1EDC":"O","\u1EDA":"O","\u1EE0":"O","\u1EDE":"O","\u1EE2":"O","\u1ECC":"O","\u1ED8":"O","\u01EA":"O","\u01EC":"O","\u00D8":"O","\u01FE":"O","\u0186":"O","\u019F":"O","\uA74A":"O","\uA74C":"O","\u01A2":"OI","\uA74E":"OO","\u0222":"OU","\u24C5":"P","\uFF30":"P","\u1E54":"P","\u1E56":"P","\u01A4":"P","\u2C63":"P","\uA750":"P","\uA752":"P","\uA754":"P","\u24C6":"Q","\uFF31":"Q","\uA756":"Q","\uA758":"Q","\u024A":"Q","\u24C7":"R","\uFF32":"R","\u0154":"R","\u1E58":"R","\u0158":"R","\u0210":"R","\u0212":"R","\u1E5A":"R","\u1E5C":"R","\u0156":"R","\u1E5E":"R","\u024C":"R","\u2C64":"R","\uA75A":"R","\uA7A6":"R","\uA782":"R","\u24C8":"S","\uFF33":"S","\u1E9E":"S","\u015A":"S","\u1E64":"S","\u015C":"S","\u1E60":"S","\u0160":"S","\u1E66":"S","\u1E62":"S","\u1E68":"S","\u0218":"S","\u015E":"S","\u2C7E":"S","\uA7A8":"S","\uA784":"S","\u24C9":"T","\uFF34":"T","\u1E6A":"T","\u0164":"T","\u1E6C":"T","\u021A":"T","\u0162":"T","\u1E70":"T","\u1E6E":"T","\u0166":"T","\u01AC":"T","\u01AE":"T","\u023E":"T","\uA786":"T","\uA728":"TZ","\u24CA":"U","\uFF35":"U","\u00D9":"U","\u00DA":"U","\u00DB":"U","\u0168":"U","\u1E78":"U","\u016A":"U","\u1E7A":"U","\u016C":"U","\u00DC":"U","\u01DB":"U","\u01D7":"U","\u01D5":"U","\u01D9":"U","\u1EE6":"U","\u016E":"U","\u0170":"U","\u01D3":"U","\u0214":"U","\u0216":"U","\u01AF":"U","\u1EEA":"U","\u1EE8":"U","\u1EEE":"U","\u1EEC":"U","\u1EF0":"U","\u1EE4":"U","\u1E72":"U","\u0172":"U","\u1E76":"U","\u1E74":"U","\u0244":"U","\u24CB":"V","\uFF36":"V","\u1E7C":"V","\u1E7E":"V","\u01B2":"V","\uA75E":"V","\u0245":"V","\uA760":"VY","\u24CC":"W","\uFF37":"W","\u1E80":"W","\u1E82":"W","\u0174":"W","\u1E86":"W","\u1E84":"W","\u1E88":"W","\u2C72":"W","\u24CD":"X","\uFF38":"X","\u1E8A":"X","\u1E8C":"X","\u24CE":"Y","\uFF39":"Y","\u1EF2":"Y","\u00DD":"Y","\u0176":"Y","\u1EF8":"Y","\u0232":"Y","\u1E8E":"Y","\u0178":"Y","\u1EF6":"Y","\u1EF4":"Y","\u01B3":"Y","\u024E":"Y","\u1EFE":"Y","\u24CF":"Z","\uFF3A":"Z","\u0179":"Z","\u1E90":"Z","\u017B":"Z","\u017D":"Z","\u1E92":"Z","\u1E94":"Z","\u01B5":"Z","\u0224":"Z","\u2C7F":"Z","\u2C6B":"Z","\uA762":"Z","\u24D0":"a","\uFF41":"a","\u1E9A":"a","\u00E0":"a","\u00E1":"a","\u00E2":"a","\u1EA7":"a","\u1EA5":"a","\u1EAB":"a","\u1EA9":"a","\u00E3":"a","\u0101":"a","\u0103":"a","\u1EB1":"a","\u1EAF":"a","\u1EB5":"a","\u1EB3":"a","\u0227":"a","\u01E1":"a","\u00E4":"a","\u01DF":"a","\u1EA3":"a","\u00E5":"a","\u01FB":"a","\u01CE":"a","\u0201":"a","\u0203":"a","\u1EA1":"a","\u1EAD":"a","\u1EB7":"a","\u1E01":"a","\u0105":"a","\u2C65":"a","\u0250":"a","\uA733":"aa","\u00E6":"ae","\u01FD":"ae","\u01E3":"ae","\uA735":"ao","\uA737":"au","\uA739":"av","\uA73B":"av","\uA73D":"ay","\u24D1":"b","\uFF42":"b","\u1E03":"b","\u1E05":"b","\u1E07":"b","\u0180":"b","\u0183":"b","\u0253":"b","\u24D2":"c","\uFF43":"c","\u0107":"c","\u0109":"c","\u010B":"c","\u010D":"c","\u00E7":"c","\u1E09":"c","\u0188":"c","\u023C":"c","\uA73F":"c","\u2184":"c","\u24D3":"d","\uFF44":"d","\u1E0B":"d","\u010F":"d","\u1E0D":"d","\u1E11":"d","\u1E13":"d","\u1E0F":"d","\u0111":"d","\u018C":"d","\u0256":"d","\u0257":"d","\uA77A":"d","\u01F3":"dz","\u01C6":"dz","\u24D4":"e","\uFF45":"e","\u00E8":"e","\u00E9":"e","\u00EA":"e","\u1EC1":"e","\u1EBF":"e","\u1EC5":"e","\u1EC3":"e","\u1EBD":"e","\u0113":"e","\u1E15":"e","\u1E17":"e","\u0115":"e","\u0117":"e","\u00EB":"e","\u1EBB":"e","\u011B":"e","\u0205":"e","\u0207":"e","\u1EB9":"e","\u1EC7":"e","\u0229":"e","\u1E1D":"e","\u0119":"e","\u1E19":"e","\u1E1B":"e","\u0247":"e","\u025B":"e","\u01DD":"e","\u24D5":"f","\uFF46":"f","\u1E1F":"f","\u0192":"f","\uA77C":"f","\u24D6":"g","\uFF47":"g","\u01F5":"g","\u011D":"g","\u1E21":"g","\u011F":"g","\u0121":"g","\u01E7":"g","\u0123":"g","\u01E5":"g","\u0260":"g","\uA7A1":"g","\u1D79":"g","\uA77F":"g","\u24D7":"h","\uFF48":"h","\u0125":"h","\u1E23":"h","\u1E27":"h","\u021F":"h","\u1E25":"h","\u1E29":"h","\u1E2B":"h","\u1E96":"h","\u0127":"h","\u2C68":"h","\u2C76":"h","\u0265":"h","\u0195":"hv","\u24D8":"i","\uFF49":"i","\u00EC":"i","\u00ED":"i","\u00EE":"i","\u0129":"i","\u012B":"i","\u012D":"i","\u00EF":"i","\u1E2F":"i","\u1EC9":"i","\u01D0":"i","\u0209":"i","\u020B":"i","\u1ECB":"i","\u012F":"i","\u1E2D":"i","\u0268":"i","\u0131":"i","\u24D9":"j","\uFF4A":"j","\u0135":"j","\u01F0":"j","\u0249":"j","\u24DA":"k","\uFF4B":"k","\u1E31":"k","\u01E9":"k","\u1E33":"k","\u0137":"k","\u1E35":"k","\u0199":"k","\u2C6A":"k","\uA741":"k","\uA743":"k","\uA745":"k","\uA7A3":"k","\u24DB":"l","\uFF4C":"l","\u0140":"l","\u013A":"l","\u013E":"l","\u1E37":"l","\u1E39":"l","\u013C":"l","\u1E3D":"l","\u1E3B":"l","\u017F":"l","\u0142":"l","\u019A":"l","\u026B":"l","\u2C61":"l","\uA749":"l","\uA781":"l","\uA747":"l","\u01C9":"lj","\u24DC":"m","\uFF4D":"m","\u1E3F":"m","\u1E41":"m","\u1E43":"m","\u0271":"m","\u026F":"m","\u24DD":"n","\uFF4E":"n","\u01F9":"n","\u0144":"n","\u00F1":"n","\u1E45":"n","\u0148":"n","\u1E47":"n","\u0146":"n","\u1E4B":"n","\u1E49":"n","\u019E":"n","\u0272":"n","\u0149":"n","\uA791":"n","\uA7A5":"n","\u01CC":"nj","\u24DE":"o","\uFF4F":"o","\u00F2":"o","\u00F3":"o","\u00F4":"o","\u1ED3":"o","\u1ED1":"o","\u1ED7":"o","\u1ED5":"o","\u00F5":"o","\u1E4D":"o","\u022D":"o","\u1E4F":"o","\u014D":"o","\u1E51":"o","\u1E53":"o","\u014F":"o","\u022F":"o","\u0231":"o","\u00F6":"o","\u022B":"o","\u1ECF":"o","\u0151":"o","\u01D2":"o","\u020D":"o","\u020F":"o","\u01A1":"o","\u1EDD":"o","\u1EDB":"o","\u1EE1":"o","\u1EDF":"o","\u1EE3":"o","\u1ECD":"o","\u1ED9":"o","\u01EB":"o","\u01ED":"o","\u00F8":"o","\u01FF":"o","\u0254":"o","\uA74B":"o","\uA74D":"o","\u0275":"o","\u01A3":"oi","\u0223":"ou","\uA74F":"oo","\u24DF":"p","\uFF50":"p","\u1E55":"p","\u1E57":"p","\u01A5":"p","\u1D7D":"p","\uA751":"p","\uA753":"p","\uA755":"p","\u24E0":"q","\uFF51":"q","\u024B":"q","\uA757":"q","\uA759":"q","\u24E1":"r","\uFF52":"r","\u0155":"r","\u1E59":"r","\u0159":"r","\u0211":"r","\u0213":"r","\u1E5B":"r","\u1E5D":"r","\u0157":"r","\u1E5F":"r","\u024D":"r","\u027D":"r","\uA75B":"r","\uA7A7":"r","\uA783":"r","\u24E2":"s","\uFF53":"s","\u00DF":"s","\u015B":"s","\u1E65":"s","\u015D":"s","\u1E61":"s","\u0161":"s","\u1E67":"s","\u1E63":"s","\u1E69":"s","\u0219":"s","\u015F":"s","\u023F":"s","\uA7A9":"s","\uA785":"s","\u1E9B":"s","\u24E3":"t","\uFF54":"t","\u1E6B":"t","\u1E97":"t","\u0165":"t","\u1E6D":"t","\u021B":"t","\u0163":"t","\u1E71":"t","\u1E6F":"t","\u0167":"t","\u01AD":"t","\u0288":"t","\u2C66":"t","\uA787":"t","\uA729":"tz","\u24E4":"u","\uFF55":"u","\u00F9":"u","\u00FA":"u","\u00FB":"u","\u0169":"u","\u1E79":"u","\u016B":"u","\u1E7B":"u","\u016D":"u","\u00FC":"u","\u01DC":"u","\u01D8":"u","\u01D6":"u","\u01DA":"u","\u1EE7":"u","\u016F":"u","\u0171":"u","\u01D4":"u","\u0215":"u","\u0217":"u","\u01B0":"u","\u1EEB":"u","\u1EE9":"u","\u1EEF":"u","\u1EED":"u","\u1EF1":"u","\u1EE5":"u","\u1E73":"u","\u0173":"u","\u1E77":"u","\u1E75":"u","\u0289":"u","\u24E5":"v","\uFF56":"v","\u1E7D":"v","\u1E7F":"v","\u028B":"v","\uA75F":"v","\u028C":"v","\uA761":"vy","\u24E6":"w","\uFF57":"w","\u1E81":"w","\u1E83":"w","\u0175":"w","\u1E87":"w","\u1E85":"w","\u1E98":"w","\u1E89":"w","\u2C73":"w","\u24E7":"x","\uFF58":"x","\u1E8B":"x","\u1E8D":"x","\u24E8":"y","\uFF59":"y","\u1EF3":"y","\u00FD":"y","\u0177":"y","\u1EF9":"y","\u0233":"y","\u1E8F":"y","\u00FF":"y","\u1EF7":"y","\u1E99":"y","\u1EF5":"y","\u01B4":"y","\u024F":"y","\u1EFF":"y","\u24E9":"z","\uFF5A":"z","\u017A":"z","\u1E91":"z","\u017C":"z","\u017E":"z","\u1E93":"z","\u1E95":"z","\u01B6":"z","\u0225":"z","\u0240":"z","\u2C6C":"z","\uA763":"z"};
-
- $document = $(document);
- nextUid=(function() { var counter=1; return function() { return counter++; }; }());
+ //Apply map config if available.
+ if ((baseParts || starMap) && map) {
+ nameParts = name.split('/');
+
+ for (i = nameParts.length; i > 0; i -= 1) {
+ nameSegment = nameParts.slice(0, i).join("/");
+
+ if (baseParts) {
+ //Find the longest baseName segment match in the config.
+ //So, do joins on the biggest to smallest lengths of baseParts.
+ for (j = baseParts.length; j > 0; j -= 1) {
+ mapValue = map[baseParts.slice(0, j).join('/')];
+
+ //baseName segment has config, find if it has one for
+ //this name.
+ if (mapValue) {
+ mapValue = mapValue[nameSegment];
+ if (mapValue) {
+ //Match, update name to the new value.
+ foundMap = mapValue;
+ foundI = i;
+ break;
+ }
+ }
+ }
+ }
+ if (foundMap) {
+ break;
+ }
- function stripDiacritics(str) {
- var ret, i, l, c;
+ //Check for a star map match, but just hold on to it,
+ //if there is a shorter segment match later in a matching
+ //config, then favor over this star map.
+ if (!foundStarMap && starMap && starMap[nameSegment]) {
+ foundStarMap = starMap[nameSegment];
+ starI = i;
+ }
+ }
- if (!str || str.length < 1) return str;
+ if (!foundMap && foundStarMap) {
+ foundMap = foundStarMap;
+ foundI = starI;
+ }
- ret = "";
- for (i = 0, l = str.length; i < l; i++) {
- c = str.charAt(i);
- ret += DIACRITICS[c] || c;
+ if (foundMap) {
+ nameParts.splice(0, foundI, foundMap);
+ name = nameParts.join('/');
+ }
}
- return ret;
+
+ return name;
}
- function indexOf(value, array) {
- var i = 0, l = array.length;
- for (; i < l; i = i + 1) {
- if (equal(value, array[i])) return i;
- }
- return -1;
+ function makeRequire(relName, forceSync) {
+ return function () {
+ //A version of a require function that passes a moduleName
+ //value for items that may need to
+ //look up paths relative to the moduleName
+ return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync]));
+ };
}
- function measureScrollbar () {
- var $template = $( MEASURE_SCROLLBAR_TEMPLATE );
- $template.appendTo('body');
+ function makeNormalize(relName) {
+ return function (name) {
+ return normalize(name, relName);
+ };
+ }
- var dim = {
- width: $template.width() - $template[0].clientWidth,
- height: $template.height() - $template[0].clientHeight
+ function makeLoad(depName) {
+ return function (value) {
+ defined[depName] = value;
};
- $template.remove();
+ }
+
+ function callDep(name) {
+ if (hasProp(waiting, name)) {
+ var args = waiting[name];
+ delete waiting[name];
+ defining[name] = true;
+ main.apply(undef, args);
+ }
- return dim;
+ if (!hasProp(defined, name) && !hasProp(defining, name)) {
+ throw new Error('No ' + name);
+ }
+ return defined[name];
}
- /**
- * Compares equality of a and b
- * @param a
- * @param b
- */
- function equal(a, b) {
- if (a === b) return true;
- if (a === undefined || b === undefined) return false;
- if (a === null || b === null) return false;
- // Check whether 'a' or 'b' is a string (primitive or object).
- // The concatenation of an empty string (+'') converts its argument to a string's primitive.
- if (a.constructor === String) return a+'' === b+''; // a+'' - in case 'a' is a String object
- if (b.constructor === String) return b+'' === a+''; // b+'' - in case 'b' is a String object
- return false;
+ //Turns a plugin!resource to [plugin, resource]
+ //with the plugin being undefined if the name
+ //did not have a plugin prefix.
+ function splitPrefix(name) {
+ var prefix,
+ index = name ? name.indexOf('!') : -1;
+ if (index > -1) {
+ prefix = name.substring(0, index);
+ name = name.substring(index + 1, name.length);
+ }
+ return [prefix, name];
}
/**
- * Splits the string into an array of values, trimming each value. An empty array is returned for nulls or empty
- * strings
- * @param string
- * @param separator
+ * Makes a name map, normalizing the name, and using a plugin
+ * for normalization if necessary. Grabs a ref to plugin
+ * too, as an optimization.
*/
- function splitVal(string, separator) {
- var val, i, l;
- if (string === null || string.length < 1) return [];
- val = string.split(separator);
- for (i = 0, l = val.length; i < l; i = i + 1) val[i] = $.trim(val[i]);
- return val;
- }
+ makeMap = function (name, relName) {
+ var plugin,
+ parts = splitPrefix(name),
+ prefix = parts[0];
- function getSideBorderPadding(element) {
- return element.outerWidth(false) - element.width();
- }
+ name = parts[1];
+
+ if (prefix) {
+ prefix = normalize(prefix, relName);
+ plugin = callDep(prefix);
+ }
- function installKeyUpChangeEvent(element) {
- var key="keyup-change-value";
- element.on("keydown", function () {
- if ($.data(element, key) === undefined) {
- $.data(element, key, element.val());
+ //Normalize according
+ if (prefix) {
+ if (plugin && plugin.normalize) {
+ name = plugin.normalize(name, makeNormalize(relName));
+ } else {
+ name = normalize(name, relName);
}
- });
- element.on("keyup", function () {
- var val= $.data(element, key);
- if (val !== undefined && element.val() !== val) {
- $.removeData(element, key);
- element.trigger("keyup-change");
+ } else {
+ name = normalize(name, relName);
+ parts = splitPrefix(name);
+ prefix = parts[0];
+ name = parts[1];
+ if (prefix) {
+ plugin = callDep(prefix);
}
- });
- }
-
- $document.on("mousemove", function (e) {
- lastMousePosition.x = e.pageX;
- lastMousePosition.y = e.pageY;
- });
+ }
- /**
- * filters mouse events so an event is fired only if the mouse moved.
- *
- * filters out mouse events that occur when mouse is stationary but
- * the elements under the pointer are scrolled.
- */
- function installFilteredMouseMove(element) {
- element.on("mousemove", function (e) {
- var lastpos = lastMousePosition;
- if (lastpos === undefined || lastpos.x !== e.pageX || lastpos.y !== e.pageY) {
- $(e.target).trigger("mousemove-filtered", e);
- }
- });
- }
+ //Using ridiculous property names for space reasons
+ return {
+ f: prefix ? prefix + '!' + name : name, //fullName
+ n: name,
+ pr: prefix,
+ p: plugin
+ };
+ };
- /**
- * Debounces a function. Returns a function that calls the original fn function only if no invocations have been made
- * within the last quietMillis milliseconds.
- *
- * @param quietMillis number of milliseconds to wait before invoking fn
- * @param fn function to be debounced
- * @param ctx object to be used as this reference within fn
- * @return debounced version of fn
- */
- function debounce(quietMillis, fn, ctx) {
- ctx = ctx || undefined;
- var timeout;
+ function makeConfig(name) {
return function () {
- var args = arguments;
- window.clearTimeout(timeout);
- timeout = window.setTimeout(function() {
- fn.apply(ctx, args);
- }, quietMillis);
+ return (config && config.config && config.config[name]) || {};
};
}
- /**
- * A simple implementation of a thunk
- * @param formula function used to lazily initialize the thunk
- * @return {Function}
- */
- function thunk(formula) {
- var evaluated = false,
- value;
- return function() {
- if (evaluated === false) { value = formula(); evaluated = true; }
- return value;
- };
+ handlers = {
+ require: function (name) {
+ return makeRequire(name);
+ },
+ exports: function (name) {
+ var e = defined[name];
+ if (typeof e !== 'undefined') {
+ return e;
+ } else {
+ return (defined[name] = {});
+ }
+ },
+ module: function (name) {
+ return {
+ id: name,
+ uri: '',
+ exports: defined[name],
+ config: makeConfig(name)
+ };
+ }
};
- function installDebouncedScroll(threshold, element) {
- var notify = debounce(threshold, function (e) { element.trigger("scroll-debounced", e);});
- element.on("scroll", function (e) {
- if (indexOf(e.target, element.get()) >= 0) notify(e);
- });
- }
-
- function focus($el) {
- if ($el[0] === document.activeElement) return;
-
- /* set the focus in a 0 timeout - that way the focus is set after the processing
- of the current event has finished - which seems like the only reliable way
- to set focus */
- window.setTimeout(function() {
- var el=$el[0], pos=$el.val().length, range;
-
- $el.focus();
-
- /* make sure el received focus so we do not error out when trying to manipulate the caret.
- sometimes modals or others listeners may steal it after its set */
- if ($el.is(":visible") && el === document.activeElement) {
-
- /* after the focus is set move the caret to the end, necessary when we val()
- just before setting focus */
- if(el.setSelectionRange)
- {
- el.setSelectionRange(pos, pos);
+ main = function (name, deps, callback, relName) {
+ var cjsModule, depName, ret, map, i,
+ args = [],
+ callbackType = typeof callback,
+ usingExports;
+
+ //Use name if no relName
+ relName = relName || name;
+
+ //Call the callback to define the module, if necessary.
+ if (callbackType === 'undefined' || callbackType === 'function') {
+ //Pull out the defined dependencies and pass the ordered
+ //values to the callback.
+ //Default to [require, exports, module] if no deps
+ deps = !deps.length && callback.length ? ['require', 'exports', 'module'] : deps;
+ for (i = 0; i < deps.length; i += 1) {
+ map = makeMap(deps[i], relName);
+ depName = map.f;
+
+ //Fast path CommonJS standard dependencies.
+ if (depName === "require") {
+ args[i] = handlers.require(name);
+ } else if (depName === "exports") {
+ //CommonJS module spec 1.1
+ args[i] = handlers.exports(name);
+ usingExports = true;
+ } else if (depName === "module") {
+ //CommonJS module spec 1.1
+ cjsModule = args[i] = handlers.module(name);
+ } else if (hasProp(defined, depName) ||
+ hasProp(waiting, depName) ||
+ hasProp(defining, depName)) {
+ args[i] = callDep(depName);
+ } else if (map.p) {
+ map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
+ args[i] = defined[depName];
+ } else {
+ throw new Error(name + ' missing ' + depName);
}
- else if (el.createTextRange) {
- range = el.createTextRange();
- range.collapse(false);
- range.select();
+ }
+
+ ret = callback ? callback.apply(defined[name], args) : undefined;
+
+ if (name) {
+ //If setting exports via "module" is in play,
+ //favor that over return value and exports. After that,
+ //favor a non-undefined return value over exports use.
+ if (cjsModule && cjsModule.exports !== undef &&
+ cjsModule.exports !== defined[name]) {
+ defined[name] = cjsModule.exports;
+ } else if (ret !== undef || !usingExports) {
+ //Use the return value from the function.
+ defined[name] = ret;
}
}
- }, 0);
- }
-
- function getCursorInfo(el) {
- el = $(el)[0];
- var offset = 0;
- var length = 0;
- if ('selectionStart' in el) {
- offset = el.selectionStart;
- length = el.selectionEnd - offset;
- } else if ('selection' in document) {
- el.focus();
- var sel = document.selection.createRange();
- length = document.selection.createRange().text.length;
- sel.moveStart('character', -el.value.length);
- offset = sel.text.length - length;
- }
- return { offset: offset, length: length };
- }
-
- function killEvent(event) {
- event.preventDefault();
- event.stopPropagation();
- }
- function killEventImmediately(event) {
- event.preventDefault();
- event.stopImmediatePropagation();
- }
-
- function measureTextWidth(e) {
- if (!sizer){
- var style = e[0].currentStyle || window.getComputedStyle(e[0], null);
- sizer = $(document.createElement("div")).css({
- position: "absolute",
- left: "-10000px",
- top: "-10000px",
- display: "none",
- fontSize: style.fontSize,
- fontFamily: style.fontFamily,
- fontStyle: style.fontStyle,
- fontWeight: style.fontWeight,
- letterSpacing: style.letterSpacing,
- textTransform: style.textTransform,
- whiteSpace: "nowrap"
- });
- sizer.attr("class","select2-sizer");
- $("body").append(sizer);
+ } else if (name) {
+ //May just be an object definition for the module. Only
+ //worry about defining if have a module name.
+ defined[name] = callback;
}
- sizer.text(e.val());
- return sizer.width();
- }
+ };
- function syncCssClasses(dest, src, adapter) {
- var classes, replacements = [], adapted;
+ requirejs = require = req = function (deps, callback, relName, forceSync, alt) {
+ if (typeof deps === "string") {
+ if (handlers[deps]) {
+ //callback in this case is really relName
+ return handlers[deps](callback);
+ }
+ //Just return the module wanted. In this scenario, the
+ //deps arg is the module name, and second arg (if passed)
+ //is just the relName.
+ //Normalize module name, if it contains . or ..
+ return callDep(makeMap(deps, callback).f);
+ } else if (!deps.splice) {
+ //deps is a config object, not an array.
+ config = deps;
+ if (config.deps) {
+ req(config.deps, config.callback);
+ }
+ if (!callback) {
+ return;
+ }
- classes = dest.attr("class");
- if (classes) {
- classes = '' + classes; // for IE which returns object
- $(classes.split(" ")).each2(function() {
- if (this.indexOf("select2-") === 0) {
- replacements.push(this);
- }
- });
- }
- classes = src.attr("class");
- if (classes) {
- classes = '' + classes; // for IE which returns object
- $(classes.split(" ")).each2(function() {
- if (this.indexOf("select2-") !== 0) {
- adapted = adapter(this);
- if (adapted) {
- replacements.push(adapted);
- }
- }
- });
+ if (callback.splice) {
+ //callback is an array, which means it is a dependency list.
+ //Adjust args if there are dependencies
+ deps = callback;
+ callback = relName;
+ relName = null;
+ } else {
+ deps = undef;
+ }
}
- dest.attr("class", replacements.join(" "));
- }
-
- function markMatch(text, term, markup, escapeMarkup) {
- var match=stripDiacritics(text.toUpperCase()).indexOf(stripDiacritics(term.toUpperCase())),
- tl=term.length;
+ //Support require(['a'])
+ callback = callback || function () {};
- if (match<0) {
- markup.push(escapeMarkup(text));
- return;
+ //If relName is a function, it is an errback handler,
+ //so remove it.
+ if (typeof relName === 'function') {
+ relName = forceSync;
+ forceSync = alt;
}
- markup.push(escapeMarkup(text.substring(0, match)));
- markup.push("
");
- markup.push(escapeMarkup(text.substring(match, match + tl)));
- markup.push(" ");
- markup.push(escapeMarkup(text.substring(match + tl, text.length)));
- }
-
- function defaultEscapeMarkup(markup) {
- var replace_map = {
- '\\': '\',
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": ''',
- "/": '/'
- };
+ //Simulate async callback;
+ if (forceSync) {
+ main(undef, deps, callback, relName);
+ } else {
+ //Using a non-zero value because of concern for what old browsers
+ //do, and latest browsers "upgrade" to 4 if lower value is used:
+ //http://www.whatwg.org/specs/web-apps/current-work/multipage/timers.html#dom-windowtimers-settimeout:
+ //If want a value immediately, use require('id') instead -- something
+ //that works in almond on the global level, but not guaranteed and
+ //unlikely to work in other AMD implementations.
+ setTimeout(function () {
+ main(undef, deps, callback, relName);
+ }, 4);
+ }
- return String(markup).replace(/[&<>"'\/\\]/g, function (match) {
- return replace_map[match];
- });
- }
+ return req;
+ };
/**
- * Produces an ajax-based query function
- *
- * @param options object containing configuration paramters
- * @param options.params parameter map for the transport ajax call, can contain such options as cache, jsonpCallback, etc. see $.ajax
- * @param options.transport function that will be used to execute the ajax request. must be compatible with parameters supported by $.ajax
- * @param options.url url for the data
- * @param options.data a function(searchTerm, pageNumber, context) that should return an object containing query string parameters for the above url.
- * @param options.dataType request data type: ajax, jsonp, other datatatypes supported by jQuery's $.ajax function or the transport function if specified
- * @param options.quietMillis (optional) milliseconds to wait before making the ajaxRequest, helps debounce the ajax function if invoked too often
- * @param options.results a function(remoteData, pageNumber) that converts data returned form the remote request to the format expected by Select2.
- * The expected format is an object containing the following keys:
- * results array of objects that will be used as choices
- * more (optional) boolean indicating whether there are more results available
- * Example: {results:[{id:1, text:'Red'},{id:2, text:'Blue'}], more:true}
+ * Just drops the config on the floor, but returns req in case
+ * the config return value is used.
*/
- function ajax(options) {
- var timeout, // current scheduled but not yet executed request
- handler = null,
- quietMillis = options.quietMillis || 100,
- ajaxUrl = options.url,
- self = this;
-
- return function (query) {
- window.clearTimeout(timeout);
- timeout = window.setTimeout(function () {
- var data = options.data, // ajax data function
- url = ajaxUrl, // ajax url string or function
- transport = options.transport || $.fn.select2.ajaxDefaults.transport,
- // deprecated - to be removed in 4.0 - use params instead
- deprecated = {
- type: options.type || 'GET', // set type of request (GET or POST)
- cache: options.cache || false,
- jsonpCallback: options.jsonpCallback||undefined,
- dataType: options.dataType||"json"
- },
- params = $.extend({}, $.fn.select2.ajaxDefaults.params, deprecated);
-
- data = data ? data.call(self, query.term, query.page, query.context) : null;
- url = (typeof url === 'function') ? url.call(self, query.term, query.page, query.context) : url;
-
- if (handler) { handler.abort(); }
-
- if (options.params) {
- if ($.isFunction(options.params)) {
- $.extend(params, options.params.call(self));
- } else {
- $.extend(params, options.params);
- }
- }
-
- $.extend(params, {
- url: url,
- dataType: options.dataType,
- data: data,
- success: function (data) {
- // TODO - replace query.page with query so users have access to term, page, etc.
- var results = options.results(data, query.page);
- query.callback(results);
- }
- });
- handler = transport.call(self, params);
- }, quietMillis);
- };
- }
+ req.config = function (cfg) {
+ return req(cfg);
+ };
/**
- * Produces a query function that works with a local array
- *
- * @param options object containing configuration parameters. The options parameter can either be an array or an
- * object.
- *
- * If the array form is used it is assumed that it contains objects with 'id' and 'text' keys.
- *
- * If the object form is used ti is assumed that it contains 'data' and 'text' keys. The 'data' key should contain
- * an array of objects that will be used as choices. These objects must contain at least an 'id' key. The 'text'
- * key can either be a String in which case it is expected that each element in the 'data' array has a key with the
- * value of 'text' which will be used to match choices. Alternatively, text can be a function(item) that can extract
- * the text.
+ * Expose module registry for debugging and tooling
*/
- function local(options) {
- var data = options, // data elements
- dataText,
- tmp,
- text = function (item) { return ""+item.text; }; // function used to retrieve the text portion of a data item that is matched against the search
-
- if ($.isArray(data)) {
- tmp = data;
- data = { results: tmp };
- }
+ requirejs._defined = defined;
- if ($.isFunction(data) === false) {
- tmp = data;
- data = function() { return tmp; };
- }
+ define = function (name, deps, callback) {
- var dataItem = data();
- if (dataItem.text) {
- text = dataItem.text;
- // if text is not a function we assume it to be a key name
- if (!$.isFunction(text)) {
- dataText = dataItem.text; // we need to store this in a separate variable because in the next step data gets reset and data.text is no longer available
- text = function (item) { return item[dataText]; };
- }
+ //This module may not have dependencies
+ if (!deps.splice) {
+ //deps is not an array, so probably means
+ //an object literal or factory function for
+ //the value. Adjust args.
+ callback = deps;
+ deps = [];
}
- return function (query) {
- var t = query.term, filtered = { results: [] }, process;
- if (t === "") {
- query.callback(data());
- return;
- }
-
- process = function(datum, collection) {
- var group, attr;
- datum = datum[0];
- if (datum.children) {
- group = {};
- for (attr in datum) {
- if (datum.hasOwnProperty(attr)) group[attr]=datum[attr];
- }
- group.children=[];
- $(datum.children).each2(function(i, childDatum) { process(childDatum, group.children); });
- if (group.children.length || query.matcher(t, text(group), datum)) {
- collection.push(group);
- }
- } else {
- if (query.matcher(t, text(datum), datum)) {
- collection.push(datum);
- }
- }
- };
-
- $(data().results).each2(function(i, datum) { process(datum, filtered.results); });
- query.callback(filtered);
- };
- }
+ if (!hasProp(defined, name) && !hasProp(waiting, name)) {
+ waiting[name] = [name, deps, callback];
+ }
+ };
- // TODO javadoc
- function tags(data) {
- var isFunc = $.isFunction(data);
- return function (query) {
- var t = query.term, filtered = {results: []};
- $(isFunc ? data() : data).each(function () {
- var isObject = this.text !== undefined,
- text = isObject ? this.text : this;
- if (t === "" || query.matcher(t, text)) {
- filtered.results.push(isObject ? this : {id: this, text: this});
- }
- });
- query.callback(filtered);
- };
+ define.amd = {
+ jQuery: true
+ };
+}());
+
+S2.requirejs = requirejs;S2.require = require;S2.define = define;
+}
+}());
+S2.define("almond", function(){});
+
+/* global jQuery:false, $:false */
+S2.define('jquery',[],function () {
+ var _$ = jQuery || $;
+
+ if (_$ == null && console && console.error) {
+ console.error(
+ 'Select2: An instance of jQuery or a jQuery-compatible library was not ' +
+ 'found. Make sure that you are including jQuery before Select2 on your ' +
+ 'web page.'
+ );
+ }
+
+ return _$;
+});
+
+S2.define('select2/utils',[
+ 'jquery'
+], function ($) {
+ var Utils = {};
+
+ Utils.Extend = function (ChildClass, SuperClass) {
+ var __hasProp = {}.hasOwnProperty;
+
+ function BaseConstructor () {
+ this.constructor = ChildClass;
}
- /**
- * Checks if the formatter function should be used.
- *
- * Throws an error if it is not a function. Returns true if it should be used,
- * false if no formatting should be performed.
- *
- * @param formatter
- */
- function checkFormatter(formatter, formatterName) {
- if ($.isFunction(formatter)) return true;
- if (!formatter) return false;
- throw new Error(formatterName +" must be a function or a falsy value");
+ for (var key in SuperClass) {
+ if (__hasProp.call(SuperClass, key)) {
+ ChildClass[key] = SuperClass[key];
+ }
}
- function evaluate(val) {
- return $.isFunction(val) ? val() : val;
- }
+ BaseConstructor.prototype = SuperClass.prototype;
+ ChildClass.prototype = new BaseConstructor();
+ ChildClass.__super__ = SuperClass.prototype;
- function countResults(results) {
- var count = 0;
- $.each(results, function(i, item) {
- if (item.children) {
- count += countResults(item.children);
- } else {
- count++;
- }
- });
- return count;
- }
+ return ChildClass;
+ };
- /**
- * Default tokenizer. This function uses breaks the input on substring match of any string from the
- * opts.tokenSeparators array and uses opts.createSearchChoice to create the choice object. Both of those
- * two options have to be defined in order for the tokenizer to work.
- *
- * @param input text user has typed so far or pasted into the search field
- * @param selection currently selected choices
- * @param selectCallback function(choice) callback tho add the choice to selection
- * @param opts select2's opts
- * @return undefined/null to leave the current input unchanged, or a string to change the input to the returned value
- */
- function defaultTokenizer(input, selection, selectCallback, opts) {
- var original = input, // store the original so we can compare and know if we need to tell the search to update its text
- dupe = false, // check for whether a token we extracted represents a duplicate selected choice
- token, // token
- index, // position at which the separator was found
- i, l, // looping variables
- separator; // the matched separator
-
- if (!opts.createSearchChoice || !opts.tokenSeparators || opts.tokenSeparators.length < 1) return undefined;
-
- while (true) {
- index = -1;
-
- for (i = 0, l = opts.tokenSeparators.length; i < l; i++) {
- separator = opts.tokenSeparators[i];
- index = input.indexOf(separator);
- if (index >= 0) break;
- }
+ function getMethods (theClass) {
+ var proto = theClass.prototype;
- if (index < 0) break; // did not find any token separator in the input string, bail
+ var methods = [];
- token = input.substring(0, index);
- input = input.substring(index + separator.length);
+ for (var methodName in proto) {
+ var m = proto[methodName];
- if (token.length > 0) {
- token = opts.createSearchChoice.call(this, token, selection);
- if (token !== undefined && token !== null && opts.id(token) !== undefined && opts.id(token) !== null) {
- dupe = false;
- for (i = 0, l = selection.length; i < l; i++) {
- if (equal(opts.id(token), opts.id(selection[i]))) {
- dupe = true; break;
- }
- }
+ if (typeof m !== 'function') {
+ continue;
+ }
- if (!dupe) selectCallback(token);
- }
- }
- }
+ if (methodName === 'constructor') {
+ continue;
+ }
- if (original!==input) return input;
+ methods.push(methodName);
}
- /**
- * Creates a new class
- *
- * @param superClass
- * @param methods
- */
- function clazz(SuperClass, methods) {
- var constructor = function () {};
- constructor.prototype = new SuperClass;
- constructor.prototype.constructor = constructor;
- constructor.prototype.parent = SuperClass.prototype;
- constructor.prototype = $.extend(constructor.prototype, methods);
- return constructor;
- }
-
- AbstractSelect2 = clazz(Object, {
-
- // abstract
- bind: function (func) {
- var self = this;
- return function () {
- func.apply(self, arguments);
- };
- },
+ return methods;
+ }
- // abstract
- init: function (opts) {
- var results, search, resultsSelector = ".select2-results";
+ Utils.Decorate = function (SuperClass, DecoratorClass) {
+ var decoratedMethods = getMethods(DecoratorClass);
+ var superMethods = getMethods(SuperClass);
- // prepare options
- this.opts = opts = this.prepareOpts(opts);
+ function DecoratedClass () {
+ var unshift = Array.prototype.unshift;
- this.id=opts.id;
+ var argCount = DecoratorClass.prototype.constructor.length;
- // destroy if called on an existing component
- if (opts.element.data("select2") !== undefined &&
- opts.element.data("select2") !== null) {
- opts.element.data("select2").destroy();
- }
+ var calledConstructor = SuperClass.prototype.constructor;
- this.container = this.createContainer();
+ if (argCount > 0) {
+ unshift.call(arguments, SuperClass.prototype.constructor);
- this.containerId="s2id_"+(opts.element.attr("id") || "autogen"+nextUid());
- this.containerSelector="#"+this.containerId.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g, '\\$1');
- this.container.attr("id", this.containerId);
+ calledConstructor = DecoratorClass.prototype.constructor;
+ }
- // cache the body so future lookups are cheap
- this.body = thunk(function() { return opts.element.closest("body"); });
+ calledConstructor.apply(this, arguments);
+ }
- syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
+ DecoratorClass.displayName = SuperClass.displayName;
- this.container.attr("style", opts.element.attr("style"));
- this.container.css(evaluate(opts.containerCss));
- this.container.addClass(evaluate(opts.containerCssClass));
+ function ctr () {
+ this.constructor = DecoratedClass;
+ }
- this.elementTabIndex = this.opts.element.attr("tabindex");
+ DecoratedClass.prototype = new ctr();
- // swap container for the element
- this.opts.element
- .data("select2", this)
- .attr("tabindex", "-1")
- .before(this.container)
- .on("click.select2", killEvent); // do not leak click events
+ for (var m = 0; m < superMethods.length; m++) {
+ var superMethod = superMethods[m];
- this.container.data("select2", this);
+ DecoratedClass.prototype[superMethod] =
+ SuperClass.prototype[superMethod];
+ }
- this.dropdown = this.container.find(".select2-drop");
+ var calledMethod = function (methodName) {
+ // Stub out the original method if it's not decorating an actual method
+ var originalMethod = function () {};
- syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass);
+ if (methodName in DecoratedClass.prototype) {
+ originalMethod = DecoratedClass.prototype[methodName];
+ }
- this.dropdown.addClass(evaluate(opts.dropdownCssClass));
- this.dropdown.data("select2", this);
- this.dropdown.on("click", killEvent);
+ var decoratedMethod = DecoratorClass.prototype[methodName];
- this.results = results = this.container.find(resultsSelector);
- this.search = search = this.container.find("input.select2-input");
+ return function () {
+ var unshift = Array.prototype.unshift;
- this.queryCount = 0;
- this.resultsPage = 0;
- this.context = null;
+ unshift.call(arguments, originalMethod);
- // initialize the container
- this.initContainer();
+ return decoratedMethod.apply(this, arguments);
+ };
+ };
- this.container.on("click", killEvent);
+ for (var d = 0; d < decoratedMethods.length; d++) {
+ var decoratedMethod = decoratedMethods[d];
- installFilteredMouseMove(this.results);
- this.dropdown.on("mousemove-filtered touchstart touchmove touchend", resultsSelector, this.bind(this.highlightUnderEvent));
+ DecoratedClass.prototype[decoratedMethod] = calledMethod(decoratedMethod);
+ }
- installDebouncedScroll(80, this.results);
- this.dropdown.on("scroll-debounced", resultsSelector, this.bind(this.loadMoreIfNeeded));
+ return DecoratedClass;
+ };
- // do not propagate change event from the search field out of the component
- $(this.container).on("change", ".select2-input", function(e) {e.stopPropagation();});
- $(this.dropdown).on("change", ".select2-input", function(e) {e.stopPropagation();});
+ var Observable = function () {
+ this.listeners = {};
+ };
- // if jquery.mousewheel plugin is installed we can prevent out-of-bounds scrolling of results via mousewheel
- if ($.fn.mousewheel) {
- results.mousewheel(function (e, delta, deltaX, deltaY) {
- var top = results.scrollTop();
- if (deltaY > 0 && top - deltaY <= 0) {
- results.scrollTop(0);
- killEvent(e);
- } else if (deltaY < 0 && results.get(0).scrollHeight - results.scrollTop() + deltaY <= results.height()) {
- results.scrollTop(results.get(0).scrollHeight - results.height());
- killEvent(e);
- }
- });
- }
+ Observable.prototype.on = function (event, callback) {
+ this.listeners = this.listeners || {};
- installKeyUpChangeEvent(search);
- search.on("keyup-change input paste", this.bind(this.updateResults));
- search.on("focus", function () { search.addClass("select2-focused"); });
- search.on("blur", function () { search.removeClass("select2-focused");});
+ if (event in this.listeners) {
+ this.listeners[event].push(callback);
+ } else {
+ this.listeners[event] = [callback];
+ }
+ };
- this.dropdown.on("mouseup", resultsSelector, this.bind(function (e) {
- if ($(e.target).closest(".select2-result-selectable").length > 0) {
- this.highlightUnderEvent(e);
- this.selectHighlighted(e);
- }
- }));
+ Observable.prototype.trigger = function (event) {
+ var slice = Array.prototype.slice;
- // trap all mouse events from leaving the dropdown. sometimes there may be a modal that is listening
- // for mouse events outside of itself so it can close itself. since the dropdown is now outside the select2's
- // dom it will trigger the popup close, which is not what we want
- this.dropdown.on("click mouseup mousedown", function (e) { e.stopPropagation(); });
+ this.listeners = this.listeners || {};
- if ($.isFunction(this.opts.initSelection)) {
- // initialize selection based on the current value of the source element
- this.initSelection();
+ if (event in this.listeners) {
+ this.invoke(this.listeners[event], slice.call(arguments, 1));
+ }
- // if the user has provided a function that can set selection based on the value of the source element
- // we monitor the change event on the element and trigger it, allowing for two way synchronization
- this.monitorSource();
- }
+ if ('*' in this.listeners) {
+ this.invoke(this.listeners['*'], arguments);
+ }
+ };
- if (opts.maximumInputLength !== null) {
- this.search.attr("maxlength", opts.maximumInputLength);
- }
+ Observable.prototype.invoke = function (listeners, params) {
+ for (var i = 0, len = listeners.length; i < len; i++) {
+ listeners[i].apply(this, params);
+ }
+ };
- var disabled = opts.element.prop("disabled");
- if (disabled === undefined) disabled = false;
- this.enable(!disabled);
+ Utils.Observable = Observable;
- var readonly = opts.element.prop("readonly");
- if (readonly === undefined) readonly = false;
- this.readonly(readonly);
+ Utils.generateChars = function (length) {
+ var chars = '';
- // Calculate size of scrollbar
- scrollBarDimensions = scrollBarDimensions || measureScrollbar();
+ for (var i = 0; i < length; i++) {
+ var randomChar = Math.floor(Math.random() * 36);
+ chars += randomChar.toString(36);
+ }
- this.autofocus = opts.element.prop("autofocus");
- opts.element.prop("autofocus", false);
- if (this.autofocus) this.focus();
+ return chars;
+ };
- this.nextSearchTerm = undefined;
- },
+ Utils.bind = function (func, context) {
+ return function () {
+ func.apply(context, arguments);
+ };
+ };
- // abstract
- destroy: function () {
- var element=this.opts.element, select2 = element.data("select2");
+ Utils._convertData = function (data) {
+ for (var originalKey in data) {
+ var keys = originalKey.split('-');
- this.close();
+ var dataLevel = data;
- if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; }
+ if (keys.length === 1) {
+ continue;
+ }
- if (select2 !== undefined) {
- select2.container.remove();
- select2.dropdown.remove();
- element
- .removeClass("select2-offscreen")
- .removeData("select2")
- .off(".select2")
- .prop("autofocus", this.autofocus || false);
- if (this.elementTabIndex) {
- element.attr({tabindex: this.elementTabIndex});
- } else {
- element.removeAttr("tabindex");
- }
- element.show();
- }
- },
+ for (var k = 0; k < keys.length; k++) {
+ var key = keys[k];
- // abstract
- optionToData: function(element) {
- if (element.is("option")) {
- return {
- id:element.prop("value"),
- text:element.text(),
- element: element.get(),
- css: element.attr("class"),
- disabled: element.prop("disabled"),
- locked: equal(element.attr("locked"), "locked") || equal(element.data("locked"), true)
- };
- } else if (element.is("optgroup")) {
- return {
- text:element.attr("label"),
- children:[],
- element: element.get(),
- css: element.attr("class")
- };
- }
- },
+ // Lowercase the first letter
+ // By default, dash-separated becomes camelCase
+ key = key.substring(0, 1).toLowerCase() + key.substring(1);
- // abstract
- prepareOpts: function (opts) {
- var element, select, idKey, ajaxUrl, self = this;
+ if (!(key in dataLevel)) {
+ dataLevel[key] = {};
+ }
- element = opts.element;
+ if (k == keys.length - 1) {
+ dataLevel[key] = data[originalKey];
+ }
- if (element.get(0).tagName.toLowerCase() === "select") {
- this.select = select = opts.element;
- }
+ dataLevel = dataLevel[key];
+ }
- if (select) {
- // these options are not allowed when attached to a select because they are picked up off the element itself
- $.each(["id", "multiple", "ajax", "query", "createSearchChoice", "initSelection", "data", "tags"], function () {
- if (this in opts) {
- throw new Error("Option '" + this + "' is not allowed for Select2 when attached to a
element.");
- }
- });
- }
+ delete data[originalKey];
+ }
- opts = $.extend({}, {
- populateResults: function(container, results, query) {
- var populate, id=this.opts.id;
+ return data;
+ };
- populate=function(results, container, depth) {
+ Utils.hasScroll = function (index, el) {
+ // Adapted from the function created by @ShadowScripter
+ // and adapted by @BillBarry on the Stack Exchange Code Review website.
+ // The original code can be found at
+ // http://codereview.stackexchange.com/q/13338
+ // and was designed to be used with the Sizzle selector engine.
- var i, l, result, selectable, disabled, compound, node, label, innerContainer, formatted;
+ var $el = $(el);
+ var overflowX = el.style.overflowX;
+ var overflowY = el.style.overflowY;
- results = opts.sortResults(results, container, query);
+ //Check both x and y declarations
+ if (overflowX === overflowY &&
+ (overflowY === 'hidden' || overflowY === 'visible')) {
+ return false;
+ }
- for (i = 0, l = results.length; i < l; i = i + 1) {
+ if (overflowX === 'scroll' || overflowY === 'scroll') {
+ return true;
+ }
- result=results[i];
+ return ($el.innerHeight() < el.scrollHeight ||
+ $el.innerWidth() < el.scrollWidth);
+ };
+
+ Utils.escapeMarkup = function (markup) {
+ var replaceMap = {
+ '\\': '\',
+ '&': '&',
+ '<': '<',
+ '>': '>',
+ '"': '"',
+ '\'': ''',
+ '/': '/'
+ };
- disabled = (result.disabled === true);
- selectable = (!disabled) && (id(result) !== undefined);
+ // Do not try to escape the markup if it's not a string
+ if (typeof markup !== 'string') {
+ return markup;
+ }
- compound=result.children && result.children.length > 0;
+ return String(markup).replace(/[&<>"'\/\\]/g, function (match) {
+ return replaceMap[match];
+ });
+ };
- node=$(" ");
- node.addClass("select2-results-dept-"+depth);
- node.addClass("select2-result");
- node.addClass(selectable ? "select2-result-selectable" : "select2-result-unselectable");
- if (disabled) { node.addClass("select2-disabled"); }
- if (compound) { node.addClass("select2-result-with-children"); }
- node.addClass(self.opts.formatResultCssClass(result));
+ // Append an array of jQuery nodes to a given element.
+ Utils.appendMany = function ($element, $nodes) {
+ // jQuery 1.7.x does not support $.fn.append() with an array
+ // Fall back to a jQuery object collection using $.fn.add()
+ if ($.fn.jquery.substr(0, 3) === '1.7') {
+ var $jqNodes = $();
- label=$(document.createElement("div"));
- label.addClass("select2-result-label");
+ $.map($nodes, function (node) {
+ $jqNodes = $jqNodes.add(node);
+ });
- formatted=opts.formatResult(result, label, query, self.opts.escapeMarkup);
- if (formatted!==undefined) {
- label.html(formatted);
- }
+ $nodes = $jqNodes;
+ }
- node.append(label);
+ $element.append($nodes);
+ };
- if (compound) {
+ return Utils;
+});
- innerContainer=$("");
- innerContainer.addClass("select2-result-sub");
- populate(result.children, innerContainer, depth+1);
- node.append(innerContainer);
- }
+S2.define('select2/results',[
+ 'jquery',
+ './utils'
+], function ($, Utils) {
+ function Results ($element, options, dataAdapter) {
+ this.$element = $element;
+ this.data = dataAdapter;
+ this.options = options;
- node.data("select2-data", result);
- container.append(node);
- }
- };
+ Results.__super__.constructor.call(this);
+ }
- populate(results, container, 0);
- }
- }, $.fn.select2.defaults, opts);
+ Utils.Extend(Results, Utils.Observable);
- if (typeof(opts.id) !== "function") {
- idKey = opts.id;
- opts.id = function (e) { return e[idKey]; };
- }
+ Results.prototype.render = function () {
+ var $results = $(
+ ''
+ );
- if ($.isArray(opts.element.data("select2Tags"))) {
- if ("tags" in opts) {
- throw "tags specified as both an attribute 'data-select2-tags' and in options of Select2 " + opts.element.attr("id");
- }
- opts.tags=opts.element.data("select2Tags");
- }
+ if (this.options.get('multiple')) {
+ $results.attr('aria-multiselectable', 'true');
+ }
- if (select) {
- opts.query = this.bind(function (query) {
- var data = { results: [], more: false },
- term = query.term,
- children, placeholderOption, process;
-
- process=function(element, collection) {
- var group;
- if (element.is("option")) {
- if (query.matcher(term, element.text(), element)) {
- collection.push(self.optionToData(element));
- }
- } else if (element.is("optgroup")) {
- group=self.optionToData(element);
- element.children().each2(function(i, elm) { process(elm, group.children); });
- if (group.children.length>0) {
- collection.push(group);
- }
- }
- };
+ this.$results = $results;
- children=element.children();
+ return $results;
+ };
- // ignore the placeholder option if there is one
- if (this.getPlaceholder() !== undefined && children.length > 0) {
- placeholderOption = this.getPlaceholderOption();
- if (placeholderOption) {
- children=children.not(placeholderOption);
- }
- }
+ Results.prototype.clear = function () {
+ this.$results.empty();
+ };
- children.each2(function(i, elm) { process(elm, data.results); });
+ Results.prototype.displayMessage = function (params) {
+ var escapeMarkup = this.options.get('escapeMarkup');
- query.callback(data);
- });
- // this is needed because inside val() we construct choices from options and there id is hardcoded
- opts.id=function(e) { return e.id; };
- opts.formatResultCssClass = function(data) { return data.css; };
- } else {
- if (!("query" in opts)) {
+ this.clear();
+ this.hideLoading();
- if ("ajax" in opts) {
- ajaxUrl = opts.element.data("ajax-url");
- if (ajaxUrl && ajaxUrl.length > 0) {
- opts.ajax.url = ajaxUrl;
- }
- opts.query = ajax.call(opts.element, opts.ajax);
- } else if ("data" in opts) {
- opts.query = local(opts.data);
- } else if ("tags" in opts) {
- opts.query = tags(opts.tags);
- if (opts.createSearchChoice === undefined) {
- opts.createSearchChoice = function (term) { return {id: $.trim(term), text: $.trim(term)}; };
- }
- if (opts.initSelection === undefined) {
- opts.initSelection = function (element, callback) {
- var data = [];
- $(splitVal(element.val(), opts.separator)).each(function () {
- var obj = { id: this, text: this },
- tags = opts.tags;
- if ($.isFunction(tags)) tags=tags();
- $(tags).each(function() { if (equal(this.id, obj.id)) { obj = this; return false; } });
- data.push(obj);
- });
-
- callback(data);
- };
- }
- }
- }
- }
- if (typeof(opts.query) !== "function") {
- throw "query function not defined for Select2 " + opts.element.attr("id");
- }
+ var $message = $(
+ ' '
+ );
- return opts;
- },
+ var message = this.options.get('translations').get(params.message);
- /**
- * Monitor the original element for changes and update select2 accordingly
- */
- // abstract
- monitorSource: function () {
- var el = this.opts.element, sync, observer;
+ $message.append(
+ escapeMarkup(
+ message(params.args)
+ )
+ );
- el.on("change.select2", this.bind(function (e) {
- if (this.opts.element.data("select2-change-triggered") !== true) {
- this.initSelection();
- }
- }));
+ this.$results.append($message);
+ };
- sync = this.bind(function () {
+ Results.prototype.append = function (data) {
+ this.hideLoading();
- // sync enabled state
- var disabled = el.prop("disabled");
- if (disabled === undefined) disabled = false;
- this.enable(!disabled);
+ var $options = [];
- var readonly = el.prop("readonly");
- if (readonly === undefined) readonly = false;
- this.readonly(readonly);
+ if (data.results == null || data.results.length === 0) {
+ if (this.$results.children().length === 0) {
+ this.trigger('results:message', {
+ message: 'noResults'
+ });
+ }
- syncCssClasses(this.container, this.opts.element, this.opts.adaptContainerCssClass);
- this.container.addClass(evaluate(this.opts.containerCssClass));
+ return;
+ }
- syncCssClasses(this.dropdown, this.opts.element, this.opts.adaptDropdownCssClass);
- this.dropdown.addClass(evaluate(this.opts.dropdownCssClass));
+ data.results = this.sort(data.results);
- });
+ for (var d = 0; d < data.results.length; d++) {
+ var item = data.results[d];
- // IE8-10
- el.on("propertychange.select2", sync);
+ var $option = this.option(item);
- // hold onto a reference of the callback to work around a chromium bug
- if (this.mutationCallback === undefined) {
- this.mutationCallback = function (mutations) {
- mutations.forEach(sync);
- }
- }
+ $options.push($option);
+ }
- // safari, chrome, firefox, IE11
- observer = window.MutationObserver || window.WebKitMutationObserver|| window.MozMutationObserver;
- if (observer !== undefined) {
- if (this.propertyObserver) { delete this.propertyObserver; this.propertyObserver = null; }
- this.propertyObserver = new observer(this.mutationCallback);
- this.propertyObserver.observe(el.get(0), { attributes:true, subtree:false });
- }
- },
+ this.$results.append($options);
+ };
- // abstract
- triggerSelect: function(data) {
- var evt = $.Event("select2-selecting", { val: this.id(data), object: data });
- this.opts.element.trigger(evt);
- return !evt.isDefaultPrevented();
- },
+ Results.prototype.position = function ($results, $dropdown) {
+ var $resultsContainer = $dropdown.find('.select2-results');
+ $resultsContainer.append($results);
+ };
- /**
- * Triggers the change event on the source element
- */
- // abstract
- triggerChange: function (details) {
-
- details = details || {};
- details= $.extend({}, details, { type: "change", val: this.val() });
- // prevents recursive triggering
- this.opts.element.data("select2-change-triggered", true);
- this.opts.element.trigger(details);
- this.opts.element.data("select2-change-triggered", false);
-
- // some validation frameworks ignore the change event and listen instead to keyup, click for selects
- // so here we trigger the click event manually
- this.opts.element.click();
-
- // ValidationEngine ignorea the change event and listens instead to blur
- // so here we trigger the blur event manually if so desired
- if (this.opts.blurOnChange)
- this.opts.element.blur();
- },
+ Results.prototype.sort = function (data) {
+ var sorter = this.options.get('sorter');
- //abstract
- isInterfaceEnabled: function()
- {
- return this.enabledInterface === true;
- },
+ return sorter(data);
+ };
- // abstract
- enableInterface: function() {
- var enabled = this._enabled && !this._readonly,
- disabled = !enabled;
+ Results.prototype.setClasses = function () {
+ var self = this;
- if (enabled === this.enabledInterface) return false;
+ this.data.current(function (selected) {
+ var selectedIds = $.map(selected, function (s) {
+ return s.id.toString();
+ });
- this.container.toggleClass("select2-container-disabled", disabled);
- this.close();
- this.enabledInterface = enabled;
+ var $options = self.$results
+ .find('.select2-results__option[aria-selected]');
- return true;
- },
+ $options.each(function () {
+ var $option = $(this);
- // abstract
- enable: function(enabled) {
- if (enabled === undefined) enabled = true;
- if (this._enabled === enabled) return;
- this._enabled = enabled;
+ var item = $.data(this, 'data');
- this.opts.element.prop("disabled", !enabled);
- this.enableInterface();
- },
+ // id needs to be converted to a string when comparing
+ var id = '' + item.id;
- // abstract
- disable: function() {
- this.enable(false);
- },
+ if ((item.element != null && item.element.selected) ||
+ (item.element == null && $.inArray(id, selectedIds) > -1)) {
+ $option.attr('aria-selected', 'true');
+ } else {
+ $option.attr('aria-selected', 'false');
+ }
+ });
+
+ var $selected = $options.filter('[aria-selected=true]');
+
+ // Check if there are any selected options
+ if ($selected.length > 0) {
+ // If there are selected options, highlight the first
+ $selected.first().trigger('mouseenter');
+ } else {
+ // If there are no selected options, highlight the first option
+ // in the dropdown
+ $options.first().trigger('mouseenter');
+ }
+ });
+ };
- // abstract
- readonly: function(enabled) {
- if (enabled === undefined) enabled = false;
- if (this._readonly === enabled) return false;
- this._readonly = enabled;
+ Results.prototype.showLoading = function (params) {
+ this.hideLoading();
- this.opts.element.prop("readonly", enabled);
- this.enableInterface();
- return true;
- },
+ var loadingMore = this.options.get('translations').get('searching');
- // abstract
- opened: function () {
- return this.container.hasClass("select2-dropdown-open");
- },
+ var loading = {
+ disabled: true,
+ loading: true,
+ text: loadingMore(params)
+ };
+ var $loading = this.option(loading);
+ $loading.className += ' loading-results';
- // abstract
- positionDropdown: function() {
- var $dropdown = this.dropdown,
- offset = this.container.offset(),
- height = this.container.outerHeight(false),
- width = this.container.outerWidth(false),
- dropHeight = $dropdown.outerHeight(false),
- $window = $(window),
- windowWidth = $window.width(),
- windowHeight = $window.height(),
- viewPortRight = $window.scrollLeft() + windowWidth,
- viewportBottom = $window.scrollTop() + windowHeight,
- dropTop = offset.top + height,
- dropLeft = offset.left,
- enoughRoomBelow = dropTop + dropHeight <= viewportBottom,
- enoughRoomAbove = (offset.top - dropHeight) >= this.body().scrollTop(),
- dropWidth = $dropdown.outerWidth(false),
- enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight,
- aboveNow = $dropdown.hasClass("select2-drop-above"),
- bodyOffset,
- above,
- changeDirection,
- css,
- resultsListNode;
-
- // always prefer the current above/below alignment, unless there is not enough room
- if (aboveNow) {
- above = true;
- if (!enoughRoomAbove && enoughRoomBelow) {
- changeDirection = true;
- above = false;
- }
- } else {
- above = false;
- if (!enoughRoomBelow && enoughRoomAbove) {
- changeDirection = true;
- above = true;
- }
- }
+ this.$results.prepend($loading);
+ };
- //if we are changing direction we need to get positions when dropdown is hidden;
- if (changeDirection) {
- $dropdown.hide();
- offset = this.container.offset();
- height = this.container.outerHeight(false);
- width = this.container.outerWidth(false);
- dropHeight = $dropdown.outerHeight(false);
- viewPortRight = $window.scrollLeft() + windowWidth;
- viewportBottom = $window.scrollTop() + windowHeight;
- dropTop = offset.top + height;
- dropLeft = offset.left;
- dropWidth = $dropdown.outerWidth(false);
- enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight;
- $dropdown.show();
- }
+ Results.prototype.hideLoading = function () {
+ this.$results.find('.loading-results').remove();
+ };
- if (this.opts.dropdownAutoWidth) {
- resultsListNode = $('.select2-results', $dropdown)[0];
- $dropdown.addClass('select2-drop-auto-width');
- $dropdown.css('width', '');
- // Add scrollbar width to dropdown if vertical scrollbar is present
- dropWidth = $dropdown.outerWidth(false) + (resultsListNode.scrollHeight === resultsListNode.clientHeight ? 0 : scrollBarDimensions.width);
- dropWidth > width ? width = dropWidth : dropWidth = width;
- enoughRoomOnRight = dropLeft + dropWidth <= viewPortRight;
- }
- else {
- this.container.removeClass('select2-drop-auto-width');
- }
+ Results.prototype.option = function (data) {
+ var option = document.createElement('li');
+ option.className = 'select2-results__option';
- //console.log("below/ droptop:", dropTop, "dropHeight", dropHeight, "sum", (dropTop+dropHeight)+" viewport bottom", viewportBottom, "enough?", enoughRoomBelow);
- //console.log("above/ offset.top", offset.top, "dropHeight", dropHeight, "top", (offset.top-dropHeight), "scrollTop", this.body().scrollTop(), "enough?", enoughRoomAbove);
+ var attrs = {
+ 'role': 'treeitem',
+ 'aria-selected': 'false'
+ };
- // fix positioning when body has an offset and is not position: static
- if (this.body().css('position') !== 'static') {
- bodyOffset = this.body().offset();
- dropTop -= bodyOffset.top;
- dropLeft -= bodyOffset.left;
- }
+ if (data.disabled) {
+ delete attrs['aria-selected'];
+ attrs['aria-disabled'] = 'true';
+ }
- if (!enoughRoomOnRight) {
- dropLeft = offset.left + width - dropWidth;
- }
+ if (data.id == null) {
+ delete attrs['aria-selected'];
+ }
- css = {
- left: dropLeft,
- width: width
- };
+ if (data._resultId != null) {
+ option.id = data._resultId;
+ }
- if (above) {
- css.bottom = windowHeight - offset.top;
- css.top = 'auto';
- this.container.addClass("select2-drop-above");
- $dropdown.addClass("select2-drop-above");
- }
- else {
- css.top = dropTop;
- css.bottom = 'auto';
- this.container.removeClass("select2-drop-above");
- $dropdown.removeClass("select2-drop-above");
- }
- css = $.extend(css, evaluate(this.opts.dropdownCss));
+ if (data.title) {
+ option.title = data.title;
+ }
- $dropdown.css(css);
- },
+ if (data.children) {
+ attrs.role = 'group';
+ attrs['aria-label'] = data.text;
+ delete attrs['aria-selected'];
+ }
- // abstract
- shouldOpen: function() {
- var event;
+ for (var attr in attrs) {
+ var val = attrs[attr];
- if (this.opened()) return false;
+ option.setAttribute(attr, val);
+ }
- if (this._enabled === false || this._readonly === true) return false;
+ if (data.children) {
+ var $option = $(option);
- event = $.Event("select2-opening");
- this.opts.element.trigger(event);
- return !event.isDefaultPrevented();
- },
+ var label = document.createElement('strong');
+ label.className = 'select2-results__group';
- // abstract
- clearDropdownAlignmentPreference: function() {
- // clear the classes used to figure out the preference of where the dropdown should be opened
- this.container.removeClass("select2-drop-above");
- this.dropdown.removeClass("select2-drop-above");
- },
+ var $label = $(label);
+ this.template(data, label);
- /**
- * Opens the dropdown
- *
- * @return {Boolean} whether or not dropdown was opened. This method will return false if, for example,
- * the dropdown is already open, or if the 'open' event listener on the element called preventDefault().
- */
- // abstract
- open: function () {
+ var $children = [];
- if (!this.shouldOpen()) return false;
+ for (var c = 0; c < data.children.length; c++) {
+ var child = data.children[c];
- this.opening();
+ var $child = this.option(child);
- return true;
- },
+ $children.push($child);
+ }
- /**
- * Performs the opening of the dropdown
- */
- // abstract
- opening: function() {
- var cid = this.containerId,
- scroll = "scroll." + cid,
- resize = "resize."+cid,
- orient = "orientationchange."+cid,
- mask;
+ var $childrenContainer = $('', {
+ 'class': 'select2-results__options select2-results__options--nested'
+ });
- this.container.addClass("select2-dropdown-open").addClass("select2-container-active");
+ $childrenContainer.append($children);
- this.clearDropdownAlignmentPreference();
+ $option.append(label);
+ $option.append($childrenContainer);
+ } else {
+ this.template(data, option);
+ }
- if(this.dropdown[0] !== this.body().children().last()[0]) {
- this.dropdown.detach().appendTo(this.body());
- }
+ $.data(option, 'data', data);
- // create the dropdown mask if doesnt already exist
- mask = $("#select2-drop-mask");
- if (mask.length == 0) {
- mask = $(document.createElement("div"));
- mask.attr("id","select2-drop-mask").attr("class","select2-drop-mask");
- mask.hide();
- mask.appendTo(this.body());
- mask.on("mousedown touchstart click", function (e) {
- var dropdown = $("#select2-drop"), self;
- if (dropdown.length > 0) {
- self=dropdown.data("select2");
- if (self.opts.selectOnBlur) {
- self.selectHighlighted({noFocus: true});
- }
- self.close({focus:true});
- e.preventDefault();
- e.stopPropagation();
- }
- });
- }
+ return option;
+ };
- // ensure the mask is always right before the dropdown
- if (this.dropdown.prev()[0] !== mask[0]) {
- this.dropdown.before(mask);
- }
+ Results.prototype.bind = function (container, $container) {
+ var self = this;
- // move the global id to the correct dropdown
- $("#select2-drop").removeAttr("id");
- this.dropdown.attr("id", "select2-drop");
+ var id = container.id + '-results';
- // show the elements
- mask.show();
+ this.$results.attr('id', id);
- this.positionDropdown();
- this.dropdown.show();
- this.positionDropdown();
+ container.on('results:all', function (params) {
+ self.clear();
+ self.append(params.data);
- this.dropdown.addClass("select2-drop-active");
+ if (container.isOpen()) {
+ self.setClasses();
+ }
+ });
- // attach listeners to events that can change the position of the container and thus require
- // the position of the dropdown to be updated as well so it does not come unglued from the container
- var that = this;
- this.container.parents().add(window).each(function () {
- $(this).on(resize+" "+scroll+" "+orient, function (e) {
- that.positionDropdown();
- });
- });
+ container.on('results:append', function (params) {
+ self.append(params.data);
+ if (container.isOpen()) {
+ self.setClasses();
+ }
+ });
- },
+ container.on('query', function (params) {
+ self.showLoading(params);
+ });
- // abstract
- close: function () {
- if (!this.opened()) return;
+ container.on('select', function () {
+ if (!container.isOpen()) {
+ return;
+ }
- var cid = this.containerId,
- scroll = "scroll." + cid,
- resize = "resize."+cid,
- orient = "orientationchange."+cid;
+ self.setClasses();
+ });
- // unbind event listeners
- this.container.parents().add(window).each(function () { $(this).off(scroll).off(resize).off(orient); });
+ container.on('unselect', function () {
+ if (!container.isOpen()) {
+ return;
+ }
- this.clearDropdownAlignmentPreference();
+ self.setClasses();
+ });
- $("#select2-drop-mask").hide();
- this.dropdown.removeAttr("id"); // only the active dropdown has the select2-drop id
- this.dropdown.hide();
- this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active");
- this.results.empty();
+ container.on('open', function () {
+ // When the dropdown is open, aria-expended="true"
+ self.$results.attr('aria-expanded', 'true');
+ self.$results.attr('aria-hidden', 'false');
+ self.setClasses();
+ self.ensureHighlightVisible();
+ });
- this.clearSearch();
- this.search.removeClass("select2-active");
- this.opts.element.trigger($.Event("select2-close"));
- },
+ container.on('close', function () {
+ // When the dropdown is closed, aria-expended="false"
+ self.$results.attr('aria-expanded', 'false');
+ self.$results.attr('aria-hidden', 'true');
+ self.$results.removeAttr('aria-activedescendant');
+ });
- /**
- * Opens control, sets input value, and updates results.
- */
- // abstract
- externalSearch: function (term) {
- this.open();
- this.search.val(term);
- this.updateResults(false);
- },
+ container.on('results:toggle', function () {
+ var $highlighted = self.getHighlightedResults();
- // abstract
- clearSearch: function () {
+ if ($highlighted.length === 0) {
+ return;
+ }
- },
+ $highlighted.trigger('mouseup');
+ });
- //abstract
- getMaximumSelectionSize: function() {
- return evaluate(this.opts.maximumSelectionSize);
- },
+ container.on('results:select', function () {
+ var $highlighted = self.getHighlightedResults();
- // abstract
- ensureHighlightVisible: function () {
- var results = this.results, children, index, child, hb, rb, y, more;
+ if ($highlighted.length === 0) {
+ return;
+ }
- index = this.highlight();
+ var data = $highlighted.data('data');
- if (index < 0) return;
+ if ($highlighted.attr('aria-selected') == 'true') {
+ self.trigger('close');
+ } else {
+ self.trigger('select', {
+ data: data
+ });
+ }
+ });
- if (index == 0) {
+ container.on('results:previous', function () {
+ var $highlighted = self.getHighlightedResults();
- // if the first element is highlighted scroll all the way to the top,
- // that way any unselectable headers above it will also be scrolled
- // into view
+ var $options = self.$results.find('[aria-selected]');
- results.scrollTop(0);
- return;
- }
+ var currentIndex = $options.index($highlighted);
- children = this.findHighlightableChoices().find('.select2-result-label');
+ // If we are already at te top, don't move further
+ if (currentIndex === 0) {
+ return;
+ }
- child = $(children[index]);
+ var nextIndex = currentIndex - 1;
- hb = child.offset().top + child.outerHeight(true);
+ // If none are highlighted, highlight the first
+ if ($highlighted.length === 0) {
+ nextIndex = 0;
+ }
- // if this is the last child lets also make sure select2-more-results is visible
- if (index === children.length - 1) {
- more = results.find("li.select2-more-results");
- if (more.length > 0) {
- hb = more.offset().top + more.outerHeight(true);
- }
- }
+ var $next = $options.eq(nextIndex);
- rb = results.offset().top + results.outerHeight(true);
- if (hb > rb) {
- results.scrollTop(results.scrollTop() + (hb - rb));
- }
- y = child.offset().top - results.offset().top;
+ $next.trigger('mouseenter');
- // make sure the top of the element is visible
- if (y < 0 && child.css('display') != 'none' ) {
- results.scrollTop(results.scrollTop() + y); // y is negative
- }
- },
+ var currentOffset = self.$results.offset().top;
+ var nextTop = $next.offset().top;
+ var nextOffset = self.$results.scrollTop() + (nextTop - currentOffset);
- // abstract
- findHighlightableChoices: function() {
- return this.results.find(".select2-result-selectable:not(.select2-disabled, .select2-selected)");
- },
+ if (nextIndex === 0) {
+ self.$results.scrollTop(0);
+ } else if (nextTop - currentOffset < 0) {
+ self.$results.scrollTop(nextOffset);
+ }
+ });
- // abstract
- moveHighlight: function (delta) {
- var choices = this.findHighlightableChoices(),
- index = this.highlight();
+ container.on('results:next', function () {
+ var $highlighted = self.getHighlightedResults();
- while (index > -1 && index < choices.length) {
- index += delta;
- var choice = $(choices[index]);
- if (choice.hasClass("select2-result-selectable") && !choice.hasClass("select2-disabled") && !choice.hasClass("select2-selected")) {
- this.highlight(index);
- break;
- }
- }
- },
+ var $options = self.$results.find('[aria-selected]');
- // abstract
- highlight: function (index) {
- var choices = this.findHighlightableChoices(),
- choice,
- data;
+ var currentIndex = $options.index($highlighted);
- if (arguments.length === 0) {
- return indexOf(choices.filter(".select2-highlighted")[0], choices.get());
- }
+ var nextIndex = currentIndex + 1;
- if (index >= choices.length) index = choices.length - 1;
- if (index < 0) index = 0;
+ // If we are at the last option, stay there
+ if (nextIndex >= $options.length) {
+ return;
+ }
- this.removeHighlight();
+ var $next = $options.eq(nextIndex);
- choice = $(choices[index]);
- choice.addClass("select2-highlighted");
+ $next.trigger('mouseenter');
- this.ensureHighlightVisible();
+ var currentOffset = self.$results.offset().top +
+ self.$results.outerHeight(false);
+ var nextBottom = $next.offset().top + $next.outerHeight(false);
+ var nextOffset = self.$results.scrollTop() + nextBottom - currentOffset;
- data = choice.data("select2-data");
- if (data) {
- this.opts.element.trigger({ type: "select2-highlight", val: this.id(data), choice: data });
- }
- },
+ if (nextIndex === 0) {
+ self.$results.scrollTop(0);
+ } else if (nextBottom > currentOffset) {
+ self.$results.scrollTop(nextOffset);
+ }
+ });
- removeHighlight: function() {
- this.results.find(".select2-highlighted").removeClass("select2-highlighted");
- },
+ container.on('results:focus', function (params) {
+ params.element.addClass('select2-results__option--highlighted');
+ });
- // abstract
- countSelectableResults: function() {
- return this.findHighlightableChoices().length;
- },
+ container.on('results:message', function (params) {
+ self.displayMessage(params);
+ });
- // abstract
- highlightUnderEvent: function (event) {
- var el = $(event.target).closest(".select2-result-selectable");
- if (el.length > 0 && !el.is(".select2-highlighted")) {
- var choices = this.findHighlightableChoices();
- this.highlight(choices.index(el));
- } else if (el.length == 0) {
- // if we are over an unselectable item remove all highlights
- this.removeHighlight();
- }
- },
+ if ($.fn.mousewheel) {
+ this.$results.on('mousewheel', function (e) {
+ var top = self.$results.scrollTop();
- // abstract
- loadMoreIfNeeded: function () {
- var results = this.results,
- more = results.find("li.select2-more-results"),
- below, // pixels the element is below the scroll fold, below==0 is when the element is starting to be visible
- page = this.resultsPage + 1,
- self=this,
- term=this.search.val(),
- context=this.context;
-
- if (more.length === 0) return;
- below = more.offset().top - results.offset().top - results.height();
-
- if (below <= this.opts.loadMorePadding) {
- more.addClass("select2-active");
- this.opts.query({
- element: this.opts.element,
- term: term,
- page: page,
- context: context,
- matcher: this.opts.matcher,
- callback: this.bind(function (data) {
-
- // ignore a response if the select2 has been closed before it was received
- if (!self.opened()) return;
-
-
- self.opts.populateResults.call(this, results, data.results, {term: term, page: page, context:context});
- self.postprocessResults(data, false, false);
-
- if (data.more===true) {
- more.detach().appendTo(results).text(self.opts.formatLoadMore(page+1));
- window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10);
- } else {
- more.remove();
- }
- self.positionDropdown();
- self.resultsPage = page;
- self.context = data.context;
- this.opts.element.trigger({ type: "select2-loaded", items: data });
- })});
- }
- },
+ var bottom = (
+ self.$results.get(0).scrollHeight -
+ self.$results.scrollTop() +
+ e.deltaY
+ );
- /**
- * Default tokenizer function which does nothing
- */
- tokenize: function() {
+ var isAtTop = e.deltaY > 0 && top - e.deltaY <= 0;
+ var isAtBottom = e.deltaY < 0 && bottom <= self.$results.height();
- },
+ if (isAtTop) {
+ self.$results.scrollTop(0);
- /**
- * @param initial whether or not this is the call to this method right after the dropdown has been opened
- */
- // abstract
- updateResults: function (initial) {
- var search = this.search,
- results = this.results,
- opts = this.opts,
- data,
- self = this,
- input,
- term = search.val(),
- lastTerm = $.data(this.container, "select2-last-term"),
- // sequence number used to drop out-of-order responses
- queryNumber;
-
- // prevent duplicate queries against the same term
- if (initial !== true && lastTerm && equal(term, lastTerm)) return;
-
- $.data(this.container, "select2-last-term", term);
-
- // if the search is currently hidden we do not alter the results
- if (initial !== true && (this.showSearchInput === false || !this.opened())) {
- return;
- }
+ e.preventDefault();
+ e.stopPropagation();
+ } else if (isAtBottom) {
+ self.$results.scrollTop(
+ self.$results.get(0).scrollHeight - self.$results.height()
+ );
- function postRender() {
- search.removeClass("select2-active");
- self.positionDropdown();
- }
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ });
+ }
- function render(html) {
- results.html(html);
- postRender();
- }
+ this.$results.on('mouseup', '.select2-results__option[aria-selected]',
+ function (evt) {
+ var $this = $(this);
- queryNumber = ++this.queryCount;
+ var data = $this.data('data');
- var maxSelSize = this.getMaximumSelectionSize();
- if (maxSelSize >=1) {
- data = this.data();
- if ($.isArray(data) && data.length >= maxSelSize && checkFormatter(opts.formatSelectionTooBig, "formatSelectionTooBig")) {
- render("" + opts.formatSelectionTooBig(maxSelSize) + " ");
- return;
- }
- }
+ if ($this.attr('aria-selected') === 'true') {
+ if (self.options.get('multiple')) {
+ self.trigger('unselect', {
+ originalEvent: evt,
+ data: data
+ });
+ } else {
+ self.trigger('close');
+ }
- if (search.val().length < opts.minimumInputLength) {
- if (checkFormatter(opts.formatInputTooShort, "formatInputTooShort")) {
- render("" + opts.formatInputTooShort(search.val(), opts.minimumInputLength) + " ");
- } else {
- render("");
- }
- if (initial && this.showSearch) this.showSearch(true);
- return;
- }
+ return;
+ }
- if (opts.maximumInputLength && search.val().length > opts.maximumInputLength) {
- if (checkFormatter(opts.formatInputTooLong, "formatInputTooLong")) {
- render("" + opts.formatInputTooLong(search.val(), opts.maximumInputLength) + " ");
- } else {
- render("");
- }
- return;
- }
+ self.trigger('select', {
+ originalEvent: evt,
+ data: data
+ });
+ });
- if (opts.formatSearching && this.findHighlightableChoices().length === 0) {
- render("" + opts.formatSearching() + " ");
- }
+ this.$results.on('mouseenter', '.select2-results__option[aria-selected]',
+ function (evt) {
+ var data = $(this).data('data');
- search.addClass("select2-active");
+ self.getHighlightedResults()
+ .removeClass('select2-results__option--highlighted');
- this.removeHighlight();
+ self.trigger('results:focus', {
+ data: data,
+ element: $(this)
+ });
+ });
+ };
- // give the tokenizer a chance to pre-process the input
- input = this.tokenize();
- if (input != undefined && input != null) {
- search.val(input);
- }
+ Results.prototype.getHighlightedResults = function () {
+ var $highlighted = this.$results
+ .find('.select2-results__option--highlighted');
- this.resultsPage = 1;
+ return $highlighted;
+ };
- opts.query({
- element: opts.element,
- term: search.val(),
- page: this.resultsPage,
- context: null,
- matcher: opts.matcher,
- callback: this.bind(function (data) {
- var def; // default choice
+ Results.prototype.destroy = function () {
+ this.$results.remove();
+ };
- // ignore old responses
- if (queryNumber != this.queryCount) {
- return;
- }
+ Results.prototype.ensureHighlightVisible = function () {
+ var $highlighted = this.getHighlightedResults();
- // ignore a response if the select2 has been closed before it was received
- if (!this.opened()) {
- this.search.removeClass("select2-active");
- return;
- }
+ if ($highlighted.length === 0) {
+ return;
+ }
- // save context, if any
- this.context = (data.context===undefined) ? null : data.context;
- // create a default choice and prepend it to the list
- if (this.opts.createSearchChoice && search.val() !== "") {
- def = this.opts.createSearchChoice.call(self, search.val(), data.results);
- if (def !== undefined && def !== null && self.id(def) !== undefined && self.id(def) !== null) {
- if ($(data.results).filter(
- function () {
- return equal(self.id(this), self.id(def));
- }).length === 0) {
- data.results.unshift(def);
- }
- }
- }
+ var $options = this.$results.find('[aria-selected]');
- if (data.results.length === 0 && checkFormatter(opts.formatNoMatches, "formatNoMatches")) {
- render("" + opts.formatNoMatches(search.val()) + " ");
- return;
- }
+ var currentIndex = $options.index($highlighted);
- results.empty();
- self.opts.populateResults.call(this, results, data.results, {term: search.val(), page: this.resultsPage, context:null});
+ var currentOffset = this.$results.offset().top;
+ var nextTop = $highlighted.offset().top;
+ var nextOffset = this.$results.scrollTop() + (nextTop - currentOffset);
- if (data.more === true && checkFormatter(opts.formatLoadMore, "formatLoadMore")) {
- results.append("" + self.opts.escapeMarkup(opts.formatLoadMore(this.resultsPage)) + " ");
- window.setTimeout(function() { self.loadMoreIfNeeded(); }, 10);
- }
+ var offsetDelta = nextTop - currentOffset;
+ nextOffset -= $highlighted.outerHeight(false) * 2;
- this.postprocessResults(data, initial);
+ if (currentIndex <= 2) {
+ this.$results.scrollTop(0);
+ } else if (offsetDelta > this.$results.outerHeight() || offsetDelta < 0) {
+ this.$results.scrollTop(nextOffset);
+ }
+ };
- postRender();
+ Results.prototype.template = function (result, container) {
+ var template = this.options.get('templateResult');
+ var escapeMarkup = this.options.get('escapeMarkup');
- this.opts.element.trigger({ type: "select2-loaded", items: data });
- })});
- },
+ var content = template(result);
- // abstract
- cancel: function () {
- this.close();
- },
+ if (content == null) {
+ container.style.display = 'none';
+ } else if (typeof content === 'string') {
+ container.innerHTML = escapeMarkup(content);
+ } else {
+ $(container).append(content);
+ }
+ };
+
+ return Results;
+});
+
+S2.define('select2/keys',[
+
+], function () {
+ var KEYS = {
+ BACKSPACE: 8,
+ TAB: 9,
+ ENTER: 13,
+ SHIFT: 16,
+ CTRL: 17,
+ ALT: 18,
+ ESC: 27,
+ SPACE: 32,
+ PAGE_UP: 33,
+ PAGE_DOWN: 34,
+ END: 35,
+ HOME: 36,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40,
+ DELETE: 46
+ };
+
+ return KEYS;
+});
+
+S2.define('select2/selection/base',[
+ 'jquery',
+ '../utils',
+ '../keys'
+], function ($, Utils, KEYS) {
+ function BaseSelection ($element, options) {
+ this.$element = $element;
+ this.options = options;
+
+ BaseSelection.__super__.constructor.call(this);
+ }
+
+ Utils.Extend(BaseSelection, Utils.Observable);
+
+ BaseSelection.prototype.render = function () {
+ var $selection = $(
+ '' +
+ ' '
+ );
+
+ this._tabindex = 0;
+
+ if (this.$element.data('old-tabindex') != null) {
+ this._tabindex = this.$element.data('old-tabindex');
+ } else if (this.$element.attr('tabindex') != null) {
+ this._tabindex = this.$element.attr('tabindex');
+ }
- // abstract
- blur: function () {
- // if selectOnBlur == true, select the currently highlighted option
- if (this.opts.selectOnBlur)
- this.selectHighlighted({noFocus: true});
-
- this.close();
- this.container.removeClass("select2-container-active");
- // synonymous to .is(':focus'), which is available in jquery >= 1.6
- if (this.search[0] === document.activeElement) { this.search.blur(); }
- this.clearSearch();
- this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
- },
+ $selection.attr('title', this.$element.attr('title'));
+ $selection.attr('tabindex', this._tabindex);
- // abstract
- focusSearch: function () {
- focus(this.search);
- },
+ this.$selection = $selection;
- // abstract
- selectHighlighted: function (options) {
- var index=this.highlight(),
- highlighted=this.results.find(".select2-highlighted"),
- data = highlighted.closest('.select2-result').data("select2-data");
-
- if (data) {
- this.highlight(index);
- this.onSelect(data, options);
- } else if (options && options.noFocus) {
- this.close();
- }
- },
+ return $selection;
+ };
- // abstract
- getPlaceholder: function () {
- var placeholderOption;
- return this.opts.element.attr("placeholder") ||
- this.opts.element.attr("data-placeholder") || // jquery 1.4 compat
- this.opts.element.data("placeholder") ||
- this.opts.placeholder ||
- ((placeholderOption = this.getPlaceholderOption()) !== undefined ? placeholderOption.text() : undefined);
- },
+ BaseSelection.prototype.bind = function (container, $container) {
+ var self = this;
- // abstract
- getPlaceholderOption: function() {
- if (this.select) {
- var firstOption = this.select.children('option').first();
- if (this.opts.placeholderOption !== undefined ) {
- //Determine the placeholder option based on the specified placeholderOption setting
- return (this.opts.placeholderOption === "first" && firstOption) ||
- (typeof this.opts.placeholderOption === "function" && this.opts.placeholderOption(this.select));
- } else if (firstOption.text() === "" && firstOption.val() === "") {
- //No explicit placeholder option specified, use the first if it's blank
- return firstOption;
- }
- }
- },
+ var id = container.id + '-container';
+ var resultsId = container.id + '-results';
- /**
- * Get the desired width for the container element. This is
- * derived first from option `width` passed to select2, then
- * the inline 'style' on the original element, and finally
- * falls back to the jQuery calculated element width.
- */
- // abstract
- initContainerWidth: function () {
- function resolveContainerWidth() {
- var style, attrs, matches, i, l, attr;
-
- if (this.opts.width === "off") {
- return null;
- } else if (this.opts.width === "element"){
- return this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px';
- } else if (this.opts.width === "copy" || this.opts.width === "resolve") {
- // check if there is inline style on the element that contains width
- style = this.opts.element.attr('style');
- if (style !== undefined) {
- attrs = style.split(';');
- for (i = 0, l = attrs.length; i < l; i = i + 1) {
- attr = attrs[i].replace(/\s/g, '');
- matches = attr.match(/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i);
- if (matches !== null && matches.length >= 1)
- return matches[1];
- }
- }
+ this.container = container;
- if (this.opts.width === "resolve") {
- // next check if css('width') can resolve a width that is percent based, this is sometimes possible
- // when attached to input type=hidden or elements hidden via css
- style = this.opts.element.css('width');
- if (style.indexOf("%") > 0) return style;
+ this.$selection.on('focus', function (evt) {
+ self.trigger('focus', evt);
+ });
- // finally, fallback on the calculated width of the element
- return (this.opts.element.outerWidth(false) === 0 ? 'auto' : this.opts.element.outerWidth(false) + 'px');
- }
+ this.$selection.on('blur', function (evt) {
+ self.trigger('blur', evt);
+ });
- return null;
- } else if ($.isFunction(this.opts.width)) {
- return this.opts.width();
- } else {
- return this.opts.width;
- }
- };
+ this.$selection.on('keydown', function (evt) {
+ self.trigger('keypress', evt);
- var width = resolveContainerWidth.call(this);
- if (width !== null) {
- this.container.css("width", width);
- }
- }
+ if (evt.which === KEYS.SPACE) {
+ evt.preventDefault();
+ }
});
- SingleSelect2 = clazz(AbstractSelect2, {
-
- // single
-
- createContainer: function () {
- var container = $(document.createElement("div")).attr({
- "class": "select2-container"
- }).html([
- "",
- " ",
- " ",
- " ",
- " ",
- "",
- "
",
- " ",
- "
",
- "
",
- "
"].join(""));
- return container;
- },
+ container.on('results:focus', function (params) {
+ self.$selection.attr('aria-activedescendant', params.data._resultId);
+ });
- // single
- enableInterface: function() {
- if (this.parent.enableInterface.apply(this, arguments)) {
- this.focusser.prop("disabled", !this.isInterfaceEnabled());
- }
- },
+ container.on('selection:update', function (params) {
+ self.update(params.data);
+ });
- // single
- opening: function () {
- var el, range, len;
+ container.on('open', function () {
+ // When the dropdown is open, aria-expanded="true"
+ self.$selection.attr('aria-expanded', 'true');
+ self.$selection.attr('aria-owns', resultsId);
- if (this.opts.minimumResultsForSearch >= 0) {
- this.showSearch(true);
- }
+ self._attachCloseHandler(container);
+ });
- this.parent.opening.apply(this, arguments);
+ container.on('close', function () {
+ // When the dropdown is closed, aria-expanded="false"
+ self.$selection.attr('aria-expanded', 'false');
+ self.$selection.removeAttr('aria-activedescendant');
+ self.$selection.removeAttr('aria-owns');
- if (this.showSearchInput !== false) {
- // IE appends focusser.val() at the end of field :/ so we manually insert it at the beginning using a range
- // all other browsers handle this just fine
+ self.$selection.focus();
- this.search.val(this.focusser.val());
- }
- this.search.focus();
- // move the cursor to the end after focussing, otherwise it will be at the beginning and
- // new text will appear *before* focusser.val()
- el = this.search.get(0);
- if (el.createTextRange) {
- range = el.createTextRange();
- range.collapse(false);
- range.select();
- } else if (el.setSelectionRange) {
- len = this.search.val().length;
- el.setSelectionRange(len, len);
- }
+ self._detachCloseHandler(container);
+ });
- // initializes search's value with nextSearchTerm (if defined by user)
- // ignore nextSearchTerm if the dropdown is opened by the user pressing a letter
- if(this.search.val() === "") {
- if(this.nextSearchTerm != undefined){
- this.search.val(this.nextSearchTerm);
- this.search.select();
- }
- }
+ container.on('enable', function () {
+ self.$selection.attr('tabindex', self._tabindex);
+ });
- this.focusser.prop("disabled", true).val("");
- this.updateResults(true);
- this.opts.element.trigger($.Event("select2-open"));
- },
+ container.on('disable', function () {
+ self.$selection.attr('tabindex', '-1');
+ });
+ };
- // single
- close: function (params) {
- if (!this.opened()) return;
- this.parent.close.apply(this, arguments);
+ BaseSelection.prototype._attachCloseHandler = function (container) {
+ var self = this;
- params = params || {focus: true};
- this.focusser.removeAttr("disabled");
+ $(document.body).on('mousedown.select2.' + container.id, function (e) {
+ var $target = $(e.target);
- if (params.focus) {
- this.focusser.focus();
- }
- },
+ var $select = $target.closest('.select2');
- // single
- focus: function () {
- if (this.opened()) {
- this.close();
- } else {
- this.focusser.removeAttr("disabled");
- this.focusser.focus();
- }
- },
+ var $all = $('.select2.select2-container--open');
- // single
- isFocused: function () {
- return this.container.hasClass("select2-container-active");
- },
+ $all.each(function () {
+ var $this = $(this);
- // single
- cancel: function () {
- this.parent.cancel.apply(this, arguments);
- this.focusser.removeAttr("disabled");
- this.focusser.focus();
- },
+ if (this == $select[0]) {
+ return;
+ }
- // single
- destroy: function() {
- $("label[for='" + this.focusser.attr('id') + "']")
- .attr('for', this.opts.element.attr("id"));
- this.parent.destroy.apply(this, arguments);
- },
+ var $element = $this.data('element');
- // single
- initContainer: function () {
+ $element.select2('close');
+ });
+ });
+ };
- var selection,
- container = this.container,
- dropdown = this.dropdown;
+ BaseSelection.prototype._detachCloseHandler = function (container) {
+ $(document.body).off('mousedown.select2.' + container.id);
+ };
- if (this.opts.minimumResultsForSearch < 0) {
- this.showSearch(false);
- } else {
- this.showSearch(true);
- }
+ BaseSelection.prototype.position = function ($selection, $container) {
+ var $selectionContainer = $container.find('.selection');
+ $selectionContainer.append($selection);
+ };
- this.selection = selection = container.find(".select2-choice");
+ BaseSelection.prototype.destroy = function () {
+ this._detachCloseHandler(this.container);
+ };
- this.focusser = container.find(".select2-focusser");
+ BaseSelection.prototype.update = function (data) {
+ throw new Error('The `update` method must be defined in child classes.');
+ };
- // rewrite labels from original element to focusser
- this.focusser.attr("id", "s2id_autogen"+nextUid());
+ return BaseSelection;
+});
- $("label[for='" + this.opts.element.attr("id") + "']")
- .attr('for', this.focusser.attr('id'));
+S2.define('select2/selection/single',[
+ 'jquery',
+ './base',
+ '../utils',
+ '../keys'
+], function ($, BaseSelection, Utils, KEYS) {
+ function SingleSelection () {
+ SingleSelection.__super__.constructor.apply(this, arguments);
+ }
- this.focusser.attr("tabindex", this.elementTabIndex);
+ Utils.Extend(SingleSelection, BaseSelection);
- this.search.on("keydown", this.bind(function (e) {
- if (!this.isInterfaceEnabled()) return;
+ SingleSelection.prototype.render = function () {
+ var $selection = SingleSelection.__super__.render.call(this);
- if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) {
- // prevent the page from scrolling
- killEvent(e);
- return;
- }
+ $selection.addClass('select2-selection--single');
- switch (e.which) {
- case KEY.UP:
- case KEY.DOWN:
- this.moveHighlight((e.which === KEY.UP) ? -1 : 1);
- killEvent(e);
- return;
- case KEY.ENTER:
- this.selectHighlighted();
- killEvent(e);
- return;
- case KEY.TAB:
- this.selectHighlighted({noFocus: true});
- return;
- case KEY.ESC:
- this.cancel(e);
- killEvent(e);
- return;
- }
- }));
-
- this.search.on("blur", this.bind(function(e) {
- // a workaround for chrome to keep the search field focussed when the scroll bar is used to scroll the dropdown.
- // without this the search field loses focus which is annoying
- if (document.activeElement === this.body().get(0)) {
- window.setTimeout(this.bind(function() {
- this.search.focus();
- }), 0);
- }
- }));
+ $selection.html(
+ ' ' +
+ '' +
+ ' ' +
+ ' '
+ );
- this.focusser.on("keydown", this.bind(function (e) {
- if (!this.isInterfaceEnabled()) return;
+ return $selection;
+ };
- if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) {
- return;
- }
+ SingleSelection.prototype.bind = function (container, $container) {
+ var self = this;
- if (this.opts.openOnEnter === false && e.which === KEY.ENTER) {
- killEvent(e);
- return;
- }
+ SingleSelection.__super__.bind.apply(this, arguments);
- if (e.which == KEY.DOWN || e.which == KEY.UP
- || (e.which == KEY.ENTER && this.opts.openOnEnter)) {
+ var id = container.id + '-container';
- if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) return;
+ this.$selection.find('.select2-selection__rendered').attr('id', id);
+ this.$selection.attr('aria-labelledby', id);
- this.open();
- killEvent(e);
- return;
- }
+ this.$selection.on('mousedown', function (evt) {
+ // Only respond to left clicks
+ if (evt.which !== 1) {
+ return;
+ }
- if (e.which == KEY.DELETE || e.which == KEY.BACKSPACE) {
- if (this.opts.allowClear) {
- this.clear();
- }
- killEvent(e);
- return;
- }
- }));
+ self.trigger('toggle', {
+ originalEvent: evt
+ });
+ });
+ this.$selection.on('focus', function (evt) {
+ // User focuses on the container
+ });
- installKeyUpChangeEvent(this.focusser);
- this.focusser.on("keyup-change input", this.bind(function(e) {
- if (this.opts.minimumResultsForSearch >= 0) {
- e.stopPropagation();
- if (this.opened()) return;
- this.open();
- }
- }));
+ this.$selection.on('blur', function (evt) {
+ // User exits the container
+ });
- selection.on("mousedown", "abbr", this.bind(function (e) {
- if (!this.isInterfaceEnabled()) return;
- this.clear();
- killEventImmediately(e);
- this.close();
- this.selection.focus();
- }));
+ container.on('selection:update', function (params) {
+ self.update(params.data);
+ });
+ };
- selection.on("mousedown", this.bind(function (e) {
+ SingleSelection.prototype.clear = function () {
+ this.$selection.find('.select2-selection__rendered').empty();
+ };
- if (!this.container.hasClass("select2-container-active")) {
- this.opts.element.trigger($.Event("select2-focus"));
- }
+ SingleSelection.prototype.display = function (data) {
+ var template = this.options.get('templateSelection');
+ var escapeMarkup = this.options.get('escapeMarkup');
- if (this.opened()) {
- this.close();
- } else if (this.isInterfaceEnabled()) {
- this.open();
- }
+ return escapeMarkup(template(data));
+ };
- killEvent(e);
- }));
+ SingleSelection.prototype.selectionContainer = function () {
+ return $(' ');
+ };
- dropdown.on("mousedown", this.bind(function() { this.search.focus(); }));
+ SingleSelection.prototype.update = function (data) {
+ if (data.length === 0) {
+ this.clear();
+ return;
+ }
- selection.on("focus", this.bind(function(e) {
- killEvent(e);
- }));
+ var selection = data[0];
- this.focusser.on("focus", this.bind(function(){
- if (!this.container.hasClass("select2-container-active")) {
- this.opts.element.trigger($.Event("select2-focus"));
- }
- this.container.addClass("select2-container-active");
- })).on("blur", this.bind(function() {
- if (!this.opened()) {
- this.container.removeClass("select2-container-active");
- this.opts.element.trigger($.Event("select2-blur"));
- }
- }));
- this.search.on("focus", this.bind(function(){
- if (!this.container.hasClass("select2-container-active")) {
- this.opts.element.trigger($.Event("select2-focus"));
- }
- this.container.addClass("select2-container-active");
- }));
+ var formatted = this.display(selection);
- this.initContainerWidth();
- this.opts.element.addClass("select2-offscreen");
- this.setPlaceholder();
+ var $rendered = this.$selection.find('.select2-selection__rendered');
+ $rendered.empty().append(formatted);
+ $rendered.prop('title', selection.title || selection.text);
+ };
- },
+ return SingleSelection;
+});
- // single
- clear: function(triggerChange) {
- var data=this.selection.data("select2-data");
- if (data) { // guard against queued quick consecutive clicks
- var evt = $.Event("select2-clearing");
- this.opts.element.trigger(evt);
- if (evt.isDefaultPrevented()) {
- return;
- }
- var placeholderOption = this.getPlaceholderOption();
- this.opts.element.val(placeholderOption ? placeholderOption.val() : "");
- this.selection.find(".select2-chosen").empty();
- this.selection.removeData("select2-data");
- this.setPlaceholder();
-
- if (triggerChange !== false){
- this.opts.element.trigger({ type: "select2-removed", val: this.id(data), choice: data });
- this.triggerChange({removed:data});
- }
- }
- },
+S2.define('select2/selection/multiple',[
+ 'jquery',
+ './base',
+ '../utils'
+], function ($, BaseSelection, Utils) {
+ function MultipleSelection ($element, options) {
+ MultipleSelection.__super__.constructor.apply(this, arguments);
+ }
- /**
- * Sets selection based on source element's value
- */
- // single
- initSelection: function () {
- var selected;
- if (this.isPlaceholderOptionSelected()) {
- this.updateSelection(null);
- this.close();
- this.setPlaceholder();
- } else {
- var self = this;
- this.opts.initSelection.call(null, this.opts.element, function(selected){
- if (selected !== undefined && selected !== null) {
- self.updateSelection(selected);
- self.close();
- self.setPlaceholder();
- }
- });
- }
- },
+ Utils.Extend(MultipleSelection, BaseSelection);
- isPlaceholderOptionSelected: function() {
- var placeholderOption;
- if (!this.getPlaceholder()) return false; // no placeholder specified so no option should be considered
- return ((placeholderOption = this.getPlaceholderOption()) !== undefined && placeholderOption.prop("selected"))
- || (this.opts.element.val() === "")
- || (this.opts.element.val() === undefined)
- || (this.opts.element.val() === null);
- },
+ MultipleSelection.prototype.render = function () {
+ var $selection = MultipleSelection.__super__.render.call(this);
- // single
- prepareOpts: function () {
- var opts = this.parent.prepareOpts.apply(this, arguments),
- self=this;
-
- if (opts.element.get(0).tagName.toLowerCase() === "select") {
- // install the selection initializer
- opts.initSelection = function (element, callback) {
- var selected = element.find("option").filter(function() { return this.selected });
- // a single select box always has a value, no need to null check 'selected'
- callback(self.optionToData(selected));
- };
- } else if ("data" in opts) {
- // install default initSelection when applied to hidden input and data is local
- opts.initSelection = opts.initSelection || function (element, callback) {
- var id = element.val();
- //search in data by id, storing the actual matching item
- var match = null;
- opts.query({
- matcher: function(term, text, el){
- var is_match = equal(id, opts.id(el));
- if (is_match) {
- match = el;
- }
- return is_match;
- },
- callback: !$.isFunction(callback) ? $.noop : function() {
- callback(match);
- }
- });
- };
- }
+ $selection.addClass('select2-selection--multiple');
- return opts;
- },
+ $selection.html(
+ ''
+ );
- // single
- getPlaceholder: function() {
- // if a placeholder is specified on a single select without a valid placeholder option ignore it
- if (this.select) {
- if (this.getPlaceholderOption() === undefined) {
- return undefined;
- }
- }
+ return $selection;
+ };
- return this.parent.getPlaceholder.apply(this, arguments);
- },
+ MultipleSelection.prototype.bind = function (container, $container) {
+ var self = this;
- // single
- setPlaceholder: function () {
- var placeholder = this.getPlaceholder();
+ MultipleSelection.__super__.bind.apply(this, arguments);
- if (this.isPlaceholderOptionSelected() && placeholder !== undefined) {
+ this.$selection.on('click', function (evt) {
+ self.trigger('toggle', {
+ originalEvent: evt
+ });
+ });
- // check for a placeholder option if attached to a select
- if (this.select && this.getPlaceholderOption() === undefined) return;
+ this.$selection.on('click', '.select2-selection__choice__remove',
+ function (evt) {
+ var $remove = $(this);
+ var $selection = $remove.parent();
- this.selection.find(".select2-chosen").html(this.opts.escapeMarkup(placeholder));
+ var data = $selection.data('data');
- this.selection.addClass("select2-default");
+ self.trigger('unselect', {
+ originalEvent: evt,
+ data: data
+ });
+ });
+ };
- this.container.removeClass("select2-allowclear");
- }
- },
+ MultipleSelection.prototype.clear = function () {
+ this.$selection.find('.select2-selection__rendered').empty();
+ };
- // single
- postprocessResults: function (data, initial, noHighlightUpdate) {
- var selected = 0, self = this, showSearchInput = true;
+ MultipleSelection.prototype.display = function (data) {
+ var template = this.options.get('templateSelection');
+ var escapeMarkup = this.options.get('escapeMarkup');
- // find the selected element in the result list
+ return escapeMarkup(template(data));
+ };
- this.findHighlightableChoices().each2(function (i, elm) {
- if (equal(self.id(elm.data("select2-data")), self.opts.element.val())) {
- selected = i;
- return false;
- }
- });
+ MultipleSelection.prototype.selectionContainer = function () {
+ var $container = $(
+ '' +
+ '' +
+ '×' +
+ ' ' +
+ ' '
+ );
- // and highlight it
- if (noHighlightUpdate !== false) {
- if (initial === true && selected >= 0) {
- this.highlight(selected);
- } else {
- this.highlight(0);
- }
- }
+ return $container;
+ };
- // hide the search box if this is the first we got the results and there are enough of them for search
+ MultipleSelection.prototype.update = function (data) {
+ this.clear();
- if (initial === true) {
- var min = this.opts.minimumResultsForSearch;
- if (min >= 0) {
- this.showSearch(countResults(data.results) >= min);
- }
- }
- },
+ if (data.length === 0) {
+ return;
+ }
- // single
- showSearch: function(showSearchInput) {
- if (this.showSearchInput === showSearchInput) return;
+ var $selections = [];
- this.showSearchInput = showSearchInput;
+ for (var d = 0; d < data.length; d++) {
+ var selection = data[d];
- this.dropdown.find(".select2-search").toggleClass("select2-search-hidden", !showSearchInput);
- this.dropdown.find(".select2-search").toggleClass("select2-offscreen", !showSearchInput);
- //add "select2-with-searchbox" to the container if search box is shown
- $(this.dropdown, this.container).toggleClass("select2-with-searchbox", showSearchInput);
- },
+ var formatted = this.display(selection);
+ var $selection = this.selectionContainer();
- // single
- onSelect: function (data, options) {
+ $selection.append(formatted);
+ $selection.prop('title', selection.title || selection.text);
- if (!this.triggerSelect(data)) { return; }
+ $selection.data('data', selection);
- var old = this.opts.element.val(),
- oldData = this.data();
+ $selections.push($selection);
+ }
- this.opts.element.val(this.id(data));
- this.updateSelection(data);
+ var $rendered = this.$selection.find('.select2-selection__rendered');
- this.opts.element.trigger({ type: "select2-selected", val: this.id(data), choice: data });
+ Utils.appendMany($rendered, $selections);
+ };
- this.nextSearchTerm = this.opts.nextSearchTerm(data, this.search.val());
- this.close();
+ return MultipleSelection;
+});
- if (!options || !options.noFocus)
- this.focusser.focus();
+S2.define('select2/selection/placeholder',[
+ '../utils'
+], function (Utils) {
+ function Placeholder (decorated, $element, options) {
+ this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
- if (!equal(old, this.id(data))) { this.triggerChange({added:data,removed:oldData}); }
- },
+ decorated.call(this, $element, options);
+ }
- // single
- updateSelection: function (data) {
+ Placeholder.prototype.normalizePlaceholder = function (_, placeholder) {
+ if (typeof placeholder === 'string') {
+ placeholder = {
+ id: '',
+ text: placeholder
+ };
+ }
- var container=this.selection.find(".select2-chosen"), formatted, cssClass;
+ return placeholder;
+ };
- this.selection.data("select2-data", data);
+ Placeholder.prototype.createPlaceholder = function (decorated, placeholder) {
+ var $placeholder = this.selectionContainer();
- container.empty();
- if (data !== null) {
- formatted=this.opts.formatSelection(data, container, this.opts.escapeMarkup);
- }
- if (formatted !== undefined) {
- container.append(formatted);
- }
- cssClass=this.opts.formatSelectionCssClass(data, container);
- if (cssClass !== undefined) {
- container.addClass(cssClass);
- }
+ $placeholder.html(this.display(placeholder));
+ $placeholder.addClass('select2-selection__placeholder')
+ .removeClass('select2-selection__choice');
- this.selection.removeClass("select2-default");
+ return $placeholder;
+ };
- if (this.opts.allowClear && this.getPlaceholder() !== undefined) {
- this.container.addClass("select2-allowclear");
- }
- },
+ Placeholder.prototype.update = function (decorated, data) {
+ var singlePlaceholder = (
+ data.length == 1 && data[0].id != this.placeholder.id
+ );
+ var multipleSelections = data.length > 1;
- // single
- val: function () {
- var val,
- triggerChange = false,
- data = null,
- self = this,
- oldData = this.data();
+ if (multipleSelections || singlePlaceholder) {
+ return decorated.call(this, data);
+ }
- if (arguments.length === 0) {
- return this.opts.element.val();
- }
+ this.clear();
- val = arguments[0];
+ var $placeholder = this.createPlaceholder(this.placeholder);
- if (arguments.length > 1) {
- triggerChange = arguments[1];
- }
+ this.$selection.find('.select2-selection__rendered').append($placeholder);
+ };
- if (this.select) {
- this.select
- .val(val)
- .find("option").filter(function() { return this.selected }).each2(function (i, elm) {
- data = self.optionToData(elm);
- return false;
- });
- this.updateSelection(data);
- this.setPlaceholder();
- if (triggerChange) {
- this.triggerChange({added: data, removed:oldData});
- }
- } else {
- // val is an id. !val is true for [undefined,null,'',0] - 0 is legal
- if (!val && val !== 0) {
- this.clear(triggerChange);
- return;
- }
- if (this.opts.initSelection === undefined) {
- throw new Error("cannot call val() if initSelection() is not defined");
- }
- this.opts.element.val(val);
- this.opts.initSelection(this.opts.element, function(data){
- self.opts.element.val(!data ? "" : self.id(data));
- self.updateSelection(data);
- self.setPlaceholder();
- if (triggerChange) {
- self.triggerChange({added: data, removed:oldData});
- }
- });
- }
- },
+ return Placeholder;
+});
- // single
- clearSearch: function () {
- this.search.val("");
- this.focusser.val("");
- },
+S2.define('select2/selection/allowClear',[
+ 'jquery',
+ '../keys'
+], function ($, KEYS) {
+ function AllowClear () { }
- // single
- data: function(value) {
- var data,
- triggerChange = false;
+ AllowClear.prototype.bind = function (decorated, container, $container) {
+ var self = this;
- if (arguments.length === 0) {
- data = this.selection.data("select2-data");
- if (data == undefined) data = null;
- return data;
- } else {
- if (arguments.length > 1) {
- triggerChange = arguments[1];
- }
- if (!value) {
- this.clear(triggerChange);
- } else {
- data = this.data();
- this.opts.element.val(!value ? "" : this.id(value));
- this.updateSelection(value);
- if (triggerChange) {
- this.triggerChange({added: value, removed:data});
- }
- }
- }
- }
+ decorated.call(this, container, $container);
+
+ if (this.placeholder == null) {
+ if (this.options.get('debug') && window.console && console.error) {
+ console.error(
+ 'Select2: The `allowClear` option should be used in combination ' +
+ 'with the `placeholder` option.'
+ );
+ }
+ }
+
+ this.$selection.on('mousedown', '.select2-selection__clear',
+ function (evt) {
+ self._handleClear(evt);
});
- MultiSelect2 = clazz(AbstractSelect2, {
-
- // multi
- createContainer: function () {
- var container = $(document.createElement("div")).attr({
- "class": "select2-container select2-container-multi"
- }).html([
- "",
- ""].join(""));
- return container;
- },
+ container.on('keypress', function (evt) {
+ self._handleKeyboardClear(evt, container);
+ });
+ };
- // multi
- prepareOpts: function () {
- var opts = this.parent.prepareOpts.apply(this, arguments),
- self=this;
-
- // TODO validate placeholder is a string if specified
-
- if (opts.element.get(0).tagName.toLowerCase() === "select") {
- // install sthe selection initializer
- opts.initSelection = function (element, callback) {
-
- var data = [];
-
- element.find("option").filter(function() { return this.selected }).each2(function (i, elm) {
- data.push(self.optionToData(elm));
- });
- callback(data);
- };
- } else if ("data" in opts) {
- // install default initSelection when applied to hidden input and data is local
- opts.initSelection = opts.initSelection || function (element, callback) {
- var ids = splitVal(element.val(), opts.separator);
- //search in data by array of ids, storing matching items in a list
- var matches = [];
- opts.query({
- matcher: function(term, text, el){
- var is_match = $.grep(ids, function(id) {
- return equal(id, opts.id(el));
- }).length;
- if (is_match) {
- matches.push(el);
- }
- return is_match;
- },
- callback: !$.isFunction(callback) ? $.noop : function() {
- // reorder matches based on the order they appear in the ids array because right now
- // they are in the order in which they appear in data array
- var ordered = [];
- for (var i = 0; i < ids.length; i++) {
- var id = ids[i];
- for (var j = 0; j < matches.length; j++) {
- var match = matches[j];
- if (equal(id, opts.id(match))) {
- ordered.push(match);
- matches.splice(j, 1);
- break;
- }
- }
- }
- callback(ordered);
- }
- });
- };
- }
+ AllowClear.prototype._handleClear = function (_, evt) {
+ // Ignore the event if it is disabled
+ if (this.options.get('disabled')) {
+ return;
+ }
- return opts;
- },
+ var $clear = this.$selection.find('.select2-selection__clear');
- selectChoice: function (choice) {
+ // Ignore the event if nothing has been selected
+ if ($clear.length === 0) {
+ return;
+ }
- var selected = this.container.find(".select2-search-choice-focus");
- if (selected.length && choice && choice[0] == selected[0]) {
+ evt.stopPropagation();
- } else {
- if (selected.length) {
- this.opts.element.trigger("choice-deselected", selected);
- }
- selected.removeClass("select2-search-choice-focus");
- if (choice && choice.length) {
- this.close();
- choice.addClass("select2-search-choice-focus");
- this.opts.element.trigger("choice-selected", choice);
- }
- }
- },
+ var data = $clear.data('data');
- // multi
- destroy: function() {
- $("label[for='" + this.search.attr('id') + "']")
- .attr('for', this.opts.element.attr("id"));
- this.parent.destroy.apply(this, arguments);
- },
+ for (var d = 0; d < data.length; d++) {
+ var unselectData = {
+ data: data[d]
+ };
- // multi
- initContainer: function () {
+ // Trigger the `unselect` event, so people can prevent it from being
+ // cleared.
+ this.trigger('unselect', unselectData);
- var selector = ".select2-choices", selection;
+ // If the event was prevented, don't clear it out.
+ if (unselectData.prevented) {
+ return;
+ }
+ }
- this.searchContainer = this.container.find(".select2-search-field");
- this.selection = selection = this.container.find(selector);
+ this.$element.val(this.placeholder.id).trigger('change');
- var _this = this;
- this.selection.on("click", ".select2-search-choice:not(.select2-locked)", function (e) {
- //killEvent(e);
- _this.search[0].focus();
- _this.selectChoice($(this));
- });
+ this.trigger('toggle');
+ };
- // rewrite labels from original element to focusser
- this.search.attr("id", "s2id_autogen"+nextUid());
- $("label[for='" + this.opts.element.attr("id") + "']")
- .attr('for', this.search.attr('id'));
+ AllowClear.prototype._handleKeyboardClear = function (_, evt, container) {
+ if (container.isOpen()) {
+ return;
+ }
- this.search.on("input paste", this.bind(function() {
- if (!this.isInterfaceEnabled()) return;
- if (!this.opened()) {
- this.open();
- }
- }));
+ if (evt.which == KEYS.DELETE || evt.which == KEYS.BACKSPACE) {
+ this._handleClear(evt);
+ }
+ };
- this.search.attr("tabindex", this.elementTabIndex);
+ AllowClear.prototype.update = function (decorated, data) {
+ decorated.call(this, data);
- this.keydowns = 0;
- this.search.on("keydown", this.bind(function (e) {
- if (!this.isInterfaceEnabled()) return;
+ if (this.$selection.find('.select2-selection__placeholder').length > 0 ||
+ data.length === 0) {
+ return;
+ }
- ++this.keydowns;
- var selected = selection.find(".select2-search-choice-focus");
- var prev = selected.prev(".select2-search-choice:not(.select2-locked)");
- var next = selected.next(".select2-search-choice:not(.select2-locked)");
- var pos = getCursorInfo(this.search);
+ var $remove = $(
+ '' +
+ '×' +
+ ' '
+ );
+ $remove.data('data', data);
- if (selected.length &&
- (e.which == KEY.LEFT || e.which == KEY.RIGHT || e.which == KEY.BACKSPACE || e.which == KEY.DELETE || e.which == KEY.ENTER)) {
- var selectedChoice = selected;
- if (e.which == KEY.LEFT && prev.length) {
- selectedChoice = prev;
- }
- else if (e.which == KEY.RIGHT) {
- selectedChoice = next.length ? next : null;
- }
- else if (e.which === KEY.BACKSPACE) {
- this.unselect(selected.first());
- this.search.width(10);
- selectedChoice = prev.length ? prev : next;
- } else if (e.which == KEY.DELETE) {
- this.unselect(selected.first());
- this.search.width(10);
- selectedChoice = next.length ? next : null;
- } else if (e.which == KEY.ENTER) {
- selectedChoice = null;
- }
+ this.$selection.find('.select2-selection__rendered').prepend($remove);
+ };
- this.selectChoice(selectedChoice);
- killEvent(e);
- if (!selectedChoice || !selectedChoice.length) {
- this.open();
- }
- return;
- } else if (((e.which === KEY.BACKSPACE && this.keydowns == 1)
- || e.which == KEY.LEFT) && (pos.offset == 0 && !pos.length)) {
+ return AllowClear;
+});
- this.selectChoice(selection.find(".select2-search-choice:not(.select2-locked)").last());
- killEvent(e);
- return;
- } else {
- this.selectChoice(null);
- }
+S2.define('select2/selection/search',[
+ 'jquery',
+ '../utils',
+ '../keys'
+], function ($, Utils, KEYS) {
+ function Search (decorated, $element, options) {
+ decorated.call(this, $element, options);
+ }
- if (this.opened()) {
- switch (e.which) {
- case KEY.UP:
- case KEY.DOWN:
- this.moveHighlight((e.which === KEY.UP) ? -1 : 1);
- killEvent(e);
- return;
- case KEY.ENTER:
- this.selectHighlighted();
- killEvent(e);
- return;
- case KEY.TAB:
- this.selectHighlighted({noFocus:true});
- this.close();
- return;
- case KEY.ESC:
- this.cancel(e);
- killEvent(e);
- return;
- }
- }
+ Search.prototype.render = function (decorated) {
+ var $search = $(
+ '' +
+ ' ' +
+ ' '
+ );
- if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e)
- || e.which === KEY.BACKSPACE || e.which === KEY.ESC) {
- return;
- }
+ this.$searchContainer = $search;
+ this.$search = $search.find('select');
- if (e.which === KEY.ENTER) {
- if (this.opts.openOnEnter === false) {
- return;
- } else if (e.altKey || e.ctrlKey || e.shiftKey || e.metaKey) {
- return;
- }
- }
+ var $rendered = decorated.call(this);
- this.open();
+ return $rendered;
+ };
- if (e.which === KEY.PAGE_UP || e.which === KEY.PAGE_DOWN) {
- // prevent the page from scrolling
- killEvent(e);
- }
+ Search.prototype.bind = function (decorated, container, $container) {
+ var self = this;
- if (e.which === KEY.ENTER) {
- // prevent form from being submitted
- killEvent(e);
- }
+ decorated.call(this, container, $container);
- }));
+ container.on('open', function () {
+ self.$search.attr('tabindex', 0);
- this.search.on("keyup", this.bind(function (e) {
- this.keydowns = 0;
- this.resizeSearch();
- })
- );
+ self.$search.focus();
+ });
- this.search.on("blur", this.bind(function(e) {
- this.container.removeClass("select2-container-active");
- this.search.removeClass("select2-focused");
- this.selectChoice(null);
- if (!this.opened()) this.clearSearch();
- e.stopImmediatePropagation();
- this.opts.element.trigger($.Event("select2-blur"));
- }));
-
- this.container.on("click", selector, this.bind(function (e) {
- if (!this.isInterfaceEnabled()) return;
- if ($(e.target).closest(".select2-search-choice").length > 0) {
- // clicked inside a select2 search choice, do not open
- return;
- }
- this.selectChoice(null);
- this.clearPlaceholder();
- if (!this.container.hasClass("select2-container-active")) {
- this.opts.element.trigger($.Event("select2-focus"));
- }
- this.open();
- this.focusSearch();
- e.preventDefault();
- }));
-
- this.container.on("focus", selector, this.bind(function () {
- if (!this.isInterfaceEnabled()) return;
- if (!this.container.hasClass("select2-container-active")) {
- this.opts.element.trigger($.Event("select2-focus"));
- }
- this.container.addClass("select2-container-active");
- this.dropdown.addClass("select2-drop-active");
- this.clearPlaceholder();
- }));
+ container.on('close', function () {
+ self.$search.attr('tabindex', -1);
- this.initContainerWidth();
- this.opts.element.addClass("select2-offscreen");
+ self.$search.val('');
+ self.$search.focus();
+ });
- // set the placeholder if necessary
- this.clearSearch();
- },
+ container.on('enable', function () {
+ self.$search.prop('disabled', false);
+ });
- // multi
- enableInterface: function() {
- if (this.parent.enableInterface.apply(this, arguments)) {
- this.search.prop("disabled", !this.isInterfaceEnabled());
- }
- },
+ container.on('disable', function () {
+ self.$search.prop('disabled', true);
+ });
- // multi
- initSelection: function () {
- var data;
- if (this.opts.element.val() === "" && this.opts.element.text() === "") {
- this.updateSelection([]);
- this.close();
- // set the placeholder if necessary
- this.clearSearch();
- }
- if (this.select || this.opts.element.val() !== "") {
- var self = this;
- this.opts.initSelection.call(null, this.opts.element, function(data){
- if (data !== undefined && data !== null) {
- self.updateSelection(data);
- self.close();
- // set the placeholder if necessary
- self.clearSearch();
- }
- });
- }
- },
+ this.$selection.on('focusin', '.select2-search--inline', function (evt) {
+ self.trigger('focus', evt);
+ });
- // multi
- clearSearch: function () {
- var placeholder = this.getPlaceholder(),
- maxWidth = this.getMaxSearchWidth();
+ this.$selection.on('focusout', '.select2-search--inline', function (evt) {
+ self.trigger('blur', evt);
+ });
- if (placeholder !== undefined && this.getVal().length === 0 && this.search.hasClass("select2-focused") === false) {
- this.search.val(placeholder).addClass("select2-default");
- // stretch the search box to full width of the container so as much of the placeholder is visible as possible
- // we could call this.resizeSearch(), but we do not because that requires a sizer and we do not want to create one so early because of a firefox bug, see #944
- this.search.width(maxWidth > 0 ? maxWidth : this.container.css("width"));
- } else {
- this.search.val("").width(10);
+ this.$selection.on('keydown', '.select2-search--inline', function (evt) {
+ evt.stopPropagation();
+
+ self.trigger('keypress', evt);
+
+ self._keyUpPrevented = evt.isDefaultPrevented();
+
+ var key = evt.which;
+
+ if (key === KEYS.BACKSPACE && self.$search.val() === '') {
+ var $previousChoice = self.$searchContainer
+ .prev('.select2-selection__choice');
+
+ if ($previousChoice.length > 0) {
+ var item = $previousChoice.data('data');
+
+ self.searchRemoveChoice(item);
+
+ evt.preventDefault();
+ }
+ }
+ });
+
+ // Workaround for browsers which do not support the `input` event
+ // This will prevent double-triggering of events for browsers which support
+ // both the `keyup` and `input` events.
+ this.$selection.on('input', '.select2-search--inline', function (evt) {
+ // Unbind the duplicated `keyup` event
+ self.$selection.off('keyup.search');
+ });
+
+ this.$selection.on('keyup.search input', '.select2-search--inline',
+ function (evt) {
+ self.handleSearch(evt);
+ });
+ };
+
+ Search.prototype.createPlaceholder = function (decorated, placeholder) {
+ this.$search.attr('placeholder', placeholder.text);
+ };
+
+ Search.prototype.update = function (decorated, data) {
+ this.$search.attr('placeholder', '');
+
+ decorated.call(this, data);
+
+ this.$selection.find('.select2-selection__rendered')
+ .append(this.$searchContainer);
+
+ this.resizeSearch();
+ };
+
+ Search.prototype.handleSearch = function () {
+ this.resizeSearch();
+
+ if (!this._keyUpPrevented) {
+ var input = this.$search.val();
+
+ this.trigger('query', {
+ term: input
+ });
+ }
+
+ this._keyUpPrevented = false;
+ };
+
+ Search.prototype.searchRemoveChoice = function (decorated, item) {
+ this.trigger('unselect', {
+ data: item
+ });
+
+ this.trigger('open');
+
+ this.$search.val(item.text + ' ');
+ };
+
+ Search.prototype.resizeSearch = function () {
+ this.$search.css('width', '25px');
+
+ var width = '';
+
+ if (this.$search.attr('placeholder') !== '') {
+ width = this.$selection.find('.select2-selection__rendered').innerWidth();
+ } else {
+ var minimumWidth = this.$search.val().length + 1;
+
+ width = (minimumWidth * 0.75) + 'em';
+ }
+
+ this.$search.css('width', width);
+ };
+
+ return Search;
+});
+
+S2.define('select2/selection/eventRelay',[
+ 'jquery'
+], function ($) {
+ function EventRelay () { }
+
+ EventRelay.prototype.bind = function (decorated, container, $container) {
+ var self = this;
+ var relayEvents = [
+ 'open', 'opening',
+ 'close', 'closing',
+ 'select', 'selecting',
+ 'unselect', 'unselecting'
+ ];
+
+ var preventableEvents = ['opening', 'closing', 'selecting', 'unselecting'];
+
+ decorated.call(this, container, $container);
+
+ container.on('*', function (name, params) {
+ // Ignore events that should not be relayed
+ if ($.inArray(name, relayEvents) === -1) {
+ return;
+ }
+
+ // The parameters should always be an object
+ params = params || {};
+
+ // Generate the jQuery event for the Select2 event
+ var evt = $.Event('select2:' + name, {
+ params: params
+ });
+
+ self.$element.trigger(evt);
+
+ // Only handle preventable events if it was one
+ if ($.inArray(name, preventableEvents) === -1) {
+ return;
+ }
+
+ params.prevented = evt.isDefaultPrevented();
+ });
+ };
+
+ return EventRelay;
+});
+
+S2.define('select2/translation',[
+ 'jquery',
+ 'require'
+], function ($, require) {
+ function Translation (dict) {
+ this.dict = dict || {};
+ }
+
+ Translation.prototype.all = function () {
+ return this.dict;
+ };
+
+ Translation.prototype.get = function (key) {
+ return this.dict[key];
+ };
+
+ Translation.prototype.extend = function (translation) {
+ this.dict = $.extend({}, translation.all(), this.dict);
+ };
+
+ // Static functions
+
+ Translation._cache = {};
+
+ Translation.loadPath = function (path) {
+ if (!(path in Translation._cache)) {
+ var translations = require(path);
+
+ Translation._cache[path] = translations;
+ }
+
+ return new Translation(Translation._cache[path]);
+ };
+
+ return Translation;
+});
+
+S2.define('select2/diacritics',[
+
+], function () {
+ var diacritics = {
+ '\u24B6': 'A',
+ '\uFF21': 'A',
+ '\u00C0': 'A',
+ '\u00C1': 'A',
+ '\u00C2': 'A',
+ '\u1EA6': 'A',
+ '\u1EA4': 'A',
+ '\u1EAA': 'A',
+ '\u1EA8': 'A',
+ '\u00C3': 'A',
+ '\u0100': 'A',
+ '\u0102': 'A',
+ '\u1EB0': 'A',
+ '\u1EAE': 'A',
+ '\u1EB4': 'A',
+ '\u1EB2': 'A',
+ '\u0226': 'A',
+ '\u01E0': 'A',
+ '\u00C4': 'A',
+ '\u01DE': 'A',
+ '\u1EA2': 'A',
+ '\u00C5': 'A',
+ '\u01FA': 'A',
+ '\u01CD': 'A',
+ '\u0200': 'A',
+ '\u0202': 'A',
+ '\u1EA0': 'A',
+ '\u1EAC': 'A',
+ '\u1EB6': 'A',
+ '\u1E00': 'A',
+ '\u0104': 'A',
+ '\u023A': 'A',
+ '\u2C6F': 'A',
+ '\uA732': 'AA',
+ '\u00C6': 'AE',
+ '\u01FC': 'AE',
+ '\u01E2': 'AE',
+ '\uA734': 'AO',
+ '\uA736': 'AU',
+ '\uA738': 'AV',
+ '\uA73A': 'AV',
+ '\uA73C': 'AY',
+ '\u24B7': 'B',
+ '\uFF22': 'B',
+ '\u1E02': 'B',
+ '\u1E04': 'B',
+ '\u1E06': 'B',
+ '\u0243': 'B',
+ '\u0182': 'B',
+ '\u0181': 'B',
+ '\u24B8': 'C',
+ '\uFF23': 'C',
+ '\u0106': 'C',
+ '\u0108': 'C',
+ '\u010A': 'C',
+ '\u010C': 'C',
+ '\u00C7': 'C',
+ '\u1E08': 'C',
+ '\u0187': 'C',
+ '\u023B': 'C',
+ '\uA73E': 'C',
+ '\u24B9': 'D',
+ '\uFF24': 'D',
+ '\u1E0A': 'D',
+ '\u010E': 'D',
+ '\u1E0C': 'D',
+ '\u1E10': 'D',
+ '\u1E12': 'D',
+ '\u1E0E': 'D',
+ '\u0110': 'D',
+ '\u018B': 'D',
+ '\u018A': 'D',
+ '\u0189': 'D',
+ '\uA779': 'D',
+ '\u01F1': 'DZ',
+ '\u01C4': 'DZ',
+ '\u01F2': 'Dz',
+ '\u01C5': 'Dz',
+ '\u24BA': 'E',
+ '\uFF25': 'E',
+ '\u00C8': 'E',
+ '\u00C9': 'E',
+ '\u00CA': 'E',
+ '\u1EC0': 'E',
+ '\u1EBE': 'E',
+ '\u1EC4': 'E',
+ '\u1EC2': 'E',
+ '\u1EBC': 'E',
+ '\u0112': 'E',
+ '\u1E14': 'E',
+ '\u1E16': 'E',
+ '\u0114': 'E',
+ '\u0116': 'E',
+ '\u00CB': 'E',
+ '\u1EBA': 'E',
+ '\u011A': 'E',
+ '\u0204': 'E',
+ '\u0206': 'E',
+ '\u1EB8': 'E',
+ '\u1EC6': 'E',
+ '\u0228': 'E',
+ '\u1E1C': 'E',
+ '\u0118': 'E',
+ '\u1E18': 'E',
+ '\u1E1A': 'E',
+ '\u0190': 'E',
+ '\u018E': 'E',
+ '\u24BB': 'F',
+ '\uFF26': 'F',
+ '\u1E1E': 'F',
+ '\u0191': 'F',
+ '\uA77B': 'F',
+ '\u24BC': 'G',
+ '\uFF27': 'G',
+ '\u01F4': 'G',
+ '\u011C': 'G',
+ '\u1E20': 'G',
+ '\u011E': 'G',
+ '\u0120': 'G',
+ '\u01E6': 'G',
+ '\u0122': 'G',
+ '\u01E4': 'G',
+ '\u0193': 'G',
+ '\uA7A0': 'G',
+ '\uA77D': 'G',
+ '\uA77E': 'G',
+ '\u24BD': 'H',
+ '\uFF28': 'H',
+ '\u0124': 'H',
+ '\u1E22': 'H',
+ '\u1E26': 'H',
+ '\u021E': 'H',
+ '\u1E24': 'H',
+ '\u1E28': 'H',
+ '\u1E2A': 'H',
+ '\u0126': 'H',
+ '\u2C67': 'H',
+ '\u2C75': 'H',
+ '\uA78D': 'H',
+ '\u24BE': 'I',
+ '\uFF29': 'I',
+ '\u00CC': 'I',
+ '\u00CD': 'I',
+ '\u00CE': 'I',
+ '\u0128': 'I',
+ '\u012A': 'I',
+ '\u012C': 'I',
+ '\u0130': 'I',
+ '\u00CF': 'I',
+ '\u1E2E': 'I',
+ '\u1EC8': 'I',
+ '\u01CF': 'I',
+ '\u0208': 'I',
+ '\u020A': 'I',
+ '\u1ECA': 'I',
+ '\u012E': 'I',
+ '\u1E2C': 'I',
+ '\u0197': 'I',
+ '\u24BF': 'J',
+ '\uFF2A': 'J',
+ '\u0134': 'J',
+ '\u0248': 'J',
+ '\u24C0': 'K',
+ '\uFF2B': 'K',
+ '\u1E30': 'K',
+ '\u01E8': 'K',
+ '\u1E32': 'K',
+ '\u0136': 'K',
+ '\u1E34': 'K',
+ '\u0198': 'K',
+ '\u2C69': 'K',
+ '\uA740': 'K',
+ '\uA742': 'K',
+ '\uA744': 'K',
+ '\uA7A2': 'K',
+ '\u24C1': 'L',
+ '\uFF2C': 'L',
+ '\u013F': 'L',
+ '\u0139': 'L',
+ '\u013D': 'L',
+ '\u1E36': 'L',
+ '\u1E38': 'L',
+ '\u013B': 'L',
+ '\u1E3C': 'L',
+ '\u1E3A': 'L',
+ '\u0141': 'L',
+ '\u023D': 'L',
+ '\u2C62': 'L',
+ '\u2C60': 'L',
+ '\uA748': 'L',
+ '\uA746': 'L',
+ '\uA780': 'L',
+ '\u01C7': 'LJ',
+ '\u01C8': 'Lj',
+ '\u24C2': 'M',
+ '\uFF2D': 'M',
+ '\u1E3E': 'M',
+ '\u1E40': 'M',
+ '\u1E42': 'M',
+ '\u2C6E': 'M',
+ '\u019C': 'M',
+ '\u24C3': 'N',
+ '\uFF2E': 'N',
+ '\u01F8': 'N',
+ '\u0143': 'N',
+ '\u00D1': 'N',
+ '\u1E44': 'N',
+ '\u0147': 'N',
+ '\u1E46': 'N',
+ '\u0145': 'N',
+ '\u1E4A': 'N',
+ '\u1E48': 'N',
+ '\u0220': 'N',
+ '\u019D': 'N',
+ '\uA790': 'N',
+ '\uA7A4': 'N',
+ '\u01CA': 'NJ',
+ '\u01CB': 'Nj',
+ '\u24C4': 'O',
+ '\uFF2F': 'O',
+ '\u00D2': 'O',
+ '\u00D3': 'O',
+ '\u00D4': 'O',
+ '\u1ED2': 'O',
+ '\u1ED0': 'O',
+ '\u1ED6': 'O',
+ '\u1ED4': 'O',
+ '\u00D5': 'O',
+ '\u1E4C': 'O',
+ '\u022C': 'O',
+ '\u1E4E': 'O',
+ '\u014C': 'O',
+ '\u1E50': 'O',
+ '\u1E52': 'O',
+ '\u014E': 'O',
+ '\u022E': 'O',
+ '\u0230': 'O',
+ '\u00D6': 'O',
+ '\u022A': 'O',
+ '\u1ECE': 'O',
+ '\u0150': 'O',
+ '\u01D1': 'O',
+ '\u020C': 'O',
+ '\u020E': 'O',
+ '\u01A0': 'O',
+ '\u1EDC': 'O',
+ '\u1EDA': 'O',
+ '\u1EE0': 'O',
+ '\u1EDE': 'O',
+ '\u1EE2': 'O',
+ '\u1ECC': 'O',
+ '\u1ED8': 'O',
+ '\u01EA': 'O',
+ '\u01EC': 'O',
+ '\u00D8': 'O',
+ '\u01FE': 'O',
+ '\u0186': 'O',
+ '\u019F': 'O',
+ '\uA74A': 'O',
+ '\uA74C': 'O',
+ '\u01A2': 'OI',
+ '\uA74E': 'OO',
+ '\u0222': 'OU',
+ '\u24C5': 'P',
+ '\uFF30': 'P',
+ '\u1E54': 'P',
+ '\u1E56': 'P',
+ '\u01A4': 'P',
+ '\u2C63': 'P',
+ '\uA750': 'P',
+ '\uA752': 'P',
+ '\uA754': 'P',
+ '\u24C6': 'Q',
+ '\uFF31': 'Q',
+ '\uA756': 'Q',
+ '\uA758': 'Q',
+ '\u024A': 'Q',
+ '\u24C7': 'R',
+ '\uFF32': 'R',
+ '\u0154': 'R',
+ '\u1E58': 'R',
+ '\u0158': 'R',
+ '\u0210': 'R',
+ '\u0212': 'R',
+ '\u1E5A': 'R',
+ '\u1E5C': 'R',
+ '\u0156': 'R',
+ '\u1E5E': 'R',
+ '\u024C': 'R',
+ '\u2C64': 'R',
+ '\uA75A': 'R',
+ '\uA7A6': 'R',
+ '\uA782': 'R',
+ '\u24C8': 'S',
+ '\uFF33': 'S',
+ '\u1E9E': 'S',
+ '\u015A': 'S',
+ '\u1E64': 'S',
+ '\u015C': 'S',
+ '\u1E60': 'S',
+ '\u0160': 'S',
+ '\u1E66': 'S',
+ '\u1E62': 'S',
+ '\u1E68': 'S',
+ '\u0218': 'S',
+ '\u015E': 'S',
+ '\u2C7E': 'S',
+ '\uA7A8': 'S',
+ '\uA784': 'S',
+ '\u24C9': 'T',
+ '\uFF34': 'T',
+ '\u1E6A': 'T',
+ '\u0164': 'T',
+ '\u1E6C': 'T',
+ '\u021A': 'T',
+ '\u0162': 'T',
+ '\u1E70': 'T',
+ '\u1E6E': 'T',
+ '\u0166': 'T',
+ '\u01AC': 'T',
+ '\u01AE': 'T',
+ '\u023E': 'T',
+ '\uA786': 'T',
+ '\uA728': 'TZ',
+ '\u24CA': 'U',
+ '\uFF35': 'U',
+ '\u00D9': 'U',
+ '\u00DA': 'U',
+ '\u00DB': 'U',
+ '\u0168': 'U',
+ '\u1E78': 'U',
+ '\u016A': 'U',
+ '\u1E7A': 'U',
+ '\u016C': 'U',
+ '\u00DC': 'U',
+ '\u01DB': 'U',
+ '\u01D7': 'U',
+ '\u01D5': 'U',
+ '\u01D9': 'U',
+ '\u1EE6': 'U',
+ '\u016E': 'U',
+ '\u0170': 'U',
+ '\u01D3': 'U',
+ '\u0214': 'U',
+ '\u0216': 'U',
+ '\u01AF': 'U',
+ '\u1EEA': 'U',
+ '\u1EE8': 'U',
+ '\u1EEE': 'U',
+ '\u1EEC': 'U',
+ '\u1EF0': 'U',
+ '\u1EE4': 'U',
+ '\u1E72': 'U',
+ '\u0172': 'U',
+ '\u1E76': 'U',
+ '\u1E74': 'U',
+ '\u0244': 'U',
+ '\u24CB': 'V',
+ '\uFF36': 'V',
+ '\u1E7C': 'V',
+ '\u1E7E': 'V',
+ '\u01B2': 'V',
+ '\uA75E': 'V',
+ '\u0245': 'V',
+ '\uA760': 'VY',
+ '\u24CC': 'W',
+ '\uFF37': 'W',
+ '\u1E80': 'W',
+ '\u1E82': 'W',
+ '\u0174': 'W',
+ '\u1E86': 'W',
+ '\u1E84': 'W',
+ '\u1E88': 'W',
+ '\u2C72': 'W',
+ '\u24CD': 'X',
+ '\uFF38': 'X',
+ '\u1E8A': 'X',
+ '\u1E8C': 'X',
+ '\u24CE': 'Y',
+ '\uFF39': 'Y',
+ '\u1EF2': 'Y',
+ '\u00DD': 'Y',
+ '\u0176': 'Y',
+ '\u1EF8': 'Y',
+ '\u0232': 'Y',
+ '\u1E8E': 'Y',
+ '\u0178': 'Y',
+ '\u1EF6': 'Y',
+ '\u1EF4': 'Y',
+ '\u01B3': 'Y',
+ '\u024E': 'Y',
+ '\u1EFE': 'Y',
+ '\u24CF': 'Z',
+ '\uFF3A': 'Z',
+ '\u0179': 'Z',
+ '\u1E90': 'Z',
+ '\u017B': 'Z',
+ '\u017D': 'Z',
+ '\u1E92': 'Z',
+ '\u1E94': 'Z',
+ '\u01B5': 'Z',
+ '\u0224': 'Z',
+ '\u2C7F': 'Z',
+ '\u2C6B': 'Z',
+ '\uA762': 'Z',
+ '\u24D0': 'a',
+ '\uFF41': 'a',
+ '\u1E9A': 'a',
+ '\u00E0': 'a',
+ '\u00E1': 'a',
+ '\u00E2': 'a',
+ '\u1EA7': 'a',
+ '\u1EA5': 'a',
+ '\u1EAB': 'a',
+ '\u1EA9': 'a',
+ '\u00E3': 'a',
+ '\u0101': 'a',
+ '\u0103': 'a',
+ '\u1EB1': 'a',
+ '\u1EAF': 'a',
+ '\u1EB5': 'a',
+ '\u1EB3': 'a',
+ '\u0227': 'a',
+ '\u01E1': 'a',
+ '\u00E4': 'a',
+ '\u01DF': 'a',
+ '\u1EA3': 'a',
+ '\u00E5': 'a',
+ '\u01FB': 'a',
+ '\u01CE': 'a',
+ '\u0201': 'a',
+ '\u0203': 'a',
+ '\u1EA1': 'a',
+ '\u1EAD': 'a',
+ '\u1EB7': 'a',
+ '\u1E01': 'a',
+ '\u0105': 'a',
+ '\u2C65': 'a',
+ '\u0250': 'a',
+ '\uA733': 'aa',
+ '\u00E6': 'ae',
+ '\u01FD': 'ae',
+ '\u01E3': 'ae',
+ '\uA735': 'ao',
+ '\uA737': 'au',
+ '\uA739': 'av',
+ '\uA73B': 'av',
+ '\uA73D': 'ay',
+ '\u24D1': 'b',
+ '\uFF42': 'b',
+ '\u1E03': 'b',
+ '\u1E05': 'b',
+ '\u1E07': 'b',
+ '\u0180': 'b',
+ '\u0183': 'b',
+ '\u0253': 'b',
+ '\u24D2': 'c',
+ '\uFF43': 'c',
+ '\u0107': 'c',
+ '\u0109': 'c',
+ '\u010B': 'c',
+ '\u010D': 'c',
+ '\u00E7': 'c',
+ '\u1E09': 'c',
+ '\u0188': 'c',
+ '\u023C': 'c',
+ '\uA73F': 'c',
+ '\u2184': 'c',
+ '\u24D3': 'd',
+ '\uFF44': 'd',
+ '\u1E0B': 'd',
+ '\u010F': 'd',
+ '\u1E0D': 'd',
+ '\u1E11': 'd',
+ '\u1E13': 'd',
+ '\u1E0F': 'd',
+ '\u0111': 'd',
+ '\u018C': 'd',
+ '\u0256': 'd',
+ '\u0257': 'd',
+ '\uA77A': 'd',
+ '\u01F3': 'dz',
+ '\u01C6': 'dz',
+ '\u24D4': 'e',
+ '\uFF45': 'e',
+ '\u00E8': 'e',
+ '\u00E9': 'e',
+ '\u00EA': 'e',
+ '\u1EC1': 'e',
+ '\u1EBF': 'e',
+ '\u1EC5': 'e',
+ '\u1EC3': 'e',
+ '\u1EBD': 'e',
+ '\u0113': 'e',
+ '\u1E15': 'e',
+ '\u1E17': 'e',
+ '\u0115': 'e',
+ '\u0117': 'e',
+ '\u00EB': 'e',
+ '\u1EBB': 'e',
+ '\u011B': 'e',
+ '\u0205': 'e',
+ '\u0207': 'e',
+ '\u1EB9': 'e',
+ '\u1EC7': 'e',
+ '\u0229': 'e',
+ '\u1E1D': 'e',
+ '\u0119': 'e',
+ '\u1E19': 'e',
+ '\u1E1B': 'e',
+ '\u0247': 'e',
+ '\u025B': 'e',
+ '\u01DD': 'e',
+ '\u24D5': 'f',
+ '\uFF46': 'f',
+ '\u1E1F': 'f',
+ '\u0192': 'f',
+ '\uA77C': 'f',
+ '\u24D6': 'g',
+ '\uFF47': 'g',
+ '\u01F5': 'g',
+ '\u011D': 'g',
+ '\u1E21': 'g',
+ '\u011F': 'g',
+ '\u0121': 'g',
+ '\u01E7': 'g',
+ '\u0123': 'g',
+ '\u01E5': 'g',
+ '\u0260': 'g',
+ '\uA7A1': 'g',
+ '\u1D79': 'g',
+ '\uA77F': 'g',
+ '\u24D7': 'h',
+ '\uFF48': 'h',
+ '\u0125': 'h',
+ '\u1E23': 'h',
+ '\u1E27': 'h',
+ '\u021F': 'h',
+ '\u1E25': 'h',
+ '\u1E29': 'h',
+ '\u1E2B': 'h',
+ '\u1E96': 'h',
+ '\u0127': 'h',
+ '\u2C68': 'h',
+ '\u2C76': 'h',
+ '\u0265': 'h',
+ '\u0195': 'hv',
+ '\u24D8': 'i',
+ '\uFF49': 'i',
+ '\u00EC': 'i',
+ '\u00ED': 'i',
+ '\u00EE': 'i',
+ '\u0129': 'i',
+ '\u012B': 'i',
+ '\u012D': 'i',
+ '\u00EF': 'i',
+ '\u1E2F': 'i',
+ '\u1EC9': 'i',
+ '\u01D0': 'i',
+ '\u0209': 'i',
+ '\u020B': 'i',
+ '\u1ECB': 'i',
+ '\u012F': 'i',
+ '\u1E2D': 'i',
+ '\u0268': 'i',
+ '\u0131': 'i',
+ '\u24D9': 'j',
+ '\uFF4A': 'j',
+ '\u0135': 'j',
+ '\u01F0': 'j',
+ '\u0249': 'j',
+ '\u24DA': 'k',
+ '\uFF4B': 'k',
+ '\u1E31': 'k',
+ '\u01E9': 'k',
+ '\u1E33': 'k',
+ '\u0137': 'k',
+ '\u1E35': 'k',
+ '\u0199': 'k',
+ '\u2C6A': 'k',
+ '\uA741': 'k',
+ '\uA743': 'k',
+ '\uA745': 'k',
+ '\uA7A3': 'k',
+ '\u24DB': 'l',
+ '\uFF4C': 'l',
+ '\u0140': 'l',
+ '\u013A': 'l',
+ '\u013E': 'l',
+ '\u1E37': 'l',
+ '\u1E39': 'l',
+ '\u013C': 'l',
+ '\u1E3D': 'l',
+ '\u1E3B': 'l',
+ '\u017F': 'l',
+ '\u0142': 'l',
+ '\u019A': 'l',
+ '\u026B': 'l',
+ '\u2C61': 'l',
+ '\uA749': 'l',
+ '\uA781': 'l',
+ '\uA747': 'l',
+ '\u01C9': 'lj',
+ '\u24DC': 'm',
+ '\uFF4D': 'm',
+ '\u1E3F': 'm',
+ '\u1E41': 'm',
+ '\u1E43': 'm',
+ '\u0271': 'm',
+ '\u026F': 'm',
+ '\u24DD': 'n',
+ '\uFF4E': 'n',
+ '\u01F9': 'n',
+ '\u0144': 'n',
+ '\u00F1': 'n',
+ '\u1E45': 'n',
+ '\u0148': 'n',
+ '\u1E47': 'n',
+ '\u0146': 'n',
+ '\u1E4B': 'n',
+ '\u1E49': 'n',
+ '\u019E': 'n',
+ '\u0272': 'n',
+ '\u0149': 'n',
+ '\uA791': 'n',
+ '\uA7A5': 'n',
+ '\u01CC': 'nj',
+ '\u24DE': 'o',
+ '\uFF4F': 'o',
+ '\u00F2': 'o',
+ '\u00F3': 'o',
+ '\u00F4': 'o',
+ '\u1ED3': 'o',
+ '\u1ED1': 'o',
+ '\u1ED7': 'o',
+ '\u1ED5': 'o',
+ '\u00F5': 'o',
+ '\u1E4D': 'o',
+ '\u022D': 'o',
+ '\u1E4F': 'o',
+ '\u014D': 'o',
+ '\u1E51': 'o',
+ '\u1E53': 'o',
+ '\u014F': 'o',
+ '\u022F': 'o',
+ '\u0231': 'o',
+ '\u00F6': 'o',
+ '\u022B': 'o',
+ '\u1ECF': 'o',
+ '\u0151': 'o',
+ '\u01D2': 'o',
+ '\u020D': 'o',
+ '\u020F': 'o',
+ '\u01A1': 'o',
+ '\u1EDD': 'o',
+ '\u1EDB': 'o',
+ '\u1EE1': 'o',
+ '\u1EDF': 'o',
+ '\u1EE3': 'o',
+ '\u1ECD': 'o',
+ '\u1ED9': 'o',
+ '\u01EB': 'o',
+ '\u01ED': 'o',
+ '\u00F8': 'o',
+ '\u01FF': 'o',
+ '\u0254': 'o',
+ '\uA74B': 'o',
+ '\uA74D': 'o',
+ '\u0275': 'o',
+ '\u01A3': 'oi',
+ '\u0223': 'ou',
+ '\uA74F': 'oo',
+ '\u24DF': 'p',
+ '\uFF50': 'p',
+ '\u1E55': 'p',
+ '\u1E57': 'p',
+ '\u01A5': 'p',
+ '\u1D7D': 'p',
+ '\uA751': 'p',
+ '\uA753': 'p',
+ '\uA755': 'p',
+ '\u24E0': 'q',
+ '\uFF51': 'q',
+ '\u024B': 'q',
+ '\uA757': 'q',
+ '\uA759': 'q',
+ '\u24E1': 'r',
+ '\uFF52': 'r',
+ '\u0155': 'r',
+ '\u1E59': 'r',
+ '\u0159': 'r',
+ '\u0211': 'r',
+ '\u0213': 'r',
+ '\u1E5B': 'r',
+ '\u1E5D': 'r',
+ '\u0157': 'r',
+ '\u1E5F': 'r',
+ '\u024D': 'r',
+ '\u027D': 'r',
+ '\uA75B': 'r',
+ '\uA7A7': 'r',
+ '\uA783': 'r',
+ '\u24E2': 's',
+ '\uFF53': 's',
+ '\u00DF': 's',
+ '\u015B': 's',
+ '\u1E65': 's',
+ '\u015D': 's',
+ '\u1E61': 's',
+ '\u0161': 's',
+ '\u1E67': 's',
+ '\u1E63': 's',
+ '\u1E69': 's',
+ '\u0219': 's',
+ '\u015F': 's',
+ '\u023F': 's',
+ '\uA7A9': 's',
+ '\uA785': 's',
+ '\u1E9B': 's',
+ '\u24E3': 't',
+ '\uFF54': 't',
+ '\u1E6B': 't',
+ '\u1E97': 't',
+ '\u0165': 't',
+ '\u1E6D': 't',
+ '\u021B': 't',
+ '\u0163': 't',
+ '\u1E71': 't',
+ '\u1E6F': 't',
+ '\u0167': 't',
+ '\u01AD': 't',
+ '\u0288': 't',
+ '\u2C66': 't',
+ '\uA787': 't',
+ '\uA729': 'tz',
+ '\u24E4': 'u',
+ '\uFF55': 'u',
+ '\u00F9': 'u',
+ '\u00FA': 'u',
+ '\u00FB': 'u',
+ '\u0169': 'u',
+ '\u1E79': 'u',
+ '\u016B': 'u',
+ '\u1E7B': 'u',
+ '\u016D': 'u',
+ '\u00FC': 'u',
+ '\u01DC': 'u',
+ '\u01D8': 'u',
+ '\u01D6': 'u',
+ '\u01DA': 'u',
+ '\u1EE7': 'u',
+ '\u016F': 'u',
+ '\u0171': 'u',
+ '\u01D4': 'u',
+ '\u0215': 'u',
+ '\u0217': 'u',
+ '\u01B0': 'u',
+ '\u1EEB': 'u',
+ '\u1EE9': 'u',
+ '\u1EEF': 'u',
+ '\u1EED': 'u',
+ '\u1EF1': 'u',
+ '\u1EE5': 'u',
+ '\u1E73': 'u',
+ '\u0173': 'u',
+ '\u1E77': 'u',
+ '\u1E75': 'u',
+ '\u0289': 'u',
+ '\u24E5': 'v',
+ '\uFF56': 'v',
+ '\u1E7D': 'v',
+ '\u1E7F': 'v',
+ '\u028B': 'v',
+ '\uA75F': 'v',
+ '\u028C': 'v',
+ '\uA761': 'vy',
+ '\u24E6': 'w',
+ '\uFF57': 'w',
+ '\u1E81': 'w',
+ '\u1E83': 'w',
+ '\u0175': 'w',
+ '\u1E87': 'w',
+ '\u1E85': 'w',
+ '\u1E98': 'w',
+ '\u1E89': 'w',
+ '\u2C73': 'w',
+ '\u24E7': 'x',
+ '\uFF58': 'x',
+ '\u1E8B': 'x',
+ '\u1E8D': 'x',
+ '\u24E8': 'y',
+ '\uFF59': 'y',
+ '\u1EF3': 'y',
+ '\u00FD': 'y',
+ '\u0177': 'y',
+ '\u1EF9': 'y',
+ '\u0233': 'y',
+ '\u1E8F': 'y',
+ '\u00FF': 'y',
+ '\u1EF7': 'y',
+ '\u1E99': 'y',
+ '\u1EF5': 'y',
+ '\u01B4': 'y',
+ '\u024F': 'y',
+ '\u1EFF': 'y',
+ '\u24E9': 'z',
+ '\uFF5A': 'z',
+ '\u017A': 'z',
+ '\u1E91': 'z',
+ '\u017C': 'z',
+ '\u017E': 'z',
+ '\u1E93': 'z',
+ '\u1E95': 'z',
+ '\u01B6': 'z',
+ '\u0225': 'z',
+ '\u0240': 'z',
+ '\u2C6C': 'z',
+ '\uA763': 'z',
+ '\u0386': '\u0391',
+ '\u0388': '\u0395',
+ '\u0389': '\u0397',
+ '\u038A': '\u0399',
+ '\u03AA': '\u0399',
+ '\u038C': '\u039F',
+ '\u038E': '\u03A5',
+ '\u03AB': '\u03A5',
+ '\u038F': '\u03A9',
+ '\u03AC': '\u03B1',
+ '\u03AD': '\u03B5',
+ '\u03AE': '\u03B7',
+ '\u03AF': '\u03B9',
+ '\u03CA': '\u03B9',
+ '\u0390': '\u03B9',
+ '\u03CC': '\u03BF',
+ '\u03CD': '\u03C5',
+ '\u03CB': '\u03C5',
+ '\u03B0': '\u03C5',
+ '\u03C9': '\u03C9',
+ '\u03C2': '\u03C3'
+ };
+
+ return diacritics;
+});
+
+S2.define('select2/data/base',[
+ '../utils'
+], function (Utils) {
+ function BaseAdapter ($element, options) {
+ BaseAdapter.__super__.constructor.call(this);
+ }
+
+ Utils.Extend(BaseAdapter, Utils.Observable);
+
+ BaseAdapter.prototype.current = function (callback) {
+ throw new Error('The `current` method must be defined in child classes.');
+ };
+
+ BaseAdapter.prototype.query = function (params, callback) {
+ throw new Error('The `query` method must be defined in child classes.');
+ };
+
+ BaseAdapter.prototype.bind = function (container, $container) {
+ // Can be implemented in subclasses
+ };
+
+ BaseAdapter.prototype.destroy = function () {
+ // Can be implemented in subclasses
+ };
+
+ BaseAdapter.prototype.generateResultId = function (container, data) {
+ var id = container.id + '-result-';
+
+ id += Utils.generateChars(4);
+
+ if (data.id != null) {
+ id += '-' + data.id.toString();
+ } else {
+ id += '-' + Utils.generateChars(4);
+ }
+ return id;
+ };
+
+ return BaseAdapter;
+});
+
+S2.define('select2/data/select',[
+ './base',
+ '../utils',
+ 'jquery'
+], function (BaseAdapter, Utils, $) {
+ function SelectAdapter ($element, options) {
+ this.$element = $element;
+ this.options = options;
+
+ SelectAdapter.__super__.constructor.call(this);
+ }
+
+ Utils.Extend(SelectAdapter, BaseAdapter);
+
+ SelectAdapter.prototype.current = function (callback) {
+ var data = [];
+ var self = this;
+
+ this.$element.find(':selected').each(function () {
+ var $option = $(this);
+
+ var option = self.item($option);
+
+ data.push(option);
+ });
+
+ callback(data);
+ };
+
+ SelectAdapter.prototype.select = function (data) {
+ var self = this;
+
+ data.selected = true;
+
+ // If data.element is a DOM node, use it instead
+ if ($(data.element).is('option')) {
+ data.element.selected = true;
+
+ this.$element.trigger('change');
+
+ return;
+ }
+
+ if (this.$element.prop('multiple')) {
+ this.current(function (currentData) {
+ var val = [];
+
+ data = [data];
+ data.push.apply(data, currentData);
+
+ for (var d = 0; d < data.length; d++) {
+ var id = data[d].id;
+
+ if ($.inArray(id, val) === -1) {
+ val.push(id);
+ }
+ }
+
+ self.$element.val(val);
+ self.$element.trigger('change');
+ });
+ } else {
+ var val = data.id;
+
+ this.$element.val(val);
+ this.$element.trigger('change');
+ }
+ };
+
+ SelectAdapter.prototype.unselect = function (data) {
+ var self = this;
+
+ if (!this.$element.prop('multiple')) {
+ return;
+ }
+
+ data.selected = false;
+
+ if ($(data.element).is('option')) {
+ data.element.selected = false;
+
+ this.$element.trigger('change');
+
+ return;
+ }
+
+ this.current(function (currentData) {
+ var val = [];
+
+ for (var d = 0; d < currentData.length; d++) {
+ var id = currentData[d].id;
+
+ if (id !== data.id && $.inArray(id, val) === -1) {
+ val.push(id);
+ }
+ }
+
+ self.$element.val(val);
+
+ self.$element.trigger('change');
+ });
+ };
+
+ SelectAdapter.prototype.bind = function (container, $container) {
+ var self = this;
+
+ this.container = container;
+
+ container.on('select', function (params) {
+ self.select(params.data);
+ });
+
+ container.on('unselect', function (params) {
+ self.unselect(params.data);
+ });
+ };
+
+ SelectAdapter.prototype.destroy = function () {
+ // Remove anything added to child elements
+ this.$element.find('*').each(function () {
+ // Remove any custom data set by Select2
+ $.removeData(this, 'data');
+ });
+ };
+
+ SelectAdapter.prototype.query = function (params, callback) {
+ var data = [];
+ var self = this;
+
+ var $options = this.$element.children();
+
+ $options.each(function () {
+ var $option = $(this);
+
+ if (!$option.is('option') && !$option.is('optgroup')) {
+ return;
+ }
+
+ var option = self.item($option);
+
+ var matches = self.matches(params, option);
+
+ if (matches !== null) {
+ data.push(matches);
+ }
+ });
+
+ callback({
+ results: data
+ });
+ };
+
+ SelectAdapter.prototype.addOptions = function ($options) {
+ Utils.appendMany(this.$element, $options);
+ };
+
+ SelectAdapter.prototype.option = function (data) {
+ var option;
+
+ if (data.children) {
+ option = document.createElement('optgroup');
+ option.label = data.text;
+ } else {
+ option = document.createElement('option');
+
+ if (option.textContent !== undefined) {
+ option.textContent = data.text;
+ } else {
+ option.innerText = data.text;
+ }
+ }
+
+ if (data.id) {
+ option.value = data.id;
+ }
+
+ if (data.disabled) {
+ option.disabled = true;
+ }
+
+ if (data.selected) {
+ option.selected = true;
+ }
+
+ if (data.title) {
+ option.title = data.title;
+ }
+
+ var $option = $(option);
+
+ var normalizedData = this._normalizeItem(data);
+ normalizedData.element = option;
+
+ // Override the option's data with the combined data
+ $.data(option, 'data', normalizedData);
+
+ return $option;
+ };
+
+ SelectAdapter.prototype.item = function ($option) {
+ var data = {};
+
+ data = $.data($option[0], 'data');
+
+ if (data != null) {
+ return data;
+ }
+
+ if ($option.is('option')) {
+ data = {
+ id: $option.val(),
+ text: $option.text(),
+ disabled: $option.prop('disabled'),
+ selected: $option.prop('selected'),
+ title: $option.prop('title')
+ };
+ } else if ($option.is('optgroup')) {
+ data = {
+ text: $option.prop('label'),
+ children: [],
+ title: $option.prop('title')
+ };
+
+ var $children = $option.children('option');
+ var children = [];
+
+ for (var c = 0; c < $children.length; c++) {
+ var $child = $($children[c]);
+
+ var child = this.item($child);
+
+ children.push(child);
+ }
+
+ data.children = children;
+ }
+
+ data = this._normalizeItem(data);
+ data.element = $option[0];
+
+ $.data($option[0], 'data', data);
+
+ return data;
+ };
+
+ SelectAdapter.prototype._normalizeItem = function (item) {
+ if (!$.isPlainObject(item)) {
+ item = {
+ id: item,
+ text: item
+ };
+ }
+
+ item = $.extend({}, {
+ text: ''
+ }, item);
+
+ var defaults = {
+ selected: false,
+ disabled: false
+ };
+
+ if (item.id != null) {
+ item.id = item.id.toString();
+ }
+
+ if (item.text != null) {
+ item.text = item.text.toString();
+ }
+
+ if (item._resultId == null && item.id && this.container != null) {
+ item._resultId = this.generateResultId(this.container, item);
+ }
+
+ return $.extend({}, defaults, item);
+ };
+
+ SelectAdapter.prototype.matches = function (params, data) {
+ var matcher = this.options.get('matcher');
+
+ return matcher(params, data);
+ };
+
+ return SelectAdapter;
+});
+
+S2.define('select2/data/array',[
+ './select',
+ '../utils',
+ 'jquery'
+], function (SelectAdapter, Utils, $) {
+ function ArrayAdapter ($element, options) {
+ var data = options.get('data') || [];
+
+ ArrayAdapter.__super__.constructor.call(this, $element, options);
+
+ this.addOptions(this.convertToOptions(data));
+ }
+
+ Utils.Extend(ArrayAdapter, SelectAdapter);
+
+ ArrayAdapter.prototype.select = function (data) {
+ var $option = this.$element.find('option').filter(function (i, elm) {
+ return elm.value == data.id.toString();
+ });
+
+ if ($option.length === 0) {
+ $option = this.option(data);
+
+ this.addOptions($option);
+ }
+
+ ArrayAdapter.__super__.select.call(this, data);
+ };
+
+ ArrayAdapter.prototype.convertToOptions = function (data) {
+ var self = this;
+
+ var $existing = this.$element.find('option');
+ var existingIds = $existing.map(function () {
+ return self.item($(this)).id;
+ }).get();
+
+ var $options = [];
+
+ // Filter out all items except for the one passed in the argument
+ function onlyItem (item) {
+ return function () {
+ return $(this).val() == item.id;
+ };
+ }
+
+ for (var d = 0; d < data.length; d++) {
+ var item = this._normalizeItem(data[d]);
+
+ // Skip items which were pre-loaded, only merge the data
+ if ($.inArray(item.id, existingIds) >= 0) {
+ var $existingOption = $existing.filter(onlyItem(item));
+
+ var existingData = this.item($existingOption);
+ var newData = $.extend(true, {}, existingData, item);
+
+ var $newOption = this.option(existingData);
+
+ $existingOption.replaceWith($newOption);
+
+ continue;
+ }
+
+ var $option = this.option(item);
+
+ if (item.children) {
+ var $children = this.convertToOptions(item.children);
+
+ Utils.appendMany($option, $children);
+ }
+
+ $options.push($option);
+ }
+
+ return $options;
+ };
+
+ return ArrayAdapter;
+});
+
+S2.define('select2/data/ajax',[
+ './array',
+ '../utils',
+ 'jquery'
+], function (ArrayAdapter, Utils, $) {
+ function AjaxAdapter ($element, options) {
+ this.ajaxOptions = this._applyDefaults(options.get('ajax'));
+
+ if (this.ajaxOptions.processResults != null) {
+ this.processResults = this.ajaxOptions.processResults;
+ }
+
+ ArrayAdapter.__super__.constructor.call(this, $element, options);
+ }
+
+ Utils.Extend(AjaxAdapter, ArrayAdapter);
+
+ AjaxAdapter.prototype._applyDefaults = function (options) {
+ var defaults = {
+ data: function (params) {
+ return {
+ q: params.term
+ };
+ },
+ transport: function (params, success, failure) {
+ var $request = $.ajax(params);
+
+ $request.then(success);
+ $request.fail(failure);
+
+ return $request;
+ }
+ };
+
+ return $.extend({}, defaults, options, true);
+ };
+
+ AjaxAdapter.prototype.processResults = function (results) {
+ return results;
+ };
+
+ AjaxAdapter.prototype.query = function (params, callback) {
+ var matches = [];
+ var self = this;
+
+ if (this._request != null) {
+ // JSONP requests cannot always be aborted
+ if ($.isFunction(this._request.abort)) {
+ this._request.abort();
+ }
+
+ this._request = null;
+ }
+
+ var options = $.extend({
+ type: 'GET'
+ }, this.ajaxOptions);
+
+ if (typeof options.url === 'function') {
+ options.url = options.url(params);
+ }
+
+ if (typeof options.data === 'function') {
+ options.data = options.data(params);
+ }
+
+ function request () {
+ var $request = options.transport(options, function (data) {
+ var results = self.processResults(data, params);
+
+ if (self.options.get('debug') && window.console && console.error) {
+ // Check to make sure that the response included a `results` key.
+ if (!results || !results.results || !$.isArray(results.results)) {
+ console.error(
+ 'Select2: The AJAX results did not return an array in the ' +
+ '`results` key of the response.'
+ );
+ }
+ }
+
+ callback(results);
+ }, function () {
+ // TODO: Handle AJAX errors
+ });
+
+ self._request = $request;
+ }
+
+ if (this.ajaxOptions.delay && params.term !== '') {
+ if (this._queryTimeout) {
+ window.clearTimeout(this._queryTimeout);
+ }
+
+ this._queryTimeout = window.setTimeout(request, this.ajaxOptions.delay);
+ } else {
+ request();
+ }
+ };
+
+ return AjaxAdapter;
+});
+
+S2.define('select2/data/tags',[
+ 'jquery'
+], function ($) {
+ function Tags (decorated, $element, options) {
+ var tags = options.get('tags');
+
+ var createTag = options.get('createTag');
+
+ if (createTag !== undefined) {
+ this.createTag = createTag;
+ }
+
+ decorated.call(this, $element, options);
+
+ if ($.isArray(tags)) {
+ for (var t = 0; t < tags.length; t++) {
+ var tag = tags[t];
+ var item = this._normalizeItem(tag);
+
+ var $option = this.option(item);
+
+ this.$element.append($option);
+ }
+ }
+ }
+
+ Tags.prototype.query = function (decorated, params, callback) {
+ var self = this;
+
+ this._removeOldTags();
+
+ if (params.term == null || params.page != null) {
+ decorated.call(this, params, callback);
+ return;
+ }
+
+ function wrapper (obj, child) {
+ var data = obj.results;
+
+ for (var i = 0; i < data.length; i++) {
+ var option = data[i];
+
+ var checkChildren = (
+ option.children != null &&
+ !wrapper({
+ results: option.children
+ }, true)
+ );
+
+ var checkText = option.text === params.term;
+
+ if (checkText || checkChildren) {
+ if (child) {
+ return false;
+ }
+
+ obj.data = data;
+ callback(obj);
+
+ return;
+ }
+ }
+
+ if (child) {
+ return true;
+ }
+
+ var tag = self.createTag(params);
+
+ if (tag != null) {
+ var $option = self.option(tag);
+ $option.attr('data-select2-tag', true);
+
+ self.addOptions([$option]);
+
+ self.insertTag(data, tag);
+ }
+
+ obj.results = data;
+
+ callback(obj);
+ }
+
+ decorated.call(this, params, wrapper);
+ };
+
+ Tags.prototype.createTag = function (decorated, params) {
+ var term = $.trim(params.term);
+
+ if (term === '') {
+ return null;
+ }
+
+ return {
+ id: term,
+ text: term
+ };
+ };
+
+ Tags.prototype.insertTag = function (_, data, tag) {
+ data.unshift(tag);
+ };
+
+ Tags.prototype._removeOldTags = function (_) {
+ var tag = this._lastTag;
+
+ var $options = this.$element.find('option[data-select2-tag]');
+
+ $options.each(function () {
+ if (this.selected) {
+ return;
+ }
+
+ $(this).remove();
+ });
+ };
+
+ return Tags;
+});
+
+S2.define('select2/data/tokenizer',[
+ 'jquery'
+], function ($) {
+ function Tokenizer (decorated, $element, options) {
+ var tokenizer = options.get('tokenizer');
+
+ if (tokenizer !== undefined) {
+ this.tokenizer = tokenizer;
+ }
+
+ decorated.call(this, $element, options);
+ }
+
+ Tokenizer.prototype.bind = function (decorated, container, $container) {
+ decorated.call(this, container, $container);
+
+ this.$search = container.dropdown.$search || container.selection.$search ||
+ $container.find('.select2-search__field');
+ };
+
+ Tokenizer.prototype.query = function (decorated, params, callback) {
+ var self = this;
+
+ function select (data) {
+ self.select(data);
+ }
+
+ params.term = params.term || '';
+
+ var tokenData = this.tokenizer(params, this.options, select);
+
+ if (tokenData.term !== params.term) {
+ // Replace the search term if we have the search box
+ if (this.$search.length) {
+ this.$search.val(tokenData.term);
+ this.$search.focus();
+ }
+
+ params.term = tokenData.term;
+ }
+
+ decorated.call(this, params, callback);
+ };
+
+ Tokenizer.prototype.tokenizer = function (_, params, options, callback) {
+ var separators = options.get('tokenSeparators') || [];
+ var term = params.term;
+ var i = 0;
+
+ var createTag = this.createTag || function (params) {
+ return {
+ id: params.term,
+ text: params.term
+ };
+ };
+
+ while (i < term.length) {
+ var termChar = term[i];
+
+ if ($.inArray(termChar, separators) === -1) {
+ i++;
+
+ continue;
+ }
+
+ var part = term.substr(0, i);
+ var partParams = $.extend({}, params, {
+ term: part
+ });
+
+ var data = createTag(partParams);
+
+ callback(data);
+
+ // Reset the term to not include the tokenized portion
+ term = term.substr(i + 1) || '';
+ i = 0;
+ }
+
+ return {
+ term: term
+ };
+ };
+
+ return Tokenizer;
+});
+
+S2.define('select2/data/minimumInputLength',[
+
+], function () {
+ function MinimumInputLength (decorated, $e, options) {
+ this.minimumInputLength = options.get('minimumInputLength');
+
+ decorated.call(this, $e, options);
+ }
+
+ MinimumInputLength.prototype.query = function (decorated, params, callback) {
+ params.term = params.term || '';
+
+ if (params.term.length < this.minimumInputLength) {
+ this.trigger('results:message', {
+ message: 'inputTooShort',
+ args: {
+ minimum: this.minimumInputLength,
+ input: params.term,
+ params: params
+ }
+ });
+
+ return;
+ }
+
+ decorated.call(this, params, callback);
+ };
+
+ return MinimumInputLength;
+});
+
+S2.define('select2/data/maximumInputLength',[
+
+], function () {
+ function MaximumInputLength (decorated, $e, options) {
+ this.maximumInputLength = options.get('maximumInputLength');
+
+ decorated.call(this, $e, options);
+ }
+
+ MaximumInputLength.prototype.query = function (decorated, params, callback) {
+ params.term = params.term || '';
+
+ if (this.maximumInputLength > 0 &&
+ params.term.length > this.maximumInputLength) {
+ this.trigger('results:message', {
+ message: 'inputTooLong',
+ args: {
+ maximum: this.maximumInputLength,
+ input: params.term,
+ params: params
+ }
+ });
+
+ return;
+ }
+
+ decorated.call(this, params, callback);
+ };
+
+ return MaximumInputLength;
+});
+
+S2.define('select2/data/maximumSelectionLength',[
+
+], function (){
+ function MaximumSelectionLength (decorated, $e, options) {
+ this.maximumSelectionLength = options.get('maximumSelectionLength');
+
+ decorated.call(this, $e, options);
+ }
+
+ MaximumSelectionLength.prototype.query =
+ function (decorated, params, callback) {
+ var self = this;
+
+ this.current(function (currentData) {
+ var count = currentData != null ? currentData.length : 0;
+ if (self.maximumSelectionLength > 0 &&
+ count >= self.maximumSelectionLength) {
+ self.trigger('results:message', {
+ message: 'maximumSelected',
+ args: {
+ maximum: self.maximumSelectionLength
}
- },
+ });
+ return;
+ }
+ decorated.call(self, params, callback);
+ });
+ };
+
+ return MaximumSelectionLength;
+});
+
+S2.define('select2/dropdown',[
+ 'jquery',
+ './utils'
+], function ($, Utils) {
+ function Dropdown ($element, options) {
+ this.$element = $element;
+ this.options = options;
+
+ Dropdown.__super__.constructor.call(this);
+ }
+
+ Utils.Extend(Dropdown, Utils.Observable);
+
+ Dropdown.prototype.render = function () {
+ var $dropdown = $(
+ '' +
+ ' ' +
+ ' '
+ );
+
+ $dropdown.attr('dir', this.options.get('dir'));
+
+ this.$dropdown = $dropdown;
+
+ return $dropdown;
+ };
+
+ Dropdown.prototype.position = function ($dropdown, $container) {
+ // Should be implmented in subclasses
+ };
+
+ Dropdown.prototype.destroy = function () {
+ // Remove the dropdown from the DOM
+ this.$dropdown.remove();
+ };
+
+ return Dropdown;
+});
+
+S2.define('select2/dropdown/search',[
+ 'jquery',
+ '../utils'
+], function ($, Utils) {
+ function Search () { }
+
+ Search.prototype.render = function (decorated) {
+ var $rendered = decorated.call(this);
+
+ var $search = $(
+ '' +
+ ' ' +
+ ' '
+ );
+
+ this.$searchContainer = $search;
+ this.$search = $search.find('input');
+
+ $rendered.prepend($search);
+
+ return $rendered;
+ };
+
+ Search.prototype.bind = function (decorated, container, $container) {
+ var self = this;
+
+ decorated.call(this, container, $container);
+
+ this.$search.on('keydown', function (evt) {
+ self.trigger('keypress', evt);
+
+ self._keyUpPrevented = evt.isDefaultPrevented();
+ });
+
+ // Workaround for browsers which do not support the `input` event
+ // This will prevent double-triggering of events for browsers which support
+ // both the `keyup` and `input` events.
+ this.$search.on('input', function (evt) {
+ // Unbind the duplicated `keyup` event
+ $(this).off('keyup');
+ });
+
+ this.$search.on('keyup input', function (evt) {
+ self.handleSearch(evt);
+ });
+
+ container.on('open', function () {
+ self.$search.attr('tabindex', 0);
+
+ self.$search.focus();
+
+ window.setTimeout(function () {
+ self.$search.focus();
+ }, 0);
+ });
+
+ container.on('close', function () {
+ self.$search.attr('tabindex', -1);
+
+ self.$search.val('');
+ });
+
+ container.on('results:all', function (params) {
+ if (params.query.term == null || params.query.term === '') {
+ var showSearch = self.showSearch(params);
+
+ if (showSearch) {
+ self.$searchContainer.removeClass('select2-search--hide');
+ } else {
+ self.$searchContainer.addClass('select2-search--hide');
+ }
+ }
+ });
+ };
+
+ Search.prototype.handleSearch = function (evt) {
+ if (!this._keyUpPrevented) {
+ var input = this.$search.val();
+
+ this.trigger('query', {
+ term: input
+ });
+ }
+
+ this._keyUpPrevented = false;
+ };
+
+ Search.prototype.showSearch = function (_, params) {
+ return true;
+ };
+
+ return Search;
+});
+
+S2.define('select2/dropdown/hidePlaceholder',[
+
+], function () {
+ function HidePlaceholder (decorated, $element, options, dataAdapter) {
+ this.placeholder = this.normalizePlaceholder(options.get('placeholder'));
+
+ decorated.call(this, $element, options, dataAdapter);
+ }
+
+ HidePlaceholder.prototype.append = function (decorated, data) {
+ data.results = this.removePlaceholder(data.results);
+
+ decorated.call(this, data);
+ };
+
+ HidePlaceholder.prototype.normalizePlaceholder = function (_, placeholder) {
+ if (typeof placeholder === 'string') {
+ placeholder = {
+ id: '',
+ text: placeholder
+ };
+ }
+
+ return placeholder;
+ };
+
+ HidePlaceholder.prototype.removePlaceholder = function (_, data) {
+ var modifiedData = data.slice(0);
+
+ for (var d = data.length - 1; d >= 0; d--) {
+ var item = data[d];
+
+ if (this.placeholder.id === item.id) {
+ modifiedData.splice(d, 1);
+ }
+ }
+
+ return modifiedData;
+ };
+
+ return HidePlaceholder;
+});
+
+S2.define('select2/dropdown/infiniteScroll',[
+ 'jquery'
+], function ($) {
+ function InfiniteScroll (decorated, $element, options, dataAdapter) {
+ this.lastParams = {};
+
+ decorated.call(this, $element, options, dataAdapter);
+
+ this.$loadingMore = this.createLoadingMore();
+ this.loading = false;
+ }
+
+ InfiniteScroll.prototype.append = function (decorated, data) {
+ this.$loadingMore.remove();
+ this.loading = false;
+
+ decorated.call(this, data);
+
+ if (this.showLoadingMore(data)) {
+ this.$results.append(this.$loadingMore);
+ }
+ };
+
+ InfiniteScroll.prototype.bind = function (decorated, container, $container) {
+ var self = this;
+
+ decorated.call(this, container, $container);
+
+ container.on('query', function (params) {
+ self.lastParams = params;
+ self.loading = true;
+ });
+
+ container.on('query:append', function (params) {
+ self.lastParams = params;
+ self.loading = true;
+ });
+
+ this.$results.on('scroll', function () {
+ var isLoadMoreVisible = $.contains(
+ document.documentElement,
+ self.$loadingMore[0]
+ );
+
+ if (self.loading || !isLoadMoreVisible) {
+ return;
+ }
+
+ var currentOffset = self.$results.offset().top +
+ self.$results.outerHeight(false);
+ var loadingMoreOffset = self.$loadingMore.offset().top +
+ self.$loadingMore.outerHeight(false);
+
+ if (currentOffset + 50 >= loadingMoreOffset) {
+ self.loadMore();
+ }
+ });
+ };
+
+ InfiniteScroll.prototype.loadMore = function () {
+ this.loading = true;
+
+ var params = $.extend({}, {page: 1}, this.lastParams);
+
+ params.page++;
+
+ this.trigger('query:append', params);
+ };
+
+ InfiniteScroll.prototype.showLoadingMore = function (_, data) {
+ return data.pagination && data.pagination.more;
+ };
+
+ InfiniteScroll.prototype.createLoadingMore = function () {
+ var $option = $(
+ ' '
+ );
+
+ var message = this.options.get('translations').get('loadingMore');
+
+ $option.html(message(this.lastParams));
+
+ return $option;
+ };
+
+ return InfiniteScroll;
+});
+
+S2.define('select2/dropdown/attachBody',[
+ 'jquery',
+ '../utils'
+], function ($, Utils) {
+ function AttachBody (decorated, $element, options) {
+ this.$dropdownParent = options.get('dropdownParent') || document.body;
+
+ decorated.call(this, $element, options);
+ }
+
+ AttachBody.prototype.bind = function (decorated, container, $container) {
+ var self = this;
+
+ var setupResultsEvents = false;
+
+ decorated.call(this, container, $container);
+
+ container.on('open', function () {
+ self._showDropdown();
+ self._attachPositioningHandler(container);
+
+ if (!setupResultsEvents) {
+ setupResultsEvents = true;
+
+ container.on('results:all', function () {
+ self._positionDropdown();
+ self._resizeDropdown();
+ });
+
+ container.on('results:append', function () {
+ self._positionDropdown();
+ self._resizeDropdown();
+ });
+ }
+ });
+
+ container.on('close', function () {
+ self._hideDropdown();
+ self._detachPositioningHandler(container);
+ });
+
+ this.$dropdownContainer.on('mousedown', function (evt) {
+ evt.stopPropagation();
+ });
+ };
+
+ AttachBody.prototype.position = function (decorated, $dropdown, $container) {
+ // Clone all of the container classes
+ $dropdown.attr('class', $container.attr('class'));
+
+ $dropdown.removeClass('select2');
+ $dropdown.addClass('select2-container--open');
+
+ $dropdown.css({
+ position: 'absolute',
+ top: -999999
+ });
+
+ this.$container = $container;
+ };
+
+ AttachBody.prototype.render = function (decorated) {
+ var $container = $(' ');
+
+ var $dropdown = decorated.call(this);
+ $container.append($dropdown);
+
+ this.$dropdownContainer = $container;
+
+ return $container;
+ };
+
+ AttachBody.prototype._hideDropdown = function (decorated) {
+ this.$dropdownContainer.detach();
+ };
+
+ AttachBody.prototype._attachPositioningHandler = function (container) {
+ var self = this;
+
+ var scrollEvent = 'scroll.select2.' + container.id;
+ var resizeEvent = 'resize.select2.' + container.id;
+ var orientationEvent = 'orientationchange.select2.' + container.id;
+
+ var $watchers = this.$container.parents().filter(Utils.hasScroll);
+ $watchers.each(function () {
+ $(this).data('select2-scroll-position', {
+ x: $(this).scrollLeft(),
+ y: $(this).scrollTop()
+ });
+ });
+
+ $watchers.on(scrollEvent, function (ev) {
+ var position = $(this).data('select2-scroll-position');
+ $(this).scrollTop(position.y);
+ });
+
+ $(window).on(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent,
+ function (e) {
+ self._positionDropdown();
+ self._resizeDropdown();
+ });
+ };
+
+ AttachBody.prototype._detachPositioningHandler = function (container) {
+ var scrollEvent = 'scroll.select2.' + container.id;
+ var resizeEvent = 'resize.select2.' + container.id;
+ var orientationEvent = 'orientationchange.select2.' + container.id;
+
+ var $watchers = this.$container.parents().filter(Utils.hasScroll);
+ $watchers.off(scrollEvent);
+
+ $(window).off(scrollEvent + ' ' + resizeEvent + ' ' + orientationEvent);
+ };
+
+ AttachBody.prototype._positionDropdown = function () {
+ var $window = $(window);
+
+ var isCurrentlyAbove = this.$dropdown.hasClass('select2-dropdown--above');
+ var isCurrentlyBelow = this.$dropdown.hasClass('select2-dropdown--below');
+
+ var newDirection = null;
+
+ var position = this.$container.position();
+ var offset = this.$container.offset();
+
+ offset.bottom = offset.top + this.$container.outerHeight(false);
+
+ var container = {
+ height: this.$container.outerHeight(false)
+ };
+
+ container.top = offset.top;
+ container.bottom = offset.top + container.height;
+
+ var dropdown = {
+ height: this.$dropdown.outerHeight(false)
+ };
+
+ var viewport = {
+ top: $window.scrollTop(),
+ bottom: $window.scrollTop() + $window.height()
+ };
+
+ var enoughRoomAbove = viewport.top < (offset.top - dropdown.height);
+ var enoughRoomBelow = viewport.bottom > (offset.bottom + dropdown.height);
+
+ var css = {
+ left: offset.left,
+ top: container.bottom
+ };
+
+ if (!isCurrentlyAbove && !isCurrentlyBelow) {
+ newDirection = 'below';
+ }
+
+ if (!enoughRoomBelow && enoughRoomAbove && !isCurrentlyAbove) {
+ newDirection = 'above';
+ } else if (!enoughRoomAbove && enoughRoomBelow && isCurrentlyAbove) {
+ newDirection = 'below';
+ }
+
+ if (newDirection == 'above' ||
+ (isCurrentlyAbove && newDirection !== 'below')) {
+ css.top = container.top - dropdown.height;
+ }
+
+ if (newDirection != null) {
+ this.$dropdown
+ .removeClass('select2-dropdown--below select2-dropdown--above')
+ .addClass('select2-dropdown--' + newDirection);
+ this.$container
+ .removeClass('select2-container--below select2-container--above')
+ .addClass('select2-container--' + newDirection);
+ }
+
+ this.$dropdownContainer.css(css);
+ };
+
+ AttachBody.prototype._resizeDropdown = function () {
+ this.$dropdownContainer.width();
+
+ var css = {
+ width: this.$container.outerWidth(false) + 'px'
+ };
+
+ if (this.options.get('dropdownAutoWidth')) {
+ css.minWidth = css.width;
+ css.width = 'auto';
+ }
+
+ this.$dropdown.css(css);
+ };
+
+ AttachBody.prototype._showDropdown = function (decorated) {
+ this.$dropdownContainer.appendTo(this.$dropdownParent);
+
+ this._positionDropdown();
+ this._resizeDropdown();
+ };
+
+ return AttachBody;
+});
+
+S2.define('select2/dropdown/minimumResultsForSearch',[
+
+], function () {
+ function countResults (data) {
+ var count = 0;
+
+ for (var d = 0; d < data.length; d++) {
+ var item = data[d];
+
+ if (item.children) {
+ count += countResults(item.children);
+ } else {
+ count++;
+ }
+ }
+
+ return count;
+ }
+
+ function MinimumResultsForSearch (decorated, $element, options, dataAdapter) {
+ this.minimumResultsForSearch = options.get('minimumResultsForSearch');
+
+ if (this.minimumResultsForSearch < 0) {
+ this.minimumResultsForSearch = Infinity;
+ }
+
+ decorated.call(this, $element, options, dataAdapter);
+ }
+
+ MinimumResultsForSearch.prototype.showSearch = function (decorated, params) {
+ if (countResults(params.data.results) < this.minimumResultsForSearch) {
+ return false;
+ }
+
+ return decorated.call(this, params);
+ };
+
+ return MinimumResultsForSearch;
+});
+
+S2.define('select2/dropdown/selectOnClose',[
+
+], function () {
+ function SelectOnClose () { }
+
+ SelectOnClose.prototype.bind = function (decorated, container, $container) {
+ var self = this;
+
+ decorated.call(this, container, $container);
+
+ container.on('close', function () {
+ self._handleSelectOnClose();
+ });
+ };
+
+ SelectOnClose.prototype._handleSelectOnClose = function () {
+ var $highlightedResults = this.getHighlightedResults();
+
+ if ($highlightedResults.length < 1) {
+ return;
+ }
+
+ this.trigger('select', {
+ data: $highlightedResults.data('data')
+ });
+ };
+
+ return SelectOnClose;
+});
+
+S2.define('select2/dropdown/closeOnSelect',[
+
+], function () {
+ function CloseOnSelect () { }
+
+ CloseOnSelect.prototype.bind = function (decorated, container, $container) {
+ var self = this;
+
+ decorated.call(this, container, $container);
+
+ container.on('select', function (evt) {
+ self._selectTriggered(evt);
+ });
+
+ container.on('unselect', function (evt) {
+ self._selectTriggered(evt);
+ });
+ };
+
+ CloseOnSelect.prototype._selectTriggered = function (_, evt) {
+ var originalEvent = evt.originalEvent;
+
+ // Don't close if the control key is being held
+ if (originalEvent && originalEvent.ctrlKey) {
+ return;
+ }
+
+ this.trigger('close');
+ };
+
+ return CloseOnSelect;
+});
+
+S2.define('select2/i18n/en',[],function () {
+ // English
+ return {
+ errorLoading: function () {
+ return 'The results could not be loaded.';
+ },
+ inputTooLong: function (args) {
+ var overChars = args.input.length - args.maximum;
+
+ var message = 'Please delete ' + overChars + ' character';
+
+ if (overChars != 1) {
+ message += 's';
+ }
+
+ return message;
+ },
+ inputTooShort: function (args) {
+ var remainingChars = args.minimum - args.input.length;
+
+ var message = 'Please enter ' + remainingChars + ' or more characters';
+
+ return message;
+ },
+ loadingMore: function () {
+ return 'Loading more results…';
+ },
+ maximumSelected: function (args) {
+ var message = 'You can only select ' + args.maximum + ' item';
+
+ if (args.maximum != 1) {
+ message += 's';
+ }
+
+ return message;
+ },
+ noResults: function () {
+ return 'No results found';
+ },
+ searching: function () {
+ return 'Searching…';
+ }
+ };
+});
+
+S2.define('select2/defaults',[
+ 'jquery',
+ 'require',
+
+ './results',
+
+ './selection/single',
+ './selection/multiple',
+ './selection/placeholder',
+ './selection/allowClear',
+ './selection/search',
+ './selection/eventRelay',
+
+ './utils',
+ './translation',
+ './diacritics',
+
+ './data/select',
+ './data/array',
+ './data/ajax',
+ './data/tags',
+ './data/tokenizer',
+ './data/minimumInputLength',
+ './data/maximumInputLength',
+ './data/maximumSelectionLength',
+
+ './dropdown',
+ './dropdown/search',
+ './dropdown/hidePlaceholder',
+ './dropdown/infiniteScroll',
+ './dropdown/attachBody',
+ './dropdown/minimumResultsForSearch',
+ './dropdown/selectOnClose',
+ './dropdown/closeOnSelect',
+
+ './i18n/en'
+], function ($, require,
+
+ ResultsList,
+
+ SingleSelection, MultipleSelection, Placeholder, AllowClear,
+ SelectionSearch, EventRelay,
+
+ Utils, Translation, DIACRITICS,
+
+ SelectData, ArrayData, AjaxData, Tags, Tokenizer,
+ MinimumInputLength, MaximumInputLength, MaximumSelectionLength,
+
+ Dropdown, DropdownSearch, HidePlaceholder, InfiniteScroll,
+ AttachBody, MinimumResultsForSearch, SelectOnClose, CloseOnSelect,
+
+ EnglishTranslation) {
+ function Defaults () {
+ this.reset();
+ }
+
+ Defaults.prototype.apply = function (options) {
+ options = $.extend({}, this.defaults, options);
+
+ if (options.dataAdapter == null) {
+ if (options.ajax != null) {
+ options.dataAdapter = AjaxData;
+ } else if (options.data != null) {
+ options.dataAdapter = ArrayData;
+ } else {
+ options.dataAdapter = SelectData;
+ }
+
+ if (options.minimumInputLength > 0) {
+ options.dataAdapter = Utils.Decorate(
+ options.dataAdapter,
+ MinimumInputLength
+ );
+ }
+
+ if (options.maximumInputLength > 0) {
+ options.dataAdapter = Utils.Decorate(
+ options.dataAdapter,
+ MaximumInputLength
+ );
+ }
+
+ if (options.maximumSelectionLength > 0) {
+ options.dataAdapter = Utils.Decorate(
+ options.dataAdapter,
+ MaximumSelectionLength
+ );
+ }
+
+ if (options.tags) {
+ options.dataAdapter = Utils.Decorate(options.dataAdapter, Tags);
+ }
+
+ if (options.tokenSeparators != null || options.tokenizer != null) {
+ options.dataAdapter = Utils.Decorate(
+ options.dataAdapter,
+ Tokenizer
+ );
+ }
+
+ if (options.query != null) {
+ var Query = require(options.amdBase + 'compat/query');
+
+ options.dataAdapter = Utils.Decorate(
+ options.dataAdapter,
+ Query
+ );
+ }
+
+ if (options.initSelection != null) {
+ var InitSelection = require(options.amdBase + 'compat/initSelection');
+
+ options.dataAdapter = Utils.Decorate(
+ options.dataAdapter,
+ InitSelection
+ );
+ }
+ }
+
+ if (options.resultsAdapter == null) {
+ options.resultsAdapter = ResultsList;
+
+ if (options.ajax != null) {
+ options.resultsAdapter = Utils.Decorate(
+ options.resultsAdapter,
+ InfiniteScroll
+ );
+ }
+
+ if (options.placeholder != null) {
+ options.resultsAdapter = Utils.Decorate(
+ options.resultsAdapter,
+ HidePlaceholder
+ );
+ }
+
+ if (options.selectOnClose) {
+ options.resultsAdapter = Utils.Decorate(
+ options.resultsAdapter,
+ SelectOnClose
+ );
+ }
+ }
+
+ if (options.dropdownAdapter == null) {
+ if (options.multiple) {
+ options.dropdownAdapter = Dropdown;
+ } else {
+ var SearchableDropdown = Utils.Decorate(Dropdown, DropdownSearch);
+
+ options.dropdownAdapter = SearchableDropdown;
+ }
+
+ if (options.minimumResultsForSearch !== 0) {
+ options.dropdownAdapter = Utils.Decorate(
+ options.dropdownAdapter,
+ MinimumResultsForSearch
+ );
+ }
+
+ if (options.closeOnSelect) {
+ options.dropdownAdapter = Utils.Decorate(
+ options.dropdownAdapter,
+ CloseOnSelect
+ );
+ }
+
+ if (
+ options.dropdownCssClass != null ||
+ options.dropdownCss != null ||
+ options.adaptDropdownCssClass != null
+ ) {
+ var DropdownCSS = require(options.amdBase + 'compat/dropdownCss');
+
+ options.dropdownAdapter = Utils.Decorate(
+ options.dropdownAdapter,
+ DropdownCSS
+ );
+ }
+
+ options.dropdownAdapter = Utils.Decorate(
+ options.dropdownAdapter,
+ AttachBody
+ );
+ }
+
+ if (options.selectionAdapter == null) {
+ if (options.multiple) {
+ options.selectionAdapter = MultipleSelection;
+ } else {
+ options.selectionAdapter = SingleSelection;
+ }
+
+ // Add the placeholder mixin if a placeholder was specified
+ if (options.placeholder != null) {
+ options.selectionAdapter = Utils.Decorate(
+ options.selectionAdapter,
+ Placeholder
+ );
+ }
+
+ if (options.allowClear) {
+ options.selectionAdapter = Utils.Decorate(
+ options.selectionAdapter,
+ AllowClear
+ );
+ }
+
+ if (options.multiple) {
+ options.selectionAdapter = Utils.Decorate(
+ options.selectionAdapter,
+ SelectionSearch
+ );
+ }
+
+ if (
+ options.containerCssClass != null ||
+ options.containerCss != null ||
+ options.adaptContainerCssClass != null
+ ) {
+ var ContainerCSS = require(options.amdBase + 'compat/containerCss');
+
+ options.selectionAdapter = Utils.Decorate(
+ options.selectionAdapter,
+ ContainerCSS
+ );
+ }
+
+ options.selectionAdapter = Utils.Decorate(
+ options.selectionAdapter,
+ EventRelay
+ );
+ }
+
+ if (typeof options.language === 'string') {
+ // Check if the language is specified with a region
+ if (options.language.indexOf('-') > 0) {
+ // Extract the region information if it is included
+ var languageParts = options.language.split('-');
+ var baseLanguage = languageParts[0];
+
+ options.language = [options.language, baseLanguage];
+ } else {
+ options.language = [options.language];
+ }
+ }
- // multi
- clearPlaceholder: function () {
- if (this.search.hasClass("select2-default")) {
- this.search.val("").removeClass("select2-default");
+ if ($.isArray(options.language)) {
+ var languages = new Translation();
+ options.language.push('en');
+
+ var languageNames = options.language;
+
+ for (var l = 0; l < languageNames.length; l++) {
+ var name = languageNames[l];
+ var language = {};
+
+ try {
+ // Try to load it with the original name
+ language = Translation.loadPath(name);
+ } catch (e) {
+ try {
+ // If we couldn't load it, check if it wasn't the full path
+ name = this.defaults.amdLanguageBase + name;
+ language = Translation.loadPath(name);
+ } catch (ex) {
+ // The translation could not be loaded at all. Sometimes this is
+ // because of a configuration problem, other times this can be
+ // because of how Select2 helps load all possible translation files.
+ if (options.debug && window.console && console.warn) {
+ console.warn(
+ 'Select2: The language file for "' + name + '" could not be ' +
+ 'automatically loaded. A fallback will be used instead.'
+ );
}
- },
- // multi
- opening: function () {
- this.clearPlaceholder(); // should be done before super so placeholder is not used to search
- this.resizeSearch();
+ continue;
+ }
+ }
- this.parent.opening.apply(this, arguments);
+ languages.extend(language);
+ }
- this.focusSearch();
+ options.translations = languages;
+ } else {
+ var baseTranslation = Translation.loadPath(
+ this.defaults.amdLanguageBase + 'en'
+ );
+ var customTranslation = new Translation(options.language);
- this.updateResults(true);
- this.search.focus();
- this.opts.element.trigger($.Event("select2-open"));
- },
+ customTranslation.extend(baseTranslation);
- // multi
- close: function () {
- if (!this.opened()) return;
- this.parent.close.apply(this, arguments);
- },
+ options.translations = customTranslation;
+ }
- // multi
- focus: function () {
- this.close();
- this.search.focus();
- },
+ return options;
+ };
- // multi
- isFocused: function () {
- return this.search.hasClass("select2-focused");
- },
+ Defaults.prototype.reset = function () {
+ function stripDiacritics (text) {
+ // Used 'uni range + named function' from http://jsperf.com/diacritics/18
+ function match(a) {
+ return DIACRITICS[a] || a;
+ }
- // multi
- updateSelection: function (data) {
- var ids = [], filtered = [], self = this;
+ return text.replace(/[^\u0000-\u007E]/g, match);
+ }
- // filter out duplicates
- $(data).each(function () {
- if (indexOf(self.id(this), ids) < 0) {
- ids.push(self.id(this));
- filtered.push(this);
- }
- });
- data = filtered;
-
- this.selection.find(".select2-search-choice").remove();
- $(data).each(function () {
- self.addSelectedChoice(this);
- });
- self.postprocessResults();
- },
+ function matcher (params, data) {
+ // Always return the object if there is nothing to compare
+ if ($.trim(params.term) === '') {
+ return data;
+ }
- // multi
- tokenize: function() {
- var input = this.search.val();
- input = this.opts.tokenizer.call(this, input, this.data(), this.bind(this.onSelect), this.opts);
- if (input != null && input != undefined) {
- this.search.val(input);
- if (input.length > 0) {
- this.open();
- }
- }
+ // Do a recursive check for options with children
+ if (data.children && data.children.length > 0) {
+ // Clone the data object if there are children
+ // This is required as we modify the object to remove any non-matches
+ var match = $.extend(true, {}, data);
- },
+ // Check each child of the option
+ for (var c = data.children.length - 1; c >= 0; c--) {
+ var child = data.children[c];
- // multi
- onSelect: function (data, options) {
+ var matches = matcher(params, child);
- if (!this.triggerSelect(data)) { return; }
+ // If there wasn't a match, remove the object in the array
+ if (matches == null) {
+ match.children.splice(c, 1);
+ }
+ }
- this.addSelectedChoice(data);
+ // If any children matched, return the new object
+ if (match.children.length > 0) {
+ return match;
+ }
- this.opts.element.trigger({ type: "selected", val: this.id(data), choice: data });
+ // If there were no matching children, check just the plain object
+ return matcher(params, match);
+ }
- if (this.select || !this.opts.closeOnSelect) this.postprocessResults(data, false, this.opts.closeOnSelect===true);
+ var original = stripDiacritics(data.text).toUpperCase();
+ var term = stripDiacritics(params.term).toUpperCase();
- if (this.opts.closeOnSelect) {
- this.close();
- this.search.width(10);
- } else {
- if (this.countSelectableResults()>0) {
- this.search.width(10);
- this.resizeSearch();
- if (this.getMaximumSelectionSize() > 0 && this.val().length >= this.getMaximumSelectionSize()) {
- // if we reached max selection size repaint the results so choices
- // are replaced with the max selection reached message
- this.updateResults(true);
- }
- this.positionDropdown();
- } else {
- // if nothing left to select close
- this.close();
- this.search.width(10);
- }
- }
+ // Check if the text contains the term
+ if (original.indexOf(term) > -1) {
+ return data;
+ }
- // since its not possible to select an element that has already been
- // added we do not need to check if this is a new element before firing change
- this.triggerChange({ added: data });
+ // If it doesn't contain the term, don't return anything
+ return null;
+ }
- if (!options || !options.noFocus)
- this.focusSearch();
- },
+ this.defaults = {
+ amdBase: './',
+ amdLanguageBase: './i18n/',
+ closeOnSelect: true,
+ debug: false,
+ dropdownAutoWidth: false,
+ escapeMarkup: Utils.escapeMarkup,
+ language: EnglishTranslation,
+ matcher: matcher,
+ minimumInputLength: 0,
+ maximumInputLength: 0,
+ maximumSelectionLength: 0,
+ minimumResultsForSearch: 0,
+ selectOnClose: false,
+ sorter: function (data) {
+ return data;
+ },
+ templateResult: function (result) {
+ return result.text;
+ },
+ templateSelection: function (selection) {
+ return selection.text;
+ },
+ theme: 'default',
+ width: 'resolve'
+ };
+ };
- // multi
- cancel: function () {
- this.close();
- this.focusSearch();
- },
+ Defaults.prototype.set = function (key, value) {
+ var camelKey = $.camelCase(key);
- addSelectedChoice: function (data) {
- var enableChoice = !data.locked,
- enabledItem = $(
- "" +
- "
" +
- " " +
- " "),
- disabledItem = $(
- "" +
- "
" +
- " ");
- var choice = enableChoice ? enabledItem : disabledItem,
- id = this.id(data),
- val = this.getVal(),
- formatted,
- cssClass;
-
- formatted=this.opts.formatSelection(data, choice.find("div"), this.opts.escapeMarkup);
- if (formatted != undefined) {
- choice.find("div").replaceWith(""+formatted+"
");
- }
- cssClass=this.opts.formatSelectionCssClass(data, choice.find("div"));
- if (cssClass != undefined) {
- choice.addClass(cssClass);
- }
+ var data = {};
+ data[camelKey] = value;
- if(enableChoice){
- choice.find(".select2-search-choice-close")
- .on("mousedown", killEvent)
- .on("click dblclick", this.bind(function (e) {
- if (!this.isInterfaceEnabled()) return;
-
- $(e.target).closest(".select2-search-choice").fadeOut('fast', this.bind(function(){
- this.unselect($(e.target));
- this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus");
- this.close();
- this.focusSearch();
- })).dequeue();
- killEvent(e);
- })).on("focus", this.bind(function () {
- if (!this.isInterfaceEnabled()) return;
- this.container.addClass("select2-container-active");
- this.dropdown.addClass("select2-drop-active");
- }));
- }
+ var convertedData = Utils._convertData(data);
- choice.data("select2-data", data);
- choice.insertBefore(this.searchContainer);
+ $.extend(this.defaults, convertedData);
+ };
- val.push(id);
- this.setVal(val);
- },
+ var defaults = new Defaults();
- // multi
- unselect: function (selected) {
- var val = this.getVal(),
- data,
- index;
+ return defaults;
+});
- selected = selected.closest(".select2-search-choice");
+S2.define('select2/options',[
+ 'require',
+ 'jquery',
+ './defaults',
+ './utils'
+], function (require, $, Defaults, Utils) {
+ function Options (options, $element) {
+ this.options = options;
- if (selected.length === 0) {
- throw "Invalid argument: " + selected + ". Must be .select2-search-choice";
- }
+ if ($element != null) {
+ this.fromElement($element);
+ }
- data = selected.data("select2-data");
+ this.options = Defaults.apply(this.options);
- if (!data) {
- // prevent a race condition when the 'x' is clicked really fast repeatedly the event can be queued
- // and invoked on an element already removed
- return;
- }
+ if ($element && $element.is('input')) {
+ var InputCompat = require(this.get('amdBase') + 'compat/inputData');
- while((index = indexOf(this.id(data), val)) >= 0) {
- val.splice(index, 1);
- this.setVal(val);
- if (this.select) this.postprocessResults();
- }
+ this.options.dataAdapter = Utils.Decorate(
+ this.options.dataAdapter,
+ InputCompat
+ );
+ }
+ }
- var evt = $.Event("select2-removing");
- evt.val = this.id(data);
- evt.choice = data;
- this.opts.element.trigger(evt);
+ Options.prototype.fromElement = function ($e) {
+ var excludedData = ['select2'];
- if (evt.isDefaultPrevented()) {
- return;
- }
+ if (this.options.multiple == null) {
+ this.options.multiple = $e.prop('multiple');
+ }
- this.opts.element.trigger({ type: "select2-removed", val: this.id(data), choice: data });
- this.triggerChange({ removed: data });
- },
+ if (this.options.disabled == null) {
+ this.options.disabled = $e.prop('disabled');
+ }
- // multi
- postprocessResults: function (data, initial, noHighlightUpdate) {
- var val = this.getVal(),
- choices = this.results.find(".select2-result"),
- compound = this.results.find(".select2-result-with-children"),
- self = this;
-
- choices.each2(function (i, choice) {
- var id = self.id(choice.data("select2-data"));
- if (indexOf(id, val) >= 0) {
- choice.addClass("select2-selected");
- // mark all children of the selected parent as selected
- choice.find(".select2-result-selectable").addClass("select2-selected");
- }
- });
+ if (this.options.language == null) {
+ if ($e.prop('lang')) {
+ this.options.language = $e.prop('lang').toLowerCase();
+ } else if ($e.closest('[lang]').prop('lang')) {
+ this.options.language = $e.closest('[lang]').prop('lang');
+ }
+ }
- compound.each2(function(i, choice) {
- // hide an optgroup if it doesnt have any selectable children
- if (!choice.is('.select2-result-selectable')
- && choice.find(".select2-result-selectable:not(.select2-selected)").length === 0) {
- choice.addClass("select2-selected");
- }
- });
+ if (this.options.dir == null) {
+ if ($e.prop('dir')) {
+ this.options.dir = $e.prop('dir');
+ } else if ($e.closest('[dir]').prop('dir')) {
+ this.options.dir = $e.closest('[dir]').prop('dir');
+ } else {
+ this.options.dir = 'ltr';
+ }
+ }
- if (this.highlight() == -1 && noHighlightUpdate !== false){
- self.highlight(0);
- }
+ $e.prop('disabled', this.options.disabled);
+ $e.prop('multiple', this.options.multiple);
- //If all results are chosen render formatNoMAtches
- if(!this.opts.createSearchChoice && !choices.filter('.select2-result:not(.select2-selected)').length > 0){
- if(!data || data && !data.more && this.results.find(".select2-no-results").length === 0) {
- if (checkFormatter(self.opts.formatNoMatches, "formatNoMatches")) {
- this.results.append("" + self.opts.formatNoMatches(self.search.val()) + " ");
- }
- }
- }
+ if ($e.data('select2Tags')) {
+ if (this.options.debug && window.console && console.warn) {
+ console.warn(
+ 'Select2: The `data-select2-tags` attribute has been changed to ' +
+ 'use the `data-data` and `data-tags="true"` attributes and will be ' +
+ 'removed in future versions of Select2.'
+ );
+ }
- },
+ $e.data('data', $e.data('select2Tags'));
+ $e.data('tags', true);
+ }
- // multi
- getMaxSearchWidth: function() {
- return this.selection.width() - getSideBorderPadding(this.search);
- },
+ if ($e.data('ajaxUrl')) {
+ if (this.options.debug && window.console && console.warn) {
+ console.warn(
+ 'Select2: The `data-ajax-url` attribute has been changed to ' +
+ '`data-ajax--url` and support for the old attribute will be removed' +
+ ' in future versions of Select2.'
+ );
+ }
+
+ $e.attr('ajax--url', $e.data('ajaxUrl'));
+ $e.data('ajax--url', $e.data('ajaxUrl'));
+ }
- // multi
- resizeSearch: function () {
- var minimumWidth, left, maxWidth, containerLeft, searchWidth,
- sideBorderPadding = getSideBorderPadding(this.search);
+ var dataset = {};
- minimumWidth = measureTextWidth(this.search) + 10;
+ // Prefer the element's `dataset` attribute if it exists
+ // jQuery 1.x does not correctly handle data attributes with multiple dashes
+ if ($.fn.jquery && $.fn.jquery.substr(0, 2) == '1.' && $e[0].dataset) {
+ dataset = $.extend(true, {}, $e[0].dataset, $e.data());
+ } else {
+ dataset = $e.data();
+ }
- left = this.search.offset().left;
+ var data = $.extend(true, {}, dataset);
- maxWidth = this.selection.width();
- containerLeft = this.selection.offset().left;
+ data = Utils._convertData(data);
- searchWidth = maxWidth - (left - containerLeft) - sideBorderPadding;
+ for (var key in data) {
+ if ($.inArray(key, excludedData) > -1) {
+ continue;
+ }
- if (searchWidth < minimumWidth) {
- searchWidth = maxWidth - sideBorderPadding;
- }
+ if ($.isPlainObject(this.options[key])) {
+ $.extend(this.options[key], data[key]);
+ } else {
+ this.options[key] = data[key];
+ }
+ }
- if (searchWidth < 40) {
- searchWidth = maxWidth - sideBorderPadding;
- }
+ return this;
+ };
+
+ Options.prototype.get = function (key) {
+ return this.options[key];
+ };
+
+ Options.prototype.set = function (key, val) {
+ this.options[key] = val;
+ };
+
+ return Options;
+});
+
+S2.define('select2/core',[
+ 'jquery',
+ './options',
+ './utils',
+ './keys'
+], function ($, Options, Utils, KEYS) {
+ var Select2 = function ($element, options) {
+ if ($element.data('select2') != null) {
+ $element.data('select2').destroy();
+ }
- if (searchWidth <= 0) {
- searchWidth = minimumWidth;
- }
+ this.$element = $element;
- this.search.width(Math.floor(searchWidth));
- },
+ this.id = this._generateId($element);
- // multi
- getVal: function () {
- var val;
- if (this.select) {
- val = this.select.val();
- return val === null ? [] : val;
- } else {
- val = this.opts.element.val();
- return splitVal(val, this.opts.separator);
- }
- },
+ options = options || {};
- // multi
- setVal: function (val) {
- var unique;
- if (this.select) {
- this.select.val(val);
- } else {
- unique = [];
- // filter out duplicates
- $(val).each(function () {
- if (indexOf(this, unique) < 0) unique.push(this);
- });
- this.opts.element.val(unique.length === 0 ? "" : unique.join(this.opts.separator));
- }
- },
+ this.options = new Options(options, $element);
- // multi
- buildChangeDetails: function (old, current) {
- var current = current.slice(0),
- old = old.slice(0);
-
- // remove intersection from each array
- for (var i = 0; i < current.length; i++) {
- for (var j = 0; j < old.length; j++) {
- if (equal(this.opts.id(current[i]), this.opts.id(old[j]))) {
- current.splice(i, 1);
- i--;
- old.splice(j, 1);
- j--;
- }
- }
- }
+ Select2.__super__.constructor.call(this);
- return {added: current, removed: old};
- },
+ // Set up the tabindex
+ var tabindex = $element.attr('tabindex') || 0;
+ $element.data('old-tabindex', tabindex);
+ $element.attr('tabindex', '-1');
- // multi
- val: function (val, triggerChange) {
- var oldData, self=this;
+ // Set up containers and adapters
- if (arguments.length === 0) {
- return this.getVal();
- }
+ var DataAdapter = this.options.get('dataAdapter');
+ this.dataAdapter = new DataAdapter($element, this.options);
- oldData=this.data();
- if (!oldData.length) oldData=[];
+ var $container = this.render();
- // val is an id. !val is true for [undefined,null,'',0] - 0 is legal
- if (!val && val !== 0) {
- this.opts.element.val("");
- this.updateSelection([]);
- this.clearSearch();
- if (triggerChange) {
- this.triggerChange({added: this.data(), removed: oldData});
- }
- return;
- }
+ this._placeContainer($container);
- // val is a list of ids
- this.setVal(val);
+ var SelectionAdapter = this.options.get('selectionAdapter');
+ this.selection = new SelectionAdapter($element, this.options);
+ this.$selection = this.selection.render();
- if (this.select) {
- this.opts.initSelection(this.select, this.bind(this.updateSelection));
- if (triggerChange) {
- this.triggerChange(this.buildChangeDetails(oldData, this.data()));
- }
- } else {
- if (this.opts.initSelection === undefined) {
- throw new Error("val() cannot be called if initSelection() is not defined");
- }
+ this.selection.position(this.$selection, $container);
- this.opts.initSelection(this.opts.element, function(data){
- var ids=$.map(data, self.id);
- self.setVal(ids);
- self.updateSelection(data);
- self.clearSearch();
- if (triggerChange) {
- self.triggerChange(self.buildChangeDetails(oldData, self.data()));
- }
- });
- }
- this.clearSearch();
- },
+ var DropdownAdapter = this.options.get('dropdownAdapter');
+ this.dropdown = new DropdownAdapter($element, this.options);
+ this.$dropdown = this.dropdown.render();
- // multi
- onSortStart: function() {
- if (this.select) {
- throw new Error("Sorting of elements is not supported when attached to . Attach to instead.");
- }
+ this.dropdown.position(this.$dropdown, $container);
- // collapse search field into 0 width so its container can be collapsed as well
- this.search.width(0);
- // hide the container
- this.searchContainer.hide();
- },
+ var ResultsAdapter = this.options.get('resultsAdapter');
+ this.results = new ResultsAdapter($element, this.options, this.dataAdapter);
+ this.$results = this.results.render();
- // multi
- onSortEnd:function() {
+ this.results.position(this.$results, this.$dropdown);
- var val=[], self=this;
+ // Bind events
- // show search and move it to the end of the list
- this.searchContainer.show();
- // make sure the search container is the last item in the list
- this.searchContainer.appendTo(this.searchContainer.parent());
- // since we collapsed the width in dragStarted, we resize it here
- this.resizeSearch();
+ var self = this;
- // update selection
- this.selection.find(".select2-search-choice").each(function() {
- val.push(self.opts.id($(this).data("select2-data")));
- });
- this.setVal(val);
- this.triggerChange();
- },
+ // Bind the container to all of the adapters
+ this._bindAdapters();
- // multi
- data: function(values, triggerChange) {
- var self=this, ids, old;
- if (arguments.length === 0) {
- return this.selection
- .find(".select2-search-choice")
- .map(function() { return $(this).data("select2-data"); })
- .get();
- } else {
- old = this.data();
- if (!values) { values = []; }
- ids = $.map(values, function(e) { return self.opts.id(e); });
- this.setVal(ids);
- this.updateSelection(values);
- this.clearSearch();
- if (triggerChange) {
- this.triggerChange(this.buildChangeDetails(old, this.data()));
- }
- }
+ // Register any DOM event handlers
+ this._registerDomEvents();
+
+ // Register any internal event handlers
+ this._registerDataEvents();
+ this._registerSelectionEvents();
+ this._registerDropdownEvents();
+ this._registerResultsEvents();
+ this._registerEvents();
+
+ // Set the initial state
+ this.dataAdapter.current(function (initialData) {
+ self.trigger('selection:update', {
+ data: initialData
+ });
+ });
+
+ // Hide the original select
+ $element.addClass('select2-hidden-accessible');
+ $element.attr('aria-hidden', 'true');
+
+ // Synchronize any monitored attributes
+ this._syncAttributes();
+
+ $element.data('select2', this);
+ };
+
+ Utils.Extend(Select2, Utils.Observable);
+
+ Select2.prototype._generateId = function ($element) {
+ var id = '';
+
+ if ($element.attr('id') != null) {
+ id = $element.attr('id');
+ } else if ($element.attr('name') != null) {
+ id = $element.attr('name') + '-' + Utils.generateChars(2);
+ } else {
+ id = Utils.generateChars(4);
+ }
+
+ id = 'select2-' + id;
+
+ return id;
+ };
+
+ Select2.prototype._placeContainer = function ($container) {
+ $container.insertAfter(this.$element);
+
+ var width = this._resolveWidth(this.$element, this.options.get('width'));
+
+ if (width != null) {
+ $container.css('width', width);
+ }
+ };
+
+ Select2.prototype._resolveWidth = function ($element, method) {
+ var WIDTH = /^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i;
+
+ if (method == 'resolve') {
+ var styleWidth = this._resolveWidth($element, 'style');
+
+ if (styleWidth != null) {
+ return styleWidth;
+ }
+
+ return this._resolveWidth($element, 'element');
+ }
+
+ if (method == 'element') {
+ var elementWidth = $element.outerWidth(false);
+
+ if (elementWidth <= 0) {
+ return 'auto';
+ }
+
+ return elementWidth + 'px';
+ }
+
+ if (method == 'style') {
+ var style = $element.attr('style');
+
+ if (typeof(style) !== 'string') {
+ return null;
+ }
+
+ var attrs = style.split(';');
+
+ for (var i = 0, l = attrs.length; i < l; i = i + 1) {
+ var attr = attrs[i].replace(/\s/g, '');
+ var matches = attr.match(WIDTH);
+
+ if (matches !== null && matches.length >= 1) {
+ return matches[1];
}
+ }
+
+ return null;
+ }
+
+ return method;
+ };
+
+ Select2.prototype._bindAdapters = function () {
+ this.dataAdapter.bind(this, this.$container);
+ this.selection.bind(this, this.$container);
+
+ this.dropdown.bind(this, this.$container);
+ this.results.bind(this, this.$container);
+ };
+
+ Select2.prototype._registerDomEvents = function () {
+ var self = this;
+
+ this.$element.on('change.select2', function () {
+ self.dataAdapter.current(function (data) {
+ self.trigger('selection:update', {
+ data: data
+ });
+ });
+ });
+
+ this._sync = Utils.bind(this._syncAttributes, this);
+
+ if (this.$element[0].attachEvent) {
+ this.$element[0].attachEvent('onpropertychange', this._sync);
+ }
+
+ var observer = window.MutationObserver ||
+ window.WebKitMutationObserver ||
+ window.MozMutationObserver
+ ;
+
+ if (observer != null) {
+ this._observer = new observer(function (mutations) {
+ $.each(mutations, self._sync);
+ });
+ this._observer.observe(this.$element[0], {
+ attributes: true,
+ subtree: false
+ });
+ } else if (this.$element[0].addEventListener) {
+ this.$element[0].addEventListener('DOMAttrModified', self._sync, false);
+ }
+ };
+
+ Select2.prototype._registerDataEvents = function () {
+ var self = this;
+
+ this.dataAdapter.on('*', function (name, params) {
+ self.trigger(name, params);
});
+ };
+
+ Select2.prototype._registerSelectionEvents = function () {
+ var self = this;
+ var nonRelayEvents = ['toggle'];
- $.fn.select2 = function () {
+ this.selection.on('toggle', function () {
+ self.toggleDropdown();
+ });
- var args = Array.prototype.slice.call(arguments, 0),
- opts,
- select2,
- method, value, multiple,
- allowedMethods = ["val", "destroy", "opened", "open", "close", "focus", "isFocused", "container", "dropdown", "onSortStart", "onSortEnd", "enable", "disable", "readonly", "positionDropdown", "data", "search"],
- valueMethods = ["opened", "isFocused", "container", "dropdown"],
- propertyMethods = ["val", "data"],
- methodsMap = { search: "externalSearch" };
+ this.selection.on('*', function (name, params) {
+ if ($.inArray(name, nonRelayEvents) !== -1) {
+ return;
+ }
- this.each(function () {
- if (args.length === 0 || typeof(args[0]) === "object") {
- opts = args.length === 0 ? {} : $.extend({}, args[0]);
- opts.element = $(this);
+ self.trigger(name, params);
+ });
+ };
- if (opts.element.get(0).tagName.toLowerCase() === "select") {
- multiple = opts.element.prop("multiple");
- } else {
- multiple = opts.multiple || false;
- if ("tags" in opts) {opts.multiple = multiple = true;}
- }
+ Select2.prototype._registerDropdownEvents = function () {
+ var self = this;
- select2 = multiple ? new MultiSelect2() : new SingleSelect2();
- select2.init(opts);
- } else if (typeof(args[0]) === "string") {
+ this.dropdown.on('*', function (name, params) {
+ self.trigger(name, params);
+ });
+ };
- if (indexOf(args[0], allowedMethods) < 0) {
- throw "Unknown method: " + args[0];
- }
+ Select2.prototype._registerResultsEvents = function () {
+ var self = this;
- value = undefined;
- select2 = $(this).data("select2");
- if (select2 === undefined) return;
+ this.results.on('*', function (name, params) {
+ self.trigger(name, params);
+ });
+ };
- method=args[0];
+ Select2.prototype._registerEvents = function () {
+ var self = this;
- if (method === "container") {
- value = select2.container;
- } else if (method === "dropdown") {
- value = select2.dropdown;
- } else {
- if (methodsMap[method]) method = methodsMap[method];
+ this.on('open', function () {
+ self.$container.addClass('select2-container--open');
+ });
- value = select2[method].apply(select2, args.slice(1));
- }
- if (indexOf(args[0], valueMethods) >= 0
- || (indexOf(args[0], propertyMethods) && args.length == 1)) {
- return false; // abort the iteration, ready to return first matched value
- }
- } else {
- throw "Invalid arguments to select2 plugin: " + args;
- }
+ this.on('close', function () {
+ self.$container.removeClass('select2-container--open');
+ });
+
+ this.on('enable', function () {
+ self.$container.removeClass('select2-container--disabled');
+ });
+
+ this.on('disable', function () {
+ self.$container.addClass('select2-container--disabled');
+ });
+
+ this.on('focus', function () {
+ self.$container.addClass('select2-container--focus');
+ });
+
+ this.on('blur', function () {
+ self.$container.removeClass('select2-container--focus');
+ });
+
+ this.on('query', function (params) {
+ if (!self.isOpen()) {
+ self.trigger('open');
+ }
+
+ this.dataAdapter.query(params, function (data) {
+ self.trigger('results:all', {
+ data: data,
+ query: params
});
- return (value === undefined) ? this : value;
- };
+ });
+ });
- // plugin defaults, accessible to users
- $.fn.select2.defaults = {
- width: "copy",
- loadMorePadding: 0,
- closeOnSelect: true,
- openOnEnter: true,
- containerCss: {},
- dropdownCss: {},
- containerCssClass: "",
- dropdownCssClass: "",
- formatResult: function(result, container, query, escapeMarkup) {
- var markup=[];
- markMatch(result.text, query.term, markup, escapeMarkup);
- return markup.join("");
- },
- formatSelection: function (data, container, escapeMarkup) {
- return data ? escapeMarkup(data.text) : undefined;
- },
- sortResults: function (results, container, query) {
- return results;
- },
- formatResultCssClass: function(data) {return undefined;},
- formatSelectionCssClass: function(data, container) {return undefined;},
- formatNoMatches: function () { return "No matches found"; },
- formatInputTooShort: function (input, min) { var n = min - input.length; return "Please enter " + n + " more character" + (n == 1? "" : "s"); },
- formatInputTooLong: function (input, max) { var n = input.length - max; return "Please delete " + n + " character" + (n == 1? "" : "s"); },
- formatSelectionTooBig: function (limit) { return "You can only select " + limit + " item" + (limit == 1 ? "" : "s"); },
- formatLoadMore: function (pageNumber) { return "Loading more results..."; },
- formatSearching: function () { return "Searching..."; },
- minimumResultsForSearch: 0,
- minimumInputLength: 0,
- maximumInputLength: null,
- maximumSelectionSize: 0,
- id: function (e) { return e.id; },
- matcher: function(term, text) {
- return stripDiacritics(''+text).toUpperCase().indexOf(stripDiacritics(''+term).toUpperCase()) >= 0;
- },
- separator: ",",
- tokenSeparators: [],
- tokenizer: defaultTokenizer,
- escapeMarkup: defaultEscapeMarkup,
- blurOnChange: false,
- selectOnBlur: false,
- adaptContainerCssClass: function(c) { return c; },
- adaptDropdownCssClass: function(c) { return null; },
- nextSearchTerm: function(selectedObject, currentSearchTerm) { return undefined; }
- };
+ this.on('query:append', function (params) {
+ this.dataAdapter.query(params, function (data) {
+ self.trigger('results:append', {
+ data: data,
+ query: params
+ });
+ });
+ });
+
+ this.on('keypress', function (evt) {
+ var key = evt.which;
+
+ if (self.isOpen()) {
+ if (key === KEYS.ENTER) {
+ self.trigger('results:select');
+
+ evt.preventDefault();
+ } else if ((key === KEYS.SPACE && evt.ctrlKey)) {
+ self.trigger('results:toggle');
+
+ evt.preventDefault();
+ } else if (key === KEYS.UP) {
+ self.trigger('results:previous');
+
+ evt.preventDefault();
+ } else if (key === KEYS.DOWN) {
+ self.trigger('results:next');
- $.fn.select2.ajaxDefaults = {
- transport: $.ajax,
- params: {
- type: "GET",
- cache: false,
- dataType: "json"
+ evt.preventDefault();
+ } else if (key === KEYS.ESC || key === KEYS.TAB) {
+ self.close();
+
+ evt.preventDefault();
}
- };
+ } else {
+ if (key === KEYS.ENTER || key === KEYS.SPACE ||
+ ((key === KEYS.DOWN || key === KEYS.UP) && evt.altKey)) {
+ self.open();
- // exports
- window.Select2 = {
- query: {
- ajax: ajax,
- local: local,
- tags: tags
- }, util: {
- debounce: debounce,
- markMatch: markMatch,
- escapeMarkup: defaultEscapeMarkup,
- stripDiacritics: stripDiacritics
- }, "class": {
- "abstract": AbstractSelect2,
- "single": SingleSelect2,
- "multi": MultiSelect2
+ evt.preventDefault();
}
+ }
+ });
+ };
+
+ Select2.prototype._syncAttributes = function () {
+ this.options.set('disabled', this.$element.prop('disabled'));
+
+ if (this.options.get('disabled')) {
+ if (this.isOpen()) {
+ this.close();
+ }
+
+ this.trigger('disable');
+ } else {
+ this.trigger('enable');
+ }
+ };
+
+ /**
+ * Override the trigger method to automatically trigger pre-events when
+ * there are events that can be prevented.
+ */
+ Select2.prototype.trigger = function (name, args) {
+ var actualTrigger = Select2.__super__.trigger;
+ var preTriggerMap = {
+ 'open': 'opening',
+ 'close': 'closing',
+ 'select': 'selecting',
+ 'unselect': 'unselecting'
};
-}(jQuery));
+ if (name in preTriggerMap) {
+ var preTriggerName = preTriggerMap[name];
+ var preTriggerArgs = {
+ prevented: false,
+ name: name,
+ args: args
+ };
+
+ actualTrigger.call(this, preTriggerName, preTriggerArgs);
+
+ if (preTriggerArgs.prevented) {
+ args.prevented = true;
+
+ return;
+ }
+ }
+
+ actualTrigger.call(this, name, args);
+ };
+
+ Select2.prototype.toggleDropdown = function () {
+ if (this.options.get('disabled')) {
+ return;
+ }
+
+ if (this.isOpen()) {
+ this.close();
+ } else {
+ this.open();
+ }
+ };
+
+ Select2.prototype.open = function () {
+ if (this.isOpen()) {
+ return;
+ }
+
+ this.trigger('query', {});
+
+ this.trigger('open');
+ };
+
+ Select2.prototype.close = function () {
+ if (!this.isOpen()) {
+ return;
+ }
+
+ this.trigger('close');
+ };
+
+ Select2.prototype.isOpen = function () {
+ return this.$container.hasClass('select2-container--open');
+ };
+
+ Select2.prototype.enable = function (args) {
+ if (this.options.get('debug') && window.console && console.warn) {
+ console.warn(
+ 'Select2: The `select2("enable")` method has been deprecated and will' +
+ ' be removed in later Select2 versions. Use $element.prop("disabled")' +
+ ' instead.'
+ );
+ }
+
+ if (args == null || args.length === 0) {
+ args = [true];
+ }
+
+ var disabled = !args[0];
+
+ this.$element.prop('disabled', disabled);
+ };
+
+ Select2.prototype.data = function () {
+ if (this.options.get('debug') &&
+ arguments.length > 0 && window.console && console.warn) {
+ console.warn(
+ 'Select2: Data can no longer be set using `select2("data")`. You ' +
+ 'should consider setting the value instead using `$element.val()`.'
+ );
+ }
+
+ var data = [];
+
+ this.dataAdapter.current(function (currentData) {
+ data = currentData;
+ });
+
+ return data;
+ };
+
+ Select2.prototype.val = function (args) {
+ if (this.options.get('debug') && window.console && console.warn) {
+ console.warn(
+ 'Select2: The `select2("val")` method has been deprecated and will be' +
+ ' removed in later Select2 versions. Use $element.val() instead.'
+ );
+ }
+
+ if (args == null || args.length === 0) {
+ return this.$element.val();
+ }
+
+ var newVal = args[0];
+
+ if ($.isArray(newVal)) {
+ newVal = $.map(newVal, function (obj) {
+ return obj.toString();
+ });
+ }
+
+ this.$element.val(newVal).trigger('change');
+ };
+
+ Select2.prototype.destroy = function () {
+ this.$container.remove();
+
+ if (this.$element[0].detachEvent) {
+ this.$element[0].detachEvent('onpropertychange', this._sync);
+ }
+
+ if (this._observer != null) {
+ this._observer.disconnect();
+ this._observer = null;
+ } else if (this.$element[0].removeEventListener) {
+ this.$element[0]
+ .removeEventListener('DOMAttrModified', this._sync, false);
+ }
+
+ this._sync = null;
+
+ this.$element.off('.select2');
+ this.$element.attr('tabindex', this.$element.data('old-tabindex'));
+
+ this.$element.removeClass('select2-hidden-accessible');
+ this.$element.attr('aria-hidden', 'false');
+ this.$element.removeData('select2');
+
+ this.dataAdapter.destroy();
+ this.selection.destroy();
+ this.dropdown.destroy();
+ this.results.destroy();
+
+ this.dataAdapter = null;
+ this.selection = null;
+ this.dropdown = null;
+ this.results = null;
+ };
+
+ Select2.prototype.render = function () {
+ var $container = $(
+ '' +
+ ' ' +
+ ' ' +
+ ' '
+ );
+
+ $container.attr('dir', this.options.get('dir'));
+
+ this.$container = $container;
+
+ this.$container.addClass('select2-container--' + this.options.get('theme'));
+
+ $container.data('element', this.$element);
+
+ return $container;
+ };
+
+ return Select2;
+});
+
+S2.define('jquery.select2',[
+ 'jquery',
+ 'require',
+
+ './select2/core',
+ './select2/defaults'
+], function ($, require, Select2, Defaults) {
+ // Force jQuery.mousewheel to be loaded if it hasn't already
+ require('jquery.mousewheel');
+
+ if ($.fn.select2 == null) {
+ // All methods that should return the element
+ var thisMethods = ['open', 'close', 'destroy'];
+
+ $.fn.select2 = function (options) {
+ options = options || {};
+
+ if (typeof options === 'object') {
+ this.each(function () {
+ var instanceOptions = $.extend({}, options, true);
+
+ var instance = new Select2($(this), instanceOptions);
+ });
+
+ return this;
+ } else if (typeof options === 'string') {
+ var instance = this.data('select2');
+
+ if (instance == null && window.console && console.error) {
+ console.error(
+ 'The select2(\'' + options + '\') method was called on an ' +
+ 'element that is not using Select2.'
+ );
+ }
+
+ var args = Array.prototype.slice.call(arguments, 1);
+
+ var ret = instance[options](args);
+
+ // Check if we should be returning `this`
+ if ($.inArray(options, thisMethods) > -1) {
+ return this;
+ }
+
+ return ret;
+ } else {
+ throw new Error('Invalid arguments for Select2: ' + options);
+ }
+ };
+ }
+
+ if ($.fn.select2.defaults == null) {
+ $.fn.select2.defaults = Defaults;
+ }
+
+ return Select2;
+});
+
+S2.define('jquery.mousewheel',[
+ 'jquery'
+], function ($) {
+ // Used to shim jQuery.mousewheel for non-full builds.
+ return $;
+});
+
+ // Return the AMD loader configuration so it can be used outside of this file
+ return {
+ define: S2.define,
+ require: S2.require
+ };
+}());
+
+ // Autoload the jQuery bindings
+ // We know that all of the modules exist above this, so we're safe
+ var select2 = S2.require('jquery.select2');
+
+ // Hold the AMD module references on the jQuery function that was just loaded
+ // This allows Select2 to use the internal loader outside of this file, such
+ // as in the language files.
+ jQuery.fn.select2.amd = S2;
+
+ // Return the Select2 instance for anyone who is importing it.
+ return select2;
+}));
diff --git a/src/inputs/select2/lib/select2.min.js b/src/inputs/select2/lib/select2.min.js
deleted file mode 100644
index 49bcfc0b..00000000
--- a/src/inputs/select2/lib/select2.min.js
+++ /dev/null
@@ -1,22 +0,0 @@
-/*
-Copyright 2012 Igor Vaynberg
-
-Version: 3.4.4 Timestamp: Thu Oct 24 13:23:11 PDT 2013
-
-This software is licensed under the Apache License, Version 2.0 (the "Apache License") or the GNU
-General Public License version 2 (the "GPL License"). You may choose either license to govern your
-use of this software only upon the condition that you accept all of the terms of either the Apache
-License or the GPL License.
-
-You may obtain a copy of the Apache License and the GPL License at:
-
-http://www.apache.org/licenses/LICENSE-2.0
-http://www.gnu.org/licenses/gpl-2.0.html
-
-Unless required by applicable law or agreed to in writing, software distributed under the Apache License
-or the GPL Licesnse is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
-either express or implied. See the Apache License and the GPL License for the specific language governing
-permissions and limitations under the Apache License and the GPL License.
-*/
-!function(a){"undefined"==typeof a.fn.each2&&a.extend(a.fn,{each2:function(b){for(var c=a([0]),d=-1,e=this.length;++dc;c++)e=a.charAt(c),b+=m[e]||e;return b}function o(a,b){for(var c=0,d=b.length;d>c;c+=1)if(q(a,b[c]))return c;return-1}function p(){var b=a(l);b.appendTo("body");var c={width:b.width()-b[0].clientWidth,height:b.height()-b[0].clientHeight};return b.remove(),c}function q(a,c){return a===c?!0:a===b||c===b?!1:null===a||null===c?!1:a.constructor===String?a+""==c+"":c.constructor===String?c+""==a+"":!1}function r(b,c){var d,e,f;if(null===b||b.length<1)return[];for(d=b.split(c),e=0,f=d.length;f>e;e+=1)d[e]=a.trim(d[e]);return d}function s(a){return a.outerWidth(!1)-a.width()}function t(c){var d="keyup-change-value";c.on("keydown",function(){a.data(c,d)===b&&a.data(c,d,c.val())}),c.on("keyup",function(){var e=a.data(c,d);e!==b&&c.val()!==e&&(a.removeData(c,d),c.trigger("keyup-change"))})}function u(c){c.on("mousemove",function(c){var d=i;(d===b||d.x!==c.pageX||d.y!==c.pageY)&&a(c.target).trigger("mousemove-filtered",c)})}function v(a,c,d){d=d||b;var e;return function(){var b=arguments;window.clearTimeout(e),e=window.setTimeout(function(){c.apply(d,b)},a)}}function w(a){var c,b=!1;return function(){return b===!1&&(c=a(),b=!0),c}}function x(a,b){var c=v(a,function(a){b.trigger("scroll-debounced",a)});b.on("scroll",function(a){o(a.target,b.get())>=0&&c(a)})}function y(a){a[0]!==document.activeElement&&window.setTimeout(function(){var d,b=a[0],c=a.val().length;a.focus(),a.is(":visible")&&b===document.activeElement&&(b.setSelectionRange?b.setSelectionRange(c,c):b.createTextRange&&(d=b.createTextRange(),d.collapse(!1),d.select()))},0)}function z(b){b=a(b)[0];var c=0,d=0;if("selectionStart"in b)c=b.selectionStart,d=b.selectionEnd-c;else if("selection"in document){b.focus();var e=document.selection.createRange();d=document.selection.createRange().text.length,e.moveStart("character",-b.value.length),c=e.text.length-d}return{offset:c,length:d}}function A(a){a.preventDefault(),a.stopPropagation()}function B(a){a.preventDefault(),a.stopImmediatePropagation()}function C(b){if(!h){var c=b[0].currentStyle||window.getComputedStyle(b[0],null);h=a(document.createElement("div")).css({position:"absolute",left:"-10000px",top:"-10000px",display:"none",fontSize:c.fontSize,fontFamily:c.fontFamily,fontStyle:c.fontStyle,fontWeight:c.fontWeight,letterSpacing:c.letterSpacing,textTransform:c.textTransform,whiteSpace:"nowrap"}),h.attr("class","select2-sizer"),a("body").append(h)}return h.text(b.val()),h.width()}function D(b,c,d){var e,g,f=[];e=b.attr("class"),e&&(e=""+e,a(e.split(" ")).each2(function(){0===this.indexOf("select2-")&&f.push(this)})),e=c.attr("class"),e&&(e=""+e,a(e.split(" ")).each2(function(){0!==this.indexOf("select2-")&&(g=d(this),g&&f.push(g))})),b.attr("class",f.join(" "))}function E(a,b,c,d){var e=n(a.toUpperCase()).indexOf(n(b.toUpperCase())),f=b.length;return 0>e?(c.push(d(a)),void 0):(c.push(d(a.substring(0,e))),c.push(""),c.push(d(a.substring(e,e+f))),c.push(" "),c.push(d(a.substring(e+f,a.length))),void 0)}function F(a){var b={"\\":"\","&":"&","<":"<",">":">",'"':""","'":"'","/":"/"};return String(a).replace(/[&<>"'\/\\]/g,function(a){return b[a]})}function G(c){var d,e=null,f=c.quietMillis||100,g=c.url,h=this;return function(i){window.clearTimeout(d),d=window.setTimeout(function(){var d=c.data,f=g,j=c.transport||a.fn.select2.ajaxDefaults.transport,k={type:c.type||"GET",cache:c.cache||!1,jsonpCallback:c.jsonpCallback||b,dataType:c.dataType||"json"},l=a.extend({},a.fn.select2.ajaxDefaults.params,k);d=d?d.call(h,i.term,i.page,i.context):null,f="function"==typeof f?f.call(h,i.term,i.page,i.context):f,e&&e.abort(),c.params&&(a.isFunction(c.params)?a.extend(l,c.params.call(h)):a.extend(l,c.params)),a.extend(l,{url:f,dataType:c.dataType,data:d,success:function(a){var b=c.results(a,i.page);i.callback(b)}}),e=j.call(h,l)},f)}}function H(b){var d,e,c=b,f=function(a){return""+a.text};a.isArray(c)&&(e=c,c={results:e}),a.isFunction(c)===!1&&(e=c,c=function(){return e});var g=c();return g.text&&(f=g.text,a.isFunction(f)||(d=g.text,f=function(a){return a[d]})),function(b){var g,d=b.term,e={results:[]};return""===d?(b.callback(c()),void 0):(g=function(c,e){var h,i;if(c=c[0],c.children){h={};for(i in c)c.hasOwnProperty(i)&&(h[i]=c[i]);h.children=[],a(c.children).each2(function(a,b){g(b,h.children)}),(h.children.length||b.matcher(d,f(h),c))&&e.push(h)}else b.matcher(d,f(c),c)&&e.push(c)},a(c().results).each2(function(a,b){g(b,e.results)}),b.callback(e),void 0)}}function I(c){var d=a.isFunction(c);return function(e){var f=e.term,g={results:[]};a(d?c():c).each(function(){var a=this.text!==b,c=a?this.text:this;(""===f||e.matcher(f,c))&&g.results.push(a?this:{id:this,text:this})}),e.callback(g)}}function J(b,c){if(a.isFunction(b))return!0;if(!b)return!1;throw new Error(c+" must be a function or a falsy value")}function K(b){return a.isFunction(b)?b():b}function L(b){var c=0;return a.each(b,function(a,b){b.children?c+=L(b.children):c++}),c}function M(a,c,d,e){var h,i,j,k,l,f=a,g=!1;if(!e.createSearchChoice||!e.tokenSeparators||e.tokenSeparators.length<1)return b;for(;;){for(i=-1,j=0,k=e.tokenSeparators.length;k>j&&(l=e.tokenSeparators[j],i=a.indexOf(l),!(i>=0));j++);if(0>i)break;if(h=a.substring(0,i),a=a.substring(i+l.length),h.length>0&&(h=e.createSearchChoice.call(this,h,c),h!==b&&null!==h&&e.id(h)!==b&&null!==e.id(h))){for(g=!1,j=0,k=c.length;k>j;j++)if(q(e.id(h),e.id(c[j]))){g=!0;break}g||d(h)}}return f!==a?a:void 0}function N(b,c){var d=function(){};return d.prototype=new b,d.prototype.constructor=d,d.prototype.parent=b.prototype,d.prototype=a.extend(d.prototype,c),d}if(window.Select2===b){var c,d,e,f,g,h,j,k,i={x:0,y:0},c={TAB:9,ENTER:13,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,SHIFT:16,CTRL:17,ALT:18,PAGE_UP:33,PAGE_DOWN:34,HOME:36,END:35,BACKSPACE:8,DELETE:46,isArrow:function(a){switch(a=a.which?a.which:a){case c.LEFT:case c.RIGHT:case c.UP:case c.DOWN:return!0}return!1},isControl:function(a){var b=a.which;switch(b){case c.SHIFT:case c.CTRL:case c.ALT:return!0}return a.metaKey?!0:!1},isFunctionKey:function(a){return a=a.which?a.which:a,a>=112&&123>=a}},l="
",m={"\u24b6":"A","\uff21":"A","\xc0":"A","\xc1":"A","\xc2":"A","\u1ea6":"A","\u1ea4":"A","\u1eaa":"A","\u1ea8":"A","\xc3":"A","\u0100":"A","\u0102":"A","\u1eb0":"A","\u1eae":"A","\u1eb4":"A","\u1eb2":"A","\u0226":"A","\u01e0":"A","\xc4":"A","\u01de":"A","\u1ea2":"A","\xc5":"A","\u01fa":"A","\u01cd":"A","\u0200":"A","\u0202":"A","\u1ea0":"A","\u1eac":"A","\u1eb6":"A","\u1e00":"A","\u0104":"A","\u023a":"A","\u2c6f":"A","\ua732":"AA","\xc6":"AE","\u01fc":"AE","\u01e2":"AE","\ua734":"AO","\ua736":"AU","\ua738":"AV","\ua73a":"AV","\ua73c":"AY","\u24b7":"B","\uff22":"B","\u1e02":"B","\u1e04":"B","\u1e06":"B","\u0243":"B","\u0182":"B","\u0181":"B","\u24b8":"C","\uff23":"C","\u0106":"C","\u0108":"C","\u010a":"C","\u010c":"C","\xc7":"C","\u1e08":"C","\u0187":"C","\u023b":"C","\ua73e":"C","\u24b9":"D","\uff24":"D","\u1e0a":"D","\u010e":"D","\u1e0c":"D","\u1e10":"D","\u1e12":"D","\u1e0e":"D","\u0110":"D","\u018b":"D","\u018a":"D","\u0189":"D","\ua779":"D","\u01f1":"DZ","\u01c4":"DZ","\u01f2":"Dz","\u01c5":"Dz","\u24ba":"E","\uff25":"E","\xc8":"E","\xc9":"E","\xca":"E","\u1ec0":"E","\u1ebe":"E","\u1ec4":"E","\u1ec2":"E","\u1ebc":"E","\u0112":"E","\u1e14":"E","\u1e16":"E","\u0114":"E","\u0116":"E","\xcb":"E","\u1eba":"E","\u011a":"E","\u0204":"E","\u0206":"E","\u1eb8":"E","\u1ec6":"E","\u0228":"E","\u1e1c":"E","\u0118":"E","\u1e18":"E","\u1e1a":"E","\u0190":"E","\u018e":"E","\u24bb":"F","\uff26":"F","\u1e1e":"F","\u0191":"F","\ua77b":"F","\u24bc":"G","\uff27":"G","\u01f4":"G","\u011c":"G","\u1e20":"G","\u011e":"G","\u0120":"G","\u01e6":"G","\u0122":"G","\u01e4":"G","\u0193":"G","\ua7a0":"G","\ua77d":"G","\ua77e":"G","\u24bd":"H","\uff28":"H","\u0124":"H","\u1e22":"H","\u1e26":"H","\u021e":"H","\u1e24":"H","\u1e28":"H","\u1e2a":"H","\u0126":"H","\u2c67":"H","\u2c75":"H","\ua78d":"H","\u24be":"I","\uff29":"I","\xcc":"I","\xcd":"I","\xce":"I","\u0128":"I","\u012a":"I","\u012c":"I","\u0130":"I","\xcf":"I","\u1e2e":"I","\u1ec8":"I","\u01cf":"I","\u0208":"I","\u020a":"I","\u1eca":"I","\u012e":"I","\u1e2c":"I","\u0197":"I","\u24bf":"J","\uff2a":"J","\u0134":"J","\u0248":"J","\u24c0":"K","\uff2b":"K","\u1e30":"K","\u01e8":"K","\u1e32":"K","\u0136":"K","\u1e34":"K","\u0198":"K","\u2c69":"K","\ua740":"K","\ua742":"K","\ua744":"K","\ua7a2":"K","\u24c1":"L","\uff2c":"L","\u013f":"L","\u0139":"L","\u013d":"L","\u1e36":"L","\u1e38":"L","\u013b":"L","\u1e3c":"L","\u1e3a":"L","\u0141":"L","\u023d":"L","\u2c62":"L","\u2c60":"L","\ua748":"L","\ua746":"L","\ua780":"L","\u01c7":"LJ","\u01c8":"Lj","\u24c2":"M","\uff2d":"M","\u1e3e":"M","\u1e40":"M","\u1e42":"M","\u2c6e":"M","\u019c":"M","\u24c3":"N","\uff2e":"N","\u01f8":"N","\u0143":"N","\xd1":"N","\u1e44":"N","\u0147":"N","\u1e46":"N","\u0145":"N","\u1e4a":"N","\u1e48":"N","\u0220":"N","\u019d":"N","\ua790":"N","\ua7a4":"N","\u01ca":"NJ","\u01cb":"Nj","\u24c4":"O","\uff2f":"O","\xd2":"O","\xd3":"O","\xd4":"O","\u1ed2":"O","\u1ed0":"O","\u1ed6":"O","\u1ed4":"O","\xd5":"O","\u1e4c":"O","\u022c":"O","\u1e4e":"O","\u014c":"O","\u1e50":"O","\u1e52":"O","\u014e":"O","\u022e":"O","\u0230":"O","\xd6":"O","\u022a":"O","\u1ece":"O","\u0150":"O","\u01d1":"O","\u020c":"O","\u020e":"O","\u01a0":"O","\u1edc":"O","\u1eda":"O","\u1ee0":"O","\u1ede":"O","\u1ee2":"O","\u1ecc":"O","\u1ed8":"O","\u01ea":"O","\u01ec":"O","\xd8":"O","\u01fe":"O","\u0186":"O","\u019f":"O","\ua74a":"O","\ua74c":"O","\u01a2":"OI","\ua74e":"OO","\u0222":"OU","\u24c5":"P","\uff30":"P","\u1e54":"P","\u1e56":"P","\u01a4":"P","\u2c63":"P","\ua750":"P","\ua752":"P","\ua754":"P","\u24c6":"Q","\uff31":"Q","\ua756":"Q","\ua758":"Q","\u024a":"Q","\u24c7":"R","\uff32":"R","\u0154":"R","\u1e58":"R","\u0158":"R","\u0210":"R","\u0212":"R","\u1e5a":"R","\u1e5c":"R","\u0156":"R","\u1e5e":"R","\u024c":"R","\u2c64":"R","\ua75a":"R","\ua7a6":"R","\ua782":"R","\u24c8":"S","\uff33":"S","\u1e9e":"S","\u015a":"S","\u1e64":"S","\u015c":"S","\u1e60":"S","\u0160":"S","\u1e66":"S","\u1e62":"S","\u1e68":"S","\u0218":"S","\u015e":"S","\u2c7e":"S","\ua7a8":"S","\ua784":"S","\u24c9":"T","\uff34":"T","\u1e6a":"T","\u0164":"T","\u1e6c":"T","\u021a":"T","\u0162":"T","\u1e70":"T","\u1e6e":"T","\u0166":"T","\u01ac":"T","\u01ae":"T","\u023e":"T","\ua786":"T","\ua728":"TZ","\u24ca":"U","\uff35":"U","\xd9":"U","\xda":"U","\xdb":"U","\u0168":"U","\u1e78":"U","\u016a":"U","\u1e7a":"U","\u016c":"U","\xdc":"U","\u01db":"U","\u01d7":"U","\u01d5":"U","\u01d9":"U","\u1ee6":"U","\u016e":"U","\u0170":"U","\u01d3":"U","\u0214":"U","\u0216":"U","\u01af":"U","\u1eea":"U","\u1ee8":"U","\u1eee":"U","\u1eec":"U","\u1ef0":"U","\u1ee4":"U","\u1e72":"U","\u0172":"U","\u1e76":"U","\u1e74":"U","\u0244":"U","\u24cb":"V","\uff36":"V","\u1e7c":"V","\u1e7e":"V","\u01b2":"V","\ua75e":"V","\u0245":"V","\ua760":"VY","\u24cc":"W","\uff37":"W","\u1e80":"W","\u1e82":"W","\u0174":"W","\u1e86":"W","\u1e84":"W","\u1e88":"W","\u2c72":"W","\u24cd":"X","\uff38":"X","\u1e8a":"X","\u1e8c":"X","\u24ce":"Y","\uff39":"Y","\u1ef2":"Y","\xdd":"Y","\u0176":"Y","\u1ef8":"Y","\u0232":"Y","\u1e8e":"Y","\u0178":"Y","\u1ef6":"Y","\u1ef4":"Y","\u01b3":"Y","\u024e":"Y","\u1efe":"Y","\u24cf":"Z","\uff3a":"Z","\u0179":"Z","\u1e90":"Z","\u017b":"Z","\u017d":"Z","\u1e92":"Z","\u1e94":"Z","\u01b5":"Z","\u0224":"Z","\u2c7f":"Z","\u2c6b":"Z","\ua762":"Z","\u24d0":"a","\uff41":"a","\u1e9a":"a","\xe0":"a","\xe1":"a","\xe2":"a","\u1ea7":"a","\u1ea5":"a","\u1eab":"a","\u1ea9":"a","\xe3":"a","\u0101":"a","\u0103":"a","\u1eb1":"a","\u1eaf":"a","\u1eb5":"a","\u1eb3":"a","\u0227":"a","\u01e1":"a","\xe4":"a","\u01df":"a","\u1ea3":"a","\xe5":"a","\u01fb":"a","\u01ce":"a","\u0201":"a","\u0203":"a","\u1ea1":"a","\u1ead":"a","\u1eb7":"a","\u1e01":"a","\u0105":"a","\u2c65":"a","\u0250":"a","\ua733":"aa","\xe6":"ae","\u01fd":"ae","\u01e3":"ae","\ua735":"ao","\ua737":"au","\ua739":"av","\ua73b":"av","\ua73d":"ay","\u24d1":"b","\uff42":"b","\u1e03":"b","\u1e05":"b","\u1e07":"b","\u0180":"b","\u0183":"b","\u0253":"b","\u24d2":"c","\uff43":"c","\u0107":"c","\u0109":"c","\u010b":"c","\u010d":"c","\xe7":"c","\u1e09":"c","\u0188":"c","\u023c":"c","\ua73f":"c","\u2184":"c","\u24d3":"d","\uff44":"d","\u1e0b":"d","\u010f":"d","\u1e0d":"d","\u1e11":"d","\u1e13":"d","\u1e0f":"d","\u0111":"d","\u018c":"d","\u0256":"d","\u0257":"d","\ua77a":"d","\u01f3":"dz","\u01c6":"dz","\u24d4":"e","\uff45":"e","\xe8":"e","\xe9":"e","\xea":"e","\u1ec1":"e","\u1ebf":"e","\u1ec5":"e","\u1ec3":"e","\u1ebd":"e","\u0113":"e","\u1e15":"e","\u1e17":"e","\u0115":"e","\u0117":"e","\xeb":"e","\u1ebb":"e","\u011b":"e","\u0205":"e","\u0207":"e","\u1eb9":"e","\u1ec7":"e","\u0229":"e","\u1e1d":"e","\u0119":"e","\u1e19":"e","\u1e1b":"e","\u0247":"e","\u025b":"e","\u01dd":"e","\u24d5":"f","\uff46":"f","\u1e1f":"f","\u0192":"f","\ua77c":"f","\u24d6":"g","\uff47":"g","\u01f5":"g","\u011d":"g","\u1e21":"g","\u011f":"g","\u0121":"g","\u01e7":"g","\u0123":"g","\u01e5":"g","\u0260":"g","\ua7a1":"g","\u1d79":"g","\ua77f":"g","\u24d7":"h","\uff48":"h","\u0125":"h","\u1e23":"h","\u1e27":"h","\u021f":"h","\u1e25":"h","\u1e29":"h","\u1e2b":"h","\u1e96":"h","\u0127":"h","\u2c68":"h","\u2c76":"h","\u0265":"h","\u0195":"hv","\u24d8":"i","\uff49":"i","\xec":"i","\xed":"i","\xee":"i","\u0129":"i","\u012b":"i","\u012d":"i","\xef":"i","\u1e2f":"i","\u1ec9":"i","\u01d0":"i","\u0209":"i","\u020b":"i","\u1ecb":"i","\u012f":"i","\u1e2d":"i","\u0268":"i","\u0131":"i","\u24d9":"j","\uff4a":"j","\u0135":"j","\u01f0":"j","\u0249":"j","\u24da":"k","\uff4b":"k","\u1e31":"k","\u01e9":"k","\u1e33":"k","\u0137":"k","\u1e35":"k","\u0199":"k","\u2c6a":"k","\ua741":"k","\ua743":"k","\ua745":"k","\ua7a3":"k","\u24db":"l","\uff4c":"l","\u0140":"l","\u013a":"l","\u013e":"l","\u1e37":"l","\u1e39":"l","\u013c":"l","\u1e3d":"l","\u1e3b":"l","\u017f":"l","\u0142":"l","\u019a":"l","\u026b":"l","\u2c61":"l","\ua749":"l","\ua781":"l","\ua747":"l","\u01c9":"lj","\u24dc":"m","\uff4d":"m","\u1e3f":"m","\u1e41":"m","\u1e43":"m","\u0271":"m","\u026f":"m","\u24dd":"n","\uff4e":"n","\u01f9":"n","\u0144":"n","\xf1":"n","\u1e45":"n","\u0148":"n","\u1e47":"n","\u0146":"n","\u1e4b":"n","\u1e49":"n","\u019e":"n","\u0272":"n","\u0149":"n","\ua791":"n","\ua7a5":"n","\u01cc":"nj","\u24de":"o","\uff4f":"o","\xf2":"o","\xf3":"o","\xf4":"o","\u1ed3":"o","\u1ed1":"o","\u1ed7":"o","\u1ed5":"o","\xf5":"o","\u1e4d":"o","\u022d":"o","\u1e4f":"o","\u014d":"o","\u1e51":"o","\u1e53":"o","\u014f":"o","\u022f":"o","\u0231":"o","\xf6":"o","\u022b":"o","\u1ecf":"o","\u0151":"o","\u01d2":"o","\u020d":"o","\u020f":"o","\u01a1":"o","\u1edd":"o","\u1edb":"o","\u1ee1":"o","\u1edf":"o","\u1ee3":"o","\u1ecd":"o","\u1ed9":"o","\u01eb":"o","\u01ed":"o","\xf8":"o","\u01ff":"o","\u0254":"o","\ua74b":"o","\ua74d":"o","\u0275":"o","\u01a3":"oi","\u0223":"ou","\ua74f":"oo","\u24df":"p","\uff50":"p","\u1e55":"p","\u1e57":"p","\u01a5":"p","\u1d7d":"p","\ua751":"p","\ua753":"p","\ua755":"p","\u24e0":"q","\uff51":"q","\u024b":"q","\ua757":"q","\ua759":"q","\u24e1":"r","\uff52":"r","\u0155":"r","\u1e59":"r","\u0159":"r","\u0211":"r","\u0213":"r","\u1e5b":"r","\u1e5d":"r","\u0157":"r","\u1e5f":"r","\u024d":"r","\u027d":"r","\ua75b":"r","\ua7a7":"r","\ua783":"r","\u24e2":"s","\uff53":"s","\xdf":"s","\u015b":"s","\u1e65":"s","\u015d":"s","\u1e61":"s","\u0161":"s","\u1e67":"s","\u1e63":"s","\u1e69":"s","\u0219":"s","\u015f":"s","\u023f":"s","\ua7a9":"s","\ua785":"s","\u1e9b":"s","\u24e3":"t","\uff54":"t","\u1e6b":"t","\u1e97":"t","\u0165":"t","\u1e6d":"t","\u021b":"t","\u0163":"t","\u1e71":"t","\u1e6f":"t","\u0167":"t","\u01ad":"t","\u0288":"t","\u2c66":"t","\ua787":"t","\ua729":"tz","\u24e4":"u","\uff55":"u","\xf9":"u","\xfa":"u","\xfb":"u","\u0169":"u","\u1e79":"u","\u016b":"u","\u1e7b":"u","\u016d":"u","\xfc":"u","\u01dc":"u","\u01d8":"u","\u01d6":"u","\u01da":"u","\u1ee7":"u","\u016f":"u","\u0171":"u","\u01d4":"u","\u0215":"u","\u0217":"u","\u01b0":"u","\u1eeb":"u","\u1ee9":"u","\u1eef":"u","\u1eed":"u","\u1ef1":"u","\u1ee5":"u","\u1e73":"u","\u0173":"u","\u1e77":"u","\u1e75":"u","\u0289":"u","\u24e5":"v","\uff56":"v","\u1e7d":"v","\u1e7f":"v","\u028b":"v","\ua75f":"v","\u028c":"v","\ua761":"vy","\u24e6":"w","\uff57":"w","\u1e81":"w","\u1e83":"w","\u0175":"w","\u1e87":"w","\u1e85":"w","\u1e98":"w","\u1e89":"w","\u2c73":"w","\u24e7":"x","\uff58":"x","\u1e8b":"x","\u1e8d":"x","\u24e8":"y","\uff59":"y","\u1ef3":"y","\xfd":"y","\u0177":"y","\u1ef9":"y","\u0233":"y","\u1e8f":"y","\xff":"y","\u1ef7":"y","\u1e99":"y","\u1ef5":"y","\u01b4":"y","\u024f":"y","\u1eff":"y","\u24e9":"z","\uff5a":"z","\u017a":"z","\u1e91":"z","\u017c":"z","\u017e":"z","\u1e93":"z","\u1e95":"z","\u01b6":"z","\u0225":"z","\u0240":"z","\u2c6c":"z","\ua763":"z"};j=a(document),g=function(){var a=1;return function(){return a++}}(),j.on("mousemove",function(a){i.x=a.pageX,i.y=a.pageY}),d=N(Object,{bind:function(a){var b=this;return function(){a.apply(b,arguments)}},init:function(c){var d,e,f=".select2-results";this.opts=c=this.prepareOpts(c),this.id=c.id,c.element.data("select2")!==b&&null!==c.element.data("select2")&&c.element.data("select2").destroy(),this.container=this.createContainer(),this.containerId="s2id_"+(c.element.attr("id")||"autogen"+g()),this.containerSelector="#"+this.containerId.replace(/([;&,\.\+\*\~':"\!\^#$%@\[\]\(\)=>\|])/g,"\\$1"),this.container.attr("id",this.containerId),this.body=w(function(){return c.element.closest("body")}),D(this.container,this.opts.element,this.opts.adaptContainerCssClass),this.container.attr("style",c.element.attr("style")),this.container.css(K(c.containerCss)),this.container.addClass(K(c.containerCssClass)),this.elementTabIndex=this.opts.element.attr("tabindex"),this.opts.element.data("select2",this).attr("tabindex","-1").before(this.container).on("click.select2",A),this.container.data("select2",this),this.dropdown=this.container.find(".select2-drop"),D(this.dropdown,this.opts.element,this.opts.adaptDropdownCssClass),this.dropdown.addClass(K(c.dropdownCssClass)),this.dropdown.data("select2",this),this.dropdown.on("click",A),this.results=d=this.container.find(f),this.search=e=this.container.find("input.select2-input"),this.queryCount=0,this.resultsPage=0,this.context=null,this.initContainer(),this.container.on("click",A),u(this.results),this.dropdown.on("mousemove-filtered touchstart touchmove touchend",f,this.bind(this.highlightUnderEvent)),x(80,this.results),this.dropdown.on("scroll-debounced",f,this.bind(this.loadMoreIfNeeded)),a(this.container).on("change",".select2-input",function(a){a.stopPropagation()}),a(this.dropdown).on("change",".select2-input",function(a){a.stopPropagation()}),a.fn.mousewheel&&d.mousewheel(function(a,b,c,e){var f=d.scrollTop();e>0&&0>=f-e?(d.scrollTop(0),A(a)):0>e&&d.get(0).scrollHeight-d.scrollTop()+e<=d.height()&&(d.scrollTop(d.get(0).scrollHeight-d.height()),A(a))}),t(e),e.on("keyup-change input paste",this.bind(this.updateResults)),e.on("focus",function(){e.addClass("select2-focused")}),e.on("blur",function(){e.removeClass("select2-focused")}),this.dropdown.on("mouseup",f,this.bind(function(b){a(b.target).closest(".select2-result-selectable").length>0&&(this.highlightUnderEvent(b),this.selectHighlighted(b))})),this.dropdown.on("click mouseup mousedown",function(a){a.stopPropagation()}),a.isFunction(this.opts.initSelection)&&(this.initSelection(),this.monitorSource()),null!==c.maximumInputLength&&this.search.attr("maxlength",c.maximumInputLength);var h=c.element.prop("disabled");h===b&&(h=!1),this.enable(!h);var i=c.element.prop("readonly");i===b&&(i=!1),this.readonly(i),k=k||p(),this.autofocus=c.element.prop("autofocus"),c.element.prop("autofocus",!1),this.autofocus&&this.focus(),this.nextSearchTerm=b},destroy:function(){var a=this.opts.element,c=a.data("select2");this.close(),this.propertyObserver&&(delete this.propertyObserver,this.propertyObserver=null),c!==b&&(c.container.remove(),c.dropdown.remove(),a.removeClass("select2-offscreen").removeData("select2").off(".select2").prop("autofocus",this.autofocus||!1),this.elementTabIndex?a.attr({tabindex:this.elementTabIndex}):a.removeAttr("tabindex"),a.show())},optionToData:function(a){return a.is("option")?{id:a.prop("value"),text:a.text(),element:a.get(),css:a.attr("class"),disabled:a.prop("disabled"),locked:q(a.attr("locked"),"locked")||q(a.data("locked"),!0)}:a.is("optgroup")?{text:a.attr("label"),children:[],element:a.get(),css:a.attr("class")}:void 0},prepareOpts:function(c){var d,e,f,g,h=this;if(d=c.element,"select"===d.get(0).tagName.toLowerCase()&&(this.select=e=c.element),e&&a.each(["id","multiple","ajax","query","createSearchChoice","initSelection","data","tags"],function(){if(this in c)throw new Error("Option '"+this+"' is not allowed for Select2 when attached to a element.")}),c=a.extend({},{populateResults:function(d,e,f){var g,i=this.opts.id;g=function(d,e,j){var k,l,m,n,o,p,q,r,s,t;for(d=c.sortResults(d,e,f),k=0,l=d.length;l>k;k+=1)m=d[k],o=m.disabled===!0,n=!o&&i(m)!==b,p=m.children&&m.children.length>0,q=a(" "),q.addClass("select2-results-dept-"+j),q.addClass("select2-result"),q.addClass(n?"select2-result-selectable":"select2-result-unselectable"),o&&q.addClass("select2-disabled"),p&&q.addClass("select2-result-with-children"),q.addClass(h.opts.formatResultCssClass(m)),r=a(document.createElement("div")),r.addClass("select2-result-label"),t=c.formatResult(m,r,f,h.opts.escapeMarkup),t!==b&&r.html(t),q.append(r),p&&(s=a(""),s.addClass("select2-result-sub"),g(m.children,s,j+1),q.append(s)),q.data("select2-data",m),e.append(q)},g(e,d,0)}},a.fn.select2.defaults,c),"function"!=typeof c.id&&(f=c.id,c.id=function(a){return a[f]}),a.isArray(c.element.data("select2Tags"))){if("tags"in c)throw"tags specified as both an attribute 'data-select2-tags' and in options of Select2 "+c.element.attr("id");c.tags=c.element.data("select2Tags")}if(e?(c.query=this.bind(function(a){var f,g,i,c={results:[],more:!1},e=a.term;i=function(b,c){var d;b.is("option")?a.matcher(e,b.text(),b)&&c.push(h.optionToData(b)):b.is("optgroup")&&(d=h.optionToData(b),b.children().each2(function(a,b){i(b,d.children)}),d.children.length>0&&c.push(d))},f=d.children(),this.getPlaceholder()!==b&&f.length>0&&(g=this.getPlaceholderOption(),g&&(f=f.not(g))),f.each2(function(a,b){i(b,c.results)}),a.callback(c)}),c.id=function(a){return a.id},c.formatResultCssClass=function(a){return a.css}):"query"in c||("ajax"in c?(g=c.element.data("ajax-url"),g&&g.length>0&&(c.ajax.url=g),c.query=G.call(c.element,c.ajax)):"data"in c?c.query=H(c.data):"tags"in c&&(c.query=I(c.tags),c.createSearchChoice===b&&(c.createSearchChoice=function(b){return{id:a.trim(b),text:a.trim(b)}}),c.initSelection===b&&(c.initSelection=function(b,d){var e=[];a(r(b.val(),c.separator)).each(function(){var b={id:this,text:this},d=c.tags;a.isFunction(d)&&(d=d()),a(d).each(function(){return q(this.id,b.id)?(b=this,!1):void 0}),e.push(b)}),d(e)}))),"function"!=typeof c.query)throw"query function not defined for Select2 "+c.element.attr("id");return c},monitorSource:function(){var c,d,a=this.opts.element;a.on("change.select2",this.bind(function(){this.opts.element.data("select2-change-triggered")!==!0&&this.initSelection()})),c=this.bind(function(){var c=a.prop("disabled");c===b&&(c=!1),this.enable(!c);var d=a.prop("readonly");d===b&&(d=!1),this.readonly(d),D(this.container,this.opts.element,this.opts.adaptContainerCssClass),this.container.addClass(K(this.opts.containerCssClass)),D(this.dropdown,this.opts.element,this.opts.adaptDropdownCssClass),this.dropdown.addClass(K(this.opts.dropdownCssClass))}),a.on("propertychange.select2",c),this.mutationCallback===b&&(this.mutationCallback=function(a){a.forEach(c)}),d=window.MutationObserver||window.WebKitMutationObserver||window.MozMutationObserver,d!==b&&(this.propertyObserver&&(delete this.propertyObserver,this.propertyObserver=null),this.propertyObserver=new d(this.mutationCallback),this.propertyObserver.observe(a.get(0),{attributes:!0,subtree:!1}))},triggerSelect:function(b){var c=a.Event("select2-selecting",{val:this.id(b),object:b});return this.opts.element.trigger(c),!c.isDefaultPrevented()},triggerChange:function(b){b=b||{},b=a.extend({},b,{type:"change",val:this.val()}),this.opts.element.data("select2-change-triggered",!0),this.opts.element.trigger(b),this.opts.element.data("select2-change-triggered",!1),this.opts.element.click(),this.opts.blurOnChange&&this.opts.element.blur()},isInterfaceEnabled:function(){return this.enabledInterface===!0},enableInterface:function(){var a=this._enabled&&!this._readonly,b=!a;return a===this.enabledInterface?!1:(this.container.toggleClass("select2-container-disabled",b),this.close(),this.enabledInterface=a,!0)},enable:function(a){a===b&&(a=!0),this._enabled!==a&&(this._enabled=a,this.opts.element.prop("disabled",!a),this.enableInterface())},disable:function(){this.enable(!1)},readonly:function(a){return a===b&&(a=!1),this._readonly===a?!1:(this._readonly=a,this.opts.element.prop("readonly",a),this.enableInterface(),!0)},opened:function(){return this.container.hasClass("select2-dropdown-open")},positionDropdown:function(){var t,u,v,w,x,b=this.dropdown,c=this.container.offset(),d=this.container.outerHeight(!1),e=this.container.outerWidth(!1),f=b.outerHeight(!1),g=a(window),h=g.width(),i=g.height(),j=g.scrollLeft()+h,l=g.scrollTop()+i,m=c.top+d,n=c.left,o=l>=m+f,p=c.top-f>=this.body().scrollTop(),q=b.outerWidth(!1),r=j>=n+q,s=b.hasClass("select2-drop-above");s?(u=!0,!p&&o&&(v=!0,u=!1)):(u=!1,!o&&p&&(v=!0,u=!0)),v&&(b.hide(),c=this.container.offset(),d=this.container.outerHeight(!1),e=this.container.outerWidth(!1),f=b.outerHeight(!1),j=g.scrollLeft()+h,l=g.scrollTop()+i,m=c.top+d,n=c.left,q=b.outerWidth(!1),r=j>=n+q,b.show()),this.opts.dropdownAutoWidth?(x=a(".select2-results",b)[0],b.addClass("select2-drop-auto-width"),b.css("width",""),q=b.outerWidth(!1)+(x.scrollHeight===x.clientHeight?0:k.width),q>e?e=q:q=e,r=j>=n+q):this.container.removeClass("select2-drop-auto-width"),"static"!==this.body().css("position")&&(t=this.body().offset(),m-=t.top,n-=t.left),r||(n=c.left+e-q),w={left:n,width:e},u?(w.bottom=i-c.top,w.top="auto",this.container.addClass("select2-drop-above"),b.addClass("select2-drop-above")):(w.top=m,w.bottom="auto",this.container.removeClass("select2-drop-above"),b.removeClass("select2-drop-above")),w=a.extend(w,K(this.opts.dropdownCss)),b.css(w)},shouldOpen:function(){var b;return this.opened()?!1:this._enabled===!1||this._readonly===!0?!1:(b=a.Event("select2-opening"),this.opts.element.trigger(b),!b.isDefaultPrevented())},clearDropdownAlignmentPreference:function(){this.container.removeClass("select2-drop-above"),this.dropdown.removeClass("select2-drop-above")},open:function(){return this.shouldOpen()?(this.opening(),!0):!1},opening:function(){var f,b=this.containerId,c="scroll."+b,d="resize."+b,e="orientationchange."+b;this.container.addClass("select2-dropdown-open").addClass("select2-container-active"),this.clearDropdownAlignmentPreference(),this.dropdown[0]!==this.body().children().last()[0]&&this.dropdown.detach().appendTo(this.body()),f=a("#select2-drop-mask"),0==f.length&&(f=a(document.createElement("div")),f.attr("id","select2-drop-mask").attr("class","select2-drop-mask"),f.hide(),f.appendTo(this.body()),f.on("mousedown touchstart click",function(b){var d,c=a("#select2-drop");c.length>0&&(d=c.data("select2"),d.opts.selectOnBlur&&d.selectHighlighted({noFocus:!0}),d.close({focus:!0}),b.preventDefault(),b.stopPropagation())})),this.dropdown.prev()[0]!==f[0]&&this.dropdown.before(f),a("#select2-drop").removeAttr("id"),this.dropdown.attr("id","select2-drop"),f.show(),this.positionDropdown(),this.dropdown.show(),this.positionDropdown(),this.dropdown.addClass("select2-drop-active");var g=this;this.container.parents().add(window).each(function(){a(this).on(d+" "+c+" "+e,function(){g.positionDropdown()})})},close:function(){if(this.opened()){var b=this.containerId,c="scroll."+b,d="resize."+b,e="orientationchange."+b;this.container.parents().add(window).each(function(){a(this).off(c).off(d).off(e)}),this.clearDropdownAlignmentPreference(),a("#select2-drop-mask").hide(),this.dropdown.removeAttr("id"),this.dropdown.hide(),this.container.removeClass("select2-dropdown-open").removeClass("select2-container-active"),this.results.empty(),this.clearSearch(),this.search.removeClass("select2-active"),this.opts.element.trigger(a.Event("select2-close"))}},externalSearch:function(a){this.open(),this.search.val(a),this.updateResults(!1)},clearSearch:function(){},getMaximumSelectionSize:function(){return K(this.opts.maximumSelectionSize)},ensureHighlightVisible:function(){var c,d,e,f,g,h,i,b=this.results;if(d=this.highlight(),!(0>d)){if(0==d)return b.scrollTop(0),void 0;c=this.findHighlightableChoices().find(".select2-result-label"),e=a(c[d]),f=e.offset().top+e.outerHeight(!0),d===c.length-1&&(i=b.find("li.select2-more-results"),i.length>0&&(f=i.offset().top+i.outerHeight(!0))),g=b.offset().top+b.outerHeight(!0),f>g&&b.scrollTop(b.scrollTop()+(f-g)),h=e.offset().top-b.offset().top,0>h&&"none"!=e.css("display")&&b.scrollTop(b.scrollTop()+h)}},findHighlightableChoices:function(){return this.results.find(".select2-result-selectable:not(.select2-disabled, .select2-selected)")},moveHighlight:function(b){for(var c=this.findHighlightableChoices(),d=this.highlight();d>-1&&d=c.length&&(b=c.length-1),0>b&&(b=0),this.removeHighlight(),d=a(c[b]),d.addClass("select2-highlighted"),this.ensureHighlightVisible(),e=d.data("select2-data"),e&&this.opts.element.trigger({type:"select2-highlight",val:this.id(e),choice:e}),void 0)},removeHighlight:function(){this.results.find(".select2-highlighted").removeClass("select2-highlighted")},countSelectableResults:function(){return this.findHighlightableChoices().length},highlightUnderEvent:function(b){var c=a(b.target).closest(".select2-result-selectable");if(c.length>0&&!c.is(".select2-highlighted")){var d=this.findHighlightableChoices();this.highlight(d.index(c))}else 0==c.length&&this.removeHighlight()},loadMoreIfNeeded:function(){var c,a=this.results,b=a.find("li.select2-more-results"),d=this.resultsPage+1,e=this,f=this.search.val(),g=this.context;0!==b.length&&(c=b.offset().top-a.offset().top-a.height(),c<=this.opts.loadMorePadding&&(b.addClass("select2-active"),this.opts.query({element:this.opts.element,term:f,page:d,context:g,matcher:this.opts.matcher,callback:this.bind(function(c){e.opened()&&(e.opts.populateResults.call(this,a,c.results,{term:f,page:d,context:g}),e.postprocessResults(c,!1,!1),c.more===!0?(b.detach().appendTo(a).text(e.opts.formatLoadMore(d+1)),window.setTimeout(function(){e.loadMoreIfNeeded()},10)):b.remove(),e.positionDropdown(),e.resultsPage=d,e.context=c.context,this.opts.element.trigger({type:"select2-loaded",items:c}))})})))},tokenize:function(){},updateResults:function(c){function m(){d.removeClass("select2-active"),h.positionDropdown()}function n(a){e.html(a),m()}var g,i,l,d=this.search,e=this.results,f=this.opts,h=this,j=d.val(),k=a.data(this.container,"select2-last-term");if((c===!0||!k||!q(j,k))&&(a.data(this.container,"select2-last-term",j),c===!0||this.showSearchInput!==!1&&this.opened())){l=++this.queryCount;var o=this.getMaximumSelectionSize();if(o>=1&&(g=this.data(),a.isArray(g)&&g.length>=o&&J(f.formatSelectionTooBig,"formatSelectionTooBig")))return n(""+f.formatSelectionTooBig(o)+" "),void 0;if(d.val().length"+f.formatInputTooShort(d.val(),f.minimumInputLength)+""):n(""),c&&this.showSearch&&this.showSearch(!0),void 0;
-if(f.maximumInputLength&&d.val().length>f.maximumInputLength)return J(f.formatInputTooLong,"formatInputTooLong")?n(""+f.formatInputTooLong(d.val(),f.maximumInputLength)+" "):n(""),void 0;f.formatSearching&&0===this.findHighlightableChoices().length&&n(""+f.formatSearching()+" "),d.addClass("select2-active"),this.removeHighlight(),i=this.tokenize(),i!=b&&null!=i&&d.val(i),this.resultsPage=1,f.query({element:f.element,term:d.val(),page:this.resultsPage,context:null,matcher:f.matcher,callback:this.bind(function(g){var i;if(l==this.queryCount){if(!this.opened())return this.search.removeClass("select2-active"),void 0;if(this.context=g.context===b?null:g.context,this.opts.createSearchChoice&&""!==d.val()&&(i=this.opts.createSearchChoice.call(h,d.val(),g.results),i!==b&&null!==i&&h.id(i)!==b&&null!==h.id(i)&&0===a(g.results).filter(function(){return q(h.id(this),h.id(i))}).length&&g.results.unshift(i)),0===g.results.length&&J(f.formatNoMatches,"formatNoMatches"))return n(""+f.formatNoMatches(d.val())+" "),void 0;e.empty(),h.opts.populateResults.call(this,e,g.results,{term:d.val(),page:this.resultsPage,context:null}),g.more===!0&&J(f.formatLoadMore,"formatLoadMore")&&(e.append(""+h.opts.escapeMarkup(f.formatLoadMore(this.resultsPage))+" "),window.setTimeout(function(){h.loadMoreIfNeeded()},10)),this.postprocessResults(g,c),m(),this.opts.element.trigger({type:"select2-loaded",items:g})}})})}},cancel:function(){this.close()},blur:function(){this.opts.selectOnBlur&&this.selectHighlighted({noFocus:!0}),this.close(),this.container.removeClass("select2-container-active"),this.search[0]===document.activeElement&&this.search.blur(),this.clearSearch(),this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus")},focusSearch:function(){y(this.search)},selectHighlighted:function(a){var b=this.highlight(),c=this.results.find(".select2-highlighted"),d=c.closest(".select2-result").data("select2-data");d?(this.highlight(b),this.onSelect(d,a)):a&&a.noFocus&&this.close()},getPlaceholder:function(){var a;return this.opts.element.attr("placeholder")||this.opts.element.attr("data-placeholder")||this.opts.element.data("placeholder")||this.opts.placeholder||((a=this.getPlaceholderOption())!==b?a.text():b)},getPlaceholderOption:function(){if(this.select){var a=this.select.children("option").first();if(this.opts.placeholderOption!==b)return"first"===this.opts.placeholderOption&&a||"function"==typeof this.opts.placeholderOption&&this.opts.placeholderOption(this.select);if(""===a.text()&&""===a.val())return a}},initContainerWidth:function(){function c(){var c,d,e,f,g,h;if("off"===this.opts.width)return null;if("element"===this.opts.width)return 0===this.opts.element.outerWidth(!1)?"auto":this.opts.element.outerWidth(!1)+"px";if("copy"===this.opts.width||"resolve"===this.opts.width){if(c=this.opts.element.attr("style"),c!==b)for(d=c.split(";"),f=0,g=d.length;g>f;f+=1)if(h=d[f].replace(/\s/g,""),e=h.match(/^width:(([-+]?([0-9]*\.)?[0-9]+)(px|em|ex|%|in|cm|mm|pt|pc))/i),null!==e&&e.length>=1)return e[1];return"resolve"===this.opts.width?(c=this.opts.element.css("width"),c.indexOf("%")>0?c:0===this.opts.element.outerWidth(!1)?"auto":this.opts.element.outerWidth(!1)+"px"):null}return a.isFunction(this.opts.width)?this.opts.width():this.opts.width}var d=c.call(this);null!==d&&this.container.css("width",d)}}),e=N(d,{createContainer:function(){var b=a(document.createElement("div")).attr({"class":"select2-container"}).html([""," "," "," "," ",""].join(""));return b},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.focusser.prop("disabled",!this.isInterfaceEnabled())},opening:function(){var c,d,e;this.opts.minimumResultsForSearch>=0&&this.showSearch(!0),this.parent.opening.apply(this,arguments),this.showSearchInput!==!1&&this.search.val(this.focusser.val()),this.search.focus(),c=this.search.get(0),c.createTextRange?(d=c.createTextRange(),d.collapse(!1),d.select()):c.setSelectionRange&&(e=this.search.val().length,c.setSelectionRange(e,e)),""===this.search.val()&&this.nextSearchTerm!=b&&(this.search.val(this.nextSearchTerm),this.search.select()),this.focusser.prop("disabled",!0).val(""),this.updateResults(!0),this.opts.element.trigger(a.Event("select2-open"))},close:function(a){this.opened()&&(this.parent.close.apply(this,arguments),a=a||{focus:!0},this.focusser.removeAttr("disabled"),a.focus&&this.focusser.focus())},focus:function(){this.opened()?this.close():(this.focusser.removeAttr("disabled"),this.focusser.focus())},isFocused:function(){return this.container.hasClass("select2-container-active")},cancel:function(){this.parent.cancel.apply(this,arguments),this.focusser.removeAttr("disabled"),this.focusser.focus()},destroy:function(){a("label[for='"+this.focusser.attr("id")+"']").attr("for",this.opts.element.attr("id")),this.parent.destroy.apply(this,arguments)},initContainer:function(){var b,d=this.container,e=this.dropdown;this.opts.minimumResultsForSearch<0?this.showSearch(!1):this.showSearch(!0),this.selection=b=d.find(".select2-choice"),this.focusser=d.find(".select2-focusser"),this.focusser.attr("id","s2id_autogen"+g()),a("label[for='"+this.opts.element.attr("id")+"']").attr("for",this.focusser.attr("id")),this.focusser.attr("tabindex",this.elementTabIndex),this.search.on("keydown",this.bind(function(a){if(this.isInterfaceEnabled()){if(a.which===c.PAGE_UP||a.which===c.PAGE_DOWN)return A(a),void 0;switch(a.which){case c.UP:case c.DOWN:return this.moveHighlight(a.which===c.UP?-1:1),A(a),void 0;case c.ENTER:return this.selectHighlighted(),A(a),void 0;case c.TAB:return this.selectHighlighted({noFocus:!0}),void 0;case c.ESC:return this.cancel(a),A(a),void 0}}})),this.search.on("blur",this.bind(function(){document.activeElement===this.body().get(0)&&window.setTimeout(this.bind(function(){this.search.focus()}),0)})),this.focusser.on("keydown",this.bind(function(a){if(this.isInterfaceEnabled()&&a.which!==c.TAB&&!c.isControl(a)&&!c.isFunctionKey(a)&&a.which!==c.ESC){if(this.opts.openOnEnter===!1&&a.which===c.ENTER)return A(a),void 0;if(a.which==c.DOWN||a.which==c.UP||a.which==c.ENTER&&this.opts.openOnEnter){if(a.altKey||a.ctrlKey||a.shiftKey||a.metaKey)return;return this.open(),A(a),void 0}return a.which==c.DELETE||a.which==c.BACKSPACE?(this.opts.allowClear&&this.clear(),A(a),void 0):void 0}})),t(this.focusser),this.focusser.on("keyup-change input",this.bind(function(a){if(this.opts.minimumResultsForSearch>=0){if(a.stopPropagation(),this.opened())return;this.open()}})),b.on("mousedown","abbr",this.bind(function(a){this.isInterfaceEnabled()&&(this.clear(),B(a),this.close(),this.selection.focus())})),b.on("mousedown",this.bind(function(b){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.opened()?this.close():this.isInterfaceEnabled()&&this.open(),A(b)})),e.on("mousedown",this.bind(function(){this.search.focus()})),b.on("focus",this.bind(function(a){A(a)})),this.focusser.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active")})).on("blur",this.bind(function(){this.opened()||(this.container.removeClass("select2-container-active"),this.opts.element.trigger(a.Event("select2-blur")))})),this.search.on("focus",this.bind(function(){this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active")})),this.initContainerWidth(),this.opts.element.addClass("select2-offscreen"),this.setPlaceholder()},clear:function(b){var c=this.selection.data("select2-data");if(c){var d=a.Event("select2-clearing");if(this.opts.element.trigger(d),d.isDefaultPrevented())return;var e=this.getPlaceholderOption();this.opts.element.val(e?e.val():""),this.selection.find(".select2-chosen").empty(),this.selection.removeData("select2-data"),this.setPlaceholder(),b!==!1&&(this.opts.element.trigger({type:"select2-removed",val:this.id(c),choice:c}),this.triggerChange({removed:c}))}},initSelection:function(){if(this.isPlaceholderOptionSelected())this.updateSelection(null),this.close(),this.setPlaceholder();else{var c=this;this.opts.initSelection.call(null,this.opts.element,function(a){a!==b&&null!==a&&(c.updateSelection(a),c.close(),c.setPlaceholder())})}},isPlaceholderOptionSelected:function(){var a;return this.getPlaceholder()?(a=this.getPlaceholderOption())!==b&&a.prop("selected")||""===this.opts.element.val()||this.opts.element.val()===b||null===this.opts.element.val():!1},prepareOpts:function(){var b=this.parent.prepareOpts.apply(this,arguments),c=this;return"select"===b.element.get(0).tagName.toLowerCase()?b.initSelection=function(a,b){var d=a.find("option").filter(function(){return this.selected});b(c.optionToData(d))}:"data"in b&&(b.initSelection=b.initSelection||function(c,d){var e=c.val(),f=null;b.query({matcher:function(a,c,d){var g=q(e,b.id(d));return g&&(f=d),g},callback:a.isFunction(d)?function(){d(f)}:a.noop})}),b},getPlaceholder:function(){return this.select&&this.getPlaceholderOption()===b?b:this.parent.getPlaceholder.apply(this,arguments)},setPlaceholder:function(){var a=this.getPlaceholder();if(this.isPlaceholderOptionSelected()&&a!==b){if(this.select&&this.getPlaceholderOption()===b)return;this.selection.find(".select2-chosen").html(this.opts.escapeMarkup(a)),this.selection.addClass("select2-default"),this.container.removeClass("select2-allowclear")}},postprocessResults:function(a,b,c){var d=0,e=this;if(this.findHighlightableChoices().each2(function(a,b){return q(e.id(b.data("select2-data")),e.opts.element.val())?(d=a,!1):void 0}),c!==!1&&(b===!0&&d>=0?this.highlight(d):this.highlight(0)),b===!0){var g=this.opts.minimumResultsForSearch;g>=0&&this.showSearch(L(a.results)>=g)}},showSearch:function(b){this.showSearchInput!==b&&(this.showSearchInput=b,this.dropdown.find(".select2-search").toggleClass("select2-search-hidden",!b),this.dropdown.find(".select2-search").toggleClass("select2-offscreen",!b),a(this.dropdown,this.container).toggleClass("select2-with-searchbox",b))},onSelect:function(a,b){if(this.triggerSelect(a)){var c=this.opts.element.val(),d=this.data();this.opts.element.val(this.id(a)),this.updateSelection(a),this.opts.element.trigger({type:"select2-selected",val:this.id(a),choice:a}),this.nextSearchTerm=this.opts.nextSearchTerm(a,this.search.val()),this.close(),b&&b.noFocus||this.focusser.focus(),q(c,this.id(a))||this.triggerChange({added:a,removed:d})}},updateSelection:function(a){var d,e,c=this.selection.find(".select2-chosen");this.selection.data("select2-data",a),c.empty(),null!==a&&(d=this.opts.formatSelection(a,c,this.opts.escapeMarkup)),d!==b&&c.append(d),e=this.opts.formatSelectionCssClass(a,c),e!==b&&c.addClass(e),this.selection.removeClass("select2-default"),this.opts.allowClear&&this.getPlaceholder()!==b&&this.container.addClass("select2-allowclear")},val:function(){var a,c=!1,d=null,e=this,f=this.data();if(0===arguments.length)return this.opts.element.val();if(a=arguments[0],arguments.length>1&&(c=arguments[1]),this.select)this.select.val(a).find("option").filter(function(){return this.selected}).each2(function(a,b){return d=e.optionToData(b),!1}),this.updateSelection(d),this.setPlaceholder(),c&&this.triggerChange({added:d,removed:f});else{if(!a&&0!==a)return this.clear(c),void 0;if(this.opts.initSelection===b)throw new Error("cannot call val() if initSelection() is not defined");this.opts.element.val(a),this.opts.initSelection(this.opts.element,function(a){e.opts.element.val(a?e.id(a):""),e.updateSelection(a),e.setPlaceholder(),c&&e.triggerChange({added:a,removed:f})})}},clearSearch:function(){this.search.val(""),this.focusser.val("")},data:function(a){var c,d=!1;return 0===arguments.length?(c=this.selection.data("select2-data"),c==b&&(c=null),c):(arguments.length>1&&(d=arguments[1]),a?(c=this.data(),this.opts.element.val(a?this.id(a):""),this.updateSelection(a),d&&this.triggerChange({added:a,removed:c})):this.clear(d),void 0)}}),f=N(d,{createContainer:function(){var b=a(document.createElement("div")).attr({"class":"select2-container select2-container-multi"}).html(["",""].join(""));return b},prepareOpts:function(){var b=this.parent.prepareOpts.apply(this,arguments),c=this;return"select"===b.element.get(0).tagName.toLowerCase()?b.initSelection=function(a,b){var d=[];a.find("option").filter(function(){return this.selected}).each2(function(a,b){d.push(c.optionToData(b))}),b(d)}:"data"in b&&(b.initSelection=b.initSelection||function(c,d){var e=r(c.val(),b.separator),f=[];b.query({matcher:function(c,d,g){var h=a.grep(e,function(a){return q(a,b.id(g))}).length;return h&&f.push(g),h},callback:a.isFunction(d)?function(){for(var a=[],c=0;c0||(this.selectChoice(null),this.clearPlaceholder(),this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.open(),this.focusSearch(),b.preventDefault()))})),this.container.on("focus",b,this.bind(function(){this.isInterfaceEnabled()&&(this.container.hasClass("select2-container-active")||this.opts.element.trigger(a.Event("select2-focus")),this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"),this.clearPlaceholder())})),this.initContainerWidth(),this.opts.element.addClass("select2-offscreen"),this.clearSearch()},enableInterface:function(){this.parent.enableInterface.apply(this,arguments)&&this.search.prop("disabled",!this.isInterfaceEnabled())},initSelection:function(){if(""===this.opts.element.val()&&""===this.opts.element.text()&&(this.updateSelection([]),this.close(),this.clearSearch()),this.select||""!==this.opts.element.val()){var c=this;this.opts.initSelection.call(null,this.opts.element,function(a){a!==b&&null!==a&&(c.updateSelection(a),c.close(),c.clearSearch())})}},clearSearch:function(){var a=this.getPlaceholder(),c=this.getMaxSearchWidth();a!==b&&0===this.getVal().length&&this.search.hasClass("select2-focused")===!1?(this.search.val(a).addClass("select2-default"),this.search.width(c>0?c:this.container.css("width"))):this.search.val("").width(10)},clearPlaceholder:function(){this.search.hasClass("select2-default")&&this.search.val("").removeClass("select2-default")},opening:function(){this.clearPlaceholder(),this.resizeSearch(),this.parent.opening.apply(this,arguments),this.focusSearch(),this.updateResults(!0),this.search.focus(),this.opts.element.trigger(a.Event("select2-open"))},close:function(){this.opened()&&this.parent.close.apply(this,arguments)},focus:function(){this.close(),this.search.focus()},isFocused:function(){return this.search.hasClass("select2-focused")},updateSelection:function(b){var c=[],d=[],e=this;a(b).each(function(){o(e.id(this),c)<0&&(c.push(e.id(this)),d.push(this))}),b=d,this.selection.find(".select2-search-choice").remove(),a(b).each(function(){e.addSelectedChoice(this)}),e.postprocessResults()},tokenize:function(){var a=this.search.val();a=this.opts.tokenizer.call(this,a,this.data(),this.bind(this.onSelect),this.opts),null!=a&&a!=b&&(this.search.val(a),a.length>0&&this.open())},onSelect:function(a,b){this.triggerSelect(a)&&(this.addSelectedChoice(a),this.opts.element.trigger({type:"selected",val:this.id(a),choice:a}),(this.select||!this.opts.closeOnSelect)&&this.postprocessResults(a,!1,this.opts.closeOnSelect===!0),this.opts.closeOnSelect?(this.close(),this.search.width(10)):this.countSelectableResults()>0?(this.search.width(10),this.resizeSearch(),this.getMaximumSelectionSize()>0&&this.val().length>=this.getMaximumSelectionSize()&&this.updateResults(!0),this.positionDropdown()):(this.close(),this.search.width(10)),this.triggerChange({added:a}),b&&b.noFocus||this.focusSearch())},cancel:function(){this.close(),this.focusSearch()},addSelectedChoice:function(c){var j,k,d=!c.locked,e=a("
"),f=a("
"),g=d?e:f,h=this.id(c),i=this.getVal();j=this.opts.formatSelection(c,g.find("div"),this.opts.escapeMarkup),j!=b&&g.find("div").replaceWith(""+j+"
"),k=this.opts.formatSelectionCssClass(c,g.find("div")),k!=b&&g.addClass(k),d&&g.find(".select2-search-choice-close").on("mousedown",A).on("click dblclick",this.bind(function(b){this.isInterfaceEnabled()&&(a(b.target).closest(".select2-search-choice").fadeOut("fast",this.bind(function(){this.unselect(a(b.target)),this.selection.find(".select2-search-choice-focus").removeClass("select2-search-choice-focus"),this.close(),this.focusSearch()})).dequeue(),A(b))})).on("focus",this.bind(function(){this.isInterfaceEnabled()&&(this.container.addClass("select2-container-active"),this.dropdown.addClass("select2-drop-active"))})),g.data("select2-data",c),g.insertBefore(this.searchContainer),i.push(h),this.setVal(i)},unselect:function(b){var d,e,c=this.getVal();if(b=b.closest(".select2-search-choice"),0===b.length)throw"Invalid argument: "+b+". Must be .select2-search-choice";if(d=b.data("select2-data")){for(;(e=o(this.id(d),c))>=0;)c.splice(e,1),this.setVal(c),this.select&&this.postprocessResults();var f=a.Event("select2-removing");f.val=this.id(d),f.choice=d,this.opts.element.trigger(f),f.isDefaultPrevented()||(this.opts.element.trigger({type:"select2-removed",val:this.id(d),choice:d}),this.triggerChange({removed:d}))}},postprocessResults:function(a,b,c){var d=this.getVal(),e=this.results.find(".select2-result"),f=this.results.find(".select2-result-with-children"),g=this;e.each2(function(a,b){var c=g.id(b.data("select2-data"));o(c,d)>=0&&(b.addClass("select2-selected"),b.find(".select2-result-selectable").addClass("select2-selected"))}),f.each2(function(a,b){b.is(".select2-result-selectable")||0!==b.find(".select2-result-selectable:not(.select2-selected)").length||b.addClass("select2-selected")}),-1==this.highlight()&&c!==!1&&g.highlight(0),!this.opts.createSearchChoice&&!e.filter(".select2-result:not(.select2-selected)").length>0&&(!a||a&&!a.more&&0===this.results.find(".select2-no-results").length)&&J(g.opts.formatNoMatches,"formatNoMatches")&&this.results.append(""+g.opts.formatNoMatches(g.search.val())+" ")},getMaxSearchWidth:function(){return this.selection.width()-s(this.search)},resizeSearch:function(){var a,b,c,d,e,f=s(this.search);a=C(this.search)+10,b=this.search.offset().left,c=this.selection.width(),d=this.selection.offset().left,e=c-(b-d)-f,a>e&&(e=c-f),40>e&&(e=c-f),0>=e&&(e=a),this.search.width(Math.floor(e))},getVal:function(){var a;return this.select?(a=this.select.val(),null===a?[]:a):(a=this.opts.element.val(),r(a,this.opts.separator))},setVal:function(b){var c;this.select?this.select.val(b):(c=[],a(b).each(function(){o(this,c)<0&&c.push(this)}),this.opts.element.val(0===c.length?"":c.join(this.opts.separator)))},buildChangeDetails:function(a,b){for(var b=b.slice(0),a=a.slice(0),c=0;c. Attach to instead.");this.search.width(0),this.searchContainer.hide()},onSortEnd:function(){var b=[],c=this;this.searchContainer.show(),this.searchContainer.appendTo(this.searchContainer.parent()),this.resizeSearch(),this.selection.find(".select2-search-choice").each(function(){b.push(c.opts.id(a(this).data("select2-data")))}),this.setVal(b),this.triggerChange()},data:function(b,c){var e,f,d=this;return 0===arguments.length?this.selection.find(".select2-search-choice").map(function(){return a(this).data("select2-data")}).get():(f=this.data(),b||(b=[]),e=a.map(b,function(a){return d.opts.id(a)}),this.setVal(e),this.updateSelection(b),this.clearSearch(),c&&this.triggerChange(this.buildChangeDetails(f,this.data())),void 0)}}),a.fn.select2=function(){var d,g,h,i,j,c=Array.prototype.slice.call(arguments,0),k=["val","destroy","opened","open","close","focus","isFocused","container","dropdown","onSortStart","onSortEnd","enable","disable","readonly","positionDropdown","data","search"],l=["opened","isFocused","container","dropdown"],m=["val","data"],n={search:"externalSearch"};return this.each(function(){if(0===c.length||"object"==typeof c[0])d=0===c.length?{}:a.extend({},c[0]),d.element=a(this),"select"===d.element.get(0).tagName.toLowerCase()?j=d.element.prop("multiple"):(j=d.multiple||!1,"tags"in d&&(d.multiple=j=!0)),g=j?new f:new e,g.init(d);else{if("string"!=typeof c[0])throw"Invalid arguments to select2 plugin: "+c;if(o(c[0],k)<0)throw"Unknown method: "+c[0];if(i=b,g=a(this).data("select2"),g===b)return;if(h=c[0],"container"===h?i=g.container:"dropdown"===h?i=g.dropdown:(n[h]&&(h=n[h]),i=g[h].apply(g,c.slice(1))),o(c[0],l)>=0||o(c[0],m)&&1==c.length)return!1}}),i===b?this:i},a.fn.select2.defaults={width:"copy",loadMorePadding:0,closeOnSelect:!0,openOnEnter:!0,containerCss:{},dropdownCss:{},containerCssClass:"",dropdownCssClass:"",formatResult:function(a,b,c,d){var e=[];return E(a.text,c.term,e,d),e.join("")},formatSelection:function(a,c,d){return a?d(a.text):b},sortResults:function(a){return a},formatResultCssClass:function(){return b},formatSelectionCssClass:function(){return b},formatNoMatches:function(){return"No matches found"},formatInputTooShort:function(a,b){var c=b-a.length;return"Please enter "+c+" more character"+(1==c?"":"s")},formatInputTooLong:function(a,b){var c=a.length-b;return"Please delete "+c+" character"+(1==c?"":"s")},formatSelectionTooBig:function(a){return"You can only select "+a+" item"+(1==a?"":"s")},formatLoadMore:function(){return"Loading more results..."},formatSearching:function(){return"Searching..."},minimumResultsForSearch:0,minimumInputLength:0,maximumInputLength:null,maximumSelectionSize:0,id:function(a){return a.id},matcher:function(a,b){return n(""+b).toUpperCase().indexOf(n(""+a).toUpperCase())>=0},separator:",",tokenSeparators:[],tokenizer:M,escapeMarkup:F,blurOnChange:!1,selectOnBlur:!1,adaptContainerCssClass:function(a){return a},adaptDropdownCssClass:function(){return null},nextSearchTerm:function(){return b}},a.fn.select2.ajaxDefaults={transport:a.ajax,params:{type:"GET",cache:!1,dataType:"json"}},window.Select2={query:{ajax:G,local:H,tags:I},util:{debounce:v,markMatch:E,escapeMarkup:F,stripDiacritics:n},"class":{"abstract":d,single:e,multi:f}}}}(jQuery);
\ No newline at end of file
diff --git a/src/inputs/select2/lib/select2.png b/src/inputs/select2/lib/select2.png
deleted file mode 100644
index 1d804ffb..00000000
Binary files a/src/inputs/select2/lib/select2.png and /dev/null differ
diff --git a/src/inputs/select2/lib/select2x2.png b/src/inputs/select2/lib/select2x2.png
deleted file mode 100644
index 4bdd5c96..00000000
Binary files a/src/inputs/select2/lib/select2x2.png and /dev/null differ
diff --git a/src/inputs/select2/select2.js b/src/inputs/select2/select2.js
index 0b3a7f3e..a42c6f2d 100644
--- a/src/inputs/select2/select2.js
+++ b/src/inputs/select2/select2.js
@@ -1,22 +1,22 @@
/**
-Select2 input. Based on amazing work of Igor Vaynberg https://github.com/ivaynberg/select2.
-Please see [original select2 docs](http://ivaynberg.github.com/select2) for detailed description and options.
-
-You should manually download and include select2 distributive:
+Select2 input. Based on amazing work of Igor Vaynberg https://github.com/ivaynberg/select2.
+Please see [original select2 docs](http://ivaynberg.github.com/select2) for detailed description and options.
-
-
-
-To make it **bootstrap-styled** you can use css from [here](https://github.com/t0m/select2-bootstrap-css):
+You should manually download and include select2 distributive:
-
-
-**Note:** currently `autotext` feature does not work for select2 with `ajax` remote source.
-You need initially put both `data-value` and element's text youself:
+
+
+
+To make it **bootstrap-styled** you can use css from [here](https://github.com/fk/select2-bootstrap-theme):
+
+
+
+**Note:** currently `autotext` feature does not work for select2 with `ajax` remote source.
+You need initially put both `data-value` and element's text youself:
Text1
-
-
+
+
@class select2
@extends abstractinput
@since 1.4.1
@@ -73,57 +73,72 @@ $(function(){
return $.get('/getCountryById', { query: element.val() }, function (data) {
callback(data);
});
- }
- }
+ }
+ }
});
});
**/
(function ($) {
"use strict";
-
+
var Constructor = function (options) {
this.init('select2', options, Constructor.defaults);
options.select2 = options.select2 || {};
- this.sourceData = null;
-
- //placeholder
- if(options.placeholder) {
+ // placeholder
+ if (options.placeholder) {
options.select2.placeholder = options.placeholder;
}
-
- //if not `tags` mode, use source
- if(!options.select2.tags && options.source) {
- var source = options.source;
- //if source is function, call it (once!)
- if ($.isFunction(options.source)) {
- source = options.source.call(options.scope);
- }
-
- if (typeof source === 'string') {
- options.select2.ajax = options.select2.ajax || {};
- //some default ajax params
- if(!options.select2.ajax.data) {
- options.select2.ajax.data = function(term) {return { query:term };};
- }
- if(!options.select2.ajax.results) {
- options.select2.ajax.results = function(data) { return {results:data };};
- }
- options.select2.ajax.url = source;
- } else {
- //check format and convert x-editable format to select2 format (if needed)
- this.sourceData = this.convertSource(source);
- options.select2.data = this.sourceData;
+
+ // Automatically recognize the old `tags` behaviour and convert it into
+ // `tags` + `data`, which is what Select2 4.0.0 expects.
+ //
+ // Also defaults to being a multiple selection, like older versions of
+ // Select2.
+ if ($.isArray(options.select2.tags)) {
+ options.select2.data = options.select2.tags;
+ options.select2.tags = true;
+ options.select2.multiple = true;
+ }
+
+ if (options.select2.formatSelection) {
+ options.select2.templateSelection = options.select2.formatSelection;
+ }
+
+ if (options.select2.formatResult) {
+ options.select2.templateResult = options.select2.formatResult;
+ }
+
+ if (options.select2.ajax) {
+ if (options.select2.ajax.results) {
+ options.select2.ajax.processResults = options.select2.ajax.results;
}
- }
+
+ if (options.select2.ajax.processResults) {
+ var processResults = options.select2.ajax.processResults;
+
+ options.select2.ajax.processResults = $.proxy(function (data) {
+ var results = processResults(data);
+
+ results.results = this.convertSource(results.results);
+
+ return results;
+ }, this);
+ }
+ }
+
+ if (options.select2.initSelection) {
+ this.options.initFunction = options.select2.initSelection;
+ delete options.select2.initSelection;
+ }
//overriding objects in config (as by default jQuery extend() is not recursive)
this.options.select2 = $.extend({}, Constructor.defaults.select2, options.select2);
//detect whether it is multi-valued
- this.isMultiple = this.options.select2.tags || this.options.select2.multiple;
+ this.isMultiple = this.options.select2.multiple;
this.isRemote = ('ajax' in this.options.select2);
//store function returning ID of item
@@ -141,128 +156,190 @@ $(function(){
}
};
- $.fn.editableutils.inherit(Constructor, $.fn.editabletypes.abstractinput);
+ $.fn.editableutils.inherit(Constructor, $.fn.editabletypes.select);
$.extend(Constructor.prototype, {
- render: function() {
- this.setClass();
+ render: function () {
+ //console.log('render');
+ if (!this.$input.data('select2')) {
+ this.$input.select2(this.options.select2);
+ }
+ //console.log(this.$input.html())
- //can not apply select2 here as it calls initSelection
- //over input that does not have correct value yet.
- //apply select2 only in value2input
- //this.$input.select2(this.options.select2);
+ if (this.options.initFunction) {
+ this.options.initFunction(this.$input, $.proxy(function (initial) {
+ //console.log('initFunction', initial);
+ if ($.isArray(initial)) {
- //when data is loaded via ajax, we need to know when it's done to populate listData
- if(this.isRemote) {
- //listen to loaded event to populate data
- this.$input.on('select2-loaded', $.proxy(function(e) {
- this.sourceData = e.items.results;
+ } else {
+ var id = this.idFunc(initial);
+ initial.id = id;
+ var option = new Option(initial.text, id);
+ option.selected = true;
+
+ $(option).data('data', initial);
+
+ this.$input.append(option);
+ this.$input.trigger('change');
+ }
}, this));
+
+ delete this.options.initFunction;
}
+ return Constructor.superclass.render.call(this);
+ },
+
+ renderList: function() {
+ //console.log('renderList', arguments)
+ var $options = this.$input.children();
+ Constructor.superclass.renderList.apply(this, arguments);
+ this.$input.prepend($options);
+
+ //can not apply select2 here as it calls initSelection
+ //over input that does not have correct value yet.
+ //apply select2 only in value2input
+ //this.$input.select2(this.options.select2);
+
//trigger resize of editableform to re-position container in multi-valued mode
- if(this.isMultiple) {
+ if (this.isMultiple) {
this.$input.on('change', function() {
$(this).closest('form').parent().triggerHandler('resize');
});
}
},
- value2html: function(value, element) {
- var text = '', data,
- that = this;
+ /**
+ * Used to convert a value (`data-value` or `options.value`) to the actual
+ * selected value that can be processed by x-editable.
+ *
+ * This is needed because x-editable does not support multiple selections
+ * by default.
+ */
+ str2value: function (str) {
+ //console.log('str2value', str);
- if(this.options.select2.tags) { //in tags mode just assign value
- data = value;
- //data = $.fn.editableutils.itemsByValue(value, this.options.select2.tags, this.idFunc);
- } else if(this.sourceData) {
- data = $.fn.editableutils.itemsByValue(value, this.sourceData, this.idFunc);
- } else {
- //can not get list of possible values
- //(e.g. autotext for select2 with ajax source)
+ if ($.isArray(str)) {
+ return str;
}
- //data may be array (when multiple values allowed)
- if($.isArray(data)) {
- //collect selected data and show with separator
- text = [];
- $.each(data, function(k, v){
- text.push(v && typeof v === 'object' ? that.formatSelection(v) : v);
- });
- } else if(data) {
- text = that.formatSelection(data);
+ if (this.isMultiple) {
+ return str.split(this.getSeparator());
}
- text = $.isArray(text) ? text.join(this.options.viewseparator) : text;
+ return str;
+ },
+
+ /**
+ * Called when no value is supplied, used to determine the value based on the text.
+ */
+ html2value: function (html) {
+ //console.log('html2value', html, this.isMultiple);
+ if (!this.isMultiple) {
+ return html;
+ }
- //$(element).text(text);
- Constructor.superclass.value2html.call(this, text, element);
+ return html.split(this.options.viewseparator);
},
- html2value: function(html) {
- return this.options.select2.tags ? this.str2value(html, this.options.viewseparator) : null;
+ /**
+ * Used to update the text in the link based on the selected value
+ */
+ value2html: function (value, element) {
+ Constructor.superclass.value2html.apply(this, arguments);
},
- value2input: function(value) {
- // if value array => join it anyway
- if($.isArray(value)) {
- value = value.join(this.getSeparator());
+ /**
+ * Used to convert the value to the text representation of it.
+ *
+ * Superclass doesn't support multiple selects, so we need to override this.
+ */
+ value2htmlFinal: function (value, element) {
+ // The select input type can handle single selects fine
+ // We have to special case multiple selects, which aren't supported
+ // by default.
+ if (!$.isArray(value)) {
+ return Constructor.superclass.value2htmlFinal.call(this, value, element);
}
- //for remote source just set value, text is updated by initSelection
- if(!this.$input.data('select2')) {
- this.$input.val(value);
- this.$input.select2(this.options.select2);
- } else {
- //second argument needed to separate initial change from user's click (for autosubmit)
- this.$input.val(value).trigger('change', true);
+ var results = [];
- //Uncaught Error: cannot call val() if initSelection() is not defined
- //this.$input.select2('val', value);
- }
+ // Convert all of the values into their text
+ for (var v = 0; v < value.length; v++) {
+ var val = value[v];
- // if defined remote source AND no multiple mode AND no user's initSelection provided -->
- // we should somehow get text for provided id.
- // The solution is to use element's text as text for that id (exclude empty)
- if(this.isRemote && !this.isMultiple && !this.options.select2.initSelection) {
- // customId and customText are methods to extract `id` and `text` from data object
- // we can use this workaround only if user did not define these methods
- // otherwise we cant construct data object
- var customId = this.options.select2.id,
- customText = this.options.select2.formatSelection;
-
- if(!customId && !customText) {
- var $el = $(this.options.scope);
- if (!$el.data('editable').isEmpty) {
- var data = {id: value, text: $el.text()};
- this.$input.select2('data', data);
- }
+ var items = $.fn.editableutils.itemsByValue(val, this.sourceData);
+
+ // There are no items in cases like tagging
+ // So just assume that the tag value is also the text
+ if (items.length === 0) {
+ results.push(value[v]);
+ } else {
+ results.push(items[0].text);
}
}
- },
-
- input2value: function() {
- return this.$input.select2('val');
+
+ //console.log('results', results);
+
+ // The output is the text joined by the viewseparator (comma by default)
+ results = results.join(this.options.viewseparator);
+
+
+ $(element)[this.options.escape ? 'text' : 'html']($.trim(results));
},
- str2value: function(str, separator) {
- if(typeof str !== 'string' || !this.isMultiple) {
- return str;
- }
+ /**
+ * Used to set the value of Select2 based on the current x-editable selections.
+ */
+ value2input: function (value) {
+ //console.log('value2input', value)
- separator = separator || this.getSeparator();
+ // The value for a multiple select can be passed in as a single string
+ // This will convert it from a string to an array of data values
+ if (value && !$.isArray(value) && this.isMultiple) {
+ value = this.str2value(value);
+ }
- var val, i, l;
+ if (!value) {
+ return;
+ }
- if (str === null || str.length < 1) {
- return null;
- }
- val = str.split(separator);
- for (i = 0, l = val.length; i < l; i = i + 1) {
- val[i] = $.trim(val[i]);
- }
+ // Branch off based on whether or not it's a multiple select
+ // Either way, we are adding `` tags for selected values that
+ // don't already exist, so they can be selected correctly.
+ if ($.isArray(value)) {
+ var $options = this.$input.find('option');
+
+ for (var v = 0; v < value.length; v++) {
+ var $filtered = $options.filter(function (i, elem) {
+ return elem.value == value[v].toString();
+ });
+
+ // Check if the option doesn't already exist
+ if ($filtered.length === 0) {
+ // Automatically create the option for the value
+ this.$input.append(new Option(value[v], value[v]));
+ }
+ }
+ } else {
+ var $filtered = this.$input.find('option').filter(function (i, elem) {
+ return elem.value == value.toString()
+ });
+
+ if ($filtered.length === 0) {
+ var $el = $(this.options.scope);
+ var text;
+ if (!$el.data('editable').isEmpty) {
+ text = $el.text();
+ } else {
+ text = value;
+ }
+ this.$input.append(new Option(text, value));
+ }
+ }
- return val;
+ // After setting the value we must trigger the change event for Select2
+ this.$input.val(value).trigger('change');
},
autosubmit: function() {
@@ -274,22 +351,26 @@ $(function(){
},
getSeparator: function() {
- return this.options.select2.separator || $.fn.select2.defaults.separator;
+ return this.options.select2.separator || this.options.separator;
},
/*
Converts source from x-editable format: {value: 1, text: "1"} to
select2 format: {id: 1, text: "1"}
+
+ Also normalizes the id for the source values to always be a string.
*/
- convertSource: function(source) {
- if($.isArray(source) && source.length && source[0].value !== undefined) {
- for(var i = 0; i
- **/
- tpl:' ',
+ Constructor.defaults = $.extend({}, $.fn.editabletypes.select.defaults, {
/**
Configuration of select2. [Full list of options](http://ivaynberg.github.com/select2).
- @property select2
+ @property select2
@type object
@default null
**/
@@ -324,7 +426,7 @@ $(function(){
/**
Placeholder attribute of select
- @property placeholder
+ @property placeholder
@type string
@default null
**/
@@ -334,19 +436,28 @@ $(function(){
Please note, that format is different from simple `select` input: use 'id' instead of 'value'.
E.g. `[{id: 1, text: "text1"}, {id: 2, text: "text2"}, ...]`.
- @property source
+ @property source
@type array|string|function
- @default null
+ @default null
**/
source: null,
/**
Separator used to display tags.
- @property viewseparator
+ @property viewseparator
+ @type string
+ @default ', '
+ **/
+ viewseparator: ', ',
+
+ /**
+ Separator of values when reading from `data-value` attribute
+
+ @property separator
@type string
- @default ', '
+ @default ','
**/
- viewseparator: ', '
+ separator: ','
});
$.fn.editabletypes.select2 = Constructor;
diff --git a/test/loader.js b/test/loader.js
index 2176d5b1..bb5d5b8e 100644
--- a/test/loader.js
+++ b/test/loader.js
@@ -2,59 +2,59 @@
Loads all js files via require.js
*/
define(function () {
-
+
function loadCss(url) {
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = url;
document.getElementsByTagName("head")[0].appendChild(link);
- };
-
+ };
+
return {
loadCss: loadCss,
getConfig: function (baseUrl) {
var
params = this.getParams(),
- f = params.f,
- c = params.c;
-
- var
+ f = params.f,
+ c = params.c;
+
+ var
jqueryui_ver = '1.10.3',
// jqueryui_ver = '1.9.1',
bs2_ver = '232',
bs3_ver = '300',
//path aliases
paths = {
- "bootstrap": "../test/libs/bootstrap"+(f === 'bootstrap2' ? bs2_ver : bs3_ver),
-
- // "jqueryui": "../test/libs/jquery-ui-"+jqueryui_ver+".custom",
- "jqueryui_js": "../test/libs/jquery-ui-"+jqueryui_ver+".custom/js/jquery-ui-"+jqueryui_ver+".custom",
-
+ "bootstrap": "../test/libs/bootstrap"+(f === 'bootstrap2' ? bs2_ver : bs3_ver),
+
+ // "jqueryui": "../test/libs/jquery-ui-"+jqueryui_ver+".custom",
+ "jqueryui_js": "../test/libs/jquery-ui-"+jqueryui_ver+".custom/js/jquery-ui-"+jqueryui_ver+".custom",
+
"dateui_js": "inputs/dateui/jquery-ui-datepicker/js/jquery-ui-"+jqueryui_ver+".custom",
-
+
"poshytip": "../test/libs/poshytip",
-
- "test": "../test"
- },
-
+
+ "test": "../test"
+ },
+
shim = {
'containers/editable-container': {
deps: ['require', 'editable-form/editable-form-utils', 'editable-form/editable-form'],
init: function(require) {
- loadCss(require.toUrl("./editable-container.css"));
- }
- },
-
+ loadCss(require.toUrl("./editable-container.css"));
+ }
+ },
+
//inline container
- 'containers/editable-inline': ['containers/editable-container'],
-
+ 'containers/editable-inline': ['containers/editable-container'],
+
'element/editable-element': {
deps: ['require'], //here should be dynamically added container
init: function(require) {
- loadCss(require.toUrl("./editable-element.css"));
- }
+ loadCss(require.toUrl("./editable-element.css"));
+ }
},
/*
common inputs
@@ -70,67 +70,67 @@ define(function () {
'inputs-ext/address/address',
'inputs/select2/select2'],
init: function(require) {
- loadCss(require.toUrl("./editable-form.css"));
- }
+ loadCss(require.toUrl("./editable-form.css"));
+ }
},
'inputs/select': ['inputs/list'],
'inputs/checklist': ['inputs/list'],
'inputs/list': ['inputs/abstract'],
'inputs/text': ['inputs/abstract'],
'inputs/textarea': ['inputs/abstract'],
- 'inputs/abstract': ['editable-form/editable-form-utils'],
- 'inputs/html5types': ['inputs/text'],
+ 'inputs/abstract': ['editable-form/editable-form-utils'],
+ 'inputs/html5types': ['inputs/text'],
'inputs/combodate/combodate': ['inputs/abstract', 'inputs/combodate/lib/combodate', 'inputs/combodate/lib/moment.min'],
//moment 1.7.2
//'inputs/combodate/combodate': ['inputs/abstract', 'inputs/combodate/lib/combodate', 'inputs/combodate/lib/moment.min.1.7.2'],
- 'inputs/typeahead': ['inputs/list'],
+ 'inputs/typeahead': ['inputs/list'],
/* ------------------------------
bootstrap
- ------------------------------ */
+ ------------------------------ */
'bootstrap/js/bootstrap': {
deps: ['require'],
init: function(require) {
- loadCss(require.toUrl("../css/bootstrap.css"));
+ loadCss(require.toUrl("../css/bootstrap.css"));
//add responsive css for bs2
if(f === 'bootstrap2') {
loadCss(require.toUrl("../css/bootstrap-responsive.css"));
- }
- }
+ }
+ }
},
'editable-form/editable-form-bootstrap': [
- 'editable-form/editable-form',
+ 'editable-form/editable-form',
'bootstrap/js/bootstrap'
],
'editable-form/editable-form-bootstrap3': [
- 'editable-form/editable-form',
+ 'editable-form/editable-form',
'bootstrap/js/bootstrap'
],
'containers/editable-popover': [
- 'containers/editable-inline',
+ 'containers/editable-inline',
'bootstrap/js/bootstrap'
],
'containers/editable-popover3': [
- 'containers/editable-inline',
+ 'containers/editable-inline',
'bootstrap/js/bootstrap'
],
'inputs/date/date': {
- deps: ['require',
+ deps: ['require',
'bootstrap/js/bootstrap',
- 'inputs/abstract',
+ 'inputs/abstract',
'inputs/date/bootstrap-datepicker/js/bootstrap-datepicker'],
init: function(require) {
- loadCss(require.toUrl("./bootstrap-datepicker/css/datepicker.css"));
+ loadCss(require.toUrl("./bootstrap-datepicker/css/datepicker.css"));
}
},
'inputs/datetime/datetime': {
- deps: ['require',
+ deps: ['require',
'bootstrap/js/bootstrap',
- 'inputs/abstract',
+ 'inputs/abstract',
'inputs/datetime/bootstrap-datetimepicker/js/bootstrap-datetimepicker'],
init: function(require) {
- loadCss(require.toUrl("./bootstrap-datetimepicker/css/datetimepicker.css"));
+ loadCss(require.toUrl("./bootstrap-datetimepicker/css/datetimepicker.css"));
}
},
@@ -138,30 +138,27 @@ define(function () {
// 'inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.min': ['inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysihtml5-0.3.0.min'],
'inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2': ['inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/wysihtml5-0.3.0'],
'inputs-ext/wysihtml5/wysihtml5': {
- deps: ['require',
+ deps: ['require',
'bootstrap/js/bootstrap',
- 'inputs/abstract',
+ 'inputs/abstract',
// 'inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.min'],
'inputs-ext/wysihtml5/bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2'],
init: function(require) {
- loadCss(require.toUrl("./bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.css"));
- //loadCss(require.toUrl("./bootstrap-wysihtml5-0.0.2/wysiwyg-color.css"));
+ loadCss(require.toUrl("./bootstrap-wysihtml5-0.0.2/bootstrap-wysihtml5-0.0.2.css"));
+ //loadCss(require.toUrl("./bootstrap-wysihtml5-0.0.2/wysiwyg-color.css"));
}
},
-
+
//select2
'inputs/select2/select2': {
- deps: ['require',
+ deps: ['require',
'inputs/select2/lib/select2',
- 'inputs/abstract'],
+ 'inputs/select'],
init: function(require) {
- loadCss(require.toUrl("./lib/select2.css"));
- if (f === 'bootstrap2' || f === 'bootstrap3') {
- loadCss(require.toUrl("./lib/select2-bootstrap.css"));
- }
+ loadCss(require.toUrl("./lib/select2.css"));
}
- },
-
+ },
+
//datefield
'inputs/date/datefield': ['inputs/date/date'],
@@ -170,67 +167,67 @@ define(function () {
/* ------------------------------
jqueryui
- ------------------------------ */
+ ------------------------------ */
'jqueryui_js': {
deps: ['require'],
//temp: test simultaneous jquery-ui with bootstrap
//deps: ['require', 'bootstrap/js/bootstrap'],
init: function(require) {
- //loadCss(require.toUrl("../css/redmond/jquery-ui-1.10.1.custom.css"));
- loadCss(require.toUrl("../test/libs/jquery-ui-"+jqueryui_ver+".custom/css/redmond/jquery-ui-"+jqueryui_ver+".custom.css"));
- }
- },
+ //loadCss(require.toUrl("../css/redmond/jquery-ui-1.10.1.custom.css"));
+ loadCss(require.toUrl("../test/libs/jquery-ui-"+jqueryui_ver+".custom/css/redmond/jquery-ui-"+jqueryui_ver+".custom.css"));
+ }
+ },
'editable-form/editable-form-jqueryui': [
- 'editable-form/editable-form',
+ 'editable-form/editable-form',
'jqueryui_js'
- ],
+ ],
'containers/editable-tooltip': [
- 'containers/editable-inline',
+ 'containers/editable-inline',
'jqueryui_js'
- ],
+ ],
'inputs/dateui/dateui': ['inputs/abstract'],
'inputs/dateui/dateuifield': ['inputs/dateui/dateui'],
/* ------------------------------
plain
- ------------------------------ */
- 'containers/editable-poshytip': [
- 'containers/editable-inline',
+ ------------------------------ */
+ 'containers/editable-poshytip': [
+ 'containers/editable-inline',
'poshytip/jquery.poshytip'
],
'poshytip/jquery.poshytip': {
deps: ['require'],
init: function(require) {
- loadCss(require.toUrl("./tip-yellowsimple/tip-yellowsimple.css"));
- }
+ loadCss(require.toUrl("./tip-yellowsimple/tip-yellowsimple.css"));
+ }
},
'dateui_js': {
deps: ['require'],
init: function(require) {
- //loadCss(require.toUrl('../css/redmond/jquery-ui-'+jqueryui_ver+'.custom.css'));
- loadCss(require.toUrl('inputs/dateui/jquery-ui-datepicker/css/redmond/jquery-ui-'+jqueryui_ver+'.custom.css'));
- }
+ //loadCss(require.toUrl('../css/redmond/jquery-ui-'+jqueryui_ver+'.custom.css'));
+ loadCss(require.toUrl('inputs/dateui/jquery-ui-datepicker/css/redmond/jquery-ui-'+jqueryui_ver+'.custom.css'));
+ }
},
-
+
/* ------------------------------
inputs-ext
- ------------------------------ */
+ ------------------------------ */
'inputs-ext/address/address': {
deps: ['require', 'inputs/abstract'],
init: function(require) {
- loadCss(require.toUrl("./address.css"));
+ loadCss(require.toUrl("./address.css"));
}
},
- 'inputs-ext/typeaheadjs/typeaheadjs': {
+ 'inputs-ext/typeaheadjs/typeaheadjs': {
deps: [
'require',
'inputs/text',
'inputs-ext/typeaheadjs/lib/typeahead'
],
init: function(require) {
- loadCss(require.toUrl("./lib/typeahead.js-bootstrap.css"));
+ loadCss(require.toUrl("./lib/typeahead.js-bootstrap.css"));
}
}
};
@@ -238,9 +235,9 @@ define(function () {
/*
modify shim for bootstrap, jqueryui or plain
*/
- if(f === 'bootstrap3') {
+ if(f === 'bootstrap3') {
//bootstrap 3
- shim['editable-form/editable-form'].deps = shim['editable-form/editable-form'].deps.concat(
+ shim['editable-form/editable-form'].deps = shim['editable-form/editable-form'].deps.concat(
[
'inputs/date/datefield',
'inputs/datetime/datetimefield',
@@ -251,9 +248,9 @@ define(function () {
shim['element/editable-element'].deps.push('editable-form/editable-form-bootstrap3');
shim['element/editable-element'].deps.push('containers/editable-popover3');
- } else if(f === 'bootstrap2') {
+ } else if(f === 'bootstrap2') {
//bootstrap 2
- shim['editable-form/editable-form'].deps = shim['editable-form/editable-form'].deps.concat(
+ shim['editable-form/editable-form'].deps = shim['editable-form/editable-form'].deps.concat(
[
'inputs/date/datefield',
'inputs/datetime/datetimefield',
@@ -267,38 +264,38 @@ define(function () {
shim['editable-form/editable-form'].deps.push('inputs/dateui/dateuifield');
shim['element/editable-element'].deps.push('editable-form/editable-form-jqueryui');
shim['element/editable-element'].deps.push('containers/editable-tooltip');
- } else {
+ } else {
//plain
shim['editable-form/editable-form'].deps.push('inputs/dateui/dateuifield');
shim['inputs/dateui/dateui'].push('dateui_js');
- shim['element/editable-element'].deps.push('containers/editable-poshytip');
- }
-
-
+ shim['element/editable-element'].deps.push('containers/editable-poshytip');
+ }
+
+
/*
return requirejs config
- */
-
+ */
+
return {
baseUrl: baseUrl,
paths: paths,
shim: shim
- };
+ };
},
getParams: function() {
var url = window.location.href, f, c;
- if(url.match(/f=jqueryui/i)) {
+ if(url.match(/f=jqueryui/i)) {
f = 'jqueryui';
} else if(url.match(/f=plain/i)) {
f = 'plain';
- } else if(url.match(/f=bootstrap3/i) || url.match(/f=bs3/i)) {
+ } else if(url.match(/f=bootstrap3/i) || url.match(/f=bs3/i)) {
f = 'bootstrap3';
- } else {
+ } else {
f = 'bootstrap2';
}
c = url.match(/c=inline/i) ? 'inline' : 'popup';
return {f: f, c: c};
}
}
-});
\ No newline at end of file
+});
diff --git a/test/unit/select2.js b/test/unit/select2.js
index 01f521cd..0d97aa16 100644
--- a/test/unit/select2.js
+++ b/test/unit/select2.js
@@ -1,13 +1,13 @@
$(function () {
-
+
module("select2", {
setup: function(){
sfx = $('#qunit-fixture'),
- fx = $('#async-fixture');
+ fx = $('#async-fixture');
$.support.transition = false;
}
- });
-
+ });
+
asyncTest("local: init-change-save (not multiple)", function () {
var s = 2, text = 'text2',
e = $(' ').appendTo(fx).editable({
@@ -17,86 +17,86 @@ $(function () {
//autotext
equal(e.data('editable').value, s, 'initial value ok');
- equal(e.text(), text, 'intial text ok');
-
+ equal(e.text(), text, 'intial text ok');
+
e.click();
var p = tip(e);
-
ok(p.is(':visible'), 'popover visible');
- var $input = p.find('input[type="hidden"]');
+ var $input = p.find('select');
ok($input.length, 'input exists');
ok($input.select2, 'select2 applied');
- equal($input.val(), e.data('editable').value, 'selected value correct');
- equal(p.find('.select2-choice span').text(), text, 'selected text correct');
-
+ equal($input.val(), e.data('editable').value, 'selected value correct');
+ equal(p.find('.select2-selection').text(), text, 'selected text correct');
+
//select new value
- s = 1;
+ s = 1;
text = 'text1';
- $input.select2('val', s);
+ $input.val(s).trigger('change');
- equal($input.val(), s, 'new value ok');
- equal(p.find('.select2-choice span').text(), text, 'new text ok');
+ equal($input.val(), s, 'new value ok');
+ equal(p.find('.select2-selection').text(), text, 'new text ok');
p.find('form').submit();
-
+
setTimeout(function() {
ok(!p.is(':visible'), 'popover closed');
equal(e.data('editable').value, s, 'new value ok');
- equal(e.text(), text, 'new text ok');
-
+ equal(e.text(), text, 'new text ok');
+
e.remove();
start();
}, timeout);
- });
-
+ });
+
asyncTest("local: init-change-save (multiple)", function () {
var s = '2,3', text = 'text2, text3',
e = $(' ').appendTo(fx).editable({
source: [{id: 1, text: 'text1'}, {id: 2, text: 'text2'}, {id: 3, text: 'text3'}],
- viewseparator: ', ',
select2: {
multiple: true
}
});
+ console.log('init', e.data('editable').value)
+
//autotext
equal(e.data('editable').value.join(','), s, 'initial value ok');
- equal(e.text(), text, 'intial text ok');
-
+ equal(e.text(), text, 'intial text ok');
+
e.click();
var p = tip(e);
-
+
ok(p.is(':visible'), 'popover visible');
- var $input = p.find('input[type="hidden"]');
+ var $input = p.find('select');
ok($input.length, 'input exists');
- ok($input.select2, 'select2 applied');
- equal($input.val(), s, 'selected value ok');
- equal(p.find('.select2-search-choice > div').length, 2, 'selected text ok');
- equal(p.find('.select2-search-choice > div').eq(0).text(), 'text2', 'text2 ok');
- equal(p.find('.select2-search-choice > div').eq(1).text(), 'text3', 'text3 ok');
-
+ ok($input.data('select2'), 'select2 applied');
+ equal($input.val(), s, 'selected value ok');
+ equal(p.find('.select2-selection__choice').length, 2, 'selected text ok');
+ equal(p.find('.select2-selection__choice').eq(0).text().substr(1), 'text2', 'text2 ok');
+ equal(p.find('.select2-selection__choice').eq(1).text().substr(1), 'text3', 'text3 ok');
+
//select new value
- s = '1,2';
+ s = '1,2';
text = 'text1, text2';
- $input.select2('val', [1, 2]);
+ $input.val([1, 2]).trigger('change');
- equal($input.val(), s, 'new value ok');
- equal(p.find('.select2-search-choice > div').length, 2, 'new text ok');
- equal(p.find('.select2-search-choice > div').eq(0).text(), 'text1', 'text1 ok');
- equal(p.find('.select2-search-choice > div').eq(1).text(), 'text2', 'text2 ok');
+ equal($input.val(), s, 'new value ok');
+ equal(p.find('.select2-selection__choice').length, 2, 'new text ok');
+ equal(p.find('.select2-selection__choice').eq(0).text().substr(1), 'text1', 'text1 ok');
+ equal(p.find('.select2-selection__choice').eq(1).text().substr(1), 'text2', 'text2 ok');
p.find('form').submit();
-
+
setTimeout(function() {
ok(!p.is(':visible'), 'popover closed');
equal(e.data('editable').value, s, 'new value ok');
- equal(e.text(), text, 'new text ok');
-
+ equal(e.text(), text, 'new text ok');
+
e.remove();
start();
}, timeout);
- });
-
+ });
+
asyncTest("local: tags (simple array)", function () {
var s = 'text2,abc', text = 'text2, abc',
e = $(''+text+' ').appendTo(fx).editable({
@@ -106,46 +106,52 @@ $(function () {
}
});
+ console.log('init', e.data('editable'))
+
equal(e.data('editable').value.join(','), s, 'initial value ok');
-
+
e.click();
var p = tip(e);
-
+
ok(p.is(':visible'), 'popover visible');
- var $input = p.find('input[type="hidden"]');
+ var $input = p.find('select');
ok($input.length, 'input exists');
- ok($input.select2, 'select2 applied');
- equal($input.val(), s, 'selected value ok');
- equal(p.find('.select2-search-choice > div').length, 2, 'selected text ok');
- equal(p.find('.select2-search-choice > div').eq(0).text(), 'text2', 'text2 ok');
- equal(p.find('.select2-search-choice > div').eq(1).text(), 'abc', 'abc ok');
-
+ ok($input.data('select2'), 'select2 applied');
+ equal($input.val(), s, 'selected value ok');
+ equal(p.find('.select2-selection__choice').length, 2, 'selected text ok');
+ equal(p.find('.select2-selection__choice').eq(0).text().substr(1), 'text2', 'text2 ok');
+ equal(p.find('.select2-selection__choice').eq(1).text().substr(1), 'abc', 'abc ok');
+
+ $input.append(new Option('cde', 'cde'));
+
//select new value
- s = 'text1,cde';
+ s = 'text1,cde';
text = 'text1, cde';
- $input.select2('val', ['text1', 'cde']);
+ $input.val(['text1', 'cde']).trigger('change');
- equal($input.val(), s, 'new value ok');
- equal(p.find('.select2-search-choice > div').length, 2, 'new text ok');
- equal(p.find('.select2-search-choice > div').eq(0).text(), 'text1', 'text1 ok');
- equal(p.find('.select2-search-choice > div').eq(1).text(), 'cde', 'cde ok');
+ equal($input.val().join(','), s, 'new value ok');
+ equal(p.find('.select2-selection__choice').length, 2, 'new text ok');
+ equal(p.find('.select2-selection__choice').eq(0).text().substr(1), 'text1', 'text1 ok');
+ equal(p.find('.select2-selection__choice').eq(1).text().substr(1), 'cde', 'cde ok');
+ console.log('pre-submit');
p.find('form').submit();
-
+ console.log('post-submit')
+
setTimeout(function() {
ok(!p.is(':visible'), 'popover closed');
- equal(e.data('editable').value, s, 'new value ok');
- equal(e.text(), text, 'new text ok');
-
+ equal(e.data('editable').value.join(','), s, 'new value ok');
+ equal(e.text(), text, 'new text ok');
+
e.remove();
start();
}, timeout);
- });
-
+ });
+
asyncTest("local: tags with space separator", function () {
var sep = ' ', vsep = '-',
- s = 'a,text2 abc d',
+ s = 'a,text2 abc d',
text = 'a,text2-abc-d',
e = $(' ').appendTo(fx).editable({
viewseparator: vsep,
@@ -157,43 +163,47 @@ $(function () {
equal(e.data('editable').value.join(sep), s, 'initial value ok');
equal(e.data('editable').value.join(vsep), text, 'initial text ok');
-
+
e.click();
var p = tip(e);
-
+
ok(p.is(':visible'), 'popover visible');
- var $input = p.find('input[type="hidden"]');
+ var $input = p.find('select');
ok($input.length, 'input exists');
- ok($input.select2, 'select2 applied');
- equal($input.val(), s, 'selected value ok');
-
- equal(p.find('.select2-search-choice > div').length, 3, 'selected text ok');
- equal(p.find('.select2-search-choice > div').eq(0).text(), 'a,text2', 'text2 ok');
- equal(p.find('.select2-search-choice > div').eq(1).text(), 'abc', 'abc ok');
- equal(p.find('.select2-search-choice > div').eq(2).text(), 'd', 'd ok');
-
+ ok($input.data('select2'), 'select2 applied');
+ equal($input.val().join(sep), s, 'selected value ok');
+
+ equal(p.find('.select2-selection__choice').length, 3, 'selected text ok');
+ equal(p.find('.select2-selection__choice').eq(0).text().substr(1), 'a,text2', 'text2 ok');
+ equal(p.find('.select2-selection__choice').eq(1).text().substr(1), 'abc', 'abc ok');
+ equal(p.find('.select2-selection__choice').eq(2).text().substr(1), 'd', 'd ok');
+
+
+ $input.append(new Option('a,text1', 'a,text1'));
+ $input.append(new Option('cde', 'cde'));
+
//select new value
- s = 'a,text1 cde';
+ s = 'a,text1 cde';
text = 'a,text1-cde';
- $input.select2('val', ['a,text1', 'cde']);
+ $input.val(['a,text1', 'cde']).trigger('change');
- equal($input.val(), s, 'new value ok');
- equal(p.find('.select2-search-choice > div').length, 2, 'new text ok');
- equal(p.find('.select2-search-choice > div').eq(0).text(), 'a,text1', 'text1 ok');
- equal(p.find('.select2-search-choice > div').eq(1).text(), 'cde', 'cde ok');
+ equal($input.val().join(sep), s, 'new value ok');
+ equal(p.find('.select2-selection__choice').length, 2, 'new text ok');
+ equal(p.find('.select2-selection__choice').eq(0).text().substr(1), 'a,text1', 'text1 ok');
+ equal(p.find('.select2-selection__choice').eq(1).text().substr(1), 'cde', 'cde ok');
p.find('form').submit();
-
+
setTimeout(function() {
ok(!p.is(':visible'), 'popover closed');
equal(e.data('editable').value.join(sep), s, 'new value ok');
- equal(e.text(), text, 'new text ok');
-
+ equal(e.text(), text, 'new text ok');
+
e.remove();
start();
}, timeout);
- });
- /*
+ });
+ /*
asyncTest("local: tags (array of objects)", function () {
var s = 'text2,abc', text = 'text2, abc',
e = $(' ').appendTo(fx).editable({
@@ -205,41 +215,41 @@ $(function () {
});
equal(e.text(), 'text1, text2', 'initial text ok');
-
+
e.click();
var p = tip(e);
-
+
ok(p.is(':visible'), 'popover visible');
var $input = p.find('input[type="hidden"]');
ok($input.length, 'input exists');
ok($input.select2, 'select2 applied');
- equal($input.val(), '1,2', 'selected value ok');
- equal(p.find('.select2-search-choice > div').length, 2, 'selected text ok');
- equal(p.find('.select2-search-choice > div').eq(0).text(), 'text1', 'text1 ok');
- equal(p.find('.select2-search-choice > div').eq(1).text(), 'text2', 'text2 ok');
-
+ equal($input.val(), '1,2', 'selected value ok');
+ equal(p.find('.select2-search-choice > div').length, 2, 'selected text ok');
+ equal(p.find('.select2-search-choice > div').eq(0).text(), 'text1', 'text1 ok');
+ equal(p.find('.select2-search-choice > div').eq(1).text(), 'text2', 'text2 ok');
+
//select new value
-// s = 'text1,cde';
+// s = 'text1,cde';
// text = 'text1, cde';
$input.select2('val', [1]);
- equal($input.val(), '1', 'new value ok');
- equal(p.find('.select2-search-choice > div').length, 1, 'new text ok');
- equal(p.find('.select2-search-choice > div').eq(0).text(), 'text1', 'text1 ok');
+ equal($input.val(), '1', 'new value ok');
+ equal(p.find('.select2-search-choice > div').length, 1, 'new text ok');
+ equal(p.find('.select2-search-choice > div').eq(0).text(), 'text1', 'text1 ok');
p.find('form').submit();
-
+
setTimeout(function() {
ok(!p.is(':visible'), 'popover closed');
equal(e.data('editable').value.length, 1, 'new value ok');
- equal(e.text(), 'text1', 'new text ok');
-
+ equal(e.text(), 'text1', 'new text ok');
+
e.remove();
start();
}, timeout);
- });
- */
-
+ });
+ */
+
test("local: setValue + x-editable source", function () {
var e = $('test2 ').appendTo('#qunit-fixture').editable({
source: [{value: 1, text: 'text1'}, {value: 2, text: 'text2'}, {value: 3, text: 'text3'}]
@@ -247,12 +257,12 @@ $(function () {
//autotext
equal(e.data('editable').value, 1, 'initial value ok');
-
+
//setValue before open
e.editable('setValue', 2);
equal(e.data('editable').value, 2, 'value ok');
equal(e.text(), 'text2', 'text ok');
-
+
//open
e.click();
var p = tip(e);
@@ -262,63 +272,68 @@ $(function () {
e.editable('setValue', 3);
equal(e.data('editable').value, 3, 'value ok');
equal(e.text(), 'text3', 'text ok');
- });
-
+ });
+
asyncTest("remote: init-change-save, just url (not multiple)", function () {
var s = 2, text = groups[s],
newVal = 0, newText = groups[newVal],
e = $(''+text+' ').appendTo(fx).editable({
source: 'groupsArr2'
});
-
+
+ //autotext
+ equal(e.data('editable').value, s, 'initial value ok');
+ equal(e.text(), text, 'intial text ok');
+
e.click();
var p = tip(e);
-
+
ok(p.is(':visible'), 'popover visible');
- equal(p.find('.select2-choice span').text(), text, 'selected text correct');
-
- var $input = p.find('input[type="hidden"]');
+
+ var $input = p.find('select');
+
ok($input.length, 'input exists');
- ok($input.select2, 'select2 applied');
- equal($input.val(), e.data('editable').value, 'selected value correct');
-
- //click to load items
- p.find('.select2-choice').mousedown();
-
+ ok($input.data('select2'), 'select2 applied');
+
setTimeout(function() {
+ equal($input.val(), e.data('editable').value, 'selected value correct');
+ equal(p.find('.select2-selection').text(), text, 'selected text correct');
+
+ $input.select2('open');
+
equal($('.select2-results li').length, groupsArr2.length, 'items loaded');
- equal($('.select2-results .select2-highlighted > .select2-result-label').text(), text, 'highlight ok');
-
+ equal($('.select2-results__option--highlighted').text(), text, 'highlight ok');
+
//select new value (0)
$('.select2-results li').eq(newVal).mouseup();
- equal(p.find('.select2-choice span').text(), newText, 'new selected text ok');
-
+ equal(p.find('.select2-selection').text(), newText, 'new selected text ok');
+
//submit
p.find('form').submit();
-
+
setTimeout(function() {
ok(!p.is(':visible'), 'popover closed');
equal(e.data('editable').value, newVal, 'new value ok');
- equal(e.text(), newText, 'new text ok');
+ equal(e.text(), newText, 'new text ok');
//open again
e.click();
p = tip(e);
- equal(p.find('.select2-choice span').text(), newText, 'text ok on second open');
- equal($input.val(), newVal, 'selected value ok on second open');
-
+ equal(p.find('.select2-selection').text(), newText, 'text ok on second open');
+ equal($input.val(), newVal, 'selected value ok on second open');
+
//setValue in closed state
p.find('.editable-cancel').click();
e.editable('setValue', 1);
equal(e.data('editable').value, 1, 'setValue: value ok');
- equal(e.text(), groups[1], 'setValue: text ok');
-
+ equal(e.text(), groups[1], 'setValue: text ok');
+
e.remove();
start();
}, timeout);
- }, timeout);
- });
-
+ }, timeout);
+ });
+
test("remote: initially empty", function () {
var s = 2, text = groups[s],
newVal = 0, newText = groups[newVal],
@@ -327,22 +342,22 @@ $(function () {
select2: {
placeholder: 'placeholder'
}
- });
-
+ });
+
e.click();
var p = tip(e);
-
+
ok(p.is(':visible'), 'popover visible');
- equal(p.find('.select2-choice span').text(), 'placeholder', 'placeholder shown in select2');
- });
-
+ equal(p.find('.select2-selection').text(), 'placeholder', 'placeholder shown in select2');
+ });
+
asyncTest("remote: custom id, custom text, init selection (not multiple)", function () {
var s = 2,
data = [
{cid: 1, name: '111'},
{cid: 2, name: '222'}
],
- idIndex,
+ idIndex,
text = '222', req = 0,
newVal = 0, newText = groups[newVal],
e = $(''+text+' ').appendTo(fx).editable({
@@ -369,13 +384,14 @@ $(function () {
return e.name;
},
initSelection: function (element, callback) {
+ console.log('initSelection');
return $.get('/select2id', { query: element.val() }, function (data) {
callback(data);
}, 'json');
- }
+ }
}
});
-
+
//mocks
$.mockjax({
url: '/select2list',
@@ -384,8 +400,8 @@ $(function () {
req++;
this.responseText = data;
}
- });
-
+ });
+
$.mockjax({
url: '/select2id',
responseTime: 50,
@@ -393,56 +409,58 @@ $(function () {
req++;
this.responseText = data[idIndex];
}
- });
-
+ });
+
//start
idIndex = 1;
e.click();
var p = tip(e);
-
+
+ var $input = p.find('select');
+
ok(p.is(':visible'), 'popover visible');
-
+
//waiting for initSelection
setTimeout(function() {
- equal(p.find('.select2-choice span').text(), text, 'selected text correct');
- equal(req, 1, '1 request ok');
-
+ equal(p.find('.select2-selection').text(), text, 'selected text correct');
+ equal(req, 1, '1 request ok');
+
//enter 1 symbol
- p.find('.select2-choice').mousedown();
- $('.select2-search .select2-input:visible').val('1').trigger('keyup-change');
-
+ $input.select2('open');
+ $('.select2-search__field').val('1').trigger('keyup');
+
//wait for list loading
setTimeout(function() {
equal($('.select2-results li').length, data.length, 'items loaded');
- equal($('.select2-results .select2-highlighted > .select2-result-label').text(), data[0].name, 'highlight ok');
-
+ equal($('.select2-results__option--highlighted').text(), data[1].name, 'highlight ok');
+
//click on first
var newVal = 1, newText = '111';
$('.select2-results li').eq(0).mouseup();
- equal(p.find('.select2-choice span').text(), data[0].name, 'new selected text ok');
-
+ equal(p.find('.select2-selection').text(), data[0].name, 'new selected text ok');
+
//submit
p.find('form').submit();
-
+
setTimeout(function() {
ok(!p.is(':visible'), 'popover closed');
equal(e.data('editable').value, newVal, 'new value ok');
- equal(e.text(), newText, 'new text ok');
+ equal(e.text(), newText, 'new text ok');
//open again
idIndex = 0;
e.click();
setTimeout(function() {
p = tip(e);
- var $input = p.find('input[type="hidden"]');
- equal(p.find('.select2-choice span').text(), newText, 'text ok on second open');
- equal($input.val(), newVal, 'selected value ok on second open');
-
+ var $input = p.find('select');
+ equal(p.find('.select2-selection').text(), newText, 'text ok on second open');
+ equal($input.val(), newVal, 'selected value ok on second open');
+
e.remove();
start();
}, timeout);
}, timeout);
- }, timeout);
+ }, timeout);
}, timeout);
- });
-});
\ No newline at end of file
+ });
+});