textext-rails 0.1.0
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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +31 -0
- data/Rakefile +21 -0
- data/latest.tar.gz +0 -0
- data/lib/textext-rails.rb +2 -0
- data/lib/textext/rails.rb +6 -0
- data/lib/textext/rails/engine.rb +6 -0
- data/lib/textext/rails/version.rb +5 -0
- data/textext-rails.gemspec +24 -0
- data/vendor/assets/javascripts/textext.core.js +1613 -0
- data/vendor/assets/javascripts/textext.plugin.ajax.js +354 -0
- data/vendor/assets/javascripts/textext.plugin.arrow.js +106 -0
- data/vendor/assets/javascripts/textext.plugin.autocomplete.js +1057 -0
- data/vendor/assets/javascripts/textext.plugin.filter.js +242 -0
- data/vendor/assets/javascripts/textext.plugin.focus.js +174 -0
- data/vendor/assets/javascripts/textext.plugin.prompt.js +292 -0
- data/vendor/assets/javascripts/textext.plugin.suggestions.js +175 -0
- data/vendor/assets/javascripts/textext.plugin.tags.js +638 -0
- data/vendor/assets/stylesheets/arrow.png +0 -0
- data/vendor/assets/stylesheets/close.png +0 -0
- data/vendor/assets/stylesheets/textext.core.css +29 -0
- data/vendor/assets/stylesheets/textext.plugin.arrow.css +13 -0
- data/vendor/assets/stylesheets/textext.plugin.autocomplete.css +35 -0
- data/vendor/assets/stylesheets/textext.plugin.focus.css +12 -0
- data/vendor/assets/stylesheets/textext.plugin.prompt.css +16 -0
- data/vendor/assets/stylesheets/textext.plugin.tags.css +49 -0
- metadata +73 -0
@@ -0,0 +1,1057 @@
|
|
1
|
+
/**
|
2
|
+
* jQuery TextExt Plugin
|
3
|
+
* http://alexgorbatchev.com/textext
|
4
|
+
*
|
5
|
+
* @version 1.2.0
|
6
|
+
* @copyright Copyright (C) 2011 Alex Gorbatchev. All rights reserved.
|
7
|
+
* @license MIT License
|
8
|
+
*/
|
9
|
+
(function($)
|
10
|
+
{
|
11
|
+
/**
|
12
|
+
* Autocomplete plugin brings the classic autocomplete functionality to the TextExt echosystem.
|
13
|
+
* The gist of functionality is when user starts typing in, for example a term or a tag, a
|
14
|
+
* dropdown would be presented with possible suggestions to complete the input quicker.
|
15
|
+
*
|
16
|
+
* @author agorbatchev
|
17
|
+
* @date 2011/08/17
|
18
|
+
* @id TextExtAutocomplete
|
19
|
+
*/
|
20
|
+
function TextExtAutocomplete() {};
|
21
|
+
|
22
|
+
$.fn.textext.TextExtAutocomplete = TextExtAutocomplete;
|
23
|
+
$.fn.textext.addPlugin('autocomplete', TextExtAutocomplete);
|
24
|
+
|
25
|
+
var p = TextExtAutocomplete.prototype,
|
26
|
+
|
27
|
+
CSS_DOT = '.',
|
28
|
+
CSS_SELECTED = 'text-selected',
|
29
|
+
CSS_DOT_SELECTED = CSS_DOT + CSS_SELECTED,
|
30
|
+
CSS_SUGGESTION = 'text-suggestion',
|
31
|
+
CSS_DOT_SUGGESTION = CSS_DOT + CSS_SUGGESTION,
|
32
|
+
|
33
|
+
/**
|
34
|
+
* Autocomplete plugin options are grouped under `autocomplete` when passed to the
|
35
|
+
* `$().textext()` function. For example:
|
36
|
+
*
|
37
|
+
* $('textarea').textext({
|
38
|
+
* plugins: 'autocomplete',
|
39
|
+
* autocomplete: {
|
40
|
+
* dropdownPosition: 'above'
|
41
|
+
* }
|
42
|
+
* })
|
43
|
+
*
|
44
|
+
* @author agorbatchev
|
45
|
+
* @date 2011/08/17
|
46
|
+
* @id TextExtAutocomplete.options
|
47
|
+
*/
|
48
|
+
|
49
|
+
/**
|
50
|
+
* This is a toggle switch to enable or disable the Autucomplete plugin. The value is checked
|
51
|
+
* each time at the top level which allows you to toggle this setting on the fly.
|
52
|
+
*
|
53
|
+
* @name autocomplete.enabled
|
54
|
+
* @default true
|
55
|
+
* @author agorbatchev
|
56
|
+
* @date 2011/08/17
|
57
|
+
* @id TextExtAutocomplete.options.autocomplete.enabled
|
58
|
+
*/
|
59
|
+
OPT_ENABLED = 'autocomplete.enabled',
|
60
|
+
|
61
|
+
/**
|
62
|
+
* This option allows to specify position of the dropdown. The two possible values
|
63
|
+
* are `above` and `below`.
|
64
|
+
*
|
65
|
+
* @name autocomplete.dropdown.position
|
66
|
+
* @default "below"
|
67
|
+
* @author agorbatchev
|
68
|
+
* @date 2011/08/17
|
69
|
+
* @id TextExtAutocomplete.options.autocomplete.dropdown.position
|
70
|
+
*/
|
71
|
+
OPT_POSITION = 'autocomplete.dropdown.position',
|
72
|
+
|
73
|
+
/**
|
74
|
+
* This option allows to specify maximum height of the dropdown. Value is taken directly, so
|
75
|
+
* if desired height is 200 pixels, value must be `200px`.
|
76
|
+
*
|
77
|
+
* @name autocomplete.dropdown.maxHeight
|
78
|
+
* @default "100px"
|
79
|
+
* @author agorbatchev
|
80
|
+
* @date 2011/12/29
|
81
|
+
* @id TextExtAutocomplete.options.autocomplete.dropdown.maxHeight
|
82
|
+
* @version 1.1
|
83
|
+
*/
|
84
|
+
OPT_MAX_HEIGHT = 'autocomplete.dropdown.maxHeight',
|
85
|
+
|
86
|
+
/**
|
87
|
+
* This option allows to override how a suggestion item is rendered. The value should be
|
88
|
+
* a function, the first argument of which is suggestion to be rendered and `this` context
|
89
|
+
* is the current instance of `TextExtAutocomplete`.
|
90
|
+
*
|
91
|
+
* [Click here](/manual/examples/autocomplete-with-custom-render.html) to see a demo.
|
92
|
+
*
|
93
|
+
* For example:
|
94
|
+
*
|
95
|
+
* $('textarea').textext({
|
96
|
+
* plugins: 'autocomplete',
|
97
|
+
* autocomplete: {
|
98
|
+
* render: function(suggestion)
|
99
|
+
* {
|
100
|
+
* return '<b>' + suggestion + '</b>';
|
101
|
+
* }
|
102
|
+
* }
|
103
|
+
* })
|
104
|
+
*
|
105
|
+
* @name autocomplete.render
|
106
|
+
* @default null
|
107
|
+
* @author agorbatchev
|
108
|
+
* @date 2011/12/23
|
109
|
+
* @id TextExtAutocomplete.options.autocomplete.render
|
110
|
+
* @version 1.1
|
111
|
+
*/
|
112
|
+
OPT_RENDER = 'autocomplete.render',
|
113
|
+
|
114
|
+
/**
|
115
|
+
* HTML source that is used to generate the dropdown.
|
116
|
+
*
|
117
|
+
* @name html.dropdown
|
118
|
+
* @default '<div class="text-dropdown"><div class="text-list"/></div>'
|
119
|
+
* @author agorbatchev
|
120
|
+
* @date 2011/08/17
|
121
|
+
* @id TextExtAutocomplete.options.html.dropdown
|
122
|
+
*/
|
123
|
+
OPT_HTML_DROPDOWN = 'html.dropdown',
|
124
|
+
|
125
|
+
/**
|
126
|
+
* HTML source that is used to generate each suggestion.
|
127
|
+
*
|
128
|
+
* @name html.suggestion
|
129
|
+
* @default '<div class="text-suggestion"><span class="text-label"/></div>'
|
130
|
+
* @author agorbatchev
|
131
|
+
* @date 2011/08/17
|
132
|
+
* @id TextExtAutocomplete.options.html.suggestion
|
133
|
+
*/
|
134
|
+
OPT_HTML_SUGGESTION = 'html.suggestion',
|
135
|
+
|
136
|
+
/**
|
137
|
+
* Autocomplete plugin triggers or reacts to the following events.
|
138
|
+
*
|
139
|
+
* @author agorbatchev
|
140
|
+
* @date 2011/08/17
|
141
|
+
* @id TextExtAutocomplete.events
|
142
|
+
*/
|
143
|
+
|
144
|
+
/**
|
145
|
+
* Autocomplete plugin triggers and reacts to the `hideDropdown` to hide the dropdown if it's
|
146
|
+
* already visible.
|
147
|
+
*
|
148
|
+
* @name hideDropdown
|
149
|
+
* @author agorbatchev
|
150
|
+
* @date 2011/08/17
|
151
|
+
* @id TextExtAutocomplete.events.hideDropdown
|
152
|
+
*/
|
153
|
+
EVENT_HIDE_DROPDOWN = 'hideDropdown',
|
154
|
+
|
155
|
+
/**
|
156
|
+
* Autocomplete plugin triggers and reacts to the `showDropdown` to show the dropdown if it's
|
157
|
+
* not already visible.
|
158
|
+
*
|
159
|
+
* It's possible to pass a render callback function which will be called instead of the
|
160
|
+
* default `TextExtAutocomplete.renderSuggestions()`.
|
161
|
+
*
|
162
|
+
* Here's how another plugin should trigger this event with the optional render callback:
|
163
|
+
*
|
164
|
+
* this.trigger('showDropdown', function(autocomplete)
|
165
|
+
* {
|
166
|
+
* autocomplete.clearItems();
|
167
|
+
* var node = autocomplete.addDropdownItem('<b>Item</b>');
|
168
|
+
* node.addClass('new-look');
|
169
|
+
* });
|
170
|
+
*
|
171
|
+
* @name showDropdown
|
172
|
+
* @author agorbatchev
|
173
|
+
* @date 2011/08/17
|
174
|
+
* @id TextExtAutocomplete.events.showDropdown
|
175
|
+
*/
|
176
|
+
EVENT_SHOW_DROPDOWN = 'showDropdown',
|
177
|
+
|
178
|
+
/**
|
179
|
+
* Autocomplete plugin reacts to the `setSuggestions` event triggered by other plugins which
|
180
|
+
* wish to populate the suggestion items. Suggestions should be passed as event argument in the
|
181
|
+
* following format: `{ data : [ ... ] }`.
|
182
|
+
*
|
183
|
+
* Here's how another plugin should trigger this event:
|
184
|
+
*
|
185
|
+
* this.trigger('setSuggestions', { data : [ "item1", "item2" ] });
|
186
|
+
*
|
187
|
+
* @name setSuggestions
|
188
|
+
* @author agorbatchev
|
189
|
+
* @date 2011/08/17
|
190
|
+
* @id TextExtAutocomplete.events.setSuggestions
|
191
|
+
*/
|
192
|
+
|
193
|
+
/**
|
194
|
+
* Autocomplete plugin triggers the `getSuggestions` event and expects to get results by listening for
|
195
|
+
* the `setSuggestions` event.
|
196
|
+
*
|
197
|
+
* @name getSuggestions
|
198
|
+
* @author agorbatchev
|
199
|
+
* @date 2011/08/17
|
200
|
+
* @id TextExtAutocomplete.events.getSuggestions
|
201
|
+
*/
|
202
|
+
EVENT_GET_SUGGESTIONS = 'getSuggestions',
|
203
|
+
|
204
|
+
/**
|
205
|
+
* Autocomplete plugin triggers `getFormData` event with the current suggestion so that the the core
|
206
|
+
* will be updated with serialized data to be submitted with the HTML form.
|
207
|
+
*
|
208
|
+
* @name getFormData
|
209
|
+
* @author agorbatchev
|
210
|
+
* @date 2011/08/18
|
211
|
+
* @id TextExtAutocomplete.events.getFormData
|
212
|
+
*/
|
213
|
+
EVENT_GET_FORM_DATA = 'getFormData',
|
214
|
+
|
215
|
+
/**
|
216
|
+
* Autocomplete plugin reacts to `toggleDropdown` event and either shows or hides the dropdown
|
217
|
+
* depending if it's currently hidden or visible.
|
218
|
+
*
|
219
|
+
* @name toggleDropdown
|
220
|
+
* @author agorbatchev
|
221
|
+
* @date 2011/12/27
|
222
|
+
* @id TextExtAutocomplete.events.toggleDropdown
|
223
|
+
* @version 1.1
|
224
|
+
*/
|
225
|
+
EVENT_TOGGLE_DROPDOWN = 'toggleDropdown',
|
226
|
+
|
227
|
+
POSITION_ABOVE = 'above',
|
228
|
+
POSITION_BELOW = 'below',
|
229
|
+
|
230
|
+
DEFAULT_OPTS = {
|
231
|
+
autocomplete : {
|
232
|
+
enabled : true,
|
233
|
+
dropdown : {
|
234
|
+
position : POSITION_BELOW,
|
235
|
+
maxHeight : '100px'
|
236
|
+
}
|
237
|
+
},
|
238
|
+
|
239
|
+
html : {
|
240
|
+
dropdown : '<div class="text-dropdown"><div class="text-list"/></div>',
|
241
|
+
suggestion : '<div class="text-suggestion"><span class="text-label"/></div>'
|
242
|
+
}
|
243
|
+
}
|
244
|
+
;
|
245
|
+
|
246
|
+
/**
|
247
|
+
* Initialization method called by the core during plugin instantiation.
|
248
|
+
*
|
249
|
+
* @signature TextExtAutocomplete.init(core)
|
250
|
+
*
|
251
|
+
* @param core {TextExt} Instance of the TextExt core class.
|
252
|
+
*
|
253
|
+
* @author agorbatchev
|
254
|
+
* @date 2011/08/17
|
255
|
+
* @id TextExtAutocomplete.init
|
256
|
+
*/
|
257
|
+
p.init = function(core)
|
258
|
+
{
|
259
|
+
var self = this;
|
260
|
+
|
261
|
+
self.baseInit(core, DEFAULT_OPTS);
|
262
|
+
|
263
|
+
var input = self.input(),
|
264
|
+
container
|
265
|
+
;
|
266
|
+
|
267
|
+
if(self.opts(OPT_ENABLED) === true)
|
268
|
+
{
|
269
|
+
self.on({
|
270
|
+
blur : self.onBlur,
|
271
|
+
anyKeyUp : self.onAnyKeyUp,
|
272
|
+
deleteKeyUp : self.onAnyKeyUp,
|
273
|
+
backspaceKeyPress : self.onBackspaceKeyPress,
|
274
|
+
enterKeyPress : self.onEnterKeyPress,
|
275
|
+
escapeKeyPress : self.onEscapeKeyPress,
|
276
|
+
setSuggestions : self.onSetSuggestions,
|
277
|
+
showDropdown : self.onShowDropdown,
|
278
|
+
hideDropdown : self.onHideDropdown,
|
279
|
+
toggleDropdown : self.onToggleDropdown,
|
280
|
+
postInvalidate : self.positionDropdown,
|
281
|
+
getFormData : self.onGetFormData,
|
282
|
+
|
283
|
+
// using keyDown for up/down keys so that repeat events are
|
284
|
+
// captured and user can scroll up/down by holding the keys
|
285
|
+
downKeyDown : self.onDownKeyDown,
|
286
|
+
upKeyDown : self.onUpKeyDown
|
287
|
+
});
|
288
|
+
|
289
|
+
container = $(self.opts(OPT_HTML_DROPDOWN));
|
290
|
+
container.insertAfter(input);
|
291
|
+
|
292
|
+
self.on(container, {
|
293
|
+
mouseover : self.onMouseOver,
|
294
|
+
click : self.onClick
|
295
|
+
});
|
296
|
+
|
297
|
+
container
|
298
|
+
.css('maxHeight', self.opts(OPT_MAX_HEIGHT))
|
299
|
+
.addClass('text-position-' + self.opts(OPT_POSITION))
|
300
|
+
;
|
301
|
+
|
302
|
+
$(self).data('container', container);
|
303
|
+
|
304
|
+
self.positionDropdown();
|
305
|
+
}
|
306
|
+
};
|
307
|
+
|
308
|
+
/**
|
309
|
+
* Returns top level dropdown container HTML element.
|
310
|
+
*
|
311
|
+
* @signature TextExtAutocomplete.containerElement()
|
312
|
+
*
|
313
|
+
* @author agorbatchev
|
314
|
+
* @date 2011/08/15
|
315
|
+
* @id TextExtAutocomplete.containerElement
|
316
|
+
*/
|
317
|
+
p.containerElement = function()
|
318
|
+
{
|
319
|
+
return $(this).data('container');
|
320
|
+
};
|
321
|
+
|
322
|
+
//--------------------------------------------------------------------------------
|
323
|
+
// User mouse/keyboard input
|
324
|
+
|
325
|
+
/**
|
326
|
+
* Reacts to the `mouseOver` event triggered by the TextExt core.
|
327
|
+
*
|
328
|
+
* @signature TextExtAutocomplete.onMouseOver(e)
|
329
|
+
*
|
330
|
+
* @param e {Object} jQuery event.
|
331
|
+
*
|
332
|
+
* @author agorbatchev
|
333
|
+
* @date 2011/08/17
|
334
|
+
* @id TextExtAutocomplete.onMouseOver
|
335
|
+
*/
|
336
|
+
p.onMouseOver = function(e)
|
337
|
+
{
|
338
|
+
var self = this,
|
339
|
+
target = $(e.target)
|
340
|
+
;
|
341
|
+
|
342
|
+
if(target.is(CSS_DOT_SUGGESTION))
|
343
|
+
{
|
344
|
+
self.clearSelected();
|
345
|
+
target.addClass(CSS_SELECTED);
|
346
|
+
}
|
347
|
+
};
|
348
|
+
|
349
|
+
/**
|
350
|
+
* Reacts to the `click` event triggered by the TextExt core.
|
351
|
+
*
|
352
|
+
* @signature TextExtAutocomplete.onClick(e)
|
353
|
+
*
|
354
|
+
* @param e {Object} jQuery event.
|
355
|
+
*
|
356
|
+
* @author agorbatchev
|
357
|
+
* @date 2011/08/17
|
358
|
+
* @id TextExtAutocomplete.onClick
|
359
|
+
*/
|
360
|
+
p.onClick = function(e)
|
361
|
+
{
|
362
|
+
var self = this,
|
363
|
+
target = $(e.target)
|
364
|
+
;
|
365
|
+
|
366
|
+
if(target.is(CSS_DOT_SUGGESTION))
|
367
|
+
self.selectFromDropdown();
|
368
|
+
};
|
369
|
+
|
370
|
+
/**
|
371
|
+
* Reacts to the `blur` event triggered by the TextExt core.
|
372
|
+
*
|
373
|
+
* @signature TextExtAutocomplete.onBlur(e)
|
374
|
+
*
|
375
|
+
* @param e {Object} jQuery event.
|
376
|
+
*
|
377
|
+
* @author agorbatchev
|
378
|
+
* @date 2011/08/17
|
379
|
+
* @id TextExtAutocomplete.onBlur
|
380
|
+
*/
|
381
|
+
p.onBlur = function(e)
|
382
|
+
{
|
383
|
+
var self = this;
|
384
|
+
|
385
|
+
// use timeout here so that onClick has a chance to fire because if
|
386
|
+
// dropdown is hidden when clicked, onClick doesn't fire
|
387
|
+
if(self.isDropdownVisible())
|
388
|
+
setTimeout(function() { self.trigger(EVENT_HIDE_DROPDOWN) }, 100);
|
389
|
+
};
|
390
|
+
|
391
|
+
/**
|
392
|
+
* Reacts to the `backspaceKeyPress` event triggered by the TextExt core.
|
393
|
+
*
|
394
|
+
* @signature TextExtAutocomplete.onBackspaceKeyPress(e)
|
395
|
+
*
|
396
|
+
* @param e {Object} jQuery event.
|
397
|
+
*
|
398
|
+
* @author agorbatchev
|
399
|
+
* @date 2011/08/17
|
400
|
+
* @id TextExtAutocomplete.onBackspaceKeyPress
|
401
|
+
*/
|
402
|
+
p.onBackspaceKeyPress = function(e)
|
403
|
+
{
|
404
|
+
var self = this,
|
405
|
+
isEmpty = self.val().length > 0
|
406
|
+
;
|
407
|
+
|
408
|
+
if(isEmpty || self.isDropdownVisible())
|
409
|
+
self.getSuggestions();
|
410
|
+
};
|
411
|
+
|
412
|
+
/**
|
413
|
+
* Reacts to the `anyKeyUp` event triggered by the TextExt core.
|
414
|
+
*
|
415
|
+
* @signature TextExtAutocomplete.onAnyKeyUp(e)
|
416
|
+
*
|
417
|
+
* @param e {Object} jQuery event.
|
418
|
+
*
|
419
|
+
* @author agorbatchev
|
420
|
+
* @date 2011/08/17
|
421
|
+
* @id TextExtAutocomplete.onAnyKeyUp
|
422
|
+
*/
|
423
|
+
p.onAnyKeyUp = function(e, keyCode)
|
424
|
+
{
|
425
|
+
var self = this,
|
426
|
+
isFunctionKey = self.opts('keys.' + keyCode) != null
|
427
|
+
;
|
428
|
+
|
429
|
+
if(self.val().length > 0 && !isFunctionKey)
|
430
|
+
self.getSuggestions();
|
431
|
+
};
|
432
|
+
|
433
|
+
/**
|
434
|
+
* Reacts to the `downKeyDown` event triggered by the TextExt core.
|
435
|
+
*
|
436
|
+
* @signature TextExtAutocomplete.onDownKeyDown(e)
|
437
|
+
*
|
438
|
+
* @param e {Object} jQuery event.
|
439
|
+
*
|
440
|
+
* @author agorbatchev
|
441
|
+
* @date 2011/08/17
|
442
|
+
* @id TextExtAutocomplete.onDownKeyDown
|
443
|
+
*/
|
444
|
+
p.onDownKeyDown = function(e)
|
445
|
+
{
|
446
|
+
var self = this;
|
447
|
+
|
448
|
+
self.isDropdownVisible()
|
449
|
+
? self.toggleNextSuggestion()
|
450
|
+
: self.getSuggestions()
|
451
|
+
;
|
452
|
+
};
|
453
|
+
|
454
|
+
/**
|
455
|
+
* Reacts to the `upKeyDown` event triggered by the TextExt core.
|
456
|
+
*
|
457
|
+
* @signature TextExtAutocomplete.onUpKeyDown(e)
|
458
|
+
*
|
459
|
+
* @param e {Object} jQuery event.
|
460
|
+
*
|
461
|
+
* @author agorbatchev
|
462
|
+
* @date 2011/08/17
|
463
|
+
* @id TextExtAutocomplete.onUpKeyDown
|
464
|
+
*/
|
465
|
+
p.onUpKeyDown = function(e)
|
466
|
+
{
|
467
|
+
this.togglePreviousSuggestion();
|
468
|
+
};
|
469
|
+
|
470
|
+
/**
|
471
|
+
* Reacts to the `enterKeyPress` event triggered by the TextExt core.
|
472
|
+
*
|
473
|
+
* @signature TextExtAutocomplete.onEnterKeyPress(e)
|
474
|
+
*
|
475
|
+
* @param e {Object} jQuery event.
|
476
|
+
*
|
477
|
+
* @author agorbatchev
|
478
|
+
* @date 2011/08/17
|
479
|
+
* @id TextExtAutocomplete.onEnterKeyPress
|
480
|
+
*/
|
481
|
+
p.onEnterKeyPress = function(e)
|
482
|
+
{
|
483
|
+
var self = this;
|
484
|
+
|
485
|
+
if(self.isDropdownVisible())
|
486
|
+
self.selectFromDropdown();
|
487
|
+
};
|
488
|
+
|
489
|
+
/**
|
490
|
+
* Reacts to the `escapeKeyPress` event triggered by the TextExt core. Hides the dropdown
|
491
|
+
* if it's currently visible.
|
492
|
+
*
|
493
|
+
* @signature TextExtAutocomplete.onEscapeKeyPress(e)
|
494
|
+
*
|
495
|
+
* @param e {Object} jQuery event.
|
496
|
+
*
|
497
|
+
* @author agorbatchev
|
498
|
+
* @date 2011/08/17
|
499
|
+
* @id TextExtAutocomplete.onEscapeKeyPress
|
500
|
+
*/
|
501
|
+
p.onEscapeKeyPress = function(e)
|
502
|
+
{
|
503
|
+
var self = this;
|
504
|
+
|
505
|
+
if(self.isDropdownVisible())
|
506
|
+
self.trigger(EVENT_HIDE_DROPDOWN);
|
507
|
+
};
|
508
|
+
|
509
|
+
//--------------------------------------------------------------------------------
|
510
|
+
// Core functionality
|
511
|
+
|
512
|
+
/**
|
513
|
+
* Positions dropdown either below or above the input based on the `autocomplete.dropdown.position`
|
514
|
+
* option specified, which could be either `above` or `below`.
|
515
|
+
*
|
516
|
+
* @signature TextExtAutocomplete.positionDropdown()
|
517
|
+
*
|
518
|
+
* @author agorbatchev
|
519
|
+
* @date 2011/08/15
|
520
|
+
* @id TextExtAutocomplete.positionDropdown
|
521
|
+
*/
|
522
|
+
p.positionDropdown = function()
|
523
|
+
{
|
524
|
+
var self = this,
|
525
|
+
container = self.containerElement(),
|
526
|
+
direction = self.opts(OPT_POSITION),
|
527
|
+
height = self.core().wrapElement().outerHeight(),
|
528
|
+
css = {}
|
529
|
+
;
|
530
|
+
|
531
|
+
css[direction === POSITION_ABOVE ? 'bottom' : 'top'] = height + 'px';
|
532
|
+
container.css(css);
|
533
|
+
};
|
534
|
+
|
535
|
+
/**
|
536
|
+
* Returns list of all the suggestion HTML elements in the dropdown.
|
537
|
+
*
|
538
|
+
* @signature TextExtAutocomplete.suggestionElements()
|
539
|
+
*
|
540
|
+
* @author agorbatchev
|
541
|
+
* @date 2011/08/17
|
542
|
+
* @id TextExtAutocomplete.suggestionElements
|
543
|
+
*/
|
544
|
+
p.suggestionElements = function()
|
545
|
+
{
|
546
|
+
return this.containerElement().find(CSS_DOT_SUGGESTION);
|
547
|
+
};
|
548
|
+
|
549
|
+
|
550
|
+
/**
|
551
|
+
* Highlights specified suggestion as selected in the dropdown.
|
552
|
+
*
|
553
|
+
* @signature TextExtAutocomplete.setSelectedSuggestion(suggestion)
|
554
|
+
*
|
555
|
+
* @param suggestion {Object} Suggestion object. With the default `ItemManager` this
|
556
|
+
* is expected to be a string, anything else with custom implementations.
|
557
|
+
*
|
558
|
+
* @author agorbatchev
|
559
|
+
* @date 2011/08/17
|
560
|
+
* @id TextExtAutocomplete.setSelectedSuggestion
|
561
|
+
*/
|
562
|
+
p.setSelectedSuggestion = function(suggestion)
|
563
|
+
{
|
564
|
+
if(!suggestion)
|
565
|
+
return;
|
566
|
+
|
567
|
+
var self = this,
|
568
|
+
all = self.suggestionElements(),
|
569
|
+
target = all.first(),
|
570
|
+
item, i
|
571
|
+
;
|
572
|
+
|
573
|
+
self.clearSelected();
|
574
|
+
|
575
|
+
for(i = 0; i < all.length; i++)
|
576
|
+
{
|
577
|
+
item = $(all[i]);
|
578
|
+
|
579
|
+
if(self.itemManager().compareItems(item.data(CSS_SUGGESTION), suggestion))
|
580
|
+
{
|
581
|
+
target = item.addClass(CSS_SELECTED);
|
582
|
+
break;
|
583
|
+
}
|
584
|
+
}
|
585
|
+
|
586
|
+
target.addClass(CSS_SELECTED);
|
587
|
+
self.scrollSuggestionIntoView(target);
|
588
|
+
};
|
589
|
+
|
590
|
+
/**
|
591
|
+
* Returns the first suggestion HTML element from the dropdown that is highlighted as selected.
|
592
|
+
*
|
593
|
+
* @signature TextExtAutocomplete.selectedSuggestionElement()
|
594
|
+
*
|
595
|
+
* @author agorbatchev
|
596
|
+
* @date 2011/08/17
|
597
|
+
* @id TextExtAutocomplete.selectedSuggestionElement
|
598
|
+
*/
|
599
|
+
p.selectedSuggestionElement = function()
|
600
|
+
{
|
601
|
+
return this.suggestionElements().filter(CSS_DOT_SELECTED).first();
|
602
|
+
};
|
603
|
+
|
604
|
+
/**
|
605
|
+
* Returns `true` if dropdown is currently visible, `false` otherwise.
|
606
|
+
*
|
607
|
+
* @signature TextExtAutocomplete.isDropdownVisible()
|
608
|
+
*
|
609
|
+
* @author agorbatchev
|
610
|
+
* @date 2011/08/17
|
611
|
+
* @id TextExtAutocomplete.isDropdownVisible
|
612
|
+
*/
|
613
|
+
p.isDropdownVisible = function()
|
614
|
+
{
|
615
|
+
return this.containerElement().is(':visible') === true;
|
616
|
+
};
|
617
|
+
|
618
|
+
/**
|
619
|
+
* Reacts to the `getFormData` event triggered by the core. Returns data with the
|
620
|
+
* weight of 100 to be *less than the Tags plugin* data weight. The weights system is
|
621
|
+
* covered in greater detail in the [`getFormData`][1] event documentation.
|
622
|
+
*
|
623
|
+
* [1]: /manual/textext.html#getformdata
|
624
|
+
*
|
625
|
+
* @signature TextExtAutocomplete.onGetFormData(e, data, keyCode)
|
626
|
+
*
|
627
|
+
* @param e {Object} jQuery event.
|
628
|
+
* @param data {Object} Data object to be populated.
|
629
|
+
* @param keyCode {Number} Key code that triggered the original update request.
|
630
|
+
*
|
631
|
+
* @author agorbatchev
|
632
|
+
* @date 2011/08/22
|
633
|
+
* @id TextExtAutocomplete.onGetFormData
|
634
|
+
*/
|
635
|
+
p.onGetFormData = function(e, data, keyCode)
|
636
|
+
{
|
637
|
+
var self = this,
|
638
|
+
val = self.val(),
|
639
|
+
inputValue = val,
|
640
|
+
formValue = val
|
641
|
+
;
|
642
|
+
data[100] = self.formDataObject(inputValue, formValue);
|
643
|
+
};
|
644
|
+
|
645
|
+
/**
|
646
|
+
* Returns initialization priority of the Autocomplete plugin which is expected to be
|
647
|
+
* *greater than the Tags plugin* because of the dependencies. The value is 200.
|
648
|
+
*
|
649
|
+
* @signature TextExtAutocomplete.initPriority()
|
650
|
+
*
|
651
|
+
* @author agorbatchev
|
652
|
+
* @date 2011/08/22
|
653
|
+
* @id TextExtAutocomplete.initPriority
|
654
|
+
*/
|
655
|
+
p.initPriority = function()
|
656
|
+
{
|
657
|
+
return 200;
|
658
|
+
};
|
659
|
+
|
660
|
+
/**
|
661
|
+
* Reacts to the `hideDropdown` event and hides the dropdown if it's already visible.
|
662
|
+
*
|
663
|
+
* @signature TextExtAutocomplete.onHideDropdown(e)
|
664
|
+
*
|
665
|
+
* @param e {Object} jQuery event.
|
666
|
+
*
|
667
|
+
* @author agorbatchev
|
668
|
+
* @date 2011/08/17
|
669
|
+
* @id TextExtAutocomplete.onHideDropdown
|
670
|
+
*/
|
671
|
+
p.onHideDropdown = function(e)
|
672
|
+
{
|
673
|
+
this.hideDropdown();
|
674
|
+
};
|
675
|
+
|
676
|
+
/**
|
677
|
+
* Reacts to the 'toggleDropdown` event and shows or hides the dropdown depending if
|
678
|
+
* it's currently hidden or visible.
|
679
|
+
*
|
680
|
+
* @signature TextExtAutocomplete.onToggleDropdown(e)
|
681
|
+
*
|
682
|
+
* @param e {Object} jQuery event.
|
683
|
+
*
|
684
|
+
* @author agorbatchev
|
685
|
+
* @date 2011/12/27
|
686
|
+
* @id TextExtAutocomplete.onToggleDropdown
|
687
|
+
* @version 1.1
|
688
|
+
*/
|
689
|
+
p.onToggleDropdown = function(e)
|
690
|
+
{
|
691
|
+
var self = this;
|
692
|
+
self.trigger(self.containerElement().is(':visible') ? EVENT_HIDE_DROPDOWN : EVENT_SHOW_DROPDOWN);
|
693
|
+
};
|
694
|
+
|
695
|
+
/**
|
696
|
+
* Reacts to the `showDropdown` event and shows the dropdown if it's not already visible.
|
697
|
+
* It's possible to pass a render callback function which will be called instead of the
|
698
|
+
* default `TextExtAutocomplete.renderSuggestions()`.
|
699
|
+
*
|
700
|
+
* If no suggestion were previously loaded, it will fire `getSuggestions` event and exit.
|
701
|
+
*
|
702
|
+
* Here's how another plugin should trigger this event with the optional render callback:
|
703
|
+
*
|
704
|
+
* this.trigger('showDropdown', function(autocomplete)
|
705
|
+
* {
|
706
|
+
* autocomplete.clearItems();
|
707
|
+
* var node = autocomplete.addDropdownItem('<b>Item</b>');
|
708
|
+
* node.addClass('new-look');
|
709
|
+
* });
|
710
|
+
*
|
711
|
+
* @signature TextExtAutocomplete.onShowDropdown(e, renderCallback)
|
712
|
+
*
|
713
|
+
* @param e {Object} jQuery event.
|
714
|
+
* @param renderCallback {Function} Optional callback function which would be used to
|
715
|
+
* render dropdown items. As a first argument, reference to the current instance of
|
716
|
+
* Autocomplete plugin will be supplied. It's assumed, that if this callback is provided
|
717
|
+
* rendering will be handled completely manually.
|
718
|
+
*
|
719
|
+
* @author agorbatchev
|
720
|
+
* @date 2011/08/17
|
721
|
+
* @id TextExtAutocomplete.onShowDropdown
|
722
|
+
*/
|
723
|
+
p.onShowDropdown = function(e, renderCallback)
|
724
|
+
{
|
725
|
+
var self = this,
|
726
|
+
current = self.selectedSuggestionElement().data(CSS_SUGGESTION),
|
727
|
+
suggestions = self._suggestions
|
728
|
+
;
|
729
|
+
|
730
|
+
if(!suggestions)
|
731
|
+
return self.trigger(EVENT_GET_SUGGESTIONS);
|
732
|
+
|
733
|
+
if($.isFunction(renderCallback))
|
734
|
+
{
|
735
|
+
renderCallback(self);
|
736
|
+
}
|
737
|
+
else
|
738
|
+
{
|
739
|
+
self.renderSuggestions(self._suggestions);
|
740
|
+
self.toggleNextSuggestion();
|
741
|
+
}
|
742
|
+
|
743
|
+
self.showDropdown(self.containerElement());
|
744
|
+
self.setSelectedSuggestion(current);
|
745
|
+
};
|
746
|
+
|
747
|
+
/**
|
748
|
+
* Reacts to the `setSuggestions` event. Expects to recieve the payload as the second argument
|
749
|
+
* in the following structure:
|
750
|
+
*
|
751
|
+
* {
|
752
|
+
* result : [ "item1", "item2" ],
|
753
|
+
* showHideDropdown : false
|
754
|
+
* }
|
755
|
+
*
|
756
|
+
* Notice the optional `showHideDropdown` option. By default, ie without the `showHideDropdown`
|
757
|
+
* value the method will trigger either `showDropdown` or `hideDropdown` depending if there are
|
758
|
+
* suggestions. If set to `false`, no event is triggered.
|
759
|
+
*
|
760
|
+
* @signature TextExtAutocomplete.onSetSuggestions(e, data)
|
761
|
+
*
|
762
|
+
* @param data {Object} Data payload.
|
763
|
+
*
|
764
|
+
* @author agorbatchev
|
765
|
+
* @date 2011/08/17
|
766
|
+
* @id TextExtAutocomplete.onSetSuggestions
|
767
|
+
*/
|
768
|
+
p.onSetSuggestions = function(e, data)
|
769
|
+
{
|
770
|
+
var self = this,
|
771
|
+
suggestions = self._suggestions = data.result
|
772
|
+
;
|
773
|
+
|
774
|
+
if(data.showHideDropdown !== false)
|
775
|
+
self.trigger(suggestions === null || suggestions.length === 0 ? EVENT_HIDE_DROPDOWN : EVENT_SHOW_DROPDOWN);
|
776
|
+
};
|
777
|
+
|
778
|
+
/**
|
779
|
+
* Prepears for and triggers the `getSuggestions` event with the `{ query : {String} }` as second
|
780
|
+
* argument.
|
781
|
+
*
|
782
|
+
* @signature TextExtAutocomplete.getSuggestions()
|
783
|
+
*
|
784
|
+
* @author agorbatchev
|
785
|
+
* @date 2011/08/17
|
786
|
+
* @id TextExtAutocomplete.getSuggestions
|
787
|
+
*/
|
788
|
+
p.getSuggestions = function()
|
789
|
+
{
|
790
|
+
var self = this,
|
791
|
+
val = self.val()
|
792
|
+
;
|
793
|
+
|
794
|
+
if(self._previousInputValue == val)
|
795
|
+
return;
|
796
|
+
|
797
|
+
// if user clears input, then we want to select first suggestion
|
798
|
+
// instead of the last one
|
799
|
+
if(val == '')
|
800
|
+
current = null;
|
801
|
+
|
802
|
+
self._previousInputValue = val;
|
803
|
+
self.trigger(EVENT_GET_SUGGESTIONS, { query : val });
|
804
|
+
};
|
805
|
+
|
806
|
+
/**
|
807
|
+
* Removes all HTML suggestion items from the dropdown.
|
808
|
+
*
|
809
|
+
* @signature TextExtAutocomplete.clearItems()
|
810
|
+
*
|
811
|
+
* @author agorbatchev
|
812
|
+
* @date 2011/08/17
|
813
|
+
* @id TextExtAutocomplete.clearItems
|
814
|
+
*/
|
815
|
+
p.clearItems = function()
|
816
|
+
{
|
817
|
+
this.containerElement().find('.text-list').children().remove();
|
818
|
+
};
|
819
|
+
|
820
|
+
/**
|
821
|
+
* Clears all and renders passed suggestions.
|
822
|
+
*
|
823
|
+
* @signature TextExtAutocomplete.renderSuggestions(suggestions)
|
824
|
+
*
|
825
|
+
* @param suggestions {Array} List of suggestions to render.
|
826
|
+
*
|
827
|
+
* @author agorbatchev
|
828
|
+
* @date 2011/08/17
|
829
|
+
* @id TextExtAutocomplete.renderSuggestions
|
830
|
+
*/
|
831
|
+
p.renderSuggestions = function(suggestions)
|
832
|
+
{
|
833
|
+
var self = this;
|
834
|
+
|
835
|
+
self.clearItems();
|
836
|
+
|
837
|
+
$.each(suggestions || [], function(index, item)
|
838
|
+
{
|
839
|
+
self.addSuggestion(item);
|
840
|
+
});
|
841
|
+
};
|
842
|
+
|
843
|
+
/**
|
844
|
+
* Shows the dropdown.
|
845
|
+
*
|
846
|
+
* @signature TextExtAutocomplete.showDropdown()
|
847
|
+
*
|
848
|
+
* @author agorbatchev
|
849
|
+
* @date 2011/08/17
|
850
|
+
* @id TextExtAutocomplete.showDropdown
|
851
|
+
*/
|
852
|
+
p.showDropdown = function()
|
853
|
+
{
|
854
|
+
this.containerElement().show();
|
855
|
+
};
|
856
|
+
|
857
|
+
/**
|
858
|
+
* Hides the dropdown.
|
859
|
+
*
|
860
|
+
* @signature TextExtAutocomplete.hideDropdown()
|
861
|
+
*
|
862
|
+
* @author agorbatchev
|
863
|
+
* @date 2011/08/17
|
864
|
+
* @id TextExtAutocomplete.hideDropdown
|
865
|
+
*/
|
866
|
+
p.hideDropdown = function()
|
867
|
+
{
|
868
|
+
var self = this,
|
869
|
+
dropdown = self.containerElement()
|
870
|
+
;
|
871
|
+
|
872
|
+
self._previousInputValue = null;
|
873
|
+
dropdown.hide();
|
874
|
+
};
|
875
|
+
|
876
|
+
/**
|
877
|
+
* Adds single suggestion to the bottom of the dropdown. Uses `ItemManager.itemToString()` to
|
878
|
+
* serialize provided suggestion to string.
|
879
|
+
*
|
880
|
+
* @signature TextExtAutocomplete.addSuggestion(suggestion)
|
881
|
+
*
|
882
|
+
* @param suggestion {Object} Suggestion item. By default expected to be a string.
|
883
|
+
*
|
884
|
+
* @author agorbatchev
|
885
|
+
* @date 2011/08/17
|
886
|
+
* @id TextExtAutocomplete.addSuggestion
|
887
|
+
*/
|
888
|
+
p.addSuggestion = function(suggestion)
|
889
|
+
{
|
890
|
+
var self = this,
|
891
|
+
renderer = self.opts(OPT_RENDER),
|
892
|
+
node = self.addDropdownItem(renderer ? renderer.call(self, suggestion) : self.itemManager().itemToString(suggestion))
|
893
|
+
;
|
894
|
+
|
895
|
+
node.data(CSS_SUGGESTION, suggestion);
|
896
|
+
};
|
897
|
+
|
898
|
+
/**
|
899
|
+
* Adds and returns HTML node to the bottom of the dropdown.
|
900
|
+
*
|
901
|
+
* @signature TextExtAutocomplete.addDropdownItem(html)
|
902
|
+
*
|
903
|
+
* @param html {String} HTML to be inserted into the item.
|
904
|
+
*
|
905
|
+
* @author agorbatchev
|
906
|
+
* @date 2011/08/17
|
907
|
+
* @id TextExtAutocomplete.addDropdownItem
|
908
|
+
*/
|
909
|
+
p.addDropdownItem = function(html)
|
910
|
+
{
|
911
|
+
var self = this,
|
912
|
+
container = self.containerElement().find('.text-list'),
|
913
|
+
node = $(self.opts(OPT_HTML_SUGGESTION))
|
914
|
+
;
|
915
|
+
|
916
|
+
node.find('.text-label').html(html);
|
917
|
+
container.append(node);
|
918
|
+
return node;
|
919
|
+
};
|
920
|
+
|
921
|
+
/**
|
922
|
+
* Removes selection highlight from all suggestion elements.
|
923
|
+
*
|
924
|
+
* @signature TextExtAutocomplete.clearSelected()
|
925
|
+
*
|
926
|
+
* @author agorbatchev
|
927
|
+
* @date 2011/08/02
|
928
|
+
* @id TextExtAutocomplete.clearSelected
|
929
|
+
*/
|
930
|
+
p.clearSelected = function()
|
931
|
+
{
|
932
|
+
this.suggestionElements().removeClass(CSS_SELECTED);
|
933
|
+
};
|
934
|
+
|
935
|
+
/**
|
936
|
+
* Selects next suggestion relative to the current one. If there's no
|
937
|
+
* currently selected suggestion, it will select the first one. Selected
|
938
|
+
* suggestion will always be scrolled into view.
|
939
|
+
*
|
940
|
+
* @signature TextExtAutocomplete.toggleNextSuggestion()
|
941
|
+
*
|
942
|
+
* @author agorbatchev
|
943
|
+
* @date 2011/08/02
|
944
|
+
* @id TextExtAutocomplete.toggleNextSuggestion
|
945
|
+
*/
|
946
|
+
p.toggleNextSuggestion = function()
|
947
|
+
{
|
948
|
+
var self = this,
|
949
|
+
selected = self.selectedSuggestionElement(),
|
950
|
+
next
|
951
|
+
;
|
952
|
+
|
953
|
+
if(selected.length > 0)
|
954
|
+
{
|
955
|
+
next = selected.next();
|
956
|
+
|
957
|
+
if(next.length > 0)
|
958
|
+
selected.removeClass(CSS_SELECTED);
|
959
|
+
}
|
960
|
+
else
|
961
|
+
{
|
962
|
+
next = self.suggestionElements().first();
|
963
|
+
}
|
964
|
+
|
965
|
+
next.addClass(CSS_SELECTED);
|
966
|
+
self.scrollSuggestionIntoView(next);
|
967
|
+
};
|
968
|
+
|
969
|
+
/**
|
970
|
+
* Selects previous suggestion relative to the current one. Selected
|
971
|
+
* suggestion will always be scrolled into view.
|
972
|
+
*
|
973
|
+
* @signature TextExtAutocomplete.togglePreviousSuggestion()
|
974
|
+
*
|
975
|
+
* @author agorbatchev
|
976
|
+
* @date 2011/08/02
|
977
|
+
* @id TextExtAutocomplete.togglePreviousSuggestion
|
978
|
+
*/
|
979
|
+
p.togglePreviousSuggestion = function()
|
980
|
+
{
|
981
|
+
var self = this,
|
982
|
+
selected = self.selectedSuggestionElement(),
|
983
|
+
prev = selected.prev()
|
984
|
+
;
|
985
|
+
|
986
|
+
if(prev.length == 0)
|
987
|
+
return;
|
988
|
+
|
989
|
+
self.clearSelected();
|
990
|
+
prev.addClass(CSS_SELECTED);
|
991
|
+
self.scrollSuggestionIntoView(prev);
|
992
|
+
};
|
993
|
+
|
994
|
+
/**
|
995
|
+
* Scrolls specified HTML suggestion element into the view.
|
996
|
+
*
|
997
|
+
* @signature TextExtAutocomplete.scrollSuggestionIntoView(item)
|
998
|
+
*
|
999
|
+
* @param item {HTMLElement} jQuery HTML suggestion element which needs to
|
1000
|
+
* scrolled into view.
|
1001
|
+
*
|
1002
|
+
* @author agorbatchev
|
1003
|
+
* @date 2011/08/17
|
1004
|
+
* @id TextExtAutocomplete.scrollSuggestionIntoView
|
1005
|
+
*/
|
1006
|
+
p.scrollSuggestionIntoView = function(item)
|
1007
|
+
{
|
1008
|
+
var itemHeight = item.outerHeight(),
|
1009
|
+
dropdown = this.containerElement(),
|
1010
|
+
dropdownHeight = dropdown.innerHeight(),
|
1011
|
+
scrollPos = dropdown.scrollTop(),
|
1012
|
+
itemTop = (item.position() || {}).top,
|
1013
|
+
scrollTo = null,
|
1014
|
+
paddingTop = parseInt(dropdown.css('paddingTop'))
|
1015
|
+
;
|
1016
|
+
|
1017
|
+
if(itemTop == null)
|
1018
|
+
return;
|
1019
|
+
|
1020
|
+
// if scrolling down and item is below the bottom fold
|
1021
|
+
if(itemTop + itemHeight > dropdownHeight)
|
1022
|
+
scrollTo = itemTop + scrollPos + itemHeight - dropdownHeight + paddingTop;
|
1023
|
+
|
1024
|
+
// if scrolling up and item is above the top fold
|
1025
|
+
if(itemTop < 0)
|
1026
|
+
scrollTo = itemTop + scrollPos - paddingTop;
|
1027
|
+
|
1028
|
+
if(scrollTo != null)
|
1029
|
+
dropdown.scrollTop(scrollTo);
|
1030
|
+
};
|
1031
|
+
|
1032
|
+
/**
|
1033
|
+
* Uses the value from the text input to finish autocomplete action. Currently selected
|
1034
|
+
* suggestion from the dropdown will be used to complete the action. Triggers `hideDropdown`
|
1035
|
+
* event.
|
1036
|
+
*
|
1037
|
+
* @signature TextExtAutocomplete.selectFromDropdown()
|
1038
|
+
*
|
1039
|
+
* @author agorbatchev
|
1040
|
+
* @date 2011/08/17
|
1041
|
+
* @id TextExtAutocomplete.selectFromDropdown
|
1042
|
+
*/
|
1043
|
+
p.selectFromDropdown = function()
|
1044
|
+
{
|
1045
|
+
var self = this,
|
1046
|
+
suggestion = self.selectedSuggestionElement().data(CSS_SUGGESTION)
|
1047
|
+
;
|
1048
|
+
|
1049
|
+
if(suggestion)
|
1050
|
+
{
|
1051
|
+
self.val(self.itemManager().itemToString(suggestion));
|
1052
|
+
self.core().getFormData();
|
1053
|
+
}
|
1054
|
+
|
1055
|
+
self.trigger(EVENT_HIDE_DROPDOWN);
|
1056
|
+
};
|
1057
|
+
})(jQuery);
|