flashgrid-ext 1.0.4 → 1.0.5
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 +0 -1
- data/lib/flashgrid/ext/version.rb +1 -1
- data/vendor/assets/javascripts/typeahead.js +364 -1120
- data/vendor/assets/stylesheets/typeahead.css.scss +2 -35
- metadata +3 -4
- data/vendor/assets/javascripts/typeahead_search.js +0 -645
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea32f79411d1e47fe5c984235a66aa81e0474f42
|
4
|
+
data.tar.gz: 413c2cca138cae97d872bf4a9e5ff59923df172d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b89fd83a0fe480e3fad323c35fa7c7200693e48703c94d89ea12bf8d13198aa15c93facf67d9ef6d6cea2e9fd546df309ba6cb3304a22d93f9efb1bcc49678f8
|
7
|
+
data.tar.gz: 1e223b9a7c0ec62bc16eaeecfe4d1bb7210d622506aed9ea8cbf2f93b8af126ed11cd49e915cf38acd10fb777026e175576fc7055983d836d41474a52decb96b
|
data/README.md
CHANGED
@@ -1,1124 +1,368 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
$.each(obj, function(key, val) {
|
39
|
-
if (!(result = test.call(null, val, key, obj))) {
|
40
|
-
return false;
|
41
|
-
}
|
42
|
-
});
|
43
|
-
return !!result;
|
44
|
-
},
|
45
|
-
some: function(obj, test) {
|
46
|
-
var result = false;
|
47
|
-
if (!obj) {
|
48
|
-
return result;
|
49
|
-
}
|
50
|
-
$.each(obj, function(key, val) {
|
51
|
-
if (result = test.call(null, val, key, obj)) {
|
52
|
-
return false;
|
53
|
-
}
|
54
|
-
});
|
55
|
-
return !!result;
|
56
|
-
},
|
57
|
-
mixin: $.extend,
|
58
|
-
getUniqueId: function() {
|
59
|
-
var counter = 0;
|
60
|
-
return function() {
|
61
|
-
return counter++;
|
62
|
-
};
|
63
|
-
}(),
|
64
|
-
templatify: function templatify(obj) {
|
65
|
-
return $.isFunction(obj) ? obj : template;
|
66
|
-
function template() {
|
67
|
-
return String(obj);
|
68
|
-
}
|
69
|
-
},
|
70
|
-
defer: function(fn) {
|
71
|
-
setTimeout(fn, 0);
|
72
|
-
},
|
73
|
-
debounce: function(func, wait, immediate) {
|
74
|
-
var timeout, result;
|
75
|
-
return function() {
|
76
|
-
var context = this, args = arguments, later, callNow;
|
77
|
-
later = function() {
|
78
|
-
timeout = null;
|
79
|
-
if (!immediate) {
|
80
|
-
result = func.apply(context, args);
|
81
|
-
}
|
82
|
-
};
|
83
|
-
callNow = immediate && !timeout;
|
84
|
-
clearTimeout(timeout);
|
85
|
-
timeout = setTimeout(later, wait);
|
86
|
-
if (callNow) {
|
87
|
-
result = func.apply(context, args);
|
88
|
-
}
|
89
|
-
return result;
|
90
|
-
};
|
91
|
-
},
|
92
|
-
throttle: function(func, wait) {
|
93
|
-
var context, args, timeout, result, previous, later;
|
94
|
-
previous = 0;
|
95
|
-
later = function() {
|
96
|
-
previous = new Date();
|
97
|
-
timeout = null;
|
98
|
-
result = func.apply(context, args);
|
99
|
-
};
|
100
|
-
return function() {
|
101
|
-
var now = new Date(), remaining = wait - (now - previous);
|
102
|
-
context = this;
|
103
|
-
args = arguments;
|
104
|
-
if (remaining <= 0) {
|
105
|
-
clearTimeout(timeout);
|
106
|
-
timeout = null;
|
107
|
-
previous = now;
|
108
|
-
result = func.apply(context, args);
|
109
|
-
} else if (!timeout) {
|
110
|
-
timeout = setTimeout(later, remaining);
|
111
|
-
}
|
112
|
-
return result;
|
113
|
-
};
|
114
|
-
},
|
115
|
-
noop: function() {}
|
116
|
-
};
|
117
|
-
var html = {
|
118
|
-
wrapper: '<span class="typeahead-wrapper"></span>',
|
119
|
-
dropdown: '<span class="typeahead-dropdown-menu"></span>',
|
120
|
-
dataset: '<div class="typeahead-dataset-%CLASS%"></div>',
|
121
|
-
suggestions: '<span class="typeahead-suggestions"></span>',
|
122
|
-
suggestion: '<div class="typeahead-suggestion">%BODY%</div>'
|
123
|
-
};
|
124
|
-
var css = {
|
125
|
-
wrapper: {
|
126
|
-
position: "relative",
|
127
|
-
display: "inline-block"
|
128
|
-
},
|
129
|
-
hint: {
|
130
|
-
position: "absolute",
|
131
|
-
top: "0",
|
132
|
-
left: "0",
|
133
|
-
borderColor: "transparent",
|
134
|
-
boxShadow: "none"
|
135
|
-
},
|
136
|
-
input: {
|
137
|
-
position: "relative",
|
138
|
-
verticalAlign: "top",
|
139
|
-
backgroundColor: "transparent"
|
140
|
-
},
|
141
|
-
inputWithNoHint: {
|
142
|
-
position: "relative",
|
143
|
-
verticalAlign: "top"
|
144
|
-
},
|
145
|
-
dropdown: {
|
146
|
-
position: "absolute",
|
147
|
-
top: "100%",
|
148
|
-
left: "0",
|
149
|
-
zIndex: "100",
|
150
|
-
display: "none"
|
151
|
-
},
|
152
|
-
suggestions: {
|
153
|
-
display: "block"
|
154
|
-
},
|
155
|
-
suggestion: {
|
156
|
-
whiteSpace: "nowrap",
|
157
|
-
cursor: "pointer"
|
158
|
-
},
|
159
|
-
suggestionChild: {
|
160
|
-
whiteSpace: "normal"
|
161
|
-
},
|
162
|
-
ltr: {
|
163
|
-
left: "0",
|
164
|
-
right: "auto"
|
165
|
-
},
|
166
|
-
rtl: {
|
167
|
-
left: "auto",
|
168
|
-
right: " 0"
|
169
|
-
}
|
170
|
-
};
|
171
|
-
if (_.isMsie()) {
|
172
|
-
_.mixin(css.input, {
|
173
|
-
backgroundImage: "url(data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7)"
|
174
|
-
});
|
1
|
+
!function($){
|
2
|
+
|
3
|
+
"use strict";
|
4
|
+
// jshint laxcomma: true
|
5
|
+
|
6
|
+
|
7
|
+
/* TYPEAHEAD PUBLIC CLASS DEFINITION
|
8
|
+
* ================================= */
|
9
|
+
|
10
|
+
var Typeahead = function (element, options) {
|
11
|
+
this.$element = $(element);
|
12
|
+
this.options = $.extend({}, $.fn.typeahead.defaults, options);
|
13
|
+
this.matcher = this.options.matcher || this.matcher;
|
14
|
+
this.sorter = this.options.sorter || this.sorter;
|
15
|
+
this.select = this.options.select || this.select;
|
16
|
+
this.autoSelect = typeof this.options.autoSelect == 'boolean' ? this.options.autoSelect : true;
|
17
|
+
this.highlighter = this.options.highlighter || this.highlighter;
|
18
|
+
this.updater = this.options.updater || this.updater;
|
19
|
+
this.source = this.options.source;
|
20
|
+
this.$menu = $(this.options.menu);
|
21
|
+
this.shown = false;
|
22
|
+
this.listen();
|
23
|
+
this.showHintOnFocus = typeof this.options.showHintOnFocus == 'boolean' ? this.options.showHintOnFocus : false;
|
24
|
+
};
|
25
|
+
|
26
|
+
Typeahead.prototype = {
|
27
|
+
|
28
|
+
constructor: Typeahead
|
29
|
+
|
30
|
+
, select: function () {
|
31
|
+
var val = this.$menu.find('.active').data('value');
|
32
|
+
if(this.autoSelect || val) {
|
33
|
+
this.$element
|
34
|
+
.val(this.updater(val))
|
35
|
+
.change();
|
36
|
+
}
|
37
|
+
return this.hide();
|
175
38
|
}
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
});
|
39
|
+
|
40
|
+
, updater: function (item) {
|
41
|
+
return item;
|
180
42
|
}
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
default:
|
424
|
-
trigger = true;
|
425
|
-
}
|
426
|
-
return trigger;
|
427
|
-
},
|
428
|
-
_checkInputValue: function checkInputValue() {
|
429
|
-
var inputValue, areEquivalent, hasDifferentWhitespace;
|
430
|
-
inputValue = this.getInputValue();
|
431
|
-
areEquivalent = areQueriesEquivalent(inputValue, this.query);
|
432
|
-
hasDifferentWhitespace = areEquivalent ? this.query.length !== inputValue.length : false;
|
433
|
-
if (!areEquivalent) {
|
434
|
-
this.trigger("queryChanged", this.query = inputValue);
|
435
|
-
} else if (hasDifferentWhitespace) {
|
436
|
-
this.trigger("whitespaceChanged", this.query);
|
437
|
-
}
|
438
|
-
},
|
439
|
-
focus: function focus() {
|
440
|
-
this.$input.focus();
|
441
|
-
},
|
442
|
-
blur: function blur() {
|
443
|
-
this.$input.blur();
|
444
|
-
},
|
445
|
-
getQuery: function getQuery() {
|
446
|
-
return this.query;
|
447
|
-
},
|
448
|
-
setQuery: function setQuery(query) {
|
449
|
-
this.query = query;
|
450
|
-
},
|
451
|
-
getInputValue: function getInputValue() {
|
452
|
-
return this.$input.val();
|
453
|
-
},
|
454
|
-
setInputValue: function setInputValue(value, silent) {
|
455
|
-
this.$input.val(value);
|
456
|
-
!silent && this._checkInputValue();
|
457
|
-
},
|
458
|
-
getHintValue: function getHintValue() {
|
459
|
-
return this.$hint.val();
|
460
|
-
},
|
461
|
-
setHintValue: function setHintValue(value) {
|
462
|
-
this.$hint.val(value);
|
463
|
-
},
|
464
|
-
resetInputValue: function resetInputValue() {
|
465
|
-
this.$input.val(this.query);
|
466
|
-
},
|
467
|
-
clearHint: function clearHint() {
|
468
|
-
this.$hint.val("");
|
469
|
-
},
|
470
|
-
getLanguageDirection: function getLanguageDirection() {
|
471
|
-
return (this.$input.css("direction") || "ltr").toLowerCase();
|
472
|
-
},
|
473
|
-
hasOverflow: function hasOverflow() {
|
474
|
-
var constraint = this.$input.width() - 2;
|
475
|
-
this.$overflowHelper.text(this.getInputValue());
|
476
|
-
return this.$overflowHelper.width() >= constraint;
|
477
|
-
},
|
478
|
-
isCursorAtEnd: function() {
|
479
|
-
var valueLength, selectionStart, range;
|
480
|
-
valueLength = this.$input.val().length;
|
481
|
-
selectionStart = this.$input[0].selectionStart;
|
482
|
-
if (_.isNumber(selectionStart)) {
|
483
|
-
return selectionStart === valueLength;
|
484
|
-
} else if (document.selection) {
|
485
|
-
range = document.selection.createRange();
|
486
|
-
range.moveStart("character", -valueLength);
|
487
|
-
return valueLength === range.text.length;
|
488
|
-
}
|
489
|
-
return true;
|
490
|
-
},
|
491
|
-
destroy: function destroy() {
|
492
|
-
this.$hint.off(".tt");
|
493
|
-
this.$input.off(".tt");
|
494
|
-
this.$hint = this.$input = this.$overflowHelper = null;
|
495
|
-
}
|
496
|
-
});
|
497
|
-
return Input;
|
498
|
-
function buildOverflowHelper($input) {
|
499
|
-
return $('<pre aria-hidden="true"></pre>').css({
|
500
|
-
position: "absolute",
|
501
|
-
visibility: "hidden",
|
502
|
-
whiteSpace: "nowrap",
|
503
|
-
fontFamily: $input.css("font-family"),
|
504
|
-
fontSize: $input.css("font-size"),
|
505
|
-
fontStyle: $input.css("font-style"),
|
506
|
-
fontVariant: $input.css("font-variant"),
|
507
|
-
fontWeight: $input.css("font-weight"),
|
508
|
-
wordSpacing: $input.css("word-spacing"),
|
509
|
-
letterSpacing: $input.css("letter-spacing"),
|
510
|
-
textIndent: $input.css("text-indent"),
|
511
|
-
textRendering: $input.css("text-rendering"),
|
512
|
-
textTransform: $input.css("text-transform")
|
513
|
-
}).insertAfter($input);
|
514
|
-
}
|
515
|
-
function areQueriesEquivalent(a, b) {
|
516
|
-
return Input.normalizeQuery(a) === Input.normalizeQuery(b);
|
517
|
-
}
|
518
|
-
function withModifier($e) {
|
519
|
-
return $e.altKey || $e.ctrlKey || $e.metaKey || $e.shiftKey;
|
520
|
-
}
|
521
|
-
}();
|
522
|
-
var Dataset = function() {
|
523
|
-
var datasetKey = "ttDataset", valueKey = "ttValue", datumKey = "ttDatum";
|
524
|
-
function Dataset(o) {
|
525
|
-
o = o || {};
|
526
|
-
o.templates = o.templates || {};
|
527
|
-
if (!o.source) {
|
528
|
-
$.error("missing source");
|
529
|
-
}
|
530
|
-
if (o.name && !isValidName(o.name)) {
|
531
|
-
$.error("invalid dataset name: " + o.name);
|
532
|
-
}
|
533
|
-
this.query = null;
|
534
|
-
this.highlight = !!o.highlight;
|
535
|
-
this.name = o.name || _.getUniqueId();
|
536
|
-
this.source = o.source;
|
537
|
-
this.displayFn = getDisplayFn(o.display || o.displayKey);
|
538
|
-
this.templates = getTemplates(o.templates, this.displayFn);
|
539
|
-
this.$el = $(html.dataset.replace("%CLASS%", this.name));
|
540
|
-
}
|
541
|
-
Dataset.extractDatasetName = function extractDatasetName(el) {
|
542
|
-
return $(el).data(datasetKey);
|
543
|
-
};
|
544
|
-
Dataset.extractValue = function extractDatum(el) {
|
545
|
-
return $(el).data(valueKey);
|
546
|
-
};
|
547
|
-
Dataset.extractDatum = function extractDatum(el) {
|
548
|
-
return $(el).data(datumKey);
|
549
|
-
};
|
550
|
-
_.mixin(Dataset.prototype, EventEmitter, {
|
551
|
-
_render: function render(query, suggestions) {
|
552
|
-
if (!this.$el) {
|
553
|
-
return;
|
554
|
-
}
|
555
|
-
var that = this, hasSuggestions;
|
556
|
-
this.$el.empty();
|
557
|
-
hasSuggestions = suggestions && suggestions.length;
|
558
|
-
if (!hasSuggestions && this.templates.empty) {
|
559
|
-
this.$el.html(getEmptyHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);
|
560
|
-
} else if (hasSuggestions) {
|
561
|
-
this.$el.html(getSuggestionsHtml()).prepend(that.templates.header ? getHeaderHtml() : null).append(that.templates.footer ? getFooterHtml() : null);
|
562
|
-
}
|
563
|
-
this.trigger("rendered");
|
564
|
-
function getEmptyHtml() {
|
565
|
-
return that.templates.empty({
|
566
|
-
query: query,
|
567
|
-
isEmpty: true
|
568
|
-
});
|
569
|
-
}
|
570
|
-
function getSuggestionsHtml() {
|
571
|
-
var $suggestions, nodes;
|
572
|
-
$suggestions = $(html.suggestions).css(css.suggestions);
|
573
|
-
nodes = _.map(suggestions, getSuggestionNode);
|
574
|
-
$suggestions.append.apply($suggestions, nodes);
|
575
|
-
that.highlight && highlight({
|
576
|
-
node: $suggestions[0],
|
577
|
-
pattern: query
|
578
|
-
});
|
579
|
-
return $suggestions;
|
580
|
-
function getSuggestionNode(suggestion) {
|
581
|
-
var $el, innerHtml, outerHtml;
|
582
|
-
innerHtml = that.templates.suggestion(suggestion);
|
583
|
-
outerHtml = html.suggestion.replace("%BODY%", innerHtml);
|
584
|
-
$el = $(outerHtml).data(datasetKey, that.name).data(valueKey, that.displayFn(suggestion)).data(datumKey, suggestion);
|
585
|
-
$el.children().each(function() {
|
586
|
-
$(this).css(css.suggestionChild);
|
587
|
-
});
|
588
|
-
return $el;
|
589
|
-
}
|
590
|
-
}
|
591
|
-
function getHeaderHtml() {
|
592
|
-
return that.templates.header({
|
593
|
-
query: query,
|
594
|
-
isEmpty: !hasSuggestions
|
595
|
-
});
|
596
|
-
}
|
597
|
-
function getFooterHtml() {
|
598
|
-
return that.templates.footer({
|
599
|
-
query: query,
|
600
|
-
isEmpty: !hasSuggestions
|
601
|
-
});
|
602
|
-
}
|
603
|
-
},
|
604
|
-
getRoot: function getRoot() {
|
605
|
-
return this.$el;
|
606
|
-
},
|
607
|
-
update: function update(query) {
|
608
|
-
var that = this;
|
609
|
-
this.query = query;
|
610
|
-
this.source(query, renderIfQueryIsSame);
|
611
|
-
function renderIfQueryIsSame(suggestions) {
|
612
|
-
query === that.query && that._render(query, suggestions);
|
613
|
-
}
|
614
|
-
},
|
615
|
-
clear: function clear() {
|
616
|
-
this._render(this.query || "");
|
617
|
-
},
|
618
|
-
isEmpty: function isEmpty() {
|
619
|
-
return this.$el.is(":empty");
|
620
|
-
},
|
621
|
-
destroy: function destroy() {
|
622
|
-
this.$el = null;
|
623
|
-
}
|
624
|
-
});
|
625
|
-
return Dataset;
|
626
|
-
function getDisplayFn(display) {
|
627
|
-
display = display || "value";
|
628
|
-
return _.isFunction(display) ? display : displayFn;
|
629
|
-
function displayFn(obj) {
|
630
|
-
return obj[display];
|
631
|
-
}
|
632
|
-
}
|
633
|
-
function getTemplates(templates, displayFn) {
|
634
|
-
return {
|
635
|
-
empty: templates.empty && _.templatify(templates.empty),
|
636
|
-
header: templates.header && _.templatify(templates.header),
|
637
|
-
footer: templates.footer && _.templatify(templates.footer),
|
638
|
-
suggestion: templates.suggestion || suggestionTemplate
|
639
|
-
};
|
640
|
-
function suggestionTemplate(context) {
|
641
|
-
return "<p>" + displayFn(context) + "</p>";
|
642
|
-
}
|
643
|
-
}
|
644
|
-
function isValidName(str) {
|
645
|
-
return /^[_a-zA-Z0-9-]+$/.test(str);
|
646
|
-
}
|
647
|
-
}();
|
648
|
-
var Dropdown = function() {
|
649
|
-
function Dropdown(o) {
|
650
|
-
var that = this, onSuggestionClick, onSuggestionMouseEnter, onSuggestionMouseLeave;
|
651
|
-
o = o || {};
|
652
|
-
if (!o.menu) {
|
653
|
-
$.error("menu is required");
|
654
|
-
}
|
655
|
-
this.isOpen = false;
|
656
|
-
this.isEmpty = true;
|
657
|
-
this.datasets = _.map(o.datasets, initializeDataset);
|
658
|
-
onSuggestionClick = _.bind(this._onSuggestionClick, this);
|
659
|
-
onSuggestionMouseEnter = _.bind(this._onSuggestionMouseEnter, this);
|
660
|
-
onSuggestionMouseLeave = _.bind(this._onSuggestionMouseLeave, this);
|
661
|
-
this.$menu = $(o.menu).on("click.tt", ".typeahead-suggestion", onSuggestionClick).on("mouseenter.tt", ".typeahead-suggestion", onSuggestionMouseEnter).on("mouseleave.tt", ".typeahead-suggestion", onSuggestionMouseLeave);
|
662
|
-
_.each(this.datasets, function(dataset) {
|
663
|
-
that.$menu.append(dataset.getRoot());
|
664
|
-
dataset.onSync("rendered", that._onRendered, that);
|
665
|
-
});
|
666
|
-
}
|
667
|
-
_.mixin(Dropdown.prototype, EventEmitter, {
|
668
|
-
_onSuggestionClick: function onSuggestionClick($e) {
|
669
|
-
this.trigger("suggestionClicked", $($e.currentTarget));
|
670
|
-
},
|
671
|
-
_onSuggestionMouseEnter: function onSuggestionMouseEnter($e) {
|
672
|
-
this._removeCursor();
|
673
|
-
this._setCursor($($e.currentTarget), true);
|
674
|
-
},
|
675
|
-
_onSuggestionMouseLeave: function onSuggestionMouseLeave($e) {
|
676
|
-
this._removeCursor();
|
677
|
-
},
|
678
|
-
_onRendered: function onRendered() {
|
679
|
-
this.isEmpty = _.every(this.datasets, isDatasetEmpty);
|
680
|
-
this.isEmpty ? this._hide() : this.isOpen && this._show();
|
681
|
-
this.trigger("datasetRendered");
|
682
|
-
function isDatasetEmpty(dataset) {
|
683
|
-
return dataset.isEmpty();
|
684
|
-
}
|
685
|
-
},
|
686
|
-
_hide: function() {
|
687
|
-
this.$menu.hide();
|
688
|
-
},
|
689
|
-
_show: function() {
|
690
|
-
this.$menu.css("display", "block");
|
691
|
-
},
|
692
|
-
_getSuggestions: function getSuggestions() {
|
693
|
-
return this.$menu.find(".typeahead-suggestion");
|
694
|
-
},
|
695
|
-
_getCursor: function getCursor() {
|
696
|
-
return this.$menu.find(".typeahead-cursor").first();
|
697
|
-
},
|
698
|
-
_setCursor: function setCursor($el, silent) {
|
699
|
-
$el.first().addClass("typeahead-cursor");
|
700
|
-
!silent && this.trigger("cursorMoved");
|
701
|
-
},
|
702
|
-
_removeCursor: function removeCursor() {
|
703
|
-
this._getCursor().removeClass("typeahead-cursor");
|
704
|
-
},
|
705
|
-
_moveCursor: function moveCursor(increment) {
|
706
|
-
var $suggestions, $oldCursor, newCursorIndex, $newCursor;
|
707
|
-
if (!this.isOpen) {
|
708
|
-
return;
|
709
|
-
}
|
710
|
-
$oldCursor = this._getCursor();
|
711
|
-
$suggestions = this._getSuggestions();
|
712
|
-
this._removeCursor();
|
713
|
-
newCursorIndex = $suggestions.index($oldCursor) + increment;
|
714
|
-
newCursorIndex = (newCursorIndex + 1) % ($suggestions.length + 1) - 1;
|
715
|
-
if (newCursorIndex === -1) {
|
716
|
-
this.trigger("cursorRemoved");
|
717
|
-
return;
|
718
|
-
} else if (newCursorIndex < -1) {
|
719
|
-
newCursorIndex = $suggestions.length - 1;
|
720
|
-
}
|
721
|
-
this._setCursor($newCursor = $suggestions.eq(newCursorIndex));
|
722
|
-
this._ensureVisible($newCursor);
|
723
|
-
},
|
724
|
-
_ensureVisible: function ensureVisible($el) {
|
725
|
-
var elTop, elBottom, menuScrollTop, menuHeight;
|
726
|
-
elTop = $el.position().top;
|
727
|
-
elBottom = elTop + $el.outerHeight(true);
|
728
|
-
menuScrollTop = this.$menu.scrollTop();
|
729
|
-
menuHeight = this.$menu.height() + parseInt(this.$menu.css("paddingTop"), 10) + parseInt(this.$menu.css("paddingBottom"), 10);
|
730
|
-
if (elTop < 0) {
|
731
|
-
this.$menu.scrollTop(menuScrollTop + elTop);
|
732
|
-
} else if (menuHeight < elBottom) {
|
733
|
-
this.$menu.scrollTop(menuScrollTop + (elBottom - menuHeight));
|
734
|
-
}
|
735
|
-
},
|
736
|
-
close: function close() {
|
737
|
-
if (this.isOpen) {
|
738
|
-
this.isOpen = false;
|
739
|
-
this._removeCursor();
|
740
|
-
this._hide();
|
741
|
-
this.trigger("closed");
|
742
|
-
}
|
743
|
-
},
|
744
|
-
open: function open() {
|
745
|
-
if (!this.isOpen) {
|
746
|
-
this.isOpen = true;
|
747
|
-
!this.isEmpty && this._show();
|
748
|
-
this.trigger("opened");
|
749
|
-
}
|
750
|
-
},
|
751
|
-
setLanguageDirection: function setLanguageDirection(dir) {
|
752
|
-
this.$menu.css(dir === "ltr" ? css.ltr : css.rtl);
|
753
|
-
},
|
754
|
-
moveCursorUp: function moveCursorUp() {
|
755
|
-
this._moveCursor(-1);
|
756
|
-
},
|
757
|
-
moveCursorDown: function moveCursorDown() {
|
758
|
-
this._moveCursor(+1);
|
759
|
-
},
|
760
|
-
getDatumForSuggestion: function getDatumForSuggestion($el) {
|
761
|
-
var datum = null;
|
762
|
-
if ($el.length) {
|
763
|
-
datum = {
|
764
|
-
raw: Dataset.extractDatum($el),
|
765
|
-
value: Dataset.extractValue($el),
|
766
|
-
datasetName: Dataset.extractDatasetName($el)
|
767
|
-
};
|
768
|
-
}
|
769
|
-
return datum;
|
770
|
-
},
|
771
|
-
getDatumForCursor: function getDatumForCursor() {
|
772
|
-
return this.getDatumForSuggestion(this._getCursor().first());
|
773
|
-
},
|
774
|
-
getDatumForTopSuggestion: function getDatumForTopSuggestion() {
|
775
|
-
return this.getDatumForSuggestion(this._getSuggestions().first());
|
776
|
-
},
|
777
|
-
update: function update(query) {
|
778
|
-
_.each(this.datasets, updateDataset);
|
779
|
-
function updateDataset(dataset) {
|
780
|
-
dataset.update(query);
|
781
|
-
}
|
782
|
-
},
|
783
|
-
empty: function empty() {
|
784
|
-
_.each(this.datasets, clearDataset);
|
785
|
-
this.isEmpty = true;
|
786
|
-
function clearDataset(dataset) {
|
787
|
-
dataset.clear();
|
788
|
-
}
|
789
|
-
},
|
790
|
-
isVisible: function isVisible() {
|
791
|
-
return this.isOpen && !this.isEmpty;
|
792
|
-
},
|
793
|
-
destroy: function destroy() {
|
794
|
-
this.$menu.off(".tt");
|
795
|
-
this.$menu = null;
|
796
|
-
_.each(this.datasets, destroyDataset);
|
797
|
-
function destroyDataset(dataset) {
|
798
|
-
dataset.destroy();
|
799
|
-
}
|
800
|
-
}
|
801
|
-
});
|
802
|
-
return Dropdown;
|
803
|
-
function initializeDataset(oDataset) {
|
804
|
-
return new Dataset(oDataset);
|
805
|
-
}
|
806
|
-
}();
|
807
|
-
var Typeahead = function() {
|
808
|
-
var attrsKey = "ttAttrs";
|
809
|
-
function Typeahead(o) {
|
810
|
-
var $menu, $input, $hint, datasets;
|
811
|
-
o = o || {};
|
812
|
-
if (!o.input) {
|
813
|
-
$.error("missing input");
|
814
|
-
}
|
815
|
-
this.autoselect = !!o.autoselect;
|
816
|
-
this.minLength = _.isNumber(o.minLength) ? o.minLength : 1;
|
817
|
-
this.$node = buildDomStructure(o.input, o.withHint);
|
818
|
-
$menu = this.$node.find(".typeahead-dropdown-menu");
|
819
|
-
$input = this.$node.find(".typeahead-input");
|
820
|
-
$hint = this.$node.find(".typeahead-hint");
|
821
|
-
this.eventBus = o.eventBus || new EventBus({
|
822
|
-
el: $input
|
823
|
-
});
|
824
|
-
this.dropdown = new Dropdown({
|
825
|
-
menu: $menu,
|
826
|
-
datasets: o.datasets
|
827
|
-
}).onSync("suggestionClicked", this._onSuggestionClicked, this).onSync("cursorMoved", this._onCursorMoved, this).onSync("cursorRemoved", this._onCursorRemoved, this).onSync("opened", this._onOpened, this).onSync("closed", this._onClosed, this).onAsync("datasetRendered", this._onDatasetRendered, this);
|
828
|
-
this.input = new Input({
|
829
|
-
input: $input,
|
830
|
-
hint: $hint
|
831
|
-
}).onSync("focused", this._onFocused, this).onSync("blurred", this._onBlurred, this).onSync("enterKeyed", this._onEnterKeyed, this).onSync("tabKeyed", this._onTabKeyed, this).onSync("escKeyed", this._onEscKeyed, this).onSync("upKeyed", this._onUpKeyed, this).onSync("downKeyed", this._onDownKeyed, this).onSync("leftKeyed", this._onLeftKeyed, this).onSync("rightKeyed", this._onRightKeyed, this).onSync("queryChanged", this._onQueryChanged, this).onSync("whitespaceChanged", this._onWhitespaceChanged, this);
|
832
|
-
$menu.on("mousedown.tt", function($e) {
|
833
|
-
if (_.isMsie() && _.isMsie() < 9) {
|
834
|
-
$input[0].onbeforedeactivate = function() {
|
835
|
-
window.event.returnValue = false;
|
836
|
-
$input[0].onbeforedeactivate = null;
|
837
|
-
};
|
838
|
-
}
|
839
|
-
$e.preventDefault();
|
840
|
-
});
|
841
|
-
}
|
842
|
-
_.mixin(Typeahead.prototype, {
|
843
|
-
_onSuggestionClicked: function onSuggestionClicked(type, $el) {
|
844
|
-
var datum;
|
845
|
-
if (datum = this.dropdown.getDatumForSuggestion($el)) {
|
846
|
-
this._select(datum);
|
847
|
-
}
|
848
|
-
},
|
849
|
-
_onCursorMoved: function onCursorMoved() {
|
850
|
-
var datum = this.dropdown.getDatumForCursor();
|
851
|
-
this.input.clearHint();
|
852
|
-
this.input.setInputValue(datum.value, true);
|
853
|
-
this.eventBus.trigger("cursorchanged", datum.raw, datum.datasetName);
|
854
|
-
},
|
855
|
-
_onCursorRemoved: function onCursorRemoved() {
|
856
|
-
this.input.resetInputValue();
|
857
|
-
this._updateHint();
|
858
|
-
},
|
859
|
-
_onDatasetRendered: function onDatasetRendered() {
|
860
|
-
this._updateHint();
|
861
|
-
},
|
862
|
-
_onOpened: function onOpened() {
|
863
|
-
this._updateHint();
|
864
|
-
this.eventBus.trigger("opened");
|
865
|
-
},
|
866
|
-
_onClosed: function onClosed() {
|
867
|
-
this.input.clearHint();
|
868
|
-
this.eventBus.trigger("closed");
|
869
|
-
},
|
870
|
-
_onFocused: function onFocused() {
|
871
|
-
this.dropdown.empty();
|
872
|
-
this.dropdown.open();
|
873
|
-
},
|
874
|
-
_onBlurred: function onBlurred() {
|
875
|
-
this.dropdown.close();
|
876
|
-
},
|
877
|
-
_onEnterKeyed: function onEnterKeyed(type, $e) {
|
878
|
-
var cursorDatum, topSuggestionDatum;
|
879
|
-
cursorDatum = this.dropdown.getDatumForCursor();
|
880
|
-
topSuggestionDatum = this.dropdown.getDatumForTopSuggestion();
|
881
|
-
if (cursorDatum) {
|
882
|
-
this._select(cursorDatum);
|
883
|
-
$e.preventDefault();
|
884
|
-
} else if (this.autoselect && topSuggestionDatum) {
|
885
|
-
this._select(topSuggestionDatum);
|
886
|
-
$e.preventDefault();
|
887
|
-
}
|
888
|
-
},
|
889
|
-
_onTabKeyed: function onTabKeyed(type, $e) {
|
890
|
-
var datum;
|
891
|
-
if (datum = this.dropdown.getDatumForCursor()) {
|
892
|
-
this._select(datum);
|
893
|
-
$e.preventDefault();
|
894
|
-
} else {
|
895
|
-
this._autocomplete();
|
896
|
-
}
|
897
|
-
},
|
898
|
-
_onEscKeyed: function onEscKeyed() {
|
899
|
-
this.dropdown.close();
|
900
|
-
this.input.resetInputValue();
|
901
|
-
},
|
902
|
-
_onUpKeyed: function onUpKeyed() {
|
903
|
-
var query = this.input.getQuery();
|
904
|
-
if (!this.dropdown.isOpen && query.length >= this.minLength) {
|
905
|
-
this.dropdown.update(query);
|
906
|
-
}
|
907
|
-
this.dropdown.open();
|
908
|
-
this.dropdown.moveCursorUp();
|
909
|
-
},
|
910
|
-
_onDownKeyed: function onDownKeyed() {
|
911
|
-
var query = this.input.getQuery();
|
912
|
-
if (!this.dropdown.isOpen && query.length >= this.minLength) {
|
913
|
-
this.dropdown.update(query);
|
914
|
-
}
|
915
|
-
this.dropdown.open();
|
916
|
-
this.dropdown.moveCursorDown();
|
917
|
-
},
|
918
|
-
_onLeftKeyed: function onLeftKeyed() {
|
919
|
-
this.dir === "rtl" && this._autocomplete();
|
920
|
-
},
|
921
|
-
_onRightKeyed: function onRightKeyed() {
|
922
|
-
this.dir === "ltr" && this._autocomplete();
|
923
|
-
},
|
924
|
-
_onQueryChanged: function onQueryChanged(e, query) {
|
925
|
-
this.input.clearHint();
|
926
|
-
this.dropdown.empty();
|
927
|
-
query.length >= this.minLength && this.dropdown.update(query);
|
928
|
-
this.dropdown.open();
|
929
|
-
this._setLanguageDirection();
|
930
|
-
},
|
931
|
-
_onWhitespaceChanged: function onWhitespaceChanged() {
|
932
|
-
this._updateHint();
|
933
|
-
this.dropdown.open();
|
934
|
-
},
|
935
|
-
_setLanguageDirection: function setLanguageDirection() {
|
936
|
-
var dir;
|
937
|
-
if (this.dir !== (dir = this.input.getLanguageDirection())) {
|
938
|
-
this.dir = dir;
|
939
|
-
this.$node.css("direction", dir);
|
940
|
-
this.dropdown.setLanguageDirection(dir);
|
941
|
-
}
|
942
|
-
},
|
943
|
-
_updateHint: function updateHint() {
|
944
|
-
var datum, inputValue, query, escapedQuery, frontMatchRegEx, match;
|
945
|
-
datum = this.dropdown.getDatumForTopSuggestion();
|
946
|
-
if (datum && this.dropdown.isVisible() && !this.input.hasOverflow()) {
|
947
|
-
inputValue = this.input.getInputValue();
|
948
|
-
query = Input.normalizeQuery(inputValue);
|
949
|
-
escapedQuery = _.escapeRegExChars(query);
|
950
|
-
frontMatchRegEx = new RegExp("^(?:" + escapedQuery + ")(.*$)", "i");
|
951
|
-
match = frontMatchRegEx.exec(datum.value);
|
952
|
-
this.input.setHintValue(inputValue + (match ? match[1] : ""));
|
953
|
-
}
|
954
|
-
},
|
955
|
-
_autocomplete: function autocomplete() {
|
956
|
-
var hint, query, datum;
|
957
|
-
hint = this.input.getHintValue();
|
958
|
-
query = this.input.getQuery();
|
959
|
-
if (hint && query !== hint && this.input.isCursorAtEnd()) {
|
960
|
-
datum = this.dropdown.getDatumForTopSuggestion();
|
961
|
-
datum && this.input.setInputValue(datum.value);
|
962
|
-
this.eventBus.trigger("autocompleted", datum.raw, datum.datasetName);
|
963
|
-
}
|
964
|
-
},
|
965
|
-
_select: function select(datum) {
|
966
|
-
this.input.clearHint();
|
967
|
-
this.input.setQuery(datum.value);
|
968
|
-
this.input.setInputValue(datum.value, true);
|
969
|
-
this._setLanguageDirection();
|
970
|
-
this.eventBus.trigger("selected", datum.raw, datum.datasetName);
|
971
|
-
this.dropdown.close();
|
972
|
-
_.defer(_.bind(this.dropdown.empty, this.dropdown));
|
973
|
-
},
|
974
|
-
open: function open() {
|
975
|
-
this.dropdown.open();
|
976
|
-
},
|
977
|
-
close: function close() {
|
978
|
-
this.dropdown.close();
|
979
|
-
},
|
980
|
-
getQuery: function getQuery() {
|
981
|
-
return this.input.getQuery();
|
982
|
-
},
|
983
|
-
setQuery: function setQuery(val) {
|
984
|
-
this.input.setInputValue(val);
|
985
|
-
},
|
986
|
-
destroy: function destroy() {
|
987
|
-
this.input.destroy();
|
988
|
-
this.dropdown.destroy();
|
989
|
-
destroyDomStructure(this.$node);
|
990
|
-
this.$node = null;
|
991
|
-
}
|
992
|
-
});
|
993
|
-
return Typeahead;
|
994
|
-
function buildDomStructure(input, withHint) {
|
995
|
-
var $input, $wrapper, $dropdown, $hint;
|
996
|
-
$input = $(input);
|
997
|
-
$wrapper = $(html.wrapper).css(css.wrapper);
|
998
|
-
$dropdown = $(html.dropdown).css(css.dropdown);
|
999
|
-
$hint = $input.clone().css(css.hint).css(getBackgroundStyles($input));
|
1000
|
-
$hint.val("").removeData().addClass("typeahead-hint").removeAttr("id name placeholder").prop("disabled", true).attr({
|
1001
|
-
autocomplete: "off",
|
1002
|
-
spellcheck: "false"
|
1003
|
-
});
|
1004
|
-
$input.data(attrsKey, {
|
1005
|
-
dir: $input.attr("dir"),
|
1006
|
-
autocomplete: $input.attr("autocomplete"),
|
1007
|
-
spellcheck: $input.attr("spellcheck"),
|
1008
|
-
style: $input.attr("style")
|
1009
|
-
});
|
1010
|
-
$input.addClass("typeahead-input").attr({
|
1011
|
-
autocomplete: "off",
|
1012
|
-
spellcheck: false
|
1013
|
-
}).css(withHint ? css.input : css.inputWithNoHint);
|
1014
|
-
try {
|
1015
|
-
!$input.attr("dir") && $input.attr("dir", "auto");
|
1016
|
-
} catch (e) {}
|
1017
|
-
return $input.wrap($wrapper).parent().prepend(withHint ? $hint : null).append($dropdown);
|
1018
|
-
}
|
1019
|
-
function getBackgroundStyles($el) {
|
1020
|
-
return {
|
1021
|
-
backgroundAttachment: $el.css("background-attachment"),
|
1022
|
-
backgroundClip: $el.css("background-clip"),
|
1023
|
-
backgroundColor: $el.css("background-color"),
|
1024
|
-
backgroundImage: $el.css("background-image"),
|
1025
|
-
backgroundOrigin: $el.css("background-origin"),
|
1026
|
-
backgroundPosition: $el.css("background-position"),
|
1027
|
-
backgroundRepeat: $el.css("background-repeat"),
|
1028
|
-
backgroundSize: $el.css("background-size")
|
1029
|
-
};
|
43
|
+
|
44
|
+
, setSource: function (source) {
|
45
|
+
this.source = source;
|
46
|
+
}
|
47
|
+
|
48
|
+
, show: function () {
|
49
|
+
var pos = $.extend({}, this.$element.position(), {
|
50
|
+
height: this.$element[0].offsetHeight
|
51
|
+
}), scrollHeight;
|
52
|
+
|
53
|
+
scrollHeight = typeof this.options.scrollHeight == 'function' ?
|
54
|
+
this.options.scrollHeight.call() :
|
55
|
+
this.options.scrollHeight;
|
56
|
+
|
57
|
+
this.$menu
|
58
|
+
.insertAfter(this.$element)
|
59
|
+
.css({
|
60
|
+
top: pos.top + pos.height + scrollHeight
|
61
|
+
, left: pos.left
|
62
|
+
})
|
63
|
+
.show();
|
64
|
+
|
65
|
+
this.shown = true;
|
66
|
+
return this;
|
67
|
+
}
|
68
|
+
|
69
|
+
, hide: function () {
|
70
|
+
this.$menu.hide();
|
71
|
+
this.shown = false;
|
72
|
+
return this;
|
73
|
+
}
|
74
|
+
|
75
|
+
, lookup: function (query) {
|
76
|
+
var items;
|
77
|
+
if (typeof(query) != 'undefined' && query !== null) {
|
78
|
+
this.query = query;
|
79
|
+
} else {
|
80
|
+
this.query = this.$element.val() || '';
|
81
|
+
}
|
82
|
+
|
83
|
+
if (this.query.length < this.options.minLength) {
|
84
|
+
return this.shown ? this.hide() : this;
|
85
|
+
}
|
86
|
+
|
87
|
+
items = $.isFunction(this.source) ? this.source(this.query, $.proxy(this.process, this)) : this.source;
|
88
|
+
|
89
|
+
return items ? this.process(items) : this;
|
90
|
+
}
|
91
|
+
|
92
|
+
, process: function (items) {
|
93
|
+
var that = this;
|
94
|
+
|
95
|
+
items = $.grep(items, function (item) {
|
96
|
+
return that.matcher(item);
|
97
|
+
});
|
98
|
+
|
99
|
+
items = this.sorter(items);
|
100
|
+
|
101
|
+
if (!items.length) {
|
102
|
+
return this.shown ? this.hide() : this;
|
103
|
+
}
|
104
|
+
|
105
|
+
if (this.options.items == 'all' || this.options.minLength === 0 && !this.$element.val()) {
|
106
|
+
return this.render(items).show();
|
107
|
+
} else {
|
108
|
+
return this.render(items.slice(0, this.options.items)).show();
|
109
|
+
}
|
110
|
+
}
|
111
|
+
|
112
|
+
, matcher: function (item) {
|
113
|
+
return ~item.toLowerCase().indexOf(this.query.toLowerCase());
|
114
|
+
}
|
115
|
+
|
116
|
+
, sorter: function (items) {
|
117
|
+
var beginswith = []
|
118
|
+
, caseSensitive = []
|
119
|
+
, caseInsensitive = []
|
120
|
+
, item;
|
121
|
+
|
122
|
+
while ((item = items.shift())) {
|
123
|
+
if (!item.toLowerCase().indexOf(this.query.toLowerCase())) beginswith.push(item);
|
124
|
+
else if (~item.indexOf(this.query)) caseSensitive.push(item);
|
125
|
+
else caseInsensitive.push(item);
|
126
|
+
}
|
127
|
+
|
128
|
+
return beginswith.concat(caseSensitive, caseInsensitive);
|
129
|
+
}
|
130
|
+
|
131
|
+
, highlighter: function (item) {
|
132
|
+
var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
|
133
|
+
return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
|
134
|
+
return '<b>' + match + '</b>';
|
135
|
+
});
|
136
|
+
}
|
137
|
+
|
138
|
+
, render: function (items) {
|
139
|
+
var that = this;
|
140
|
+
|
141
|
+
items = $(items).map(function (i, item) {
|
142
|
+
i = $(that.options.item).data('value', item);
|
143
|
+
i.find('a').html(that.highlighter(item));
|
144
|
+
return i[0];
|
145
|
+
});
|
146
|
+
|
147
|
+
if (this.autoSelect) {
|
148
|
+
items.first().addClass('active');
|
149
|
+
}
|
150
|
+
this.$menu.html(items);
|
151
|
+
return this;
|
152
|
+
}
|
153
|
+
|
154
|
+
, next: function (event) {
|
155
|
+
var active = this.$menu.find('.active').removeClass('active')
|
156
|
+
, next = active.next();
|
157
|
+
|
158
|
+
if (!next.length) {
|
159
|
+
next = $(this.$menu.find('li')[0]);
|
160
|
+
}
|
161
|
+
|
162
|
+
next.addClass('active');
|
163
|
+
}
|
164
|
+
|
165
|
+
, prev: function (event) {
|
166
|
+
var active = this.$menu.find('.active').removeClass('active')
|
167
|
+
, prev = active.prev();
|
168
|
+
|
169
|
+
if (!prev.length) {
|
170
|
+
prev = this.$menu.find('li').last();
|
171
|
+
}
|
172
|
+
|
173
|
+
prev.addClass('active');
|
174
|
+
}
|
175
|
+
|
176
|
+
, listen: function () {
|
177
|
+
this.$element
|
178
|
+
.on('focus', $.proxy(this.focus, this))
|
179
|
+
.on('blur', $.proxy(this.blur, this))
|
180
|
+
.on('keypress', $.proxy(this.keypress, this))
|
181
|
+
.on('keyup', $.proxy(this.keyup, this));
|
182
|
+
|
183
|
+
if (this.eventSupported('keydown')) {
|
184
|
+
this.$element.on('keydown', $.proxy(this.keydown, this));
|
185
|
+
}
|
186
|
+
|
187
|
+
this.$menu
|
188
|
+
.on('click', $.proxy(this.click, this))
|
189
|
+
.on('mouseenter', 'li', $.proxy(this.mouseenter, this))
|
190
|
+
.on('mouseleave', 'li', $.proxy(this.mouseleave, this));
|
191
|
+
}
|
192
|
+
, destroy : function () {
|
193
|
+
this.$element.data('typeahead',null);
|
194
|
+
this.$element
|
195
|
+
.off('focus')
|
196
|
+
.off('blur')
|
197
|
+
.off('keypress')
|
198
|
+
.off('keyup');
|
199
|
+
|
200
|
+
if (this.eventSupported('keydown')) {
|
201
|
+
this.$element.off('keydown');
|
202
|
+
}
|
203
|
+
|
204
|
+
this.$menu.remove();
|
205
|
+
}
|
206
|
+
, eventSupported: function(eventName) {
|
207
|
+
var isSupported = eventName in this.$element;
|
208
|
+
if (!isSupported) {
|
209
|
+
this.$element.setAttribute(eventName, 'return;');
|
210
|
+
isSupported = typeof this.$element[eventName] === 'function';
|
211
|
+
}
|
212
|
+
return isSupported;
|
213
|
+
}
|
214
|
+
|
215
|
+
, move: function (e) {
|
216
|
+
if (!this.shown) return;
|
217
|
+
|
218
|
+
switch(e.keyCode) {
|
219
|
+
case 9: // tab
|
220
|
+
case 13: // enter
|
221
|
+
case 27: // escape
|
222
|
+
e.preventDefault();
|
223
|
+
break;
|
224
|
+
|
225
|
+
case 38: // up arrow
|
226
|
+
e.preventDefault();
|
227
|
+
this.prev();
|
228
|
+
break;
|
229
|
+
|
230
|
+
case 40: // down arrow
|
231
|
+
e.preventDefault();
|
232
|
+
this.next();
|
233
|
+
break;
|
234
|
+
}
|
235
|
+
|
236
|
+
e.stopPropagation();
|
237
|
+
}
|
238
|
+
|
239
|
+
, keydown: function (e) {
|
240
|
+
this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27]);
|
241
|
+
if (!this.shown && e.keyCode == 40) {
|
242
|
+
this.lookup("");
|
243
|
+
} else {
|
244
|
+
this.move(e);
|
245
|
+
}
|
246
|
+
}
|
247
|
+
|
248
|
+
, keypress: function (e) {
|
249
|
+
if (this.suppressKeyPressRepeat) return;
|
250
|
+
this.move(e);
|
251
|
+
}
|
252
|
+
|
253
|
+
, keyup: function (e) {
|
254
|
+
switch(e.keyCode) {
|
255
|
+
case 40: // down arrow
|
256
|
+
case 38: // up arrow
|
257
|
+
case 16: // shift
|
258
|
+
case 17: // ctrl
|
259
|
+
case 18: // alt
|
260
|
+
break;
|
261
|
+
|
262
|
+
case 9: // tab
|
263
|
+
case 13: // enter
|
264
|
+
if (!this.shown) return;
|
265
|
+
this.select();
|
266
|
+
break;
|
267
|
+
|
268
|
+
case 27: // escape
|
269
|
+
if (!this.shown) return;
|
270
|
+
this.hide();
|
271
|
+
break;
|
272
|
+
default:
|
273
|
+
this.lookup();
|
274
|
+
}
|
275
|
+
|
276
|
+
e.stopPropagation();
|
277
|
+
e.preventDefault();
|
278
|
+
}
|
279
|
+
|
280
|
+
, focus: function (e) {
|
281
|
+
if (!this.focused) {
|
282
|
+
this.focused = true;
|
283
|
+
if (this.options.minLength === 0 && !this.$element.val() || this.options.showHintOnFocus) {
|
284
|
+
this.lookup();
|
1030
285
|
}
|
1031
|
-
|
1032
|
-
|
1033
|
-
|
1034
|
-
|
1035
|
-
|
1036
|
-
|
1037
|
-
|
286
|
+
}
|
287
|
+
}
|
288
|
+
|
289
|
+
, blur: function (e) {
|
290
|
+
this.focused = false;
|
291
|
+
if (!this.mousedover && this.shown) this.hide();
|
292
|
+
}
|
293
|
+
|
294
|
+
, click: function (e) {
|
295
|
+
e.stopPropagation();
|
296
|
+
e.preventDefault();
|
297
|
+
this.select();
|
298
|
+
this.$element.focus();
|
299
|
+
}
|
300
|
+
|
301
|
+
, mouseenter: function (e) {
|
302
|
+
this.mousedover = true;
|
303
|
+
this.$menu.find('.active').removeClass('active');
|
304
|
+
$(e.currentTarget).addClass('active');
|
305
|
+
}
|
306
|
+
|
307
|
+
, mouseleave: function (e) {
|
308
|
+
this.mousedover = false;
|
309
|
+
if (!this.focused && this.shown) this.hide();
|
310
|
+
}
|
311
|
+
|
312
|
+
};
|
313
|
+
|
314
|
+
|
315
|
+
/* TYPEAHEAD PLUGIN DEFINITION
|
316
|
+
* =========================== */
|
317
|
+
|
318
|
+
var old = $.fn.typeahead;
|
319
|
+
|
320
|
+
$.fn.typeahead = function (option) {
|
321
|
+
var arg = arguments;
|
322
|
+
return this.each(function () {
|
323
|
+
var $this = $(this)
|
324
|
+
, data = $this.data('typeahead')
|
325
|
+
, options = typeof option == 'object' && option;
|
326
|
+
if (!data) $this.data('typeahead', (data = new Typeahead(this, options)));
|
327
|
+
if (typeof option == 'string') {
|
328
|
+
if (arg.length > 1) {
|
329
|
+
data[option].apply(data, Array.prototype.slice.call(arg ,1));
|
330
|
+
} else {
|
331
|
+
data[option]();
|
1038
332
|
}
|
1039
|
-
|
1040
|
-
|
1041
|
-
|
1042
|
-
|
1043
|
-
|
1044
|
-
|
1045
|
-
|
1046
|
-
|
1047
|
-
|
1048
|
-
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1056
|
-
|
1057
|
-
|
1058
|
-
|
1059
|
-
|
1060
|
-
|
1061
|
-
|
1062
|
-
|
1063
|
-
|
1064
|
-
|
1065
|
-
|
1066
|
-
|
1067
|
-
|
1068
|
-
|
1069
|
-
|
1070
|
-
|
1071
|
-
|
1072
|
-
|
1073
|
-
|
1074
|
-
|
1075
|
-
},
|
1076
|
-
close: function close() {
|
1077
|
-
return this.each(closeTypeahead);
|
1078
|
-
function closeTypeahead() {
|
1079
|
-
var $input = $(this), typeahead;
|
1080
|
-
if (typeahead = $input.data(typeaheadKey)) {
|
1081
|
-
typeahead.close();
|
1082
|
-
}
|
1083
|
-
}
|
1084
|
-
},
|
1085
|
-
val: function val(newVal) {
|
1086
|
-
return !arguments.length ? getQuery(this.first()) : this.each(setQuery);
|
1087
|
-
function setQuery() {
|
1088
|
-
var $input = $(this), typeahead;
|
1089
|
-
if (typeahead = $input.data(typeaheadKey)) {
|
1090
|
-
typeahead.setQuery(newVal);
|
1091
|
-
}
|
1092
|
-
}
|
1093
|
-
function getQuery($input) {
|
1094
|
-
var typeahead, query;
|
1095
|
-
if (typeahead = $input.data(typeaheadKey)) {
|
1096
|
-
query = typeahead.getQuery();
|
1097
|
-
}
|
1098
|
-
return query;
|
1099
|
-
}
|
1100
|
-
},
|
1101
|
-
destroy: function destroy() {
|
1102
|
-
return this.each(unattach);
|
1103
|
-
function unattach() {
|
1104
|
-
var $input = $(this), typeahead;
|
1105
|
-
if (typeahead = $input.data(typeaheadKey)) {
|
1106
|
-
typeahead.destroy();
|
1107
|
-
$input.removeData(typeaheadKey);
|
1108
|
-
}
|
1109
|
-
}
|
1110
|
-
}
|
1111
|
-
};
|
1112
|
-
$.fn.typeahead = function(method) {
|
1113
|
-
if (methods[method]) {
|
1114
|
-
return methods[method].apply(this, [].slice.call(arguments, 1));
|
1115
|
-
} else {
|
1116
|
-
return methods.initialize.apply(this, arguments);
|
1117
|
-
}
|
1118
|
-
};
|
1119
|
-
$.fn.typeahead.noConflict = function noConflict() {
|
1120
|
-
$.fn.typeahead = old;
|
1121
|
-
return this;
|
1122
|
-
};
|
1123
|
-
})();
|
1124
|
-
})(window.jQuery);
|
333
|
+
}
|
334
|
+
});
|
335
|
+
};
|
336
|
+
|
337
|
+
$.fn.typeahead.defaults = {
|
338
|
+
source: []
|
339
|
+
, items: 8
|
340
|
+
, menu: '<ul class="typeahead dropdown-menu"></ul>'
|
341
|
+
, item: '<li><a href="#"></a></li>'
|
342
|
+
, minLength: 1
|
343
|
+
, scrollHeight: 0
|
344
|
+
, autoSelect: true
|
345
|
+
};
|
346
|
+
|
347
|
+
$.fn.typeahead.Constructor = Typeahead;
|
348
|
+
|
349
|
+
|
350
|
+
/* TYPEAHEAD NO CONFLICT
|
351
|
+
* =================== */
|
352
|
+
|
353
|
+
$.fn.typeahead.noConflict = function () {
|
354
|
+
$.fn.typeahead = old;
|
355
|
+
return this;
|
356
|
+
};
|
357
|
+
|
358
|
+
|
359
|
+
/* TYPEAHEAD DATA-API
|
360
|
+
* ================== */
|
361
|
+
|
362
|
+
$(document).on('focus.typeahead.data-api', '[data-provide="typeahead"]', function (e) {
|
363
|
+
var $this = $(this);
|
364
|
+
if ($this.data('typeahead')) return;
|
365
|
+
$this.typeahead($this.data());
|
366
|
+
});
|
367
|
+
|
368
|
+
}(window.jQuery);
|