selectize-rails 0.1.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/lib/selectize-rails/version.rb +1 -1
- data/vendor/assets/javascripts/selectize.js +1325 -522
- data/vendor/assets/stylesheets/selectize.css +118 -15
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 593dca340fc41a504f86cf87414f89fd259c9e53
|
4
|
+
data.tar.gz: 191e50886524103975c3ed0b41d15d3ef02660b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72c76cb2a46c77530aad637ab86ed92ed72d3519afa0db9130d2283ce4acabc85872d8cbe7be31fb0f3edef23dcd36dd418e69b0f5cc67c11c415d748e90b212
|
7
|
+
data.tar.gz: 07f2912e36d5cc23cd8f5f00a8525f63bd7ecd631cda7d57ac9131fc000bd1f006598ed303d96f27be8cca6cdc3f38dc42c377101c969e2234d2339c422accbd
|
data/README.md
CHANGED
@@ -35,6 +35,7 @@ See the [demo page of Brian Reavis](http://brianreavis.github.io/selectize.js/)
|
|
35
35
|
|
36
36
|
| Version | Notes |
|
37
37
|
|---------+---------------------------------------------------------------------------|
|
38
|
+
| 0.6.1 | update and set gem version equal to selectize.js version |
|
38
39
|
| 0.1.0 | Initial release with plugin version 0.1.5 |
|
39
40
|
|
40
41
|
## License
|
@@ -1,6 +1,6 @@
|
|
1
|
-
/*! selectize.js | https://github.com/brianreavis/selectize.js | Apache License (v2) */
|
1
|
+
/*! selectize.js - v0.6.1 | https://github.com/brianreavis/selectize.js | Apache License (v2) */
|
2
2
|
|
3
|
-
(function
|
3
|
+
(function(factory) {
|
4
4
|
if (typeof exports === 'object') {
|
5
5
|
factory(require('jquery'));
|
6
6
|
} else if (typeof define === 'function' && define.amd) {
|
@@ -9,10 +9,10 @@
|
|
9
9
|
factory(jQuery);
|
10
10
|
}
|
11
11
|
}(function ($) {
|
12
|
-
"use strict";
|
13
|
-
|
14
|
-
|
15
|
-
|
12
|
+
"use strict";
|
13
|
+
|
14
|
+
/* --- file: "src/contrib/highlight.js" --- */
|
15
|
+
|
16
16
|
/**
|
17
17
|
* highlight v3 | MIT license | Johann Burkard <jb@eaio.com>
|
18
18
|
* Highlights arbitrary terms in a node.
|
@@ -20,11 +20,11 @@
|
|
20
20
|
* - Modified by Marshal <beatgates@gmail.com> 2011-6-24 (added regex)
|
21
21
|
* - Modified by Brian Reavis <brian@thirdroute.com> 2012-8-27 (cleanup)
|
22
22
|
*/
|
23
|
-
|
23
|
+
|
24
24
|
var highlight = function($element, pattern) {
|
25
25
|
if (typeof pattern === 'string' && !pattern.length) return;
|
26
26
|
var regex = (typeof pattern === 'string') ? new RegExp(pattern, 'i') : pattern;
|
27
|
-
|
27
|
+
|
28
28
|
var highlight = function(node) {
|
29
29
|
var skip = 0;
|
30
30
|
if (node.nodeType === 3) {
|
@@ -47,12 +47,12 @@
|
|
47
47
|
}
|
48
48
|
return skip;
|
49
49
|
};
|
50
|
-
|
50
|
+
|
51
51
|
return $element.each(function() {
|
52
52
|
highlight(this);
|
53
53
|
});
|
54
54
|
};
|
55
|
-
|
55
|
+
|
56
56
|
var unhighlight = function($element) {
|
57
57
|
return $element.find('span.highlight').each(function() {
|
58
58
|
var parent = this.parentNode;
|
@@ -60,9 +60,56 @@
|
|
60
60
|
parent.normalize();
|
61
61
|
}).end();
|
62
62
|
};
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
|
64
|
+
/* --- file: "src/contrib/microevent.js" --- */
|
65
|
+
|
66
|
+
/**
|
67
|
+
* MicroEvent - to make any js object an event emitter
|
68
|
+
*
|
69
|
+
* - pure javascript - server compatible, browser compatible
|
70
|
+
* - dont rely on the browser doms
|
71
|
+
* - super simple - you get it immediatly, no mistery, no magic involved
|
72
|
+
*
|
73
|
+
* @author Jerome Etienne (https://github.com/jeromeetienne)
|
74
|
+
*/
|
75
|
+
|
76
|
+
var MicroEvent = function() {};
|
77
|
+
MicroEvent.prototype = {
|
78
|
+
on: function(event, fct){
|
79
|
+
this._events = this._events || {};
|
80
|
+
this._events[event] = this._events[event] || [];
|
81
|
+
this._events[event].push(fct);
|
82
|
+
},
|
83
|
+
off: function(event, fct){
|
84
|
+
this._events = this._events || {};
|
85
|
+
if (event in this._events === false) return;
|
86
|
+
this._events[event].splice(this._events[event].indexOf(fct), 1);
|
87
|
+
},
|
88
|
+
trigger: function(event /* , args... */){
|
89
|
+
this._events = this._events || {};
|
90
|
+
if (event in this._events === false) return;
|
91
|
+
for (var i = 0; i < this._events[event].length; i++){
|
92
|
+
this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1));
|
93
|
+
}
|
94
|
+
}
|
95
|
+
};
|
96
|
+
|
97
|
+
/**
|
98
|
+
* Mixin will delegate all MicroEvent.js function in the destination object.
|
99
|
+
*
|
100
|
+
* - MicroEvent.mixin(Foobar) will make Foobar able to use MicroEvent
|
101
|
+
*
|
102
|
+
* @param {object} the object which will support MicroEvent
|
103
|
+
*/
|
104
|
+
MicroEvent.mixin = function(destObject){
|
105
|
+
var props = ['on', 'off', 'trigger'];
|
106
|
+
for (var i = 0; i < props.length; i++){
|
107
|
+
destObject.prototype[props[i]] = MicroEvent.prototype[props[i]];
|
108
|
+
}
|
109
|
+
};
|
110
|
+
|
111
|
+
/* --- file: "src/constants.js" --- */
|
112
|
+
|
66
113
|
/**
|
67
114
|
* selectize - A highly customizable select control with autocomplete.
|
68
115
|
* Copyright (c) 2013 Brian Reavis & contributors
|
@@ -78,9 +125,10 @@
|
|
78
125
|
*
|
79
126
|
* @author Brian Reavis <brian@thirdroute.com>
|
80
127
|
*/
|
81
|
-
|
128
|
+
|
82
129
|
var IS_MAC = /Mac/.test(navigator.userAgent);
|
83
|
-
|
130
|
+
|
131
|
+
var KEY_A = 65;
|
84
132
|
var KEY_COMMA = 188;
|
85
133
|
var KEY_RETURN = 13;
|
86
134
|
var KEY_ESC = 27;
|
@@ -91,12 +139,13 @@
|
|
91
139
|
var KEY_BACKSPACE = 8;
|
92
140
|
var KEY_DELETE = 46;
|
93
141
|
var KEY_SHIFT = 16;
|
142
|
+
var KEY_CMD = IS_MAC ? 91 : 17;
|
94
143
|
var KEY_CTRL = IS_MAC ? 18 : 17;
|
95
144
|
var KEY_TAB = 9;
|
96
|
-
|
145
|
+
|
97
146
|
var TAG_SELECT = 1;
|
98
147
|
var TAG_INPUT = 2;
|
99
|
-
|
148
|
+
|
100
149
|
var DIACRITICS = {
|
101
150
|
'a': '[aÀÁÂÃÄÅàáâãäå]',
|
102
151
|
'c': '[cÇç]',
|
@@ -109,130 +158,134 @@
|
|
109
158
|
'y': '[yŸÿý]',
|
110
159
|
'z': '[zŽž]'
|
111
160
|
};
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
var
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
onItemRemove : null, // function(value) { ... }
|
147
|
-
onClear : null, // function() { ... }
|
148
|
-
onOptionAdd : null, // function(value, data) { ... }
|
149
|
-
onOptionRemove : null, // function(value) { ... }
|
150
|
-
onDropdownOpen : null, // function($dropdown) { ... }
|
151
|
-
onDropdownClose : null, // function($dropdown) { ... }
|
152
|
-
onType : null, // function(str) { ... }
|
153
|
-
|
154
|
-
render: {
|
155
|
-
item: null,
|
156
|
-
option: null,
|
157
|
-
option_create: null
|
158
|
-
}
|
159
|
-
};
|
160
|
-
|
161
|
-
$.fn.selectize = function (settings) {
|
162
|
-
var defaults = $.fn.selectize.defaults;
|
163
|
-
settings = settings || {};
|
164
|
-
|
165
|
-
return this.each(function() {
|
166
|
-
var instance, value, values, i, n, data, dataAttr, settings_element, tagName;
|
167
|
-
var $options, $option, $input = $(this);
|
168
|
-
|
169
|
-
tagName = $input[0].tagName.toLowerCase();
|
170
|
-
|
171
|
-
if (typeof settings === 'string') {
|
172
|
-
instance = $input.data('selectize');
|
173
|
-
instance[settings].apply(instance, Array.prototype.splice.apply(arguments, 1));
|
174
|
-
} else {
|
175
|
-
dataAttr = settings.dataAttr || defaults.dataAttr;
|
176
|
-
settings_element = {};
|
177
|
-
settings_element.placeholder = $input.attr('placeholder');
|
178
|
-
settings_element.options = {};
|
179
|
-
settings_element.items = [];
|
180
|
-
|
181
|
-
if (tagName === 'select') {
|
182
|
-
settings_element.maxItems = !!$input.attr('multiple') ? null : 1;
|
183
|
-
$options = $input.children();
|
184
|
-
for (i = 0, n = $options.length; i < n; i++) {
|
185
|
-
$option = $($options[i]);
|
186
|
-
value = $option.attr('value') || '';
|
187
|
-
if (!value.length) continue;
|
188
|
-
data = (dataAttr && $option.attr(dataAttr)) || {
|
189
|
-
'text' : $option.html(),
|
190
|
-
'value' : value
|
191
|
-
};
|
192
|
-
|
193
|
-
if (typeof data === 'string') data = JSON.parse(data);
|
194
|
-
settings_element.options[value] = data;
|
195
|
-
if ($option.is(':selected')) {
|
196
|
-
settings_element.items.push(value);
|
197
|
-
}
|
198
|
-
}
|
199
|
-
} else {
|
200
|
-
value = $.trim($input.val() || '');
|
201
|
-
if (value.length) {
|
202
|
-
values = value.split(settings.delimiter || defaults.delimiter);
|
203
|
-
for (i = 0, n = values.length; i < n; i++) {
|
204
|
-
settings_element.options[values[i]] = {
|
205
|
-
'text' : values[i],
|
206
|
-
'value' : values[i]
|
207
|
-
};
|
208
|
-
}
|
209
|
-
settings_element.items = values;
|
161
|
+
|
162
|
+
/* --- file: "src/plugins.js" --- */
|
163
|
+
|
164
|
+
var Plugins = {};
|
165
|
+
|
166
|
+
Plugins.mixin = function(Interface, interfaceName) {
|
167
|
+
Interface.plugins = {};
|
168
|
+
|
169
|
+
/**
|
170
|
+
* Initializes the provided functions.
|
171
|
+
* Acceptable formats:
|
172
|
+
*
|
173
|
+
* List (without options):
|
174
|
+
* ['a', 'b', 'c']
|
175
|
+
*
|
176
|
+
* List (with options)
|
177
|
+
* {'a': { ... }, 'b': { ... }, 'c': { ... }}
|
178
|
+
*
|
179
|
+
* @param {mixed} plugins
|
180
|
+
*/
|
181
|
+
Interface.prototype.loadPlugins = function(plugins) {
|
182
|
+
var i, n, key;
|
183
|
+
this.plugins = [];
|
184
|
+
this.pluginSettings = {};
|
185
|
+
|
186
|
+
if ($.isArray(plugins)) {
|
187
|
+
for (i = 0, n = plugins.length; i < n; i++) {
|
188
|
+
this.loadPlugin(plugins[i]);
|
189
|
+
}
|
190
|
+
} else if (plugins) {
|
191
|
+
this.pluginSettings = $.extend({}, plugins);
|
192
|
+
for (key in plugins) {
|
193
|
+
if (plugins.hasOwnProperty(key)) {
|
194
|
+
this.loadPlugin(key);
|
210
195
|
}
|
211
196
|
}
|
212
|
-
|
213
|
-
instance = new Selectize($input, $.extend(true, {}, defaults, settings_element, settings));
|
214
|
-
$input.data('selectize', instance);
|
215
|
-
$input.addClass('selectized');
|
216
197
|
}
|
217
|
-
}
|
198
|
+
};
|
199
|
+
|
200
|
+
/**
|
201
|
+
* Initializes a plugin.
|
202
|
+
*
|
203
|
+
* @param {string} name
|
204
|
+
*/
|
205
|
+
Interface.prototype.loadPlugin = function(name) {
|
206
|
+
var plugin, i, n;
|
207
|
+
|
208
|
+
if (this.plugins.indexOf(name) !== -1) return;
|
209
|
+
if (!Interface.plugins.hasOwnProperty(name)) {
|
210
|
+
throw new Error(interfaceName + ' unable to find "' + name + '" plugin');
|
211
|
+
}
|
212
|
+
|
213
|
+
plugin = Interface.plugins[name];
|
214
|
+
|
215
|
+
// initialize plugin and dependencies
|
216
|
+
this.plugins.push(name);
|
217
|
+
for (i = 0, n = plugin.dependencies.length; i < n; i++) {
|
218
|
+
this.loadPlugin(plugin.dependencies[i]);
|
219
|
+
}
|
220
|
+
plugin.fn.apply(this, [this.pluginSettings[name] || {}]);
|
221
|
+
};
|
222
|
+
|
223
|
+
/**
|
224
|
+
* Registers a plugin.
|
225
|
+
*
|
226
|
+
* @param {string} name
|
227
|
+
* @param {array} dependencies (optional)
|
228
|
+
* @param {function} fn
|
229
|
+
*/
|
230
|
+
Interface.registerPlugin = function(name) {
|
231
|
+
var args = arguments;
|
232
|
+
Interface.plugins[name] = {
|
233
|
+
'name' : name,
|
234
|
+
'fn' : args[args.length - 1],
|
235
|
+
'dependencies' : args.length === 3 ? args[1] : []
|
236
|
+
};
|
237
|
+
};
|
218
238
|
};
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
// --- src/utils.js ---
|
223
|
-
|
239
|
+
|
240
|
+
/* --- file: "src/utils.js" --- */
|
241
|
+
|
224
242
|
var isset = function(object) {
|
225
243
|
return typeof object !== 'undefined';
|
226
244
|
};
|
227
|
-
|
245
|
+
|
228
246
|
var htmlEntities = function(str) {
|
229
247
|
return String(str).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"');
|
230
248
|
};
|
231
|
-
|
249
|
+
|
232
250
|
var quoteRegExp = function(str) {
|
233
251
|
return (str + '').replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
|
234
252
|
};
|
235
|
-
|
253
|
+
|
254
|
+
var hook = {};
|
255
|
+
|
256
|
+
/**
|
257
|
+
* Wraps `method` on `self` so that `fn`
|
258
|
+
* is invoked before the original method.
|
259
|
+
*
|
260
|
+
* @param {object} self
|
261
|
+
* @param {string} method
|
262
|
+
* @param {function} fn
|
263
|
+
*/
|
264
|
+
hook.before = function(self, method, fn) {
|
265
|
+
var original = self[method];
|
266
|
+
self[method] = function() {
|
267
|
+
fn.apply(self, arguments);
|
268
|
+
return original.apply(self, arguments);
|
269
|
+
};
|
270
|
+
};
|
271
|
+
|
272
|
+
/**
|
273
|
+
* Wraps `method` on `self` so that `fn`
|
274
|
+
* is invoked after the original method.
|
275
|
+
*
|
276
|
+
* @param {object} self
|
277
|
+
* @param {string} method
|
278
|
+
* @param {function} fn
|
279
|
+
*/
|
280
|
+
hook.after = function(self, method, fn) {
|
281
|
+
var original = self[method];
|
282
|
+
self[method] = function() {
|
283
|
+
var result = original.apply(self, arguments);
|
284
|
+
fn.apply(self, arguments);
|
285
|
+
return result;
|
286
|
+
};
|
287
|
+
};
|
288
|
+
|
236
289
|
var once = function(fn) {
|
237
290
|
var called = false;
|
238
291
|
return function() {
|
@@ -241,7 +294,7 @@
|
|
241
294
|
fn.apply(this, arguments);
|
242
295
|
};
|
243
296
|
};
|
244
|
-
|
297
|
+
|
245
298
|
var debounce = function(fn, delay) {
|
246
299
|
var timeout;
|
247
300
|
return function() {
|
@@ -253,7 +306,37 @@
|
|
253
306
|
}, delay);
|
254
307
|
};
|
255
308
|
};
|
256
|
-
|
309
|
+
|
310
|
+
/**
|
311
|
+
* Debounce all fired events types listed in `types`
|
312
|
+
* while executing the provided `fn`.
|
313
|
+
*
|
314
|
+
* @param {object} self
|
315
|
+
* @param {array} types
|
316
|
+
* @param {function} fn
|
317
|
+
*/
|
318
|
+
var debounce_events = function(self, types, fn) {
|
319
|
+
var type;
|
320
|
+
var trigger = self.trigger;
|
321
|
+
var event_args = {};
|
322
|
+
|
323
|
+
// override trigger method
|
324
|
+
self.trigger = function() {
|
325
|
+
event_args[arguments[0]] = arguments;
|
326
|
+
};
|
327
|
+
|
328
|
+
// invoke provided function
|
329
|
+
fn.apply(self, []);
|
330
|
+
self.trigger = trigger;
|
331
|
+
|
332
|
+
// trigger queued events
|
333
|
+
for (type in event_args) {
|
334
|
+
if (event_args.hasOwnProperty(type)) {
|
335
|
+
trigger.apply(self, event_args[type]);
|
336
|
+
}
|
337
|
+
}
|
338
|
+
};
|
339
|
+
|
257
340
|
/**
|
258
341
|
* A workaround for http://bugs.jquery.com/ticket/6696
|
259
342
|
*
|
@@ -272,7 +355,7 @@
|
|
272
355
|
return fn.apply(this, [e]);
|
273
356
|
});
|
274
357
|
};
|
275
|
-
|
358
|
+
|
276
359
|
var getSelection = function(input) {
|
277
360
|
var result = {};
|
278
361
|
if ('selectionStart' in input) {
|
@@ -288,7 +371,7 @@
|
|
288
371
|
}
|
289
372
|
return result;
|
290
373
|
};
|
291
|
-
|
374
|
+
|
292
375
|
var transferStyles = function($from, $to, properties) {
|
293
376
|
var styles = {};
|
294
377
|
if (properties) {
|
@@ -301,7 +384,7 @@
|
|
301
384
|
$to.css(styles);
|
302
385
|
return $to;
|
303
386
|
};
|
304
|
-
|
387
|
+
|
305
388
|
var measureString = function(str, $parent) {
|
306
389
|
var $test = $('<test>').css({
|
307
390
|
position: 'absolute',
|
@@ -311,7 +394,7 @@
|
|
311
394
|
padding: 0,
|
312
395
|
whiteSpace: 'nowrap'
|
313
396
|
}).text(str).appendTo('body');
|
314
|
-
|
397
|
+
|
315
398
|
transferStyles($parent, $test, [
|
316
399
|
'letterSpacing',
|
317
400
|
'fontSize',
|
@@ -319,19 +402,22 @@
|
|
319
402
|
'fontWeight',
|
320
403
|
'textTransform'
|
321
404
|
]);
|
322
|
-
|
405
|
+
|
323
406
|
var width = $test.width();
|
324
407
|
$test.remove();
|
325
|
-
|
408
|
+
|
326
409
|
return width;
|
327
410
|
};
|
328
|
-
|
411
|
+
|
329
412
|
var autoGrow = function($input) {
|
330
413
|
var update = function(e) {
|
331
414
|
var value, keyCode, printable, placeholder, width;
|
332
|
-
var shift, character;
|
333
|
-
|
334
|
-
|
415
|
+
var shift, character, selection;
|
416
|
+
e = e || window.event || {};
|
417
|
+
|
418
|
+
if (e.metaKey || e.altKey) return;
|
419
|
+
if ($input.data('grow') === false) return;
|
420
|
+
|
335
421
|
value = $input.val();
|
336
422
|
if (e.type && e.type.toLowerCase() === 'keydown') {
|
337
423
|
keyCode = e.keyCode;
|
@@ -341,8 +427,17 @@
|
|
341
427
|
(keyCode >= 48 && keyCode <= 57) || // 0-9
|
342
428
|
keyCode == 32 // space
|
343
429
|
);
|
344
|
-
|
345
|
-
if (
|
430
|
+
|
431
|
+
if (keyCode === KEY_DELETE || keyCode === KEY_BACKSPACE) {
|
432
|
+
selection = getSelection($input[0]);
|
433
|
+
if (selection.length) {
|
434
|
+
value = value.substring(0, selection.start) + value.substring(selection.start + selection.length);
|
435
|
+
} else if (keyCode === KEY_BACKSPACE && selection.start) {
|
436
|
+
value = value.substring(0, selection.start - 1) + value.substring(selection.start + 1);
|
437
|
+
} else if (keyCode === KEY_DELETE && typeof selection.start !== 'undefined') {
|
438
|
+
value = value.substring(0, selection.start) + value.substring(selection.start + 1);
|
439
|
+
}
|
440
|
+
} else if (printable) {
|
346
441
|
shift = e.shiftKey;
|
347
442
|
character = String.fromCharCode(e.keyCode);
|
348
443
|
if (shift) character = character.toUpperCase();
|
@@ -350,24 +445,25 @@
|
|
350
445
|
value += character;
|
351
446
|
}
|
352
447
|
}
|
353
|
-
|
448
|
+
|
354
449
|
placeholder = $input.attr('placeholder') || '';
|
355
450
|
if (!value.length && placeholder.length) {
|
356
451
|
value = placeholder;
|
357
452
|
}
|
358
|
-
|
453
|
+
|
359
454
|
width = measureString(value, $input) + 4;
|
360
455
|
if (width !== $input.width()) {
|
361
456
|
$input.width(width);
|
362
457
|
$input.triggerHandler('resize');
|
363
458
|
}
|
364
459
|
};
|
460
|
+
|
365
461
|
$input.on('keydown keyup update blur', update);
|
366
|
-
update(
|
462
|
+
update();
|
367
463
|
};
|
368
|
-
|
369
|
-
|
370
|
-
|
464
|
+
|
465
|
+
/* --- file: "src/selectize.js" --- */
|
466
|
+
|
371
467
|
/**
|
372
468
|
* selectize.js
|
373
469
|
* Copyright (c) 2013 Brian Reavis & contributors
|
@@ -383,42 +479,48 @@
|
|
383
479
|
*
|
384
480
|
* @author Brian Reavis <brian@thirdroute.com>
|
385
481
|
*/
|
386
|
-
|
482
|
+
|
387
483
|
var Selectize = function($input, settings) {
|
484
|
+
var key, i, n;
|
388
485
|
$input[0].selectize = this;
|
389
|
-
|
486
|
+
|
390
487
|
this.$input = $input;
|
391
488
|
this.tagType = $input[0].tagName.toLowerCase() === 'select' ? TAG_SELECT : TAG_INPUT;
|
392
489
|
this.settings = settings;
|
393
|
-
|
490
|
+
|
394
491
|
this.highlightedValue = null;
|
395
492
|
this.isOpen = false;
|
493
|
+
this.isDisabled = false;
|
396
494
|
this.isLocked = false;
|
397
495
|
this.isFocused = false;
|
398
496
|
this.isInputFocused = false;
|
497
|
+
this.isInputHidden = false;
|
399
498
|
this.isSetup = false;
|
400
499
|
this.isShiftDown = false;
|
500
|
+
this.isCmdDown = false;
|
401
501
|
this.isCtrlDown = false;
|
402
502
|
this.ignoreFocus = false;
|
503
|
+
this.ignoreHover = false;
|
403
504
|
this.hasOptions = false;
|
404
505
|
this.currentResults = null;
|
405
506
|
this.lastValue = '';
|
406
507
|
this.caretPos = 0;
|
407
508
|
this.loading = 0;
|
408
509
|
this.loadedSearches = {};
|
409
|
-
|
510
|
+
|
410
511
|
this.$activeOption = null;
|
411
512
|
this.$activeItems = [];
|
412
|
-
|
513
|
+
|
514
|
+
this.optgroups = {};
|
413
515
|
this.options = {};
|
414
516
|
this.userOptions = {};
|
415
517
|
this.items = [];
|
416
518
|
this.renderCache = {};
|
417
519
|
this.onSearchChange = debounce(this.onSearchChange, this.settings.loadThrottle);
|
418
|
-
|
520
|
+
|
419
521
|
if ($.isArray(settings.options)) {
|
420
|
-
|
421
|
-
for (
|
522
|
+
key = settings.valueField;
|
523
|
+
for (i = 0, n = settings.options.length; i < n; i++) {
|
422
524
|
if (settings.options[i].hasOwnProperty(key)) {
|
423
525
|
this.options[settings.options[i][key]] = settings.options[i];
|
424
526
|
}
|
@@ -427,16 +529,39 @@
|
|
427
529
|
$.extend(this.options, settings.options);
|
428
530
|
delete this.settings.options;
|
429
531
|
}
|
430
|
-
|
532
|
+
|
533
|
+
if ($.isArray(settings.optgroups)) {
|
534
|
+
key = settings.optgroupValueField;
|
535
|
+
for (i = 0, n = settings.optgroups.length; i < n; i++) {
|
536
|
+
if (settings.optgroups[i].hasOwnProperty(key)) {
|
537
|
+
this.optgroups[settings.optgroups[i][key]] = settings.optgroups[i];
|
538
|
+
}
|
539
|
+
}
|
540
|
+
} else if (typeof settings.optgroups === 'object') {
|
541
|
+
$.extend(this.optgroups, settings.optgroups);
|
542
|
+
delete this.settings.optgroups;
|
543
|
+
}
|
544
|
+
|
431
545
|
// option-dependent defaults
|
432
546
|
this.settings.mode = this.settings.mode || (this.settings.maxItems === 1 ? 'single' : 'multi');
|
433
547
|
if (typeof this.settings.hideSelected !== 'boolean') {
|
434
548
|
this.settings.hideSelected = this.settings.mode === 'multi';
|
435
549
|
}
|
436
|
-
|
550
|
+
|
551
|
+
this.loadPlugins(this.settings.plugins);
|
552
|
+
this.setupCallbacks();
|
437
553
|
this.setup();
|
438
554
|
};
|
439
|
-
|
555
|
+
|
556
|
+
// mixins
|
557
|
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
558
|
+
|
559
|
+
MicroEvent.mixin(Selectize);
|
560
|
+
Plugins.mixin(Selectize, 'Selectize');
|
561
|
+
|
562
|
+
// methods
|
563
|
+
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
564
|
+
|
440
565
|
/**
|
441
566
|
* Creates all elements and sets up event bindings.
|
442
567
|
*/
|
@@ -446,54 +571,61 @@
|
|
446
571
|
var $control;
|
447
572
|
var $control_input;
|
448
573
|
var $dropdown;
|
574
|
+
var $dropdown_content;
|
449
575
|
var inputMode;
|
450
|
-
var displayMode;
|
451
576
|
var timeout_blur;
|
452
577
|
var timeout_focus;
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
578
|
+
var tab_index;
|
579
|
+
var classes;
|
580
|
+
|
581
|
+
tab_index = this.$input.attr('tabindex') || '';
|
582
|
+
classes = this.$input.attr('class') || '';
|
583
|
+
$wrapper = $('<div>').addClass(this.settings.theme).addClass(this.settings.wrapperClass).addClass(classes);
|
584
|
+
$control = $('<div>').addClass(this.settings.inputClass).addClass('items').toggleClass('has-options', !$.isEmptyObject(this.options)).appendTo($wrapper);
|
585
|
+
$control_input = $('<input type="text">').appendTo($control).attr('tabindex',tab_index);
|
586
|
+
$dropdown = $('<div>').addClass(this.settings.dropdownClass).hide().appendTo($wrapper);
|
587
|
+
$dropdown_content = $('<div>').addClass(this.settings.dropdownContentClass).appendTo($dropdown);
|
588
|
+
|
460
589
|
$wrapper.css({
|
461
590
|
width: this.$input[0].style.width,
|
462
|
-
display:
|
591
|
+
display: this.$input.css('display')
|
463
592
|
});
|
464
|
-
|
593
|
+
|
594
|
+
if (this.plugins.length) {
|
595
|
+
$wrapper.addClass('plugin-' + this.plugins.join(' plugin-'));
|
596
|
+
}
|
597
|
+
|
465
598
|
inputMode = this.settings.mode;
|
466
599
|
$wrapper.toggleClass('single', inputMode === 'single');
|
467
600
|
$wrapper.toggleClass('multi', inputMode === 'multi');
|
468
|
-
|
601
|
+
|
469
602
|
if ((this.settings.maxItems === null || this.settings.maxItems > 1) && this.tagType === TAG_SELECT) {
|
470
603
|
this.$input.attr('multiple', 'multiple');
|
471
604
|
}
|
472
|
-
|
605
|
+
|
473
606
|
if (this.settings.placeholder) {
|
474
607
|
$control_input.attr('placeholder', this.settings.placeholder);
|
475
608
|
}
|
476
|
-
|
477
|
-
this.$wrapper
|
478
|
-
this.$control
|
479
|
-
this.$control_input
|
480
|
-
this.$dropdown
|
481
|
-
|
609
|
+
|
610
|
+
this.$wrapper = $wrapper;
|
611
|
+
this.$control = $control;
|
612
|
+
this.$control_input = $control_input;
|
613
|
+
this.$dropdown = $dropdown;
|
614
|
+
this.$dropdown_content = $dropdown_content;
|
615
|
+
|
482
616
|
$control.on('mousedown', function(e) {
|
483
|
-
if (e.
|
484
|
-
|
485
|
-
|
486
|
-
|
617
|
+
if (!e.isDefaultPrevented()) {
|
618
|
+
window.setTimeout(function() {
|
619
|
+
self.focus(true);
|
620
|
+
}, 0);
|
487
621
|
}
|
488
|
-
e.preventDefault();
|
489
622
|
});
|
490
|
-
|
491
|
-
|
492
|
-
|
623
|
+
|
624
|
+
$dropdown.on('mouseenter', '[data-selectable]', function() { return self.onOptionHover.apply(self, arguments); });
|
625
|
+
$dropdown.on('mousedown', '[data-selectable]', function() { return self.onOptionSelect.apply(self, arguments); });
|
493
626
|
watchChildEvent($control, 'mousedown', '*:not(input)', function() { return self.onItemSelect.apply(self, arguments); });
|
494
|
-
|
495
627
|
autoGrow($control_input);
|
496
|
-
|
628
|
+
|
497
629
|
$control_input.on({
|
498
630
|
mousedown : function(e) { e.stopPropagation(); },
|
499
631
|
keydown : function() { return self.onKeyDown.apply(self, arguments); },
|
@@ -503,25 +635,20 @@
|
|
503
635
|
blur : function() { return self.onBlur.apply(self, arguments); },
|
504
636
|
focus : function() { return self.onFocus.apply(self, arguments); }
|
505
637
|
});
|
506
|
-
|
638
|
+
|
507
639
|
$(document).on({
|
508
640
|
keydown: function(e) {
|
641
|
+
self.isCmdDown = e[IS_MAC ? 'metaKey' : 'ctrlKey'];
|
509
642
|
self.isCtrlDown = e[IS_MAC ? 'altKey' : 'ctrlKey'];
|
510
643
|
self.isShiftDown = e.shiftKey;
|
511
|
-
if (self.isFocused && !self.isLocked) {
|
512
|
-
var tagName = (e.target.tagName || '').toLowerCase();
|
513
|
-
if (tagName === 'input' || tagName === 'textarea') return;
|
514
|
-
if ([KEY_SHIFT, KEY_BACKSPACE, KEY_DELETE, KEY_ESC, KEY_LEFT, KEY_RIGHT, KEY_TAB].indexOf(e.keyCode) !== -1) {
|
515
|
-
return self.onKeyDown.apply(self, arguments);
|
516
|
-
}
|
517
|
-
}
|
518
644
|
},
|
519
645
|
keyup: function(e) {
|
520
646
|
if (e.keyCode === KEY_CTRL) self.isCtrlDown = false;
|
521
|
-
|
647
|
+
if (e.keyCode === KEY_SHIFT) self.isShiftDown = false;
|
648
|
+
if (e.keyCode === KEY_CMD) self.isCmdDown = false;
|
522
649
|
},
|
523
650
|
mousedown: function(e) {
|
524
|
-
if (self.isFocused
|
651
|
+
if (self.isFocused) {
|
525
652
|
// prevent events on the dropdown scrollbar from causing the control to blur
|
526
653
|
if (e.target === self.$dropdown[0]) {
|
527
654
|
var ignoreFocus = self.ignoreFocus;
|
@@ -539,42 +666,80 @@
|
|
539
666
|
}
|
540
667
|
}
|
541
668
|
});
|
542
|
-
|
669
|
+
|
543
670
|
$(window).on({
|
544
671
|
resize: function() {
|
545
672
|
if (self.isOpen) {
|
546
673
|
self.positionDropdown.apply(self, arguments);
|
547
674
|
}
|
675
|
+
},
|
676
|
+
mousemove: function() {
|
677
|
+
self.ignoreHover = false;
|
548
678
|
}
|
549
679
|
});
|
550
|
-
|
551
|
-
this.$input.hide().after(this.$wrapper);
|
552
|
-
|
680
|
+
|
681
|
+
this.$input.attr('tabindex',-1).hide().after(this.$wrapper);
|
682
|
+
|
553
683
|
if ($.isArray(this.settings.items)) {
|
554
684
|
this.setValue(this.settings.items);
|
555
685
|
delete this.settings.items;
|
556
686
|
}
|
557
|
-
|
687
|
+
|
558
688
|
this.updateOriginalInput();
|
559
689
|
this.refreshItems();
|
560
690
|
this.updatePlaceholder();
|
561
691
|
this.isSetup = true;
|
692
|
+
|
693
|
+
if (this.$input.is(':disabled')) {
|
694
|
+
this.disable();
|
695
|
+
}
|
696
|
+
|
697
|
+
// preload options
|
698
|
+
if (this.settings.preload) {
|
699
|
+
this.onSearchChange('');
|
700
|
+
}
|
701
|
+
};
|
702
|
+
|
703
|
+
/**
|
704
|
+
* Maps fired events to callbacks provided
|
705
|
+
* in the settings used when creating the control.
|
706
|
+
*/
|
707
|
+
Selectize.prototype.setupCallbacks = function() {
|
708
|
+
var key, fn, callbacks = {
|
709
|
+
'change' : 'onChange',
|
710
|
+
'item_add' : 'onItemAdd',
|
711
|
+
'item_remove' : 'onItemRemove',
|
712
|
+
'clear' : 'onClear',
|
713
|
+
'option_add' : 'onOptionAdd',
|
714
|
+
'option_remove' : 'onOptionRemove',
|
715
|
+
'option_clear' : 'onOptionClear',
|
716
|
+
'dropdown_open' : 'onDropdownOpen',
|
717
|
+
'dropdown_close' : 'onDropdownClose',
|
718
|
+
'type' : 'onType'
|
719
|
+
};
|
720
|
+
|
721
|
+
for (key in callbacks) {
|
722
|
+
if (callbacks.hasOwnProperty(key)) {
|
723
|
+
fn = this.settings[callbacks[key]];
|
724
|
+
if (fn) this.on(key, fn);
|
725
|
+
}
|
726
|
+
}
|
562
727
|
};
|
563
|
-
|
728
|
+
|
564
729
|
/**
|
565
730
|
* Triggers a callback defined in the user-provided settings.
|
566
731
|
* Events: onItemAdd, onOptionAdd, etc
|
567
732
|
*
|
568
733
|
* @param {string} event
|
569
734
|
*/
|
570
|
-
Selectize.prototype.
|
735
|
+
Selectize.prototype.triggerCallback = function(event) {
|
571
736
|
var args;
|
572
737
|
if (typeof this.settings[event] === 'function') {
|
573
738
|
args = Array.prototype.slice.apply(arguments, [1]);
|
574
|
-
this.settings
|
739
|
+
this.settings[event].apply(this, args);
|
575
740
|
}
|
576
741
|
};
|
577
|
-
|
742
|
+
|
578
743
|
/**
|
579
744
|
* Triggered on <input> keypress.
|
580
745
|
*
|
@@ -582,7 +747,7 @@
|
|
582
747
|
* @returns {boolean}
|
583
748
|
*/
|
584
749
|
Selectize.prototype.onKeyPress = function(e) {
|
585
|
-
if (this.isLocked) return;
|
750
|
+
if (this.isLocked) return e && e.preventDefault();
|
586
751
|
var character = String.fromCharCode(e.keyCode || e.which);
|
587
752
|
if (this.settings.create && character === this.settings.delimiter) {
|
588
753
|
this.createItem();
|
@@ -590,7 +755,7 @@
|
|
590
755
|
return false;
|
591
756
|
}
|
592
757
|
};
|
593
|
-
|
758
|
+
|
594
759
|
/**
|
595
760
|
* Triggered on <input> keydown.
|
596
761
|
*
|
@@ -598,62 +763,73 @@
|
|
598
763
|
* @returns {boolean}
|
599
764
|
*/
|
600
765
|
Selectize.prototype.onKeyDown = function(e) {
|
601
|
-
if (this.isLocked) return;
|
602
766
|
var isInput = e.target === this.$control_input[0];
|
603
|
-
|
604
|
-
|
767
|
+
|
768
|
+
if (this.isLocked) {
|
769
|
+
if (e.keyCode !== KEY_TAB) {
|
770
|
+
e.preventDefault();
|
771
|
+
}
|
772
|
+
return;
|
773
|
+
}
|
774
|
+
|
775
|
+
switch (e.keyCode) {
|
776
|
+
case KEY_A:
|
777
|
+
if (this.isCmdDown) {
|
778
|
+
this.selectAll();
|
779
|
+
e.preventDefault();
|
780
|
+
return;
|
781
|
+
}
|
782
|
+
break;
|
605
783
|
case KEY_ESC:
|
606
784
|
this.blur();
|
607
785
|
return;
|
608
786
|
case KEY_DOWN:
|
609
|
-
if (!this.isOpen && this.hasOptions
|
787
|
+
if (!this.isOpen && this.hasOptions) {
|
610
788
|
this.open();
|
611
789
|
} else if (this.$activeOption) {
|
612
|
-
|
790
|
+
this.ignoreHover = true;
|
791
|
+
var $next = this.getAdjacentOption(this.$activeOption, 1);
|
613
792
|
if ($next.length) this.setActiveOption($next, true, true);
|
614
793
|
}
|
615
794
|
e.preventDefault();
|
616
|
-
|
795
|
+
return;
|
617
796
|
case KEY_UP:
|
618
797
|
if (this.$activeOption) {
|
619
|
-
|
798
|
+
this.ignoreHover = true;
|
799
|
+
var $prev = this.getAdjacentOption(this.$activeOption, -1);
|
620
800
|
if ($prev.length) this.setActiveOption($prev, true, true);
|
621
801
|
}
|
622
802
|
e.preventDefault();
|
623
|
-
|
803
|
+
return;
|
624
804
|
case KEY_RETURN:
|
625
805
|
if (this.$activeOption) {
|
626
806
|
this.onOptionSelect({currentTarget: this.$activeOption});
|
627
807
|
}
|
628
808
|
e.preventDefault();
|
629
|
-
|
809
|
+
return;
|
630
810
|
case KEY_LEFT:
|
631
811
|
this.advanceSelection(-1, e);
|
632
|
-
|
812
|
+
return;
|
633
813
|
case KEY_RIGHT:
|
634
814
|
this.advanceSelection(1, e);
|
635
|
-
|
815
|
+
return;
|
636
816
|
case KEY_TAB:
|
637
817
|
if (this.settings.create && $.trim(this.$control_input.val()).length) {
|
638
818
|
this.createItem();
|
639
819
|
e.preventDefault();
|
640
820
|
}
|
641
|
-
|
821
|
+
return;
|
642
822
|
case KEY_BACKSPACE:
|
643
823
|
case KEY_DELETE:
|
644
824
|
this.deleteSelection(e);
|
645
|
-
|
646
|
-
default:
|
647
|
-
if (this.isFull()) {
|
648
|
-
e.preventDefault();
|
649
|
-
return;
|
650
|
-
}
|
825
|
+
return;
|
651
826
|
}
|
652
|
-
if (
|
653
|
-
|
827
|
+
if (this.isFull() || this.isInputHidden) {
|
828
|
+
e.preventDefault();
|
829
|
+
return;
|
654
830
|
}
|
655
831
|
};
|
656
|
-
|
832
|
+
|
657
833
|
/**
|
658
834
|
* Triggered on <input> keyup.
|
659
835
|
*
|
@@ -661,16 +837,16 @@
|
|
661
837
|
* @returns {boolean}
|
662
838
|
*/
|
663
839
|
Selectize.prototype.onKeyUp = function(e) {
|
664
|
-
if (this.isLocked) return;
|
840
|
+
if (this.isLocked) return e && e.preventDefault();
|
665
841
|
var value = this.$control_input.val() || '';
|
666
842
|
if (this.lastValue !== value) {
|
667
843
|
this.lastValue = value;
|
668
844
|
this.onSearchChange(value);
|
669
845
|
this.refreshOptions();
|
670
|
-
this.trigger('
|
846
|
+
this.trigger('type', value);
|
671
847
|
}
|
672
848
|
};
|
673
|
-
|
849
|
+
|
674
850
|
/**
|
675
851
|
* Invokes the user-provide option provider / loader.
|
676
852
|
*
|
@@ -680,43 +856,38 @@
|
|
680
856
|
* @param {string} value
|
681
857
|
*/
|
682
858
|
Selectize.prototype.onSearchChange = function(value) {
|
683
|
-
if (!this.settings.load) return;
|
684
|
-
if (this.loadedSearches.hasOwnProperty(value)) return;
|
685
859
|
var self = this;
|
686
|
-
var
|
687
|
-
|
688
|
-
|
689
|
-
|
690
|
-
|
691
|
-
|
692
|
-
|
693
|
-
self.addOption(results);
|
694
|
-
self.refreshOptions(false);
|
695
|
-
if (self.isInputFocused) self.open();
|
696
|
-
}
|
697
|
-
if (!self.loading) {
|
698
|
-
$wrapper.removeClass('loading');
|
699
|
-
}
|
700
|
-
}]);
|
860
|
+
var fn = self.settings.load;
|
861
|
+
if (!fn) return;
|
862
|
+
if (self.loadedSearches.hasOwnProperty(value)) return;
|
863
|
+
self.loadedSearches[value] = true;
|
864
|
+
self.load(function(callback) {
|
865
|
+
fn.apply(self, [value, callback]);
|
866
|
+
});
|
701
867
|
};
|
702
|
-
|
868
|
+
|
703
869
|
/**
|
704
870
|
* Triggered on <input> focus.
|
705
871
|
*
|
706
|
-
* @param {object} e
|
872
|
+
* @param {object} e (optional)
|
707
873
|
* @returns {boolean}
|
708
874
|
*/
|
709
875
|
Selectize.prototype.onFocus = function(e) {
|
710
|
-
this.showInput();
|
711
876
|
this.isInputFocused = true;
|
712
877
|
this.isFocused = true;
|
878
|
+
if (this.isDisabled) {
|
879
|
+
this.blur();
|
880
|
+
e.preventDefault();
|
881
|
+
return false;
|
882
|
+
}
|
713
883
|
if (this.ignoreFocus) return;
|
714
|
-
|
884
|
+
|
885
|
+
this.showInput();
|
715
886
|
this.setActiveItem(null);
|
716
|
-
this.$control.addClass('focus');
|
717
887
|
this.refreshOptions(!!this.settings.openOnFocus);
|
888
|
+
this.refreshClasses();
|
718
889
|
};
|
719
|
-
|
890
|
+
|
720
891
|
/**
|
721
892
|
* Triggered on <input> blur.
|
722
893
|
*
|
@@ -726,17 +897,16 @@
|
|
726
897
|
Selectize.prototype.onBlur = function(e) {
|
727
898
|
this.isInputFocused = false;
|
728
899
|
if (this.ignoreFocus) return;
|
729
|
-
|
900
|
+
|
730
901
|
this.close();
|
731
902
|
this.setTextboxValue('');
|
903
|
+
this.setActiveItem(null);
|
732
904
|
this.setActiveOption(null);
|
733
|
-
this.setCaret(this.items.length
|
734
|
-
|
735
|
-
|
736
|
-
this.isFocused = false;
|
737
|
-
}
|
905
|
+
this.setCaret(this.items.length);
|
906
|
+
this.isFocused = false;
|
907
|
+
this.refreshClasses();
|
738
908
|
};
|
739
|
-
|
909
|
+
|
740
910
|
/**
|
741
911
|
* Triggered when the user rolls over
|
742
912
|
* an option in the autocomplete dropdown menu.
|
@@ -745,9 +915,10 @@
|
|
745
915
|
* @returns {boolean}
|
746
916
|
*/
|
747
917
|
Selectize.prototype.onOptionHover = function(e) {
|
918
|
+
if (this.ignoreHover) return;
|
748
919
|
this.setActiveOption(e.currentTarget, false);
|
749
920
|
};
|
750
|
-
|
921
|
+
|
751
922
|
/**
|
752
923
|
* Triggered when the user clicks on an option
|
753
924
|
* in the autocomplete dropdown menu.
|
@@ -756,18 +927,22 @@
|
|
756
927
|
* @returns {boolean}
|
757
928
|
*/
|
758
929
|
Selectize.prototype.onOptionSelect = function(e) {
|
930
|
+
e.preventDefault && e.preventDefault();
|
931
|
+
e.stopPropagation && e.stopPropagation();
|
932
|
+
this.focus(false);
|
933
|
+
|
759
934
|
var $target = $(e.currentTarget);
|
760
935
|
if ($target.hasClass('create')) {
|
761
936
|
this.createItem();
|
762
937
|
} else {
|
763
938
|
var value = $target.attr('data-value');
|
764
939
|
if (value) {
|
765
|
-
this.addItem(value);
|
766
940
|
this.setTextboxValue('');
|
941
|
+
this.addItem(value);
|
767
942
|
}
|
768
943
|
}
|
769
944
|
};
|
770
|
-
|
945
|
+
|
771
946
|
/**
|
772
947
|
* Triggered when the user clicks on an item
|
773
948
|
* that has been selected.
|
@@ -777,22 +952,49 @@
|
|
777
952
|
*/
|
778
953
|
Selectize.prototype.onItemSelect = function(e) {
|
779
954
|
if (this.settings.mode === 'multi') {
|
780
|
-
|
955
|
+
e.preventDefault();
|
781
956
|
this.setActiveItem(e.currentTarget, e);
|
782
|
-
|
957
|
+
this.focus(false);
|
958
|
+
this.hideInput();
|
783
959
|
}
|
784
960
|
};
|
785
|
-
|
961
|
+
|
962
|
+
/**
|
963
|
+
* Invokes the provided method that provides
|
964
|
+
* results to a callback---which are then added
|
965
|
+
* as options to the control.
|
966
|
+
*
|
967
|
+
* @param {function} fn
|
968
|
+
*/
|
969
|
+
Selectize.prototype.load = function(fn) {
|
970
|
+
var self = this;
|
971
|
+
var $wrapper = self.$wrapper.addClass('loading');
|
972
|
+
|
973
|
+
self.loading++;
|
974
|
+
fn.apply(self, [function(results) {
|
975
|
+
self.loading = Math.max(self.loading - 1, 0);
|
976
|
+
if (results && results.length) {
|
977
|
+
self.addOption(results);
|
978
|
+
self.refreshOptions(false);
|
979
|
+
if (self.isInputFocused) self.open();
|
980
|
+
}
|
981
|
+
if (!self.loading) {
|
982
|
+
$wrapper.removeClass('loading');
|
983
|
+
}
|
984
|
+
self.trigger('load', results);
|
985
|
+
}]);
|
986
|
+
};
|
987
|
+
|
786
988
|
/**
|
787
989
|
* Sets the input field of the control to the specified value.
|
788
990
|
*
|
789
991
|
* @param {string} value
|
790
992
|
*/
|
791
993
|
Selectize.prototype.setTextboxValue = function(value) {
|
792
|
-
this.$control_input.val(value);
|
994
|
+
this.$control_input.val(value).triggerHandler('update');
|
793
995
|
this.lastValue = value;
|
794
996
|
};
|
795
|
-
|
997
|
+
|
796
998
|
/**
|
797
999
|
* Returns the value of the control. If multiple items
|
798
1000
|
* can be selected (e.g. <select multiple>), this returns
|
@@ -808,20 +1010,22 @@
|
|
808
1010
|
return this.items.join(this.settings.delimiter);
|
809
1011
|
}
|
810
1012
|
};
|
811
|
-
|
1013
|
+
|
812
1014
|
/**
|
813
1015
|
* Resets the selected items to the given value.
|
814
1016
|
*
|
815
1017
|
* @param {mixed} value
|
816
1018
|
*/
|
817
1019
|
Selectize.prototype.setValue = function(value) {
|
818
|
-
this
|
819
|
-
|
820
|
-
|
821
|
-
|
822
|
-
|
1020
|
+
debounce_events(this, ['change'], function() {
|
1021
|
+
this.clear();
|
1022
|
+
var items = $.isArray(value) ? value : [value];
|
1023
|
+
for (var i = 0, n = items.length; i < n; i++) {
|
1024
|
+
this.addItem(items[i]);
|
1025
|
+
}
|
1026
|
+
});
|
823
1027
|
};
|
824
|
-
|
1028
|
+
|
825
1029
|
/**
|
826
1030
|
* Sets the selected item.
|
827
1031
|
*
|
@@ -832,9 +1036,9 @@
|
|
832
1036
|
var eventName;
|
833
1037
|
var i, idx, begin, end, item, swap;
|
834
1038
|
var $last;
|
835
|
-
|
1039
|
+
|
836
1040
|
$item = $($item);
|
837
|
-
|
1041
|
+
|
838
1042
|
// clear the active selection
|
839
1043
|
if (!$item.length) {
|
840
1044
|
$(this.$activeItems).removeClass('active');
|
@@ -842,10 +1046,10 @@
|
|
842
1046
|
this.isFocused = this.isInputFocused;
|
843
1047
|
return;
|
844
1048
|
}
|
845
|
-
|
1049
|
+
|
846
1050
|
// modify selection
|
847
1051
|
eventName = e && e.type.toLowerCase();
|
848
|
-
|
1052
|
+
|
849
1053
|
if (eventName === 'mousedown' && this.isShiftDown && this.$activeItems.length) {
|
850
1054
|
$last = this.$control.children('.active:last');
|
851
1055
|
begin = Array.prototype.indexOf.apply(this.$control[0].childNodes, [$last[0]]);
|
@@ -875,10 +1079,10 @@
|
|
875
1079
|
$(this.$activeItems).removeClass('active');
|
876
1080
|
this.$activeItems = [$item.addClass('active')[0]];
|
877
1081
|
}
|
878
|
-
|
1082
|
+
|
879
1083
|
this.isFocused = !!this.$activeItems.length || this.isInputFocused;
|
880
1084
|
};
|
881
|
-
|
1085
|
+
|
882
1086
|
/**
|
883
1087
|
* Sets the selected item in the dropdown menu
|
884
1088
|
* of available options.
|
@@ -890,49 +1094,61 @@
|
|
890
1094
|
Selectize.prototype.setActiveOption = function($option, scroll, animate) {
|
891
1095
|
var height_menu, height_item, y;
|
892
1096
|
var scroll_top, scroll_bottom;
|
893
|
-
|
1097
|
+
|
894
1098
|
if (this.$activeOption) this.$activeOption.removeClass('active');
|
895
1099
|
this.$activeOption = null;
|
896
|
-
|
1100
|
+
|
897
1101
|
$option = $($option);
|
898
1102
|
if (!$option.length) return;
|
899
|
-
|
1103
|
+
|
900
1104
|
this.$activeOption = $option.addClass('active');
|
901
|
-
|
1105
|
+
|
902
1106
|
if (scroll || !isset(scroll)) {
|
903
|
-
|
1107
|
+
|
904
1108
|
height_menu = this.$dropdown.height();
|
905
1109
|
height_item = this.$activeOption.outerHeight(true);
|
906
1110
|
scroll = this.$dropdown.scrollTop() || 0;
|
907
1111
|
y = this.$activeOption.offset().top - this.$dropdown.offset().top + scroll;
|
908
1112
|
scroll_top = y;
|
909
1113
|
scroll_bottom = y - height_menu + height_item;
|
910
|
-
|
1114
|
+
|
911
1115
|
if (y + height_item > height_menu - scroll) {
|
912
1116
|
this.$dropdown.stop().animate({scrollTop: scroll_bottom}, animate ? this.settings.scrollDuration : 0);
|
913
1117
|
} else if (y < scroll) {
|
914
1118
|
this.$dropdown.stop().animate({scrollTop: scroll_top}, animate ? this.settings.scrollDuration : 0);
|
915
1119
|
}
|
916
|
-
|
1120
|
+
|
917
1121
|
}
|
918
1122
|
};
|
919
|
-
|
1123
|
+
|
1124
|
+
/**
|
1125
|
+
* Selects all items (CTRL + A).
|
1126
|
+
*/
|
1127
|
+
Selectize.prototype.selectAll = function() {
|
1128
|
+
this.$activeItems = Array.prototype.slice.apply(this.$control.children(':not(input)').addClass('active'));
|
1129
|
+
this.isFocused = true;
|
1130
|
+
if (this.$activeItems.length) this.hideInput();
|
1131
|
+
};
|
1132
|
+
|
920
1133
|
/**
|
921
1134
|
* Hides the input element out of view, while
|
922
1135
|
* retaining its focus.
|
923
1136
|
*/
|
924
1137
|
Selectize.prototype.hideInput = function() {
|
925
|
-
this
|
926
|
-
this.
|
1138
|
+
this.close();
|
1139
|
+
this.setTextboxValue('');
|
1140
|
+
this.$control_input.css({opacity: 0, position: 'absolute', left: -10000});
|
1141
|
+
this.isInputHidden = true;
|
927
1142
|
};
|
928
|
-
|
1143
|
+
|
929
1144
|
/**
|
930
1145
|
* Restores input visibility.
|
931
1146
|
*/
|
932
1147
|
Selectize.prototype.showInput = function() {
|
933
|
-
this.$control_input.css({opacity: 1});
|
1148
|
+
this.$control_input.css({opacity: 1, position: 'relative', left: 0});
|
1149
|
+
this.isInputHidden = false;
|
934
1150
|
};
|
935
|
-
|
1151
|
+
|
936
1152
|
/**
|
937
1153
|
* Gives the control focus. If "trigger" is falsy,
|
938
1154
|
* focus handlers won't be fired--causing the focus
|
@@ -941,20 +1157,24 @@
|
|
941
1157
|
* @param {boolean} trigger
|
942
1158
|
*/
|
943
1159
|
Selectize.prototype.focus = function(trigger) {
|
944
|
-
|
945
|
-
|
946
|
-
|
947
|
-
|
1160
|
+
if (this.isDisabled) return;
|
1161
|
+
var self = this;
|
1162
|
+
self.ignoreFocus = true;
|
1163
|
+
self.$control_input[0].focus();
|
1164
|
+
self.isInputFocused = true;
|
1165
|
+
window.setTimeout(function() {
|
1166
|
+
self.ignoreFocus = false;
|
1167
|
+
if (trigger) self.onFocus();
|
1168
|
+
}, 0);
|
948
1169
|
};
|
949
|
-
|
1170
|
+
|
950
1171
|
/**
|
951
1172
|
* Forces the control out of focus.
|
952
1173
|
*/
|
953
1174
|
Selectize.prototype.blur = function() {
|
954
1175
|
this.$control_input.trigger('blur');
|
955
|
-
this.setActiveItem(null);
|
956
1176
|
};
|
957
|
-
|
1177
|
+
|
958
1178
|
/**
|
959
1179
|
* Splits a search string into an array of
|
960
1180
|
* individual regexps to be used to match results.
|
@@ -965,11 +1185,11 @@
|
|
965
1185
|
Selectize.prototype.parseSearchTokens = function(query) {
|
966
1186
|
query = $.trim(String(query || '').toLowerCase());
|
967
1187
|
if (!query || !query.length) return [];
|
968
|
-
|
1188
|
+
|
969
1189
|
var i, n, regex, letter;
|
970
1190
|
var tokens = [];
|
971
1191
|
var words = query.split(/ +/);
|
972
|
-
|
1192
|
+
|
973
1193
|
for (i = 0, n = words.length; i < n; i++) {
|
974
1194
|
regex = quoteRegExp(words[i]);
|
975
1195
|
if (this.settings.diacritics) {
|
@@ -984,10 +1204,10 @@
|
|
984
1204
|
regex : new RegExp(regex, 'i')
|
985
1205
|
});
|
986
1206
|
}
|
987
|
-
|
1207
|
+
|
988
1208
|
return tokens;
|
989
1209
|
};
|
990
|
-
|
1210
|
+
|
991
1211
|
/**
|
992
1212
|
* Returns a function to be used to score individual results.
|
993
1213
|
* Results will be sorted by the score (descending). Scores less
|
@@ -1000,14 +1220,14 @@
|
|
1000
1220
|
Selectize.prototype.getScoreFunction = function(search) {
|
1001
1221
|
var self = this;
|
1002
1222
|
var tokens = search.tokens;
|
1003
|
-
|
1223
|
+
|
1004
1224
|
var calculateFieldScore = (function() {
|
1005
1225
|
if (!tokens.length) {
|
1006
1226
|
return function() { return 0; };
|
1007
1227
|
} else if (tokens.length === 1) {
|
1008
1228
|
return function(value) {
|
1009
1229
|
var score, pos;
|
1010
|
-
|
1230
|
+
|
1011
1231
|
value = String(value || '').toLowerCase();
|
1012
1232
|
pos = value.search(tokens[0].regex);
|
1013
1233
|
if (pos === -1) return 0;
|
@@ -1018,7 +1238,7 @@
|
|
1018
1238
|
} else {
|
1019
1239
|
return function(value) {
|
1020
1240
|
var score, pos, i, j;
|
1021
|
-
|
1241
|
+
|
1022
1242
|
value = String(value || '').toLowerCase();
|
1023
1243
|
score = 0;
|
1024
1244
|
for (i = 0, j = tokens.length; i < j; i++) {
|
@@ -1031,7 +1251,7 @@
|
|
1031
1251
|
};
|
1032
1252
|
}
|
1033
1253
|
})();
|
1034
|
-
|
1254
|
+
|
1035
1255
|
var calculateScore = (function() {
|
1036
1256
|
var fields = self.settings.searchField;
|
1037
1257
|
if (typeof fields === 'string') {
|
@@ -1059,10 +1279,10 @@
|
|
1059
1279
|
};
|
1060
1280
|
}
|
1061
1281
|
})();
|
1062
|
-
|
1282
|
+
|
1063
1283
|
return calculateScore;
|
1064
1284
|
};
|
1065
|
-
|
1285
|
+
|
1066
1286
|
/**
|
1067
1287
|
* Searches through available options and returns
|
1068
1288
|
* a sorted array of matches. Includes options that
|
@@ -1088,20 +1308,20 @@
|
|
1088
1308
|
Selectize.prototype.search = function(query, settings) {
|
1089
1309
|
var self = this;
|
1090
1310
|
var value, score, search, calculateScore;
|
1091
|
-
|
1311
|
+
|
1092
1312
|
settings = settings || {};
|
1093
1313
|
query = $.trim(String(query || '').toLowerCase());
|
1094
|
-
|
1314
|
+
|
1095
1315
|
if (query !== this.lastQuery) {
|
1096
1316
|
this.lastQuery = query;
|
1097
|
-
|
1317
|
+
|
1098
1318
|
search = {
|
1099
1319
|
query : query,
|
1100
1320
|
tokens : this.parseSearchTokens(query),
|
1101
1321
|
total : 0,
|
1102
1322
|
items : []
|
1103
1323
|
};
|
1104
|
-
|
1324
|
+
|
1105
1325
|
// generate result scoring function
|
1106
1326
|
if (this.settings.score) {
|
1107
1327
|
calculateScore = this.settings.score.apply(this, [search]);
|
@@ -1111,7 +1331,7 @@
|
|
1111
1331
|
} else {
|
1112
1332
|
calculateScore = this.getScoreFunction(search);
|
1113
1333
|
}
|
1114
|
-
|
1334
|
+
|
1115
1335
|
// perform search and sort
|
1116
1336
|
if (query.length) {
|
1117
1337
|
for (value in this.options) {
|
@@ -1155,11 +1375,11 @@
|
|
1155
1375
|
} else {
|
1156
1376
|
search = $.extend(true, {}, this.currentResults);
|
1157
1377
|
}
|
1158
|
-
|
1378
|
+
|
1159
1379
|
// apply limits and return
|
1160
1380
|
return this.prepareResults(search, settings);
|
1161
1381
|
};
|
1162
|
-
|
1382
|
+
|
1163
1383
|
/**
|
1164
1384
|
* Filters out any items that have already been selected
|
1165
1385
|
* and applies search limits.
|
@@ -1176,15 +1396,15 @@
|
|
1176
1396
|
}
|
1177
1397
|
}
|
1178
1398
|
}
|
1179
|
-
|
1399
|
+
|
1180
1400
|
search.total = search.items.length;
|
1181
1401
|
if (typeof settings.limit === 'number') {
|
1182
1402
|
search.items = search.items.slice(0, settings.limit);
|
1183
1403
|
}
|
1184
|
-
|
1404
|
+
|
1185
1405
|
return search;
|
1186
1406
|
};
|
1187
|
-
|
1407
|
+
|
1188
1408
|
/**
|
1189
1409
|
* Refreshes the list of available options shown
|
1190
1410
|
* in the autocomplete dropdown menu.
|
@@ -1195,80 +1415,150 @@
|
|
1195
1415
|
if (typeof triggerDropdown === 'undefined') {
|
1196
1416
|
triggerDropdown = true;
|
1197
1417
|
}
|
1198
|
-
|
1199
|
-
var i, n;
|
1418
|
+
|
1419
|
+
var i, n, groups, groups_order, option, optgroup, html, html_children;
|
1200
1420
|
var hasCreateOption;
|
1201
1421
|
var query = this.$control_input.val();
|
1202
1422
|
var results = this.search(query, {});
|
1203
|
-
var
|
1204
|
-
|
1423
|
+
var $active, $create;
|
1424
|
+
var $dropdown_content = this.$dropdown_content;
|
1425
|
+
|
1205
1426
|
// build markup
|
1206
1427
|
n = results.items.length;
|
1207
1428
|
if (typeof this.settings.maxOptions === 'number') {
|
1208
1429
|
n = Math.min(n, this.settings.maxOptions);
|
1209
1430
|
}
|
1431
|
+
|
1432
|
+
// render and group available options individually
|
1433
|
+
groups = {};
|
1434
|
+
|
1435
|
+
if (this.settings.optgroupOrder) {
|
1436
|
+
groups_order = this.settings.optgroupOrder;
|
1437
|
+
for (i = 0; i < groups_order.length; i++) {
|
1438
|
+
groups[groups_order[i]] = [];
|
1439
|
+
}
|
1440
|
+
} else {
|
1441
|
+
groups_order = [];
|
1442
|
+
}
|
1443
|
+
|
1210
1444
|
for (i = 0; i < n; i++) {
|
1211
|
-
|
1445
|
+
option = this.options[results.items[i].value];
|
1446
|
+
optgroup = option[this.settings.optgroupField] || '';
|
1447
|
+
if (!this.optgroups.hasOwnProperty(optgroup)) {
|
1448
|
+
optgroup = '';
|
1449
|
+
}
|
1450
|
+
if (!groups.hasOwnProperty(optgroup)) {
|
1451
|
+
groups[optgroup] = [];
|
1452
|
+
groups_order.push(optgroup);
|
1453
|
+
}
|
1454
|
+
groups[optgroup].push(this.render('option', option));
|
1212
1455
|
}
|
1213
|
-
|
1214
|
-
|
1215
|
-
|
1456
|
+
|
1457
|
+
// render optgroup headers & join groups
|
1458
|
+
html = [];
|
1459
|
+
for (i = 0, n = groups_order.length; i < n; i++) {
|
1460
|
+
optgroup = groups_order[i];
|
1461
|
+
if (this.optgroups.hasOwnProperty(optgroup) && groups[optgroup].length) {
|
1462
|
+
// render the optgroup header and options within it,
|
1463
|
+
// then pass it to the wrapper template
|
1464
|
+
html_children = this.render('optgroup_header', this.optgroups[optgroup]) || '';
|
1465
|
+
html_children += groups[optgroup].join('');
|
1466
|
+
html.push(this.render('optgroup', $.extend({}, this.optgroups[optgroup], {
|
1467
|
+
html: html_children
|
1468
|
+
})));
|
1469
|
+
} else {
|
1470
|
+
html.push(groups[optgroup].join(''));
|
1471
|
+
}
|
1472
|
+
}
|
1473
|
+
|
1474
|
+
$dropdown_content.html(html.join(''));
|
1475
|
+
|
1216
1476
|
// highlight matching terms inline
|
1217
1477
|
if (this.settings.highlight && results.query.length && results.tokens.length) {
|
1218
1478
|
for (i = 0, n = results.tokens.length; i < n; i++) {
|
1219
|
-
highlight(
|
1479
|
+
highlight($dropdown_content, results.tokens[i].regex);
|
1220
1480
|
}
|
1221
1481
|
}
|
1222
|
-
|
1482
|
+
|
1223
1483
|
// add "selected" class to selected options
|
1224
1484
|
if (!this.settings.hideSelected) {
|
1225
1485
|
for (i = 0, n = this.items.length; i < n; i++) {
|
1226
1486
|
this.getOption(this.items[i]).addClass('selected');
|
1227
1487
|
}
|
1228
1488
|
}
|
1229
|
-
|
1489
|
+
|
1230
1490
|
// add create option
|
1231
1491
|
hasCreateOption = this.settings.create && results.query.length;
|
1232
1492
|
if (hasCreateOption) {
|
1233
|
-
|
1493
|
+
$dropdown_content.prepend(this.render('option_create', {input: query}));
|
1494
|
+
$create = $($dropdown_content[0].childNodes[0]);
|
1234
1495
|
}
|
1235
|
-
|
1496
|
+
|
1236
1497
|
// activate
|
1237
1498
|
this.hasOptions = results.items.length > 0 || hasCreateOption;
|
1238
1499
|
if (this.hasOptions) {
|
1239
|
-
|
1500
|
+
if (results.items.length > 0) {
|
1501
|
+
if ($create) {
|
1502
|
+
$active = this.getAdjacentOption($create, 1);
|
1503
|
+
} else {
|
1504
|
+
$active = $dropdown_content.find("[data-selectable]").first();
|
1505
|
+
}
|
1506
|
+
} else {
|
1507
|
+
$active = $create;
|
1508
|
+
}
|
1509
|
+
this.setActiveOption($active);
|
1240
1510
|
if (triggerDropdown && !this.isOpen) { this.open(); }
|
1241
1511
|
} else {
|
1242
1512
|
this.setActiveOption(null);
|
1243
1513
|
if (triggerDropdown && this.isOpen) { this.close(); }
|
1244
1514
|
}
|
1245
1515
|
};
|
1246
|
-
|
1516
|
+
|
1247
1517
|
/**
|
1248
1518
|
* Adds an available option. If it already exists,
|
1249
1519
|
* nothing will happen. Note: this does not refresh
|
1250
1520
|
* the options list dropdown (use `refreshOptions`
|
1251
1521
|
* for that).
|
1252
1522
|
*
|
1523
|
+
* Usage:
|
1524
|
+
*
|
1525
|
+
* this.addOption(value, data)
|
1526
|
+
* this.addOption(data)
|
1527
|
+
*
|
1253
1528
|
* @param {string} value
|
1254
1529
|
* @param {object} data
|
1255
1530
|
*/
|
1256
1531
|
Selectize.prototype.addOption = function(value, data) {
|
1532
|
+
var i, n, optgroup;
|
1533
|
+
|
1257
1534
|
if ($.isArray(value)) {
|
1258
|
-
for (
|
1535
|
+
for (i = 0, n = value.length; i < n; i++) {
|
1259
1536
|
this.addOption(value[i][this.settings.valueField], value[i]);
|
1260
1537
|
}
|
1261
1538
|
return;
|
1262
1539
|
}
|
1263
|
-
|
1540
|
+
|
1541
|
+
value = value || '';
|
1264
1542
|
if (this.options.hasOwnProperty(value)) return;
|
1265
|
-
|
1543
|
+
|
1266
1544
|
this.userOptions[value] = true;
|
1267
1545
|
this.options[value] = data;
|
1268
1546
|
this.lastQuery = null;
|
1269
|
-
this.trigger('
|
1547
|
+
this.trigger('option_add', value, data);
|
1548
|
+
};
|
1549
|
+
|
1550
|
+
/**
|
1551
|
+
* Registers a new optgroup for options
|
1552
|
+
* to be bucketed into.
|
1553
|
+
*
|
1554
|
+
* @param {string} id
|
1555
|
+
* @param {object} data
|
1556
|
+
*/
|
1557
|
+
Selectize.prototype.addOptionGroup = function(id, data) {
|
1558
|
+
this.optgroups[id] = data;
|
1559
|
+
this.trigger('optgroup_add', value, data);
|
1270
1560
|
};
|
1271
|
-
|
1561
|
+
|
1272
1562
|
/**
|
1273
1563
|
* Updates an option available for selection. If
|
1274
1564
|
* it is visible in the selected items or options
|
@@ -1282,21 +1572,21 @@
|
|
1282
1572
|
this.options[value] = data;
|
1283
1573
|
if (isset(this.renderCache['item'])) delete this.renderCache['item'][value];
|
1284
1574
|
if (isset(this.renderCache['option'])) delete this.renderCache['option'][value];
|
1285
|
-
|
1575
|
+
|
1286
1576
|
if (this.items.indexOf(value) !== -1) {
|
1287
1577
|
var $item = this.getItem(value);
|
1288
1578
|
var $item_new = $(this.render('item', data));
|
1289
1579
|
if ($item.hasClass('active')) $item_new.addClass('active');
|
1290
1580
|
$item.replaceWith($item_new);
|
1291
1581
|
}
|
1292
|
-
|
1582
|
+
|
1293
1583
|
if (this.isOpen) {
|
1294
1584
|
this.refreshOptions(false);
|
1295
1585
|
}
|
1296
1586
|
};
|
1297
|
-
|
1587
|
+
|
1298
1588
|
/**
|
1299
|
-
* Removes
|
1589
|
+
* Removes a single option.
|
1300
1590
|
*
|
1301
1591
|
* @param {string} value
|
1302
1592
|
*/
|
@@ -1305,9 +1595,22 @@
|
|
1305
1595
|
delete this.userOptions[value];
|
1306
1596
|
delete this.options[value];
|
1307
1597
|
this.lastQuery = null;
|
1308
|
-
this.trigger('
|
1598
|
+
this.trigger('option_remove', value);
|
1599
|
+
this.removeItem(value);
|
1600
|
+
};
|
1601
|
+
|
1602
|
+
/**
|
1603
|
+
* Clears all options.
|
1604
|
+
*/
|
1605
|
+
Selectize.prototype.clearOptions = function() {
|
1606
|
+
this.loadedSearches = {};
|
1607
|
+
this.userOptions = {};
|
1608
|
+
this.options = {};
|
1609
|
+
this.lastQuery = null;
|
1610
|
+
this.trigger('option_clear');
|
1611
|
+
this.clear();
|
1309
1612
|
};
|
1310
|
-
|
1613
|
+
|
1311
1614
|
/**
|
1312
1615
|
* Returns the jQuery element of the option
|
1313
1616
|
* matching the given value.
|
@@ -1316,9 +1619,24 @@
|
|
1316
1619
|
* @returns {object}
|
1317
1620
|
*/
|
1318
1621
|
Selectize.prototype.getOption = function(value) {
|
1319
|
-
return this.$
|
1622
|
+
return value ? this.$dropdown_content.find('[data-selectable]').filter('[data-value="' + value.replace(/(['"])/g, '\\$1') + '"]:first') : $();
|
1320
1623
|
};
|
1321
|
-
|
1624
|
+
|
1625
|
+
/**
|
1626
|
+
* Returns the jQuery element of the next or
|
1627
|
+
* previous selectable option.
|
1628
|
+
*
|
1629
|
+
* @param {object} $option
|
1630
|
+
* @param {int} direction can be 1 for next or -1 for previous
|
1631
|
+
* @return {object}
|
1632
|
+
*/
|
1633
|
+
Selectize.prototype.getAdjacentOption = function($option, direction) {
|
1634
|
+
var $options = this.$dropdown.find('[data-selectable]');
|
1635
|
+
var index = $options.index($option) + direction;
|
1636
|
+
|
1637
|
+
return index >= 0 && index < $options.length ? $options.eq(index) : $();
|
1638
|
+
};
|
1639
|
+
|
1322
1640
|
/**
|
1323
1641
|
* Returns the jQuery element of the item
|
1324
1642
|
* matching the given value.
|
@@ -1337,7 +1655,7 @@
|
|
1337
1655
|
}
|
1338
1656
|
return $();
|
1339
1657
|
};
|
1340
|
-
|
1658
|
+
|
1341
1659
|
/**
|
1342
1660
|
* "Selects" an item. Adds it to the list
|
1343
1661
|
* at the current caret position.
|
@@ -1345,65 +1663,60 @@
|
|
1345
1663
|
* @param {string} value
|
1346
1664
|
*/
|
1347
1665
|
Selectize.prototype.addItem = function(value) {
|
1348
|
-
|
1349
|
-
|
1350
|
-
|
1351
|
-
|
1352
|
-
|
1353
|
-
|
1354
|
-
|
1355
|
-
|
1356
|
-
|
1357
|
-
|
1358
|
-
|
1359
|
-
|
1360
|
-
|
1361
|
-
|
1362
|
-
|
1363
|
-
|
1364
|
-
|
1365
|
-
|
1366
|
-
|
1367
|
-
|
1368
|
-
|
1369
|
-
|
1370
|
-
|
1371
|
-
|
1372
|
-
|
1373
|
-
$option.remove();
|
1374
|
-
if ($option[0] === this.$activeOption[0]) {
|
1375
|
-
this.setActiveOption(options.length ? $(options[0]).addClass('active') : null);
|
1376
|
-
}
|
1377
|
-
break;
|
1666
|
+
debounce_events(this, ['change'], function() {
|
1667
|
+
var $item, $option;
|
1668
|
+
var self = this;
|
1669
|
+
var inputMode = this.settings.mode;
|
1670
|
+
var i, active, options, value_next;
|
1671
|
+
value = String(value);
|
1672
|
+
|
1673
|
+
if (inputMode === 'single') this.clear();
|
1674
|
+
if (inputMode === 'multi' && this.isFull()) return;
|
1675
|
+
if (this.items.indexOf(value) !== -1) return;
|
1676
|
+
if (!this.options.hasOwnProperty(value)) return;
|
1677
|
+
|
1678
|
+
$item = $(this.render('item', this.options[value]));
|
1679
|
+
this.items.splice(this.caretPos, 0, value);
|
1680
|
+
this.insertAtCaret($item);
|
1681
|
+
this.refreshClasses();
|
1682
|
+
|
1683
|
+
if (this.isSetup) {
|
1684
|
+
// remove the option from the menu
|
1685
|
+
options = this.$dropdown_content.find('[data-selectable]');
|
1686
|
+
$option = this.getOption(value);
|
1687
|
+
value_next = this.getAdjacentOption($option, 1).attr('data-value');
|
1688
|
+
this.refreshOptions(true);
|
1689
|
+
if (value_next) {
|
1690
|
+
this.setActiveOption(this.getOption(value_next));
|
1378
1691
|
}
|
1692
|
+
|
1693
|
+
// hide the menu if the maximum number of items have been selected or no options are left
|
1694
|
+
if (!options.length || (this.settings.maxItems !== null && this.items.length >= this.settings.maxItems)) {
|
1695
|
+
this.close();
|
1696
|
+
} else {
|
1697
|
+
this.positionDropdown();
|
1698
|
+
}
|
1699
|
+
|
1700
|
+
// restore focus to input
|
1701
|
+
if (this.isFocused) {
|
1702
|
+
window.setTimeout(function() {
|
1703
|
+
if (inputMode === 'single') {
|
1704
|
+
self.blur();
|
1705
|
+
self.focus(false);
|
1706
|
+
self.hideInput();
|
1707
|
+
} else {
|
1708
|
+
self.focus(false);
|
1709
|
+
}
|
1710
|
+
}, 0);
|
1711
|
+
}
|
1712
|
+
|
1713
|
+
this.updatePlaceholder();
|
1714
|
+
this.trigger('item_add', value, $item);
|
1715
|
+
this.updateOriginalInput();
|
1379
1716
|
}
|
1380
|
-
|
1381
|
-
// hide the menu if the maximum number of items have been selected or no options are left
|
1382
|
-
if (!options.length || (this.settings.maxItems !== null && this.items.length >= this.settings.maxItems)) {
|
1383
|
-
this.close();
|
1384
|
-
} else {
|
1385
|
-
this.positionDropdown();
|
1386
|
-
}
|
1387
|
-
|
1388
|
-
// restore focus to input
|
1389
|
-
if (this.isFocused) {
|
1390
|
-
window.setTimeout(function() {
|
1391
|
-
if (inputMode === 'single') {
|
1392
|
-
self.blur();
|
1393
|
-
self.focus(false);
|
1394
|
-
self.hideInput();
|
1395
|
-
} else {
|
1396
|
-
self.focus(false);
|
1397
|
-
}
|
1398
|
-
}, 0);
|
1399
|
-
}
|
1400
|
-
|
1401
|
-
this.updatePlaceholder();
|
1402
|
-
this.updateOriginalInput();
|
1403
|
-
this.trigger('onItemAdd', value, $item);
|
1404
|
-
}
|
1717
|
+
});
|
1405
1718
|
};
|
1406
|
-
|
1719
|
+
|
1407
1720
|
/**
|
1408
1721
|
* Removes the selected item matching
|
1409
1722
|
* the provided value.
|
@@ -1412,38 +1725,36 @@
|
|
1412
1725
|
*/
|
1413
1726
|
Selectize.prototype.removeItem = function(value) {
|
1414
1727
|
var $item, i, idx;
|
1415
|
-
|
1728
|
+
|
1416
1729
|
$item = (typeof value === 'object') ? value : this.getItem(value);
|
1417
1730
|
value = String($item.attr('data-value'));
|
1418
1731
|
i = this.items.indexOf(value);
|
1419
|
-
|
1732
|
+
|
1420
1733
|
if (i !== -1) {
|
1421
1734
|
$item.remove();
|
1422
1735
|
if ($item.hasClass('active')) {
|
1423
1736
|
idx = this.$activeItems.indexOf($item[0]);
|
1424
1737
|
this.$activeItems.splice(idx, 1);
|
1425
1738
|
}
|
1426
|
-
|
1739
|
+
|
1427
1740
|
this.items.splice(i, 1);
|
1428
|
-
this.$control.toggleClass('has-items', this.items.length > 0);
|
1429
|
-
this.$control.removeClass('full').addClass('not-full');
|
1430
1741
|
this.lastQuery = null;
|
1431
1742
|
if (!this.settings.persist && this.userOptions.hasOwnProperty(value)) {
|
1432
1743
|
this.removeOption(value);
|
1433
1744
|
}
|
1434
|
-
|
1435
|
-
this.
|
1436
|
-
|
1437
|
-
|
1438
|
-
|
1439
|
-
|
1440
|
-
|
1745
|
+
|
1746
|
+
if (i < this.caretPos) {
|
1747
|
+
this.setCaret(this.caretPos - 1);
|
1748
|
+
}
|
1749
|
+
|
1750
|
+
this.refreshClasses();
|
1441
1751
|
this.updatePlaceholder();
|
1442
1752
|
this.updateOriginalInput();
|
1443
|
-
this.
|
1753
|
+
this.positionDropdown();
|
1754
|
+
this.trigger('item_remove', value);
|
1444
1755
|
}
|
1445
1756
|
};
|
1446
|
-
|
1757
|
+
|
1447
1758
|
/**
|
1448
1759
|
* Invokes the `create` method provided in the
|
1449
1760
|
* selectize options that should provide the data
|
@@ -1458,53 +1769,66 @@
|
|
1458
1769
|
var caret = this.caretPos;
|
1459
1770
|
if (!input.length) return;
|
1460
1771
|
this.lock();
|
1461
|
-
|
1462
|
-
|
1772
|
+
|
1463
1773
|
var setup = (typeof this.settings.create === 'function') ? this.settings.create : function(input) {
|
1464
1774
|
var data = {};
|
1465
1775
|
data[self.settings.labelField] = input;
|
1466
1776
|
data[self.settings.valueField] = input;
|
1467
1777
|
return data;
|
1468
1778
|
};
|
1469
|
-
|
1779
|
+
|
1470
1780
|
var create = once(function(data) {
|
1471
1781
|
self.unlock();
|
1472
1782
|
self.focus(false);
|
1473
|
-
|
1783
|
+
|
1474
1784
|
var value = data && data[self.settings.valueField];
|
1475
1785
|
if (!value) return;
|
1476
|
-
|
1786
|
+
|
1787
|
+
self.setTextboxValue('');
|
1477
1788
|
self.addOption(value, data);
|
1478
|
-
self.setCaret(caret
|
1789
|
+
self.setCaret(caret);
|
1479
1790
|
self.addItem(value);
|
1480
|
-
self.refreshOptions(
|
1481
|
-
self.
|
1791
|
+
self.refreshOptions(true);
|
1792
|
+
self.focus(false);
|
1482
1793
|
});
|
1483
|
-
|
1484
|
-
var output = setup(input, create);
|
1485
|
-
if (typeof output
|
1794
|
+
|
1795
|
+
var output = setup.apply(this, [input, create]);
|
1796
|
+
if (typeof output !== 'undefined') {
|
1486
1797
|
create(output);
|
1487
1798
|
}
|
1488
1799
|
};
|
1489
|
-
|
1800
|
+
|
1490
1801
|
/**
|
1491
1802
|
* Re-renders the selected item lists.
|
1492
1803
|
*/
|
1493
1804
|
Selectize.prototype.refreshItems = function() {
|
1494
|
-
var isFull = this.isFull();
|
1495
1805
|
this.lastQuery = null;
|
1496
|
-
|
1497
|
-
this.$control.toggleClass('has-items', this.items.length > 0);
|
1498
|
-
|
1806
|
+
|
1499
1807
|
if (this.isSetup) {
|
1500
1808
|
for (var i = 0; i < this.items.length; i++) {
|
1501
1809
|
this.addItem(this.items);
|
1502
1810
|
}
|
1503
1811
|
}
|
1504
|
-
|
1812
|
+
|
1813
|
+
this.refreshClasses();
|
1505
1814
|
this.updateOriginalInput();
|
1506
1815
|
};
|
1507
|
-
|
1816
|
+
|
1817
|
+
/**
|
1818
|
+
* Updates all state-dependent CSS classes.
|
1819
|
+
*/
|
1820
|
+
Selectize.prototype.refreshClasses = function() {
|
1821
|
+
var isFull = this.isFull();
|
1822
|
+
var isLocked = this.isLocked;
|
1823
|
+
this.$control
|
1824
|
+
.toggleClass('focus', this.isFocused)
|
1825
|
+
.toggleClass('disabled', this.isDisabled)
|
1826
|
+
.toggleClass('locked', isLocked)
|
1827
|
+
.toggleClass('full', isFull).toggleClass('not-full', !isFull)
|
1828
|
+
.toggleClass('has-items', this.items.length > 0);
|
1829
|
+
this.$control_input.data('grow', !isFull && !isLocked);
|
1830
|
+
};
|
1831
|
+
|
1508
1832
|
/**
|
1509
1833
|
* Determines whether or not more items can be added
|
1510
1834
|
* to the control without exceeding the user-defined maximum.
|
@@ -1514,14 +1838,14 @@
|
|
1514
1838
|
Selectize.prototype.isFull = function() {
|
1515
1839
|
return this.settings.maxItems !== null && this.items.length >= this.settings.maxItems;
|
1516
1840
|
};
|
1517
|
-
|
1841
|
+
|
1518
1842
|
/**
|
1519
1843
|
* Refreshes the original <select> or <input>
|
1520
1844
|
* element to reflect the current state.
|
1521
1845
|
*/
|
1522
1846
|
Selectize.prototype.updateOriginalInput = function() {
|
1523
1847
|
var i, n, options;
|
1524
|
-
|
1848
|
+
|
1525
1849
|
if (this.$input[0].tagName.toLowerCase() === 'select') {
|
1526
1850
|
options = [];
|
1527
1851
|
for (i = 0, n = this.items.length; i < n; i++) {
|
@@ -1534,13 +1858,13 @@
|
|
1534
1858
|
} else {
|
1535
1859
|
this.$input.val(this.getValue());
|
1536
1860
|
}
|
1537
|
-
|
1861
|
+
|
1538
1862
|
this.$input.trigger('change');
|
1539
1863
|
if (this.isSetup) {
|
1540
|
-
this.trigger('
|
1864
|
+
this.trigger('change', this.$input.val());
|
1541
1865
|
}
|
1542
1866
|
};
|
1543
|
-
|
1867
|
+
|
1544
1868
|
/**
|
1545
1869
|
* Shows/hide the input placeholder depending
|
1546
1870
|
* on if there items in the list already.
|
@@ -1548,7 +1872,7 @@
|
|
1548
1872
|
Selectize.prototype.updatePlaceholder = function() {
|
1549
1873
|
if (!this.settings.placeholder) return;
|
1550
1874
|
var $input = this.$control_input;
|
1551
|
-
|
1875
|
+
|
1552
1876
|
if (this.items.length) {
|
1553
1877
|
$input.removeAttr('placeholder');
|
1554
1878
|
} else {
|
@@ -1556,20 +1880,22 @@
|
|
1556
1880
|
}
|
1557
1881
|
$input.triggerHandler('update');
|
1558
1882
|
};
|
1559
|
-
|
1883
|
+
|
1560
1884
|
/**
|
1561
1885
|
* Shows the autocomplete dropdown containing
|
1562
1886
|
* the available options.
|
1563
1887
|
*/
|
1564
1888
|
Selectize.prototype.open = function() {
|
1565
|
-
if (this.isOpen || (this.settings.mode === 'multi' && this.isFull())) return;
|
1889
|
+
if (this.isLocked || this.isOpen || (this.settings.mode === 'multi' && this.isFull())) return;
|
1890
|
+
this.focus();
|
1566
1891
|
this.isOpen = true;
|
1567
|
-
this.
|
1892
|
+
this.$dropdown.css({visibility: 'hidden', display: 'block'});
|
1568
1893
|
this.$control.addClass('dropdown-active');
|
1569
|
-
this
|
1570
|
-
this.
|
1894
|
+
this.positionDropdown();
|
1895
|
+
this.$dropdown.css({visibility: 'visible'});
|
1896
|
+
this.trigger('dropdown_open', this.$dropdown);
|
1571
1897
|
};
|
1572
|
-
|
1898
|
+
|
1573
1899
|
/**
|
1574
1900
|
* Closes the autocomplete dropdown menu.
|
1575
1901
|
*/
|
@@ -1577,10 +1903,11 @@
|
|
1577
1903
|
if (!this.isOpen) return;
|
1578
1904
|
this.$dropdown.hide();
|
1579
1905
|
this.$control.removeClass('dropdown-active');
|
1906
|
+
this.setActiveOption(null);
|
1580
1907
|
this.isOpen = false;
|
1581
|
-
this.trigger('
|
1908
|
+
this.trigger('dropdown_close', this.$dropdown);
|
1582
1909
|
};
|
1583
|
-
|
1910
|
+
|
1584
1911
|
/**
|
1585
1912
|
* Calculates and applies the appropriate
|
1586
1913
|
* position of the dropdown.
|
@@ -1589,29 +1916,30 @@
|
|
1589
1916
|
var $control = this.$control;
|
1590
1917
|
var offset = $control.position();
|
1591
1918
|
offset.top += $control.outerHeight(true);
|
1592
|
-
|
1919
|
+
|
1593
1920
|
this.$dropdown.css({
|
1594
1921
|
width : $control.outerWidth(),
|
1595
1922
|
top : offset.top,
|
1596
1923
|
left : offset.left
|
1597
1924
|
});
|
1598
1925
|
};
|
1599
|
-
|
1926
|
+
|
1600
1927
|
/**
|
1601
1928
|
* Resets / clears all selected items
|
1602
1929
|
* from the control.
|
1603
1930
|
*/
|
1604
1931
|
Selectize.prototype.clear = function() {
|
1605
1932
|
if (!this.items.length) return;
|
1606
|
-
this.$control.removeClass('has-items');
|
1607
1933
|
this.$control.children(':not(input)').remove();
|
1608
1934
|
this.items = [];
|
1609
1935
|
this.setCaret(0);
|
1610
1936
|
this.updatePlaceholder();
|
1611
1937
|
this.updateOriginalInput();
|
1612
|
-
this.
|
1938
|
+
this.refreshClasses();
|
1939
|
+
this.showInput();
|
1940
|
+
this.trigger('clear');
|
1613
1941
|
};
|
1614
|
-
|
1942
|
+
|
1615
1943
|
/**
|
1616
1944
|
* A helper method for inserting an element
|
1617
1945
|
* at the current caret position.
|
@@ -1627,42 +1955,60 @@
|
|
1627
1955
|
}
|
1628
1956
|
this.setCaret(caret + 1);
|
1629
1957
|
};
|
1630
|
-
|
1958
|
+
|
1631
1959
|
/**
|
1632
1960
|
* Removes the current selected item(s).
|
1633
1961
|
*
|
1634
1962
|
* @param {object} e (optional)
|
1963
|
+
* @returns {boolean}
|
1635
1964
|
*/
|
1636
1965
|
Selectize.prototype.deleteSelection = function(e) {
|
1637
1966
|
var i, n, direction, selection, values, caret, $tail;
|
1638
|
-
|
1639
|
-
direction = (e.keyCode === KEY_BACKSPACE) ? -1 : 1;
|
1967
|
+
|
1968
|
+
direction = (e && e.keyCode === KEY_BACKSPACE) ? -1 : 1;
|
1640
1969
|
selection = getSelection(this.$control_input[0]);
|
1970
|
+
|
1971
|
+
// determine items that will be removed
|
1972
|
+
values = [];
|
1973
|
+
|
1641
1974
|
if (this.$activeItems.length) {
|
1642
1975
|
$tail = this.$control.children('.active:' + (direction > 0 ? 'last' : 'first'));
|
1643
|
-
caret =
|
1644
|
-
if (
|
1645
|
-
|
1646
|
-
values = [];
|
1976
|
+
caret = this.$control.children(':not(input)').index($tail);
|
1977
|
+
if (direction > 0) { caret++; }
|
1978
|
+
|
1647
1979
|
for (i = 0, n = this.$activeItems.length; i < n; i++) {
|
1648
1980
|
values.push($(this.$activeItems[i]).attr('data-value'));
|
1649
1981
|
}
|
1650
|
-
|
1651
|
-
|
1982
|
+
if (e) {
|
1983
|
+
e.preventDefault();
|
1984
|
+
e.stopPropagation();
|
1652
1985
|
}
|
1653
|
-
|
1654
|
-
this.setCaret(caret);
|
1655
|
-
e.preventDefault();
|
1656
|
-
e.stopPropagation();
|
1657
|
-
} else if ((this.isInputFocused || this.settings.mode === 'single') && this.items.length) {
|
1986
|
+
} else if ((this.isFocused || this.settings.mode === 'single') && this.items.length) {
|
1658
1987
|
if (direction < 0 && selection.start === 0 && selection.length === 0) {
|
1659
|
-
|
1988
|
+
values.push(this.items[this.caretPos - 1]);
|
1660
1989
|
} else if (direction > 0 && selection.start === this.$control_input.val().length) {
|
1661
|
-
|
1990
|
+
values.push(this.items[this.caretPos]);
|
1662
1991
|
}
|
1663
1992
|
}
|
1993
|
+
|
1994
|
+
// allow the callback to abort
|
1995
|
+
if (!values.length || (typeof this.settings.onDelete === 'function' && this.settings.onDelete(values) === false)) {
|
1996
|
+
return false;
|
1997
|
+
}
|
1998
|
+
|
1999
|
+
// perform removal
|
2000
|
+
if (typeof caret !== 'undefined') {
|
2001
|
+
this.setCaret(caret);
|
2002
|
+
}
|
2003
|
+
while (values.length) {
|
2004
|
+
this.removeItem(values.pop());
|
2005
|
+
}
|
2006
|
+
|
2007
|
+
this.showInput();
|
2008
|
+
this.refreshOptions(true);
|
2009
|
+
return true;
|
1664
2010
|
};
|
1665
|
-
|
2011
|
+
|
1666
2012
|
/**
|
1667
2013
|
* Selects the previous / next item (depending
|
1668
2014
|
* on the `direction` argument).
|
@@ -1674,28 +2020,33 @@
|
|
1674
2020
|
* @param {object} e (optional)
|
1675
2021
|
*/
|
1676
2022
|
Selectize.prototype.advanceSelection = function(direction, e) {
|
2023
|
+
var tail, selection, idx, valueLength, cursorAtEdge, $tail;
|
2024
|
+
|
1677
2025
|
if (direction === 0) return;
|
1678
|
-
|
1679
|
-
|
1680
|
-
|
1681
|
-
|
1682
|
-
|
1683
|
-
|
2026
|
+
|
2027
|
+
tail = direction > 0 ? 'last' : 'first';
|
2028
|
+
selection = getSelection(this.$control_input[0]);
|
2029
|
+
|
2030
|
+
if (this.isInputFocused && !this.isInputHidden) {
|
2031
|
+
valueLength = this.$control_input.val().length;
|
2032
|
+
cursorAtEdge = direction < 0
|
1684
2033
|
? selection.start === 0 && selection.length === 0
|
1685
2034
|
: selection.start === valueLength;
|
1686
|
-
|
2035
|
+
|
1687
2036
|
if (cursorAtEdge && !valueLength) {
|
1688
2037
|
this.advanceCaret(direction, e);
|
1689
2038
|
}
|
1690
2039
|
} else {
|
1691
|
-
|
2040
|
+
$tail = this.$control.children('.active:' + tail);
|
1692
2041
|
if ($tail.length) {
|
1693
|
-
|
2042
|
+
idx = this.$control.children(':not(input)').index($tail);
|
2043
|
+
this.setActiveItem(null);
|
1694
2044
|
this.setCaret(direction > 0 ? idx + 1 : idx);
|
2045
|
+
this.showInput();
|
1695
2046
|
}
|
1696
2047
|
}
|
1697
2048
|
};
|
1698
|
-
|
2049
|
+
|
1699
2050
|
/**
|
1700
2051
|
* Moves the caret left / right.
|
1701
2052
|
*
|
@@ -1708,7 +2059,7 @@
|
|
1708
2059
|
if (this.isShiftDown) {
|
1709
2060
|
var $adj = this.$control_input[fn]();
|
1710
2061
|
if ($adj.length) {
|
1711
|
-
this.
|
2062
|
+
this.hideInput();
|
1712
2063
|
this.setActiveItem($adj);
|
1713
2064
|
e && e.preventDefault();
|
1714
2065
|
}
|
@@ -1716,52 +2067,72 @@
|
|
1716
2067
|
this.setCaret(this.caretPos + direction);
|
1717
2068
|
}
|
1718
2069
|
};
|
1719
|
-
|
2070
|
+
|
1720
2071
|
/**
|
1721
2072
|
* Moves the caret to the specified index.
|
1722
2073
|
*
|
1723
2074
|
* @param {int} i
|
1724
|
-
* @param {boolean} focus
|
1725
2075
|
*/
|
1726
|
-
Selectize.prototype.setCaret = function(i
|
1727
|
-
if (this.settings.mode === 'single'
|
2076
|
+
Selectize.prototype.setCaret = function(i) {
|
2077
|
+
if (this.settings.mode === 'single') {
|
1728
2078
|
i = this.items.length;
|
1729
2079
|
} else {
|
1730
2080
|
i = Math.max(0, Math.min(this.items.length, i));
|
1731
2081
|
}
|
1732
|
-
|
1733
|
-
|
1734
|
-
|
1735
|
-
|
1736
|
-
|
1737
|
-
|
1738
|
-
|
1739
|
-
|
1740
|
-
|
1741
|
-
|
1742
|
-
|
2082
|
+
|
2083
|
+
// the input must be moved by leaving it in place and moving the
|
2084
|
+
// siblings, due to the fact that focus cannot be restored once lost
|
2085
|
+
// on mobile webkit devices
|
2086
|
+
var j, n, fn, $children, $child;
|
2087
|
+
$children = this.$control.children(':not(input)');
|
2088
|
+
for (j = 0, n = $children.length; j < n; j++) {
|
2089
|
+
$child = $($children[j]).detach();
|
2090
|
+
if (j < i) {
|
2091
|
+
this.$control_input.before($child);
|
2092
|
+
} else {
|
2093
|
+
this.$control.append($child);
|
2094
|
+
}
|
1743
2095
|
}
|
1744
|
-
|
2096
|
+
|
1745
2097
|
this.caretPos = i;
|
1746
2098
|
};
|
1747
|
-
|
2099
|
+
|
1748
2100
|
/**
|
1749
2101
|
* Disables user input on the control. Used while
|
1750
2102
|
* items are being asynchronously created.
|
1751
2103
|
*/
|
1752
2104
|
Selectize.prototype.lock = function() {
|
2105
|
+
this.close();
|
1753
2106
|
this.isLocked = true;
|
1754
|
-
this
|
2107
|
+
this.refreshClasses();
|
1755
2108
|
};
|
1756
|
-
|
2109
|
+
|
1757
2110
|
/**
|
1758
2111
|
* Re-enables user input on the control.
|
1759
2112
|
*/
|
1760
2113
|
Selectize.prototype.unlock = function() {
|
1761
2114
|
this.isLocked = false;
|
1762
|
-
this
|
2115
|
+
this.refreshClasses();
|
2116
|
+
};
|
2117
|
+
|
2118
|
+
/**
|
2119
|
+
* Disables user input on the control completely.
|
2120
|
+
* While disabled, it cannot receive focus.
|
2121
|
+
*/
|
2122
|
+
Selectize.prototype.disable = function() {
|
2123
|
+
this.isDisabled = true;
|
2124
|
+
this.lock();
|
2125
|
+
};
|
2126
|
+
|
2127
|
+
/**
|
2128
|
+
* Enables the control so that it can respond
|
2129
|
+
* to focus and user input.
|
2130
|
+
*/
|
2131
|
+
Selectize.prototype.enable = function() {
|
2132
|
+
this.isDisabled = false;
|
2133
|
+
this.unlock();
|
1763
2134
|
};
|
1764
|
-
|
2135
|
+
|
1765
2136
|
/**
|
1766
2137
|
* A helper method for rendering "item" and
|
1767
2138
|
* "option" templates, given the data.
|
@@ -1771,17 +2142,17 @@
|
|
1771
2142
|
* @returns {string}
|
1772
2143
|
*/
|
1773
2144
|
Selectize.prototype.render = function(templateName, data) {
|
1774
|
-
|
1775
|
-
|
1776
|
-
var value, label;
|
2145
|
+
var value, id, label;
|
1777
2146
|
var html = '';
|
1778
2147
|
var cache = false;
|
1779
|
-
|
1780
|
-
|
2148
|
+
var regex_tag = /^[\ ]*<([a-z][a-z0-9\-_]*(?:\:[a-z][a-z0-9\-_]*)?)/i;
|
2149
|
+
|
2150
|
+
if (templateName === 'option' || templateName === 'item') {
|
1781
2151
|
value = data[this.settings.valueField];
|
1782
2152
|
cache = isset(value);
|
1783
2153
|
}
|
1784
|
-
|
2154
|
+
|
2155
|
+
// pull markup from cache if it exists
|
1785
2156
|
if (cache) {
|
1786
2157
|
if (!isset(this.renderCache[templateName])) {
|
1787
2158
|
this.renderCache[templateName] = {};
|
@@ -1790,34 +2161,466 @@
|
|
1790
2161
|
return this.renderCache[templateName][value];
|
1791
2162
|
}
|
1792
2163
|
}
|
1793
|
-
|
2164
|
+
|
2165
|
+
// render markup
|
1794
2166
|
if (this.settings.render && typeof this.settings.render[templateName] === 'function') {
|
1795
|
-
html = this.settings.render[templateName].apply(this, [data]);
|
2167
|
+
html = this.settings.render[templateName].apply(this, [data, htmlEntities]);
|
1796
2168
|
} else {
|
1797
2169
|
label = data[this.settings.labelField];
|
1798
2170
|
switch (templateName) {
|
2171
|
+
case 'optgroup':
|
2172
|
+
html = '<div class="optgroup">' + data.html + "</div>";
|
2173
|
+
break;
|
2174
|
+
case 'optgroup_header':
|
2175
|
+
label = data[this.settings.optgroupLabelField];
|
2176
|
+
html = '<div class="optgroup-header">' + htmlEntities(label) + '</div>';
|
2177
|
+
break;
|
1799
2178
|
case 'option':
|
1800
|
-
html = '<div class="option">' + label + '</div>';
|
2179
|
+
html = '<div class="option">' + htmlEntities(label) + '</div>';
|
1801
2180
|
break;
|
1802
2181
|
case 'item':
|
1803
|
-
html = '<div class="item">' + label + '</div>';
|
2182
|
+
html = '<div class="item">' + htmlEntities(label) + '</div>';
|
1804
2183
|
break;
|
1805
2184
|
case 'option_create':
|
1806
2185
|
html = '<div class="create">Create <strong>' + htmlEntities(data.input) + '</strong>…</div>';
|
1807
2186
|
break;
|
1808
2187
|
}
|
1809
2188
|
}
|
1810
|
-
|
1811
|
-
|
1812
|
-
|
2189
|
+
|
2190
|
+
// add mandatory attributes
|
2191
|
+
if (templateName === 'option' || templateName === 'option_create') {
|
2192
|
+
html = html.replace(regex_tag, '<$1 data-selectable');
|
2193
|
+
}
|
2194
|
+
if (templateName === 'optgroup') {
|
2195
|
+
id = data[this.settings.optgroupValueField] || '';
|
2196
|
+
html = html.replace(regex_tag, '<$1 data-group="' + htmlEntities(id) + '"');
|
1813
2197
|
}
|
2198
|
+
if (templateName === 'option' || templateName === 'item') {
|
2199
|
+
html = html.replace(regex_tag, '<$1 data-value="' + htmlEntities(value || '') + '"');
|
2200
|
+
}
|
2201
|
+
|
2202
|
+
// update cache
|
1814
2203
|
if (cache) {
|
1815
2204
|
this.renderCache[templateName][value] = html;
|
1816
2205
|
}
|
1817
|
-
|
2206
|
+
|
1818
2207
|
return html;
|
1819
2208
|
};
|
1820
2209
|
|
2210
|
+
Selectize.defaults = {
|
2211
|
+
plugins: [],
|
2212
|
+
delimiter: ',',
|
2213
|
+
persist: true,
|
2214
|
+
diacritics: true,
|
2215
|
+
create: false,
|
2216
|
+
highlight: true,
|
2217
|
+
openOnFocus: true,
|
2218
|
+
maxOptions: 1000,
|
2219
|
+
maxItems: null,
|
2220
|
+
hideSelected: null,
|
2221
|
+
preload: false,
|
2222
|
+
|
2223
|
+
scrollDuration: 60,
|
2224
|
+
loadThrottle: 300,
|
2225
|
+
|
2226
|
+
dataAttr: 'data-data',
|
2227
|
+
optgroupField: 'optgroup',
|
2228
|
+
sortField: null,
|
2229
|
+
sortDirection: 'asc',
|
2230
|
+
valueField: 'value',
|
2231
|
+
labelField: 'text',
|
2232
|
+
optgroupLabelField: 'label',
|
2233
|
+
optgroupValueField: 'value',
|
2234
|
+
optgroupOrder: null,
|
2235
|
+
searchField: ['text'],
|
2236
|
+
|
2237
|
+
mode: null,
|
2238
|
+
theme: 'default',
|
2239
|
+
wrapperClass: 'selectize-control',
|
2240
|
+
inputClass: 'selectize-input',
|
2241
|
+
dropdownClass: 'selectize-dropdown',
|
2242
|
+
dropdownContentClass: 'selectize-dropdown-content',
|
2243
|
+
|
2244
|
+
load : null, // function(query, callback)
|
2245
|
+
score : null, // function(search)
|
2246
|
+
onChange : null, // function(value)
|
2247
|
+
onItemAdd : null, // function(value, $item) { ... }
|
2248
|
+
onItemRemove : null, // function(value) { ... }
|
2249
|
+
onClear : null, // function() { ... }
|
2250
|
+
onOptionAdd : null, // function(value, data) { ... }
|
2251
|
+
onOptionRemove : null, // function(value) { ... }
|
2252
|
+
onOptionClear : null, // function() { ... }
|
2253
|
+
onDropdownOpen : null, // function($dropdown) { ... }
|
2254
|
+
onDropdownClose : null, // function($dropdown) { ... }
|
2255
|
+
onType : null, // function(str) { ... }
|
2256
|
+
onDelete : null, // function(values) { ... }
|
2257
|
+
|
2258
|
+
render: {
|
2259
|
+
item: null,
|
2260
|
+
optgroup: null,
|
2261
|
+
optgroup_header: null,
|
2262
|
+
option: null,
|
2263
|
+
option_create: null
|
2264
|
+
}
|
2265
|
+
};
|
2266
|
+
|
2267
|
+
/* --- file: "src/selectize.jquery.js" --- */
|
2268
|
+
|
2269
|
+
$.fn.selectize = function(settings) {
|
2270
|
+
settings = settings || {};
|
2271
|
+
|
2272
|
+
var defaults = $.fn.selectize.defaults;
|
2273
|
+
var dataAttr = settings.dataAttr || defaults.dataAttr;
|
2274
|
+
|
2275
|
+
/**
|
2276
|
+
* Initializes selectize from a <input type="text"> element.
|
2277
|
+
*
|
2278
|
+
* @param {object} $input
|
2279
|
+
* @param {object} settings
|
2280
|
+
*/
|
2281
|
+
var init_textbox = function($input, settings_element) {
|
2282
|
+
var i, n, values, value = $.trim($input.val() || '');
|
2283
|
+
if (!value.length) return;
|
2284
|
+
|
2285
|
+
values = value.split(settings.delimiter || defaults.delimiter);
|
2286
|
+
for (i = 0, n = values.length; i < n; i++) {
|
2287
|
+
settings_element.options[values[i]] = {
|
2288
|
+
'text' : values[i],
|
2289
|
+
'value' : values[i]
|
2290
|
+
};
|
2291
|
+
}
|
2292
|
+
|
2293
|
+
settings_element.items = values;
|
2294
|
+
};
|
2295
|
+
|
2296
|
+
/**
|
2297
|
+
* Initializes selectize from a <select> element.
|
2298
|
+
*
|
2299
|
+
* @param {object} $input
|
2300
|
+
* @param {object} settings
|
2301
|
+
*/
|
2302
|
+
var init_select = function($input, settings_element) {
|
2303
|
+
var i, n, tagName;
|
2304
|
+
var $children;
|
2305
|
+
settings_element.maxItems = !!$input.attr('multiple') ? null : 1;
|
2306
|
+
|
2307
|
+
var readData = function($el) {
|
2308
|
+
var data = dataAttr && $el.attr(dataAttr);
|
2309
|
+
if (typeof data === 'string' && data.length) {
|
2310
|
+
return JSON.parse(data);
|
2311
|
+
}
|
2312
|
+
return null;
|
2313
|
+
};
|
2314
|
+
|
2315
|
+
var addOption = function($option, group) {
|
2316
|
+
$option = $($option);
|
2317
|
+
|
2318
|
+
var value = $option.attr('value') || '';
|
2319
|
+
if (!value.length) return;
|
2320
|
+
|
2321
|
+
settings_element.options[value] = readData($option) || {
|
2322
|
+
'text' : $option.html(),
|
2323
|
+
'value' : value,
|
2324
|
+
'optgroup' : group
|
2325
|
+
};
|
2326
|
+
if ($option.is(':selected')) {
|
2327
|
+
settings_element.items.push(value);
|
2328
|
+
}
|
2329
|
+
};
|
2330
|
+
|
2331
|
+
var addGroup = function($optgroup) {
|
2332
|
+
var i, n, $options = $('option', $optgroup);
|
2333
|
+
$optgroup = $($optgroup);
|
2334
|
+
|
2335
|
+
var id = $optgroup.attr('label');
|
2336
|
+
if (id && id.length) {
|
2337
|
+
settings_element.optgroups[id] = readData($optgroup) || {
|
2338
|
+
'label': id
|
2339
|
+
};
|
2340
|
+
}
|
2341
|
+
|
2342
|
+
for (i = 0, n = $options.length; i < n; i++) {
|
2343
|
+
addOption($options[i], id);
|
2344
|
+
}
|
2345
|
+
};
|
2346
|
+
|
2347
|
+
$children = $input.children();
|
2348
|
+
for (i = 0, n = $children.length; i < n; i++) {
|
2349
|
+
tagName = $children[i].tagName.toLowerCase();
|
2350
|
+
if (tagName === 'optgroup') {
|
2351
|
+
addGroup($children[i]);
|
2352
|
+
} else if (tagName === 'option') {
|
2353
|
+
addOption($children[i]);
|
2354
|
+
}
|
2355
|
+
}
|
2356
|
+
};
|
2357
|
+
|
2358
|
+
return this.each(function() {
|
2359
|
+
var instance;
|
2360
|
+
var $input = $(this);
|
2361
|
+
var tag_name = $input[0].tagName.toLowerCase();
|
2362
|
+
var settings_element = {
|
2363
|
+
'placeholder' : $input.attr('placeholder'),
|
2364
|
+
'options' : {},
|
2365
|
+
'optgroups' : {},
|
2366
|
+
'items' : []
|
2367
|
+
};
|
2368
|
+
|
2369
|
+
if (tag_name === 'select') {
|
2370
|
+
init_select($input, settings_element);
|
2371
|
+
} else {
|
2372
|
+
init_textbox($input, settings_element);
|
2373
|
+
}
|
2374
|
+
|
2375
|
+
instance = new Selectize($input, $.extend(true, {}, defaults, settings_element, settings));
|
2376
|
+
$input.data('selectize', instance);
|
2377
|
+
$input.addClass('selectized');
|
2378
|
+
});
|
2379
|
+
};
|
2380
|
+
|
2381
|
+
$.fn.selectize.defaults = Selectize.defaults;
|
2382
|
+
|
2383
|
+
/* --- file: "src/plugins/drag_drop/plugin.js" --- */
|
2384
|
+
|
2385
|
+
/**
|
2386
|
+
* Plugin: "drag_drop" (selectize.js)
|
2387
|
+
* Copyright (c) 2013 Brian Reavis & contributors
|
2388
|
+
*
|
2389
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
|
2390
|
+
* file except in compliance with the License. You may obtain a copy of the License at:
|
2391
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
2392
|
+
*
|
2393
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
2394
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
2395
|
+
* ANY KIND, either express or implied. See the License for the specific language
|
2396
|
+
* governing permissions and limitations under the License.
|
2397
|
+
*
|
2398
|
+
* @author Brian Reavis <brian@thirdroute.com>
|
2399
|
+
*/
|
2400
|
+
|
2401
|
+
Selectize.registerPlugin('drag_drop', function(options) {
|
2402
|
+
if (!$.fn.sortable) throw new Error('The "drag_drop" Selectize plugin requires jQuery UI "sortable".');
|
2403
|
+
if (this.settings.mode !== 'multi') return;
|
2404
|
+
var self = this;
|
2405
|
+
|
2406
|
+
this.setup = (function() {
|
2407
|
+
var original = self.setup;
|
2408
|
+
return function() {
|
2409
|
+
original.apply(this, arguments);
|
2410
|
+
|
2411
|
+
var $control = this.$control.sortable({
|
2412
|
+
items: '[data-value]',
|
2413
|
+
forcePlaceholderSize: true,
|
2414
|
+
start: function(e, ui) {
|
2415
|
+
ui.placeholder.css('width', ui.helper.css('width'));
|
2416
|
+
$control.css({overflow: 'visible'});
|
2417
|
+
},
|
2418
|
+
stop: function() {
|
2419
|
+
$control.css({overflow: 'hidden'});
|
2420
|
+
var active = this.$activeItems ? this.$activeItems.slice() : null;
|
2421
|
+
var values = [];
|
2422
|
+
$control.children('[data-value]').each(function() {
|
2423
|
+
values.push($(this).attr('data-value'));
|
2424
|
+
});
|
2425
|
+
self.setValue(values);
|
2426
|
+
self.setActiveItem(active);
|
2427
|
+
}
|
2428
|
+
});
|
2429
|
+
};
|
2430
|
+
})();
|
2431
|
+
|
2432
|
+
});
|
2433
|
+
|
2434
|
+
/* --- file: "src/plugins/optgroup_columns/plugin.js" --- */
|
2435
|
+
|
2436
|
+
/**
|
2437
|
+
* Plugin: "optgroup_columns" (selectize.js)
|
2438
|
+
* Copyright (c) 2013 Simon Hewitt & contributors
|
2439
|
+
*
|
2440
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
|
2441
|
+
* file except in compliance with the License. You may obtain a copy of the License at:
|
2442
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
2443
|
+
*
|
2444
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
2445
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
2446
|
+
* ANY KIND, either express or implied. See the License for the specific language
|
2447
|
+
* governing permissions and limitations under the License.
|
2448
|
+
*
|
2449
|
+
* @author Simon Hewitt <si@sjhewitt.co.uk>
|
2450
|
+
*/
|
2451
|
+
|
2452
|
+
Selectize.registerPlugin('optgroup_columns', function(options) {
|
2453
|
+
var self = this;
|
2454
|
+
|
2455
|
+
options = $.extend({
|
2456
|
+
equalizeWidth : true,
|
2457
|
+
equalizeHeight : true
|
2458
|
+
}, options);
|
2459
|
+
|
2460
|
+
this.getAdjacentOption = function($option, direction) {
|
2461
|
+
var $options = $option.closest('[data-group]').find('[data-selectable]');
|
2462
|
+
var index = $options.index($option) + direction;
|
2463
|
+
|
2464
|
+
return index >= 0 && index < $options.length ? $options.eq(index) : $();
|
2465
|
+
};
|
2466
|
+
|
2467
|
+
this.onKeyDown = (function() {
|
2468
|
+
var original = self.onKeyDown;
|
2469
|
+
return function(e) {
|
2470
|
+
var index, $option, $options, $optgroup;
|
2471
|
+
|
2472
|
+
if (this.isOpen && (e.keyCode === KEY_LEFT || e.keyCode === KEY_RIGHT)) {
|
2473
|
+
self.ignoreHover = true;
|
2474
|
+
$optgroup = this.$activeOption.closest('[data-group]');
|
2475
|
+
index = $optgroup.find('[data-selectable]').index(this.$activeOption);
|
2476
|
+
|
2477
|
+
if(e.keyCode === KEY_LEFT) {
|
2478
|
+
$optgroup = $optgroup.prev('[data-group]');
|
2479
|
+
} else {
|
2480
|
+
$optgroup = $optgroup.next('[data-group]');
|
2481
|
+
}
|
2482
|
+
|
2483
|
+
$options = $optgroup.find('[data-selectable]');
|
2484
|
+
$option = $options.eq(Math.min($options.length - 1, index));
|
2485
|
+
if ($option.length) {
|
2486
|
+
this.setActiveOption($option);
|
2487
|
+
}
|
2488
|
+
return;
|
2489
|
+
}
|
2490
|
+
|
2491
|
+
return original.apply(this, arguments);
|
2492
|
+
};
|
2493
|
+
})();
|
2494
|
+
|
2495
|
+
var equalizeSizes = function() {
|
2496
|
+
var i, n, height_max, width, width_last, width_parent, $optgroups;
|
2497
|
+
|
2498
|
+
$optgroups = $('[data-group]', self.$dropdown_content);
|
2499
|
+
n = $optgroups.length;
|
2500
|
+
if (!n || !self.$dropdown_content.width()) return;
|
2501
|
+
|
2502
|
+
if (options.equalizeHeight) {
|
2503
|
+
height_max = 0;
|
2504
|
+
for (i = 0; i < n; i++) {
|
2505
|
+
height_max = Math.max(height_max, $optgroups.eq(i).height());
|
2506
|
+
}
|
2507
|
+
$optgroups.css({height: height_max});
|
2508
|
+
}
|
2509
|
+
|
2510
|
+
if (options.equalizeWidth) {
|
2511
|
+
width_parent = self.$dropdown_content.innerWidth();
|
2512
|
+
width = Math.round(width_parent / n);
|
2513
|
+
$optgroups.css({width: width});
|
2514
|
+
if (n > 1) {
|
2515
|
+
width_last = width_parent - width * (n - 1);
|
2516
|
+
$optgroups.eq(n - 1).css({width: width_last});
|
2517
|
+
}
|
2518
|
+
}
|
2519
|
+
};
|
2520
|
+
|
2521
|
+
if (options.equalizeHeight || options.equalizeWidth) {
|
2522
|
+
hook.after(this, 'positionDropdown', equalizeSizes);
|
2523
|
+
hook.after(this, 'refreshOptions', equalizeSizes);
|
2524
|
+
}
|
2525
|
+
|
2526
|
+
|
2527
|
+
});
|
2528
|
+
|
2529
|
+
/* --- file: "src/plugins/remove_button/plugin.js" --- */
|
2530
|
+
|
2531
|
+
/**
|
2532
|
+
* Plugin: "remove_button" (selectize.js)
|
2533
|
+
* Copyright (c) 2013 Brian Reavis & contributors
|
2534
|
+
*
|
2535
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
|
2536
|
+
* file except in compliance with the License. You may obtain a copy of the License at:
|
2537
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
2538
|
+
*
|
2539
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
2540
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
2541
|
+
* ANY KIND, either express or implied. See the License for the specific language
|
2542
|
+
* governing permissions and limitations under the License.
|
2543
|
+
*
|
2544
|
+
* @author Brian Reavis <brian@thirdroute.com>
|
2545
|
+
*/
|
2546
|
+
|
2547
|
+
Selectize.registerPlugin('remove_button', function(options) {
|
2548
|
+
var self = this;
|
2549
|
+
|
2550
|
+
// override the item rendering method to add a "x" to each
|
2551
|
+
this.settings.render.item = function(data) {
|
2552
|
+
var label = data[self.settings.labelField];
|
2553
|
+
return '<div class="item">' + label + ' <a href="javascript:void(0)" class="remove" tabindex="-1" title="Remove">×</a></div>';
|
2554
|
+
};
|
2555
|
+
|
2556
|
+
// override the setup method to add an extra "click" handler
|
2557
|
+
// that listens for mousedown events on the "x"
|
2558
|
+
this.setup = (function() {
|
2559
|
+
var original = self.setup;
|
2560
|
+
return function() {
|
2561
|
+
original.apply(this, arguments);
|
2562
|
+
this.$control.on('click', '.remove', function(e) {
|
2563
|
+
e.preventDefault();
|
2564
|
+
var $item = $(e.target).parent();
|
2565
|
+
self.setActiveItem($item);
|
2566
|
+
if (self.deleteSelection()) {
|
2567
|
+
self.setCaret(self.items.length);
|
2568
|
+
}
|
2569
|
+
});
|
2570
|
+
};
|
2571
|
+
})();
|
2572
|
+
|
2573
|
+
});
|
2574
|
+
|
2575
|
+
/* --- file: "src/plugins/restore_on_backspace/plugin.js" --- */
|
2576
|
+
|
2577
|
+
/**
|
2578
|
+
* Plugin: "restore_on_backspace" (selectize.js)
|
2579
|
+
* Copyright (c) 2013 Brian Reavis & contributors
|
2580
|
+
*
|
2581
|
+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
|
2582
|
+
* file except in compliance with the License. You may obtain a copy of the License at:
|
2583
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
2584
|
+
*
|
2585
|
+
* Unless required by applicable law or agreed to in writing, software distributed under
|
2586
|
+
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
|
2587
|
+
* ANY KIND, either express or implied. See the License for the specific language
|
2588
|
+
* governing permissions and limitations under the License.
|
2589
|
+
*
|
2590
|
+
* @author Brian Reavis <brian@thirdroute.com>
|
2591
|
+
*/
|
2592
|
+
|
2593
|
+
(function() {
|
2594
|
+
Selectize.registerPlugin('restore_on_backspace', function(options) {
|
2595
|
+
var self = this;
|
2596
|
+
|
2597
|
+
options.text = options.text || function(option) {
|
2598
|
+
return option[this.settings.labelField];
|
2599
|
+
};
|
2600
|
+
|
2601
|
+
this.onKeyDown = (function(e) {
|
2602
|
+
var original = self.onKeyDown;
|
2603
|
+
return function(e) {
|
2604
|
+
var index, option;
|
2605
|
+
if (e.keyCode === KEY_BACKSPACE && this.$control_input.val() === '' && !this.$activeItems.length) {
|
2606
|
+
index = this.caretPos - 1;
|
2607
|
+
if (index >= 0 && index < this.items.length) {
|
2608
|
+
option = this.options[this.items[index]];
|
2609
|
+
if (this.deleteSelection(e)) {
|
2610
|
+
this.setTextboxValue(options.text.apply(this, [option]));
|
2611
|
+
this.refreshOptions(true);
|
2612
|
+
}
|
2613
|
+
e.preventDefault();
|
2614
|
+
return;
|
2615
|
+
}
|
2616
|
+
}
|
2617
|
+
return original.apply(this, arguments);
|
2618
|
+
};
|
2619
|
+
})();
|
2620
|
+
|
2621
|
+
});
|
2622
|
+
})();
|
2623
|
+
|
1821
2624
|
return Selectize;
|
1822
2625
|
|
1823
2626
|
}));
|