|
585 | 585 | }));
|
586 | 586 |
|
587 | 587 | /**
|
588 |
| - * selectize.js (v0.9.1) |
| 588 | + * selectize.js (v0.10.0) |
589 | 589 | * Copyright (c) 2013 Brian Reavis & contributors
|
590 | 590 | *
|
591 | 591 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
|
|
1077 | 1077 | isCmdDown : false,
|
1078 | 1078 | isCtrlDown : false,
|
1079 | 1079 | ignoreFocus : false,
|
| 1080 | + ignoreBlur : false, |
1080 | 1081 | ignoreHover : false,
|
1081 | 1082 | hasOptions : false,
|
1082 | 1083 | currentResults : null,
|
|
1113 | 1114 | self.settings.hideSelected = self.settings.mode === 'multi';
|
1114 | 1115 | }
|
1115 | 1116 |
|
| 1117 | + if (self.settings.create) { |
| 1118 | + self.canCreate = function(input) { |
| 1119 | + var filter = self.settings.createFilter; |
| 1120 | + return input.length |
| 1121 | + && (typeof filter !== 'function' || filter(input)) |
| 1122 | + && (typeof filter !== 'string' || new RegExp(filter).test(input)) |
| 1123 | + && (!(filter instanceof RegExp) || filter.test(input)); |
| 1124 | + }; |
| 1125 | + } |
| 1126 | + |
1116 | 1127 | self.initializePlugins(self.settings.plugins);
|
1117 | 1128 | self.setupCallbacks();
|
1118 | 1129 | self.setupTemplates();
|
|
1139 | 1150 | var eventNS = self.eventNS;
|
1140 | 1151 | var $window = $(window);
|
1141 | 1152 | var $document = $(document);
|
| 1153 | + var $input = self.$input; |
1142 | 1154 |
|
1143 | 1155 | var $wrapper;
|
1144 | 1156 | var $control;
|
|
1154 | 1166 | var classes_plugins;
|
1155 | 1167 |
|
1156 | 1168 | inputMode = self.settings.mode;
|
1157 |
| - tab_index = self.$input.attr('tabindex') || ''; |
1158 |
| - classes = self.$input.attr('class') || ''; |
| 1169 | + tab_index = $input.attr('tabindex') || ''; |
| 1170 | + classes = $input.attr('class') || ''; |
1159 | 1171 |
|
1160 | 1172 | $wrapper = $('<div>').addClass(settings.wrapperClass).addClass(classes).addClass(inputMode);
|
1161 | 1173 | $control = $('<div>').addClass(settings.inputClass).addClass('items').appendTo($wrapper);
|
|
1165 | 1177 | $dropdown_content = $('<div>').addClass(settings.dropdownContentClass).appendTo($dropdown);
|
1166 | 1178 |
|
1167 | 1179 | $wrapper.css({
|
1168 |
| - width: self.$input[0].style.width |
| 1180 | + width: $input[0].style.width |
1169 | 1181 | });
|
1170 | 1182 |
|
1171 | 1183 | if (self.plugins.names.length) {
|
|
1175 | 1187 | }
|
1176 | 1188 |
|
1177 | 1189 | if ((settings.maxItems === null || settings.maxItems > 1) && self.tagType === TAG_SELECT) {
|
1178 |
| - self.$input.attr('multiple', 'multiple'); |
| 1190 | + $input.attr('multiple', 'multiple'); |
1179 | 1191 | }
|
1180 | 1192 |
|
1181 | 1193 | if (self.settings.placeholder) {
|
1182 | 1194 | $control_input.attr('placeholder', settings.placeholder);
|
1183 | 1195 | }
|
1184 | 1196 |
|
1185 |
| - if (self.$input.attr('autocorrect')) { |
1186 |
| - $control_input.attr('autocorrect', self.$input.attr('autocorrect')); |
| 1197 | + if ($input.attr('autocorrect')) { |
| 1198 | + $control_input.attr('autocorrect', $input.attr('autocorrect')); |
1187 | 1199 | }
|
1188 | 1200 |
|
1189 |
| - if (self.$input.attr('autocapitalize')) { |
1190 |
| - $control_input.attr('autocapitalize', self.$input.attr('autocapitalize')); |
| 1201 | + if ($input.attr('autocapitalize')) { |
| 1202 | + $control_input.attr('autocapitalize', $input.attr('autocapitalize')); |
1191 | 1203 | }
|
1192 | 1204 |
|
1193 | 1205 | self.$wrapper = $wrapper;
|
|
1213 | 1225 | keypress : function() { return self.onKeyPress.apply(self, arguments); },
|
1214 | 1226 | resize : function() { self.positionDropdown.apply(self, []); },
|
1215 | 1227 | blur : function() { return self.onBlur.apply(self, arguments); },
|
1216 |
| - focus : function() { return self.onFocus.apply(self, arguments); }, |
| 1228 | + focus : function() { self.ignoreBlur = false; return self.onFocus.apply(self, arguments); }, |
1217 | 1229 | paste : function() { return self.onPaste.apply(self, arguments); }
|
1218 | 1230 | });
|
1219 | 1231 |
|
|
1254 | 1266 | // store original children and tab index so that they can be
|
1255 | 1267 | // restored when the destroy() method is called.
|
1256 | 1268 | this.revertSettings = {
|
1257 |
| - $children : self.$input.children().detach(), |
1258 |
| - tabindex : self.$input.attr('tabindex') |
| 1269 | + $children : $input.children().detach(), |
| 1270 | + tabindex : $input.attr('tabindex') |
1259 | 1271 | };
|
1260 | 1272 |
|
1261 |
| - self.$input.attr('tabindex', -1).hide().after(self.$wrapper); |
| 1273 | + $input.attr('tabindex', -1).hide().after(self.$wrapper); |
1262 | 1274 |
|
1263 | 1275 | if ($.isArray(settings.items)) {
|
1264 | 1276 | self.setValue(settings.items);
|
1265 | 1277 | delete settings.items;
|
1266 | 1278 | }
|
1267 | 1279 |
|
1268 | 1280 | // feature detect for the validation API
|
1269 |
| - if (self.$input[0].validity) { |
1270 |
| - self.$input.on('invalid' + eventNS, function(e) { |
| 1281 | + if ($input[0].validity) { |
| 1282 | + $input.on('invalid' + eventNS, function(e) { |
1271 | 1283 | e.preventDefault();
|
1272 | 1284 | self.isInvalid = true;
|
1273 | 1285 | self.refreshState();
|
|
1280 | 1292 | self.updatePlaceholder();
|
1281 | 1293 | self.isSetup = true;
|
1282 | 1294 |
|
1283 |
| - if (self.$input.is(':disabled')) { |
| 1295 | + if ($input.is(':disabled')) { |
1284 | 1296 | self.disable();
|
1285 | 1297 | }
|
1286 | 1298 |
|
1287 | 1299 | self.on('change', this.onChange);
|
| 1300 | + |
| 1301 | + $input.data('selectize', self); |
| 1302 | + $input.addClass('selectized'); |
1288 | 1303 | self.trigger('initialize');
|
1289 | 1304 |
|
1290 | 1305 | // preload options
|
1291 | 1306 | if (settings.preload === true) {
|
1292 | 1307 | self.onSearchChange('');
|
1293 | 1308 | }
|
| 1309 | + |
1294 | 1310 | },
|
1295 | 1311 |
|
1296 | 1312 | /**
|
|
1505 | 1521 | case KEY_TAB:
|
1506 | 1522 | if (self.settings.selectOnTab && self.isOpen && self.$activeOption) {
|
1507 | 1523 | self.onOptionSelect({currentTarget: self.$activeOption});
|
| 1524 | + e.preventDefault(); |
1508 | 1525 | }
|
1509 | 1526 | if (self.settings.create && self.createItem()) {
|
1510 | 1527 | e.preventDefault();
|
|
1599 | 1616 | self.isFocused = false;
|
1600 | 1617 | if (self.ignoreFocus) return;
|
1601 | 1618 |
|
| 1619 | + // necessary to prevent IE closing the dropdown when the scrollbar is clicked |
| 1620 | + if (!self.ignoreBlur && document.activeElement === self.$dropdown_content[0]) { |
| 1621 | + self.ignoreBlur = true; |
| 1622 | + self.onFocus(e); |
| 1623 | + |
| 1624 | + return; |
| 1625 | + } |
| 1626 | + |
1602 | 1627 | if (self.settings.create && self.settings.createOnBlur) {
|
1603 | 1628 | self.createItem(false);
|
1604 | 1629 | }
|
|
2077 | 2102 | }
|
2078 | 2103 |
|
2079 | 2104 | // add create option
|
2080 |
| - has_create_option = self.settings.create && results.query.length; |
| 2105 | + has_create_option = self.settings.create && self.canCreate(results.query); |
2081 | 2106 | if (has_create_option) {
|
2082 | 2107 | $dropdown_content.prepend(self.render('option_create', {input: query}));
|
2083 | 2108 | $create = $($dropdown_content[0].childNodes[0]);
|
|
2331 | 2356 | var $item, $option, $options;
|
2332 | 2357 | var self = this;
|
2333 | 2358 | var inputMode = self.settings.mode;
|
2334 |
| - var i, active, value_next; |
| 2359 | + var i, active, value_next, wasFull; |
2335 | 2360 | value = hash_key(value);
|
2336 | 2361 |
|
2337 | 2362 | if (self.items.indexOf(value) !== -1) {
|
|
2344 | 2369 | if (inputMode === 'multi' && self.isFull()) return;
|
2345 | 2370 |
|
2346 | 2371 | $item = $(self.render('item', self.options[value]));
|
| 2372 | + wasFull = self.isFull(); |
2347 | 2373 | self.items.splice(self.caretPos, 0, value);
|
2348 | 2374 | self.insertAtCaret($item);
|
2349 |
| - self.refreshState(); |
| 2375 | + if (!self.isPending || (!wasFull && self.isFull())) { |
| 2376 | + self.refreshState(); |
| 2377 | + } |
2350 | 2378 |
|
2351 | 2379 | if (self.isSetup) {
|
2352 | 2380 | $options = self.$dropdown_content.find('[data-selectable]');
|
2353 | 2381 |
|
2354 | 2382 | // update menu / remove the option (if this is not one item being added as part of series)
|
2355 |
| - if (!this.isPending) { |
| 2383 | + if (!self.isPending) { |
2356 | 2384 | $option = self.getOption(value);
|
2357 | 2385 | value_next = self.getAdjacentOption($option, 1).attr('data-value');
|
2358 | 2386 | self.refreshOptions(self.isFocused && inputMode !== 'single');
|
|
2362 | 2390 | }
|
2363 | 2391 |
|
2364 | 2392 | // hide the menu if the maximum number of items have been selected or no options are left
|
2365 |
| - if (!$options.length || (self.settings.maxItems !== null && self.items.length >= self.settings.maxItems)) { |
| 2393 | + if (!$options.length || self.isFull()) { |
2366 | 2394 | self.close();
|
2367 | 2395 | } else {
|
2368 | 2396 | self.positionDropdown();
|
|
2428 | 2456 | var self = this;
|
2429 | 2457 | var input = $.trim(self.$control_input.val() || '');
|
2430 | 2458 | var caret = self.caretPos;
|
2431 |
| - if (!input.length) return false; |
| 2459 | + if (!self.canCreate(input)) return false; |
2432 | 2460 | self.lock();
|
2433 | 2461 |
|
2434 | 2462 | if (typeof triggerDropdown === 'undefined') {
|
|
2485 | 2513 | * and CSS classes.
|
2486 | 2514 | */
|
2487 | 2515 | refreshState: function() {
|
2488 |
| - var self = this; |
2489 |
| - var invalid = self.isRequired && !self.items.length; |
2490 |
| - if (!invalid) self.isInvalid = false; |
2491 |
| - self.$control_input.prop('required', invalid); |
| 2516 | + var invalid, self = this; |
| 2517 | + if (self.isRequired) { |
| 2518 | + if (self.items.length) self.isInvalid = false; |
| 2519 | + self.$control_input.prop('required', invalid); |
| 2520 | + } |
2492 | 2521 | self.refreshClasses();
|
2493 | 2522 | },
|
2494 | 2523 |
|
|
2535 | 2564 | updateOriginalInput: function() {
|
2536 | 2565 | var i, n, options, self = this;
|
2537 | 2566 |
|
2538 |
| - if (self.$input[0].tagName.toLowerCase() === 'select') { |
| 2567 | + if (self.tagType === TAG_SELECT) { |
2539 | 2568 | options = [];
|
2540 | 2569 | for (i = 0, n = self.items.length; i < n; i++) {
|
2541 | 2570 | options.push('<option value="' + escape_html(self.items[i]) + '" selected="selected"></option>');
|
|
2546 | 2575 | self.$input.html(options.join(''));
|
2547 | 2576 | } else {
|
2548 | 2577 | self.$input.val(self.getValue());
|
| 2578 | + self.$input.attr('value',self.$input.val()); |
2549 | 2579 | }
|
2550 | 2580 |
|
2551 | 2581 | if (self.isSetup) {
|
|
2631 | 2661 | if (!self.items.length) return;
|
2632 | 2662 | self.$control.children(':not(input)').remove();
|
2633 | 2663 | self.items = [];
|
| 2664 | + self.lastQuery = null; |
2634 | 2665 | self.setCaret(0);
|
| 2666 | + self.setActiveItem(null); |
2635 | 2667 | self.updatePlaceholder();
|
2636 | 2668 | self.updateOriginalInput();
|
2637 | 2669 | self.refreshState();
|
|
2800 | 2832 | i = Math.max(0, Math.min(self.items.length, i));
|
2801 | 2833 | }
|
2802 | 2834 |
|
2803 |
| - // the input must be moved by leaving it in place and moving the |
2804 |
| - // siblings, due to the fact that focus cannot be restored once lost |
2805 |
| - // on mobile webkit devices |
2806 |
| - var j, n, fn, $children, $child; |
2807 |
| - $children = self.$control.children(':not(input)'); |
2808 |
| - for (j = 0, n = $children.length; j < n; j++) { |
2809 |
| - $child = $($children[j]).detach(); |
2810 |
| - if (j < i) { |
2811 |
| - self.$control_input.before($child); |
2812 |
| - } else { |
2813 |
| - self.$control.append($child); |
| 2835 | + if(!self.isPending) { |
| 2836 | + // the input must be moved by leaving it in place and moving the |
| 2837 | + // siblings, due to the fact that focus cannot be restored once lost |
| 2838 | + // on mobile webkit devices |
| 2839 | + var j, n, fn, $children, $child; |
| 2840 | + $children = self.$control.children(':not(input)'); |
| 2841 | + for (j = 0, n = $children.length; j < n; j++) { |
| 2842 | + $child = $($children[j]).detach(); |
| 2843 | + if (j < i) { |
| 2844 | + self.$control_input.before($child); |
| 2845 | + } else { |
| 2846 | + self.$control.append($child); |
| 2847 | + } |
2814 | 2848 | }
|
2815 | 2849 | }
|
2816 | 2850 |
|
|
2876 | 2910 | .html('')
|
2877 | 2911 | .append(revertSettings.$children)
|
2878 | 2912 | .removeAttr('tabindex')
|
| 2913 | + .removeClass('selectized') |
2879 | 2914 | .attr({tabindex: revertSettings.tabindex})
|
2880 | 2915 | .show();
|
2881 | 2916 |
|
| 2917 | + self.$control_input.removeData('grow'); |
| 2918 | + self.$input.removeData('selectize'); |
| 2919 | + |
2882 | 2920 | $(window).off(eventNS);
|
2883 | 2921 | $(document).off(eventNS);
|
2884 | 2922 | $(document.body).off(eventNS);
|
|
2937 | 2975 | }
|
2938 | 2976 |
|
2939 | 2977 | return html;
|
| 2978 | + }, |
| 2979 | + |
| 2980 | + /** |
| 2981 | + * Clears the render cache for a template. If |
| 2982 | + * no template is given, clears all render |
| 2983 | + * caches. |
| 2984 | + * |
| 2985 | + * @param {string} templateName |
| 2986 | + */ |
| 2987 | + clearCache: function(templateName) { |
| 2988 | + var self = this; |
| 2989 | + if (typeof templateName === 'undefined') { |
| 2990 | + self.renderCache = {}; |
| 2991 | + } else { |
| 2992 | + delete self.renderCache[templateName]; |
| 2993 | + } |
2940 | 2994 | }
|
2941 | 2995 |
|
| 2996 | + |
2942 | 2997 | });
|
2943 | 2998 |
|
2944 | 2999 |
|
|
2950 | 3005 | diacritics: true,
|
2951 | 3006 | create: false,
|
2952 | 3007 | createOnBlur: false,
|
| 3008 | + createFilter: null, |
2953 | 3009 | highlight: true,
|
2954 | 3010 | openOnFocus: true,
|
2955 | 3011 | maxOptions: 1000,
|
|
3150 | 3206 | }
|
3151 | 3207 |
|
3152 | 3208 | instance = new Selectize($input, $.extend(true, {}, defaults, settings_element, settings_user));
|
3153 |
| - $input.data('selectize', instance); |
3154 |
| - $input.addClass('selectized'); |
3155 | 3209 | });
|
3156 | 3210 | };
|
3157 | 3211 |
|
3158 | 3212 | $.fn.selectize.defaults = Selectize.defaults;
|
3159 | 3213 |
|
| 3214 | + |
3160 | 3215 | Selectize.define('drag_drop', function(options) {
|
3161 | 3216 | if (!$.fn.sortable) throw new Error('The "drag_drop" plugin requires jQuery UI "sortable".');
|
3162 | 3217 | if (this.settings.mode !== 'multi') return;
|
|
3285 | 3340 | };
|
3286 | 3341 | })();
|
3287 | 3342 |
|
| 3343 | + var getScrollbarWidth = function() { |
| 3344 | + var div; |
| 3345 | + var width = getScrollbarWidth.width; |
| 3346 | + var doc = document; |
| 3347 | + |
| 3348 | + if (typeof width === 'undefined') { |
| 3349 | + div = doc.createElement('div'); |
| 3350 | + div.innerHTML = '<div style="width:50px;height:50px;position:absolute;left:-50px;top:-50px;overflow:auto;"><div style="width:1px;height:100px;"></div></div>'; |
| 3351 | + div = div.firstChild; |
| 3352 | + doc.body.appendChild(div); |
| 3353 | + width = getScrollbarWidth.width = div.offsetWidth - div.clientWidth; |
| 3354 | + doc.body.removeChild(div); |
| 3355 | + } |
| 3356 | + return width; |
| 3357 | + }; |
| 3358 | + |
3288 | 3359 | var equalizeSizes = function() {
|
3289 | 3360 | var i, n, height_max, width, width_last, width_parent, $optgroups;
|
3290 | 3361 |
|
|
3301 | 3372 | }
|
3302 | 3373 |
|
3303 | 3374 | if (options.equalizeWidth) {
|
3304 |
| - width_parent = self.$dropdown_content.innerWidth(); |
| 3375 | + width_parent = self.$dropdown_content.innerWidth() - getScrollbarWidth(); |
3305 | 3376 | width = Math.round(width_parent / n);
|
3306 | 3377 | $optgroups.css({width: width});
|
3307 | 3378 | if (n > 1) {
|
|
0 commit comments