Mercurial > hg > dml-open-vis
comparison src/DML/MainVisBundle/Resources/assets/marionette/modules/MainRegionModule/MainRegionModule.50-cgpma.textfield.js @ 0:493bcb69166c
added public content
author | Daniel Wolff |
---|---|
date | Tue, 09 Feb 2016 20:54:02 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:493bcb69166c |
---|---|
1 "use strict"; | |
2 | |
3 (function($) { | |
4 $.widget("cgpma.textfield", { | |
5 | |
6 options: { | |
7 value: "", | |
8 baseValue: "", | |
9 autocompleteMaxItemCount: 15, | |
10 autocompleteSort: false, | |
11 autocompleteSuggestions: null, | |
12 autocompleteIsAdvisory: false, | |
13 autocompleteCSSClasses: "" | |
14 }, | |
15 | |
16 isFocused: function() { | |
17 var widget = this; | |
18 return widget.$input.is(":focus"); | |
19 }, | |
20 | |
21 focus: function() { | |
22 var widget = this; | |
23 return widget.$input.focus(); | |
24 }, | |
25 | |
26 getTextRange: function() { | |
27 var widget = this; | |
28 return widget.$input.textrange(); | |
29 }, | |
30 | |
31 setTextRange: function(textRange) { | |
32 var widget = this; | |
33 if (textRange.start != textRange.end) { | |
34 return widget.$input.textrange("set", textRange.start, textRange.end); | |
35 } | |
36 return widget.$input.textrange("setcursor", textRange.position); | |
37 }, | |
38 | |
39 _create : function() { | |
40 var widget = this; | |
41 widget.$element = this.element; | |
42 widget.$input = $.bem.generateElement("input", "cgpma", "textfield-input"); | |
43 widget.$input.appendTo(widget.$element); | |
44 | |
45 widget.$input.data("widget", widget); | |
46 | |
47 widget._applyAutocompleteSuggestions(); | |
48 | |
49 widget.$input.bind("input", widget.__handleInputChange); | |
50 widget.$input.bind("keydown", widget.__handleInputKeyDown); | |
51 widget.$input.bind("keyup", widget.__handleInputKeyUp); | |
52 widget.$input.bind("click", widget.__handleInputClick); | |
53 | |
54 }, | |
55 | |
56 _applyAutocompleteSuggestions: function() { | |
57 var widget = this; | |
58 | |
59 if (widget.$input.data("ui-autocomplete")) { | |
60 widget.$input.autocomplete("destroy"); | |
61 } | |
62 | |
63 var autocompleteSuggestions = widget.options.autocompleteSuggestions; | |
64 if (!autocompleteSuggestions) { | |
65 return; | |
66 delete widget._invertedAutocompleteSuggestions; | |
67 } | |
68 widget._invertedAutocompleteSuggestions = _.invert(autocompleteSuggestions); | |
69 | |
70 widget.$input.autocomplete({ | |
71 delay : 0, | |
72 minLength : 0, | |
73 source : $.proxy(widget, "_autocompleteSource") | |
74 }); | |
75 | |
76 widget.$input.autocomplete( | |
77 "widget").addClass(widget.options.autocompleteCSSClasses); | |
78 | |
79 widget._on(widget.$input, { | |
80 autocompleteselect : widget.__handleInputChange, | |
81 autocompleteopen : widget.__handleAutocompleteOpen, | |
82 autocompleteclose : widget.__handleAutocompleteClose, | |
83 //autocompletechange : widget.__handleInputChange | |
84 }); | |
85 }, | |
86 | |
87 _autocompleteSource: function(request, response) { | |
88 var widget = this; | |
89 | |
90 var matcher = new RegExp($.ui.autocomplete | |
91 .escapeRegex(_.str.trim(request.term)), "i"); | |
92 | |
93 var responseItems = []; | |
94 _.each(widget.options.autocompleteSuggestions, function(kindName, kind) { | |
95 if (widget.options.autocompleteAlwaysFull || !request.term || matcher.test(kindName)) { | |
96 responseItems.push({ | |
97 label : kindName, | |
98 value : kindName, | |
99 }); | |
100 }; | |
101 }); | |
102 | |
103 if (responseItems.length == 1 && responseItems[0].label === request.term) { | |
104 responseItems = []; | |
105 } | |
106 if (responseItems.length > widget.options.autocompleteMaxItemCount) { | |
107 responseItems = responseItems.slice(0, widget.options.autocompleteMaxItemCount); | |
108 } | |
109 if (widget.options.autocompleteSort) { | |
110 responseItems = _.sortBy(responseItems, "label"); | |
111 } | |
112 | |
113 response(responseItems); | |
114 }, | |
115 | |
116 _createShowAllButton : function() { | |
117 return; | |
118 var input = this.input, wasOpen = false; | |
119 $("<a>").attr("tabIndex", -1).attr("title", | |
120 "Show All Items").tooltip().appendTo( | |
121 this.wrapper).button({ | |
122 icons : { | |
123 primary : "ui-icon-triangle-1-s" | |
124 }, | |
125 text : false | |
126 }).removeClass("ui-corner-all").addClass( | |
127 "custom-combobox-toggle ui-corner-right") | |
128 .mousedown( | |
129 function() { | |
130 wasOpen = input.autocomplete( | |
131 "widget") | |
132 .is(":visible"); | |
133 }).click(function() { | |
134 input.focus(); | |
135 // Close if already visible | |
136 if (wasOpen) { | |
137 return; | |
138 } | |
139 // Pass empty string as value to search | |
140 // for, displaying all results | |
141 input.autocomplete("search", ""); | |
142 }); | |
143 }, | |
144 | |
145 _isAutocompleteVisible : function() { | |
146 var widget = this; | |
147 if (widget.$input.data("ui-autocomplete")) { | |
148 return widget.$input.autocomplete("widget").is(":visible"); | |
149 } else { | |
150 return false; | |
151 } | |
152 }, | |
153 | |
154 _destroy : function() { | |
155 this.$input.removeData(); | |
156 }, | |
157 | |
158 _setOption: function (key, value) { | |
159 var widget = this; | |
160 | |
161 // Check if such option exists, throw an error if not | |
162 if (!widget.options.hasOwnProperty(key)) { | |
163 throw "Option " + key + " does not exist"; | |
164 } | |
165 | |
166 // Check if value matches what it was, do nothing if yes | |
167 if (value === widget.options[key] || (_.isArray(value) && _.isEqual(value, widget.options[key]))) { | |
168 return; | |
169 } | |
170 | |
171 // Save old option value | |
172 var prev = widget.options[key]; | |
173 | |
174 // Apply the option | |
175 this._super(key, value); | |
176 | |
177 // Call corresponding update method depending on the option key | |
178 switch (key) { | |
179 | |
180 case "value": | |
181 this._applyValue(); | |
182 break; | |
183 | |
184 case "baseValue": | |
185 this._updateStatus(); | |
186 break; | |
187 | |
188 case "autocompleteSuggestions": | |
189 this._applyAutocompleteSuggestions(); | |
190 break; | |
191 } | |
192 widget._trigger("change" + key.toLowerCase(), null, {newValue: value, prevValue: prev}); | |
193 }, | |
194 | |
195 _realValueToInputValue: function(realValue) { | |
196 var widget = this; | |
197 | |
198 var value = realValue; | |
199 var valueInOptionsIsString = _.isString(value); | |
200 var trimmedValueInOptions = valueInOptionsIsString ? _.str.trim(value) : value; | |
201 var trimmedCharsOnLeft = valueInOptionsIsString ? value.indexOf(trimmedValueInOptions) : null; | |
202 var trimmedCharsOnRight = valueInOptionsIsString ? value.length - trimmedValueInOptions.length - trimmedCharsOnLeft : null; | |
203 | |
204 if (valueInOptionsIsString && widget.options.autocompleteSuggestions && widget.options.autocompleteSuggestions[trimmedValueInOptions] !== undefined) { | |
205 value = value.substring(0, trimmedCharsOnLeft) + widget.options.autocompleteSuggestions[trimmedValueInOptions] + value.substring(value.length - trimmedCharsOnRight); | |
206 } | |
207 if (valueInOptionsIsString && value.length >= 4 && value.substring(0, 2) == "__" && value.substring(value.length - 2) == "__") { | |
208 value = value.substring(2, value.length - 2); | |
209 } | |
210 | |
211 return value; | |
212 | |
213 }, | |
214 | |
215 _inputValueToRealValue: function(inputValue) { | |
216 var widget = this; | |
217 | |
218 var value = inputValue; | |
219 var trimmedValueInInput = _.str.trim(value); | |
220 var trimmedCharsOnLeft = value.indexOf(trimmedValueInInput); | |
221 var trimmedCharsOnRight = value.length - trimmedValueInInput.length - trimmedCharsOnLeft; | |
222 | |
223 if (widget.options.autocompleteSuggestions && widget.options.autocompleteSuggestions[trimmedValueInInput] && widget.options.autocompleteSuggestions[trimmedValueInInput] !== trimmedValueInInput) { | |
224 value = "__" + value + "__"; | |
225 } | |
226 if (widget._invertedAutocompleteSuggestions && widget._invertedAutocompleteSuggestions[trimmedValueInInput] !== undefined) { | |
227 value = value.substring(0, trimmedCharsOnLeft) + widget._invertedAutocompleteSuggestions[trimmedValueInInput] + value.substring(value.length - trimmedCharsOnRight); | |
228 } | |
229 | |
230 return value; | |
231 }, | |
232 | |
233 _applyValue: function() { | |
234 var widget = this; | |
235 | |
236 var inputValue = widget._realValueToInputValue(widget.options.value); | |
237 | |
238 if (inputValue !== widget.$input.val() && !widget._doNotUpdateInputOnValueChange) { | |
239 widget.$input.val(inputValue); | |
240 } | |
241 widget._updateStatus(); | |
242 }, | |
243 | |
244 _updateStatus: function() { | |
245 var widget = this; | |
246 widget.$element.toggleClass("cgpma__textfield_status_modified", widget.options.baseValue !== widget.options.value); | |
247 }, | |
248 | |
249 __handleInputChange: function() { | |
250 | |
251 // this can be an instance of the widget or the DOM node | |
252 var $input = null; | |
253 if (this.element) { | |
254 $input = this.$input; | |
255 } else { | |
256 $input = $(this); | |
257 } | |
258 var widget = $input.data("widget"); | |
259 var valueInInput = $input.val(); | |
260 | |
261 if (arguments[1] && arguments[1].item) { | |
262 valueInInput = arguments[1].item.value; | |
263 } | |
264 | |
265 var realValue = widget._inputValueToRealValue(valueInInput); | |
266 | |
267 widget._setOption("value", realValue); | |
268 }, | |
269 | |
270 __handleInputKeyDown: function(event) { | |
271 var $this = $(this); | |
272 var widget = $this.data("widget"); | |
273 if (event.keyCode == 13) { | |
274 //widget._lastInputChangeWasCausedByAutocomplete = widget.$nput.autocomplete("widget").is(":visible"); | |
275 } | |
276 if (event.keyCode == 38 || event.keyCode == 40) { // up or down | |
277 if (widget.$input.data("ui-autocomplete")) { | |
278 if (!widget._isAutocompleteVisible()) { | |
279 widget.$input.autocomplete("search", ""); | |
280 } else { | |
281 widget._doNotUpdateInputOnValueChange = true; | |
282 widget._setOption("value", widget._inputValueToRealValue(widget.$input.val())); | |
283 delete widget._doNotUpdateInputOnValueChange; | |
284 } | |
285 } | |
286 } | |
287 }, | |
288 | |
289 __handleInputKeyUp: function(event) { | |
290 var $this = $(this); | |
291 var widget = $this.data("widget"); | |
292 if (event.keyCode == 13) { | |
293 if (widget._lastInputChangeWasCausedByAutocomplete) { | |
294 widget._lastInputChangeWasCausedByAutocomplete = false; | |
295 } else { | |
296 widget._trigger("apply"); | |
297 if (widget.$input.data("ui-autocomplete")) { | |
298 widget.$input.autocomplete("close"); | |
299 } | |
300 } | |
301 } | |
302 if (event.keyCode == 27) { | |
303 if (!widget._isAutocompleteVisible()) { | |
304 widget._trigger("discard"); | |
305 } | |
306 event.preventDefault(); | |
307 } | |
308 }, | |
309 | |
310 __handleAutocompleteOpen: function(event) { | |
311 var widget = this; | |
312 widget.$element.addClass("cgpma__textfield_autocomplete-is-open"); | |
313 }, | |
314 | |
315 __handleAutocompleteClose: function(event) { | |
316 var widget = this; | |
317 widget.$element.removeClass("cgpma__textfield_autocomplete-is-open"); | |
318 }, | |
319 | |
320 __handleInputClick: function() { | |
321 var $this = $(this); | |
322 var widget = $this.data("widget"); | |
323 if (widget.$input.data("ui-autocomplete")) { | |
324 widget.$input.autocomplete("search", ""); | |
325 } | |
326 } | |
327 | |
328 }); | |
329 })(jQuery); |