├── jquery.a-tools-1.4.1.js
└── jquery.asuggest.js
/jquery.a-tools-1.4.1.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * a-tools 1.4.1
3 | *
4 | * Copyright (c) 2009 Andrey Kramarev(andrey.kramarev[at]ampparit.com), Ampparit Inc. (www.ampparit.com)
5 | * Licensed under the MIT license.
6 | * http://www.ampparit.fi/a-tools/license.txt
7 | *
8 | * Basic usage:
9 |
10 |
11 |
12 |
13 | // Get current selection
14 | var sel = $("textarea").getSelection()
15 |
16 | // Replace current selection
17 | $("input").replaceSelection("foo");
18 |
19 | // Count characters
20 | alert($("textarea").countCharacters());
21 |
22 | // Set max length without callback function
23 | $("textarea").setMaxLength(7);
24 |
25 | // Set max length with callback function which will be called when limit is exceeded
26 | $("textarea").setMaxLength(10, function() {
27 | alert("hello")
28 | });
29 |
30 | // Removing limit:
31 | $("textarea").setMaxLength(-1);
32 |
33 | // Insert text at current caret position
34 | $("#textarea").insertAtCaretPos("hello");
35 |
36 | // Set caret position (1 = beginning, -1 = end)
37 | $("#textArea").setCaretPos(10);
38 |
39 | // Set Selection
40 | $("#textArea").setSelection(10,15);
41 |
42 | */
43 | var caretPositionAmp;
44 |
45 | jQuery.fn.extend({
46 | getSelection: function() { // function for getting selection, and position of the selected text
47 | var input = this.jquery ? this[0] : this;
48 | var start;
49 | var end;
50 | var part;
51 | var number = 0;
52 | input.onmousedown = function() { // for IE because it loses caret position when focus changed
53 | if (document.selection && typeof(input.selectionStart) != "number") {
54 | document.selection.empty();
55 | } else {
56 | window.getSelection().removeAllRanges();
57 | }
58 | }
59 | if (document.selection) {
60 | // part for IE and Opera
61 | var s = document.selection.createRange();
62 | var minus = 0;
63 | var position = 0;
64 | var minusEnd = 0;
65 | var re;
66 | var rc;
67 | if (input.value.match(/\n/g) != null) {
68 | number = input.value.match(/\n/g).length;// number of EOL simbols
69 | }
70 | if (s.text) {
71 | part = s.text;
72 | // OPERA support
73 | if (typeof(input.selectionStart) == "number") {
74 | start = input.selectionStart;
75 | end = input.selectionEnd;
76 | // return null if the selected text not from the needed area
77 | if (start == end) {
78 | return { start: start, end: end, text: s.text, length: end - start };
79 | }
80 | } else {
81 | // IE support
82 | var firstRe;
83 | var secondRe;
84 | re = input.createTextRange();
85 | rc = re.duplicate();
86 | firstRe = re.text;
87 | re.moveToBookmark(s.getBookmark());
88 | secondRe = re.text;
89 | rc.setEndPoint("EndToStart", re);
90 | // return null if the selectyed text not from the needed area
91 | if (firstRe == secondRe && firstRe != s.text) {
92 | return this;
93 | }
94 | start = rc.text.length;
95 | end = rc.text.length + s.text.length;
96 | }
97 | // remove all EOL to have the same start and end positons as in MOZILLA
98 | if (number > 0) {
99 | for (var i = 0; i <= number; i++) {
100 | var w = input.value.indexOf("\n", position);
101 | if (w != -1 && w < start) {
102 | position = w + 1;
103 | minus++;
104 | minusEnd = minus;
105 | } else if (w != -1 && w >= start && w <= end) {
106 | if (w == start + 1) {
107 | minus--;
108 | minusEnd--;
109 | position = w + 1;
110 | continue;
111 | }
112 | position = w + 1;
113 | minusEnd++;
114 | } else {
115 | i = number;
116 | }
117 | }
118 | }
119 | if (s.text.indexOf("\n", 0) == 1) {
120 | minusEnd = minusEnd + 2;
121 | }
122 | start = start - minus;
123 | end = end - minusEnd;
124 |
125 | return { start: start, end: end, text: s.text, length: end - start };
126 | }
127 | input.focus ();
128 | if (typeof(input.selectionStart) == "number") {
129 | start = input.selectionStart;
130 | } else {
131 | s = document.selection.createRange();
132 | re = input.createTextRange();
133 | rc = re.duplicate();
134 | re.moveToBookmark(s.getBookmark());
135 | rc.setEndPoint("EndToStart", re);
136 | start = rc.text.length;
137 | }
138 | if (number > 0) {
139 | for (var i = 0; i <= number; i++) {
140 | var w = input.value.indexOf("\n", position);
141 | if (w != -1 && w < start) {
142 | position = w + 1;
143 | minus++;
144 | } else {
145 | i = number;
146 | }
147 | }
148 | }
149 | start = start - minus;
150 | return { start: start, end: start, text: s.text, length: 0 };
151 | } else if (typeof(input.selectionStart) == "number" ) {
152 | start = input.selectionStart;
153 | end = input.selectionEnd;
154 | part = input.value.substring(input.selectionStart, input.selectionEnd);
155 | return { start: start, end: end, text: part, length: end - start };
156 | } else { return { start: undefined, end: undefined, text: undefined, length: undefined }; }
157 | },
158 |
159 | // function for the replacement of the selected text
160 | replaceSelection: function(inputStr) {
161 | var input = this.jquery ? this[0] : this;
162 | //part for IE and Opera
163 | var start;
164 | var end;
165 | var position = 0;
166 | var rc;
167 | var re;
168 | var number = 0;
169 | var minus = 0;
170 | var mozScrollFix = ( input.scrollTop == undefined ) ? 0 : input.scrollTop;
171 | if (document.selection && typeof(input.selectionStart) != "number") {
172 | var s = document.selection.createRange();
173 |
174 | // IE support
175 | if (typeof(input.selectionStart) != "number") { // return null if the selected text not from the needed area
176 | var firstRe;
177 | var secondRe;
178 | re = input.createTextRange();
179 | rc = re.duplicate();
180 | firstRe = re.text;
181 | re.moveToBookmark(s.getBookmark());
182 | secondRe = re.text;
183 | rc.setEndPoint("EndToStart", re);
184 | if (firstRe == secondRe && firstRe != s.text) {
185 | return this;
186 | }
187 | }
188 | if (s.text) {
189 | part = s.text;
190 | if (input.value.match(/\n/g) != null) {
191 | number = input.value.match(/\n/g).length;// number of EOL simbols
192 | }
193 | // IE support
194 | start = rc.text.length;
195 | // remove all EOL to have the same start and end positons as in MOZILLA
196 | if (number > 0) {
197 | for (var i = 0; i <= number; i++) {
198 | var w = input.value.indexOf("\n", position);
199 | if (w != -1 && w < start) {
200 | position = w + 1;
201 | minus++;
202 |
203 | } else {
204 | i = number;
205 | }
206 | }
207 | }
208 | s.text = inputStr;
209 | caretPositionAmp = rc.text.length + inputStr.length;
210 | re.move("character", caretPositionAmp);
211 | document.selection.empty();
212 | input.blur();
213 | }
214 | return this;
215 | } else if (typeof(input.selectionStart) == "number" && // MOZILLA support
216 | input.selectionStart != input.selectionEnd) {
217 |
218 | start = input.selectionStart;
219 | end = input.selectionEnd;
220 | input.value = input.value.substr(0, start) + inputStr + input.value.substr(end);
221 | position = start + inputStr.length;
222 | input.setSelectionRange(position, position);
223 | input.scrollTop = mozScrollFix;
224 | return this;
225 | }
226 | return this;
227 | },
228 |
229 | //Set Selection in text
230 | setSelection: function(startPosition, endPosition) {
231 | startPosition = parseInt(startPosition);
232 | endPosition = parseInt(endPosition);
233 |
234 | var input = this.jquery ? this[0] : this;
235 | input.focus ();
236 | if (typeof(input.selectionStart) != "number") {
237 | re = input.createTextRange();
238 | if (re.text.length < endPosition) {
239 | endPosition = re.text.length+1;
240 | }
241 | }
242 | if (endPosition < startPosition) {
243 | return this;
244 | }
245 | if (document.selection) {
246 | var number = 0;
247 | var plus = 0;
248 | var position = 0;
249 | var plusEnd = 0;
250 | if (typeof(input.selectionStart) != "number") { // IE
251 | re.collapse(true);
252 | re.moveEnd('character', endPosition);
253 | re.moveStart('character', startPosition);
254 | re.select();
255 | return this;
256 | } else if (typeof(input.selectionStart) == "number") { // Opera
257 | if (input.value.match(/\n/g) != null) {
258 | number = input.value.match(/\n/g).length;// number of EOL simbols
259 | }
260 | if (number > 0) {
261 | for (var i = 0; i <= number; i++) {
262 | var w = input.value.indexOf("\n", position);
263 | if (w != -1 && w < startPosition) {
264 | position = w + 1;
265 | plus++;
266 | plusEnd = plus;
267 | } else if (w != -1 && w >= startPosition && w <= endPosition) {
268 | if (w == startPosition + 1) {
269 | plus--;
270 | plusEnd--;
271 | position = w + 1;
272 | continue;
273 | }
274 | position = w + 1;
275 | plusEnd++;
276 | } else {
277 | i = number;
278 | }
279 | }
280 | }
281 | startPosition = startPosition +plus;
282 | endPosition = endPosition + plusEnd;
283 | input.selectionStart = startPosition;
284 | input.selectionEnd = endPosition;
285 | return this;
286 | } else {
287 | return this;
288 | }
289 | }
290 | else if (input.selectionStart) { // MOZILLA support
291 | input.focus ();
292 | input.selectionStart = startPosition;
293 | input.selectionEnd = endPosition;
294 | return this;
295 | }
296 | },
297 |
298 | // insert text at current caret position
299 | insertAtCaretPos: function(inputStr) {
300 | var input = this.jquery ? this[0] : this;
301 | var start;
302 | var end;
303 | var position;
304 | var s;
305 | var re;
306 | var rc;
307 | var point;
308 | var minus = 0;
309 | var number = 0;
310 | var mozScrollFix = ( input.scrollTop == undefined ) ? 0 : input.scrollTop;
311 | input.focus();
312 | if (document.selection && typeof(input.selectionStart) != "number") {
313 | if (input.value.match(/\n/g) != null) {
314 | number = input.value.match(/\n/g).length;// number of EOL simbols
315 | }
316 | point = parseInt(caretPositionAmp);
317 | if (number > 0) {
318 | for (var i = 0; i <= number; i++) {
319 | var w = input.value.indexOf("\n", position);
320 | if (w != -1 && w <= point) {
321 | position = w + 1;
322 | point = point - 1;
323 | minus++;
324 | }
325 | }
326 | }
327 | }
328 | caretPositionAmp = parseInt(caretPositionAmp);
329 | // IE
330 | input.onmouseup = function() { // for IE because it loses caret position when focus changed
331 | if (document.selection && typeof(input.selectionStart) != "number") {
332 | input.focus();
333 | s = document.selection.createRange();
334 | re = input.createTextRange();
335 | rc = re.duplicate();
336 | re.moveToBookmark(s.getBookmark());
337 | rc.setEndPoint("EndToStart", re);
338 | caretPositionAmp = rc.text.length;
339 | }
340 | }
341 |
342 | if (document.selection && typeof(input.selectionStart) != "number") {
343 | s = document.selection.createRange();
344 | if (s.text.length != 0) {
345 | return this;
346 | }
347 | re = input.createTextRange();
348 | textLength = re.text.length;
349 | rc = re.duplicate();
350 | re.moveToBookmark(s.getBookmark());
351 | rc.setEndPoint("EndToStart", re);
352 | start = rc.text.length;
353 | if (caretPositionAmp > 0 && start ==0) {
354 | minus = caretPositionAmp - minus;
355 | re.move("character", minus);
356 | re.select();
357 | s = document.selection.createRange();
358 | caretPositionAmp += inputStr.length;
359 | } else if (!(caretPositionAmp >= 0) && textLength ==0) {
360 | s = document.selection.createRange();
361 | caretPositionAmp = inputStr.length + textLength;
362 | } else if (!(caretPositionAmp >= 0) && start ==0) {
363 | re.move("character", textLength);
364 | re.select();
365 | s = document.selection.createRange();
366 | caretPositionAmp = inputStr.length + textLength;
367 | } else if (!(caretPositionAmp >= 0) && start > 0) {
368 | re.move("character", 0);
369 | document.selection.empty();
370 | re.select();
371 | s = document.selection.createRange();
372 | caretPositionAmp = start + inputStr.length;
373 | } else if (caretPositionAmp >= 0 && caretPositionAmp == textLength) {
374 | if (textLength != 0) {
375 | re.move("character", textLength);
376 | re.select();
377 | } else {
378 | re.move("character", 0);
379 | }
380 | s = document.selection.createRange();
381 | caretPositionAmp = inputStr.length + textLength;
382 | } else if (caretPositionAmp >= 0 && start != 0 && caretPositionAmp >= start) {
383 | minus = caretPositionAmp - start;
384 | re.move("character", minus);
385 | document.selection.empty();
386 | re.select();
387 | s = document.selection.createRange();
388 | caretPositionAmp = caretPositionAmp + inputStr.length;
389 | } else if (caretPositionAmp >= 0 && start != 0 && caretPositionAmp < start) {
390 | re.move("character", 0);
391 | document.selection.empty();
392 | re.select();
393 | s = document.selection.createRange();
394 | caretPositionAmp = caretPositionAmp + inputStr.length;
395 | } else {
396 | document.selection.empty();
397 | re.select();
398 | s = document.selection.createRange();
399 | caretPositionAmp = caretPositionAmp + inputStr.length;
400 | }
401 | s.text = inputStr;
402 | input.focus();
403 |
404 | return this;
405 | } else if (typeof(input.selectionStart) == "number" && // MOZILLA support
406 | input.selectionStart == input.selectionEnd) {
407 | position = input.selectionStart + inputStr.length;
408 | start = input.selectionStart;
409 | end = input.selectionEnd;
410 | input.value = input.value.substr(0, start) + inputStr + input.value.substr(end);
411 | input.setSelectionRange(position, position);
412 | input.scrollTop = mozScrollFix;
413 | return this;
414 | }
415 | return this;
416 | },
417 |
418 |
419 | // Set caret position
420 | setCaretPos: function(inputStr) {
421 |
422 | var input = this.jquery ? this[0] : this;
423 | var s;
424 | var re;
425 | var position;
426 | var number = 0;
427 | var minus = 0;
428 | var w;
429 | input.focus();
430 | if (parseInt(inputStr) == 0) {
431 | return this;
432 | }
433 | //if (document.selection && typeof(input.selectionStart) == "number") {
434 | if (parseInt(inputStr) > 0) {
435 | inputStr = parseInt(inputStr) - 1;
436 | if (document.selection && typeof(input.selectionStart) == "number" && input.selectionStart == input.selectionEnd) {
437 | if (input.value.match(/\n/g) != null) {
438 | number = input.value.match(/\n/g).length;// number of EOL simbols
439 | }
440 | if (number > 0) {
441 | for (var i = 0; i <= number; i++) {
442 | w = input.value.indexOf("\n", position);
443 | if (w != -1 && w <= inputStr) {
444 | position = w + 1;
445 | inputStr = parseInt(inputStr) + 1;
446 | }
447 | }
448 | }
449 | }
450 | }
451 | else if (parseInt(inputStr) < 0) {
452 | inputStr = parseInt(inputStr) + 1;
453 | if (document.selection && typeof(input.selectionStart) != "number") {
454 | inputStr = input.value.length + parseInt(inputStr);
455 | if (input.value.match(/\n/g) != null) {
456 | number = input.value.match(/\n/g).length;// number of EOL simbols
457 | }
458 | if (number > 0) {
459 | for (var i = 0; i <= number; i++) {
460 | w = input.value.indexOf("\n", position);
461 | if (w != -1 && w <= inputStr) {
462 | position = w + 1;
463 | inputStr = parseInt(inputStr) - 1;
464 | minus += 1;
465 | }
466 | }
467 | inputStr = inputStr + minus - number;
468 | }
469 | } else if (document.selection && typeof(input.selectionStart) == "number") {
470 | inputStr = input.value.length + parseInt(inputStr);
471 | if (input.value.match(/\n/g) != null) {
472 | number = input.value.match(/\n/g).length;// number of EOL simbols
473 | }
474 | if (number > 0) {
475 | inputStr = parseInt(inputStr) - number;
476 | for (var i = 0; i <= number; i++) {
477 | w = input.value.indexOf("\n", position);
478 | if (w != -1 && w <= (inputStr)) {
479 | position = w + 1;
480 | inputStr = parseInt(inputStr) + 1;
481 | minus += 1;
482 | }
483 | }
484 | }
485 | } else { inputStr = input.value.length + parseInt(inputStr); }
486 | } else { return this; }
487 | // IE
488 | if (document.selection && typeof(input.selectionStart) != "number") {
489 | s = document.selection.createRange();
490 | if (s.text != 0) {
491 | return this;
492 | }
493 | re = input.createTextRange();
494 | re.collapse(true);
495 | re.moveEnd('character', inputStr);
496 | re.moveStart('character', inputStr);
497 | re.select();
498 | caretPositionAmp = inputStr;
499 |
500 | return this;
501 | } else if (typeof(input.selectionStart) == "number" && // MOZILLA support
502 | input.selectionStart == input.selectionEnd) {
503 | input.setSelectionRange(inputStr, inputStr);
504 | return this;
505 | }
506 | return this;
507 |
508 | },
509 |
510 | countCharacters: function(str) {
511 | var input = this.jquery ? this[0] : this;
512 | if (input.value.match(/\r/g) != null) {
513 | return input.value.length - input.value.match(/\r/g).length;
514 | }
515 | return input.value.length;
516 | },
517 |
518 | setMaxLength: function(max, f) {
519 | this.each(function() {
520 | var input = this.jquery ? this[0] : this;
521 | var type = input.type;
522 | var isSelected;
523 | var maxCharacters;
524 | // remove limit if input is a negative number
525 | if (parseInt(max) < 0) {
526 | max=100000000;
527 | }
528 | if (type == "text") {
529 | input.maxLength = max;
530 | }
531 | if (type == "textarea" || type == "text") {
532 | input.onkeypress = function(e) {
533 | var spacesR = input.value.match(/\r/g);
534 | maxCharacters = max;
535 | if (spacesR != null) {
536 | maxCharacters = parseInt(maxCharacters) + spacesR.length;
537 | }
538 | // get event
539 | var key = e || event;
540 | var keyCode = key.keyCode;
541 | // check if any part of text is selected
542 | if (document.selection) {
543 | isSelected = document.selection.createRange().text.length > 0;
544 | } else {
545 | isSelected = input.selectionStart != input.selectionEnd;
546 | }
547 | if (input.value.length >= maxCharacters && (keyCode > 47 || keyCode == 32 ||
548 | keyCode == 0 || keyCode == 13) && !key.ctrlKey && !key.altKey && !isSelected) {
549 | input.value = input.value.substring(0,maxCharacters);
550 | if (typeof(f) == "function") { f() } //callback function
551 | return false;
552 | }
553 | }
554 | input.onkeyup = function() {
555 | var spacesR = input.value.match(/\r/g);
556 | var plus = 0;
557 | var position = 0;
558 | maxCharacters = max;
559 | if (spacesR != null) {
560 | for (var i = 0; i <= spacesR.length; i++) {
561 | if (input.value.indexOf("\n", position) <= parseInt(max)) {
562 | plus++;
563 | position = input.value.indexOf("\n", position) + 1;
564 | }
565 | }
566 | maxCharacters = parseInt(max) + plus;
567 | }
568 | if (input.value.length > maxCharacters) {
569 | input.value = input.value.substring(0, maxCharacters);
570 | if (typeof(f) == "function") { f() }
571 | return this;
572 | }
573 | }
574 | } else { return this; }
575 | })
576 | return this;
577 | }
578 | });
579 |
--------------------------------------------------------------------------------
/jquery.asuggest.js:
--------------------------------------------------------------------------------
1 | /*
2 | * jQuery textarea suggest plugin
3 | *
4 | * Copyright (c) 2009-2010 Roman Imankulov
5 | *
6 | * Dual licensed under the MIT and GPL licenses:
7 | * http://www.opensource.org/licenses/mit-license.php
8 | * http://www.gnu.org/licenses/gpl.html
9 | *
10 | * Requires:
11 | * - jQuery (tested with 1.3.x and 1.4.x)
12 | * - jquery.a-tools >= 1.4.1 (http://plugins.jquery.com/project/a-tools)
13 | */
14 |
15 | /*globals jQuery,document */
16 |
17 | (function ($) {
18 | // workaround for Opera browser
19 | if (navigator.userAgent.match(/opera/i)) {
20 | $(document).keypress(function (e) {
21 | if ($.asuggestFocused) {
22 | $.asuggestFocused.focus();
23 | $.asuggestFocused = null;
24 | e.preventDefault();
25 | e.stopPropagation();
26 | }
27 | });
28 | }
29 |
30 | $.asuggestKeys = {
31 | UNKNOWN: 0,
32 | SHIFT: 16,
33 | CTRL: 17,
34 | ALT: 18,
35 | LEFT: 37,
36 | UP: 38,
37 | RIGHT: 39,
38 | DOWN: 40,
39 | DEL: 46,
40 | TAB: 9,
41 | RETURN: 13,
42 | ESC: 27,
43 | COMMA: 188,
44 | PAGEUP: 33,
45 | PAGEDOWN: 34,
46 | BACKSPACE: 8,
47 | SPACE: 32
48 | };
49 | $.asuggestFocused = null;
50 |
51 | $.fn.asuggest = function (suggests, options) {
52 | return this.each(function () {
53 | $.makeSuggest(this, suggests, options);
54 | });
55 | };
56 |
57 | $.fn.asuggest.defaults = {
58 | 'delimiters': '\n ',
59 | 'minChunkSize': 1,
60 | 'cycleOnTab': true,
61 | 'autoComplete': true,
62 | 'endingSymbols': ' ',
63 | 'stopSuggestionKeys': [$.asuggestKeys.RETURN, $.asuggestKeys.SPACE],
64 | 'ignoreCase': false
65 | };
66 |
67 | /* Make suggest:
68 | *
69 | * create and return jQuery object on the top of DOM object
70 | * and store suggests as part of this object
71 | *
72 | * @param area: HTML DOM element to add suggests to
73 | * @param suggests: The array of suggest strings
74 | * @param options: The options object
75 | */
76 | $.makeSuggest = function (area, suggests, options) {
77 | options = $.extend({}, $.fn.asuggest.defaults, options);
78 |
79 | var KEY = $.asuggestKeys,
80 | $area = $(area);
81 | $area.suggests = suggests;
82 | $area.options = options;
83 |
84 | /* Internal method: get the chunk of text before the cursor */
85 | $area.getChunk = function () {
86 | var delimiters = this.options.delimiters.split(''), // array of chars
87 | textBeforeCursor = this.val().substr(0, this.getSelection().start),
88 | indexOfDelimiter = -1,
89 | i,
90 | d,
91 | idx;
92 | for (i = 0; i < delimiters.length; i++) {
93 | d = delimiters[i];
94 | idx = textBeforeCursor.lastIndexOf(d);
95 | if (idx > indexOfDelimiter) {
96 | indexOfDelimiter = idx;
97 | }
98 | }
99 | if (indexOfDelimiter < 0) {
100 | return textBeforeCursor;
101 | } else {
102 | return textBeforeCursor.substr(indexOfDelimiter + 1);
103 | }
104 | };
105 |
106 | /* Internal method: get completion.
107 | * If performCycle is true then analyze getChunk() and and getSelection()
108 | */
109 | $area.getCompletion = function (performCycle) {
110 | var text = this.getChunk(),
111 | selectionText = this.getSelection().text,
112 | suggests = this.suggests,
113 | foundAlreadySelectedValue = false,
114 | firstMatchedValue = null,
115 | i,
116 | suggest;
117 | // search the variant
118 | for (i = 0; i < suggests.length; i++) {
119 | suggest = suggests[i];
120 | if ($area.options.ignoreCase) {
121 | suggest = suggest.toLowerCase();
122 | text = text.toLowerCase();
123 | }
124 | // some variant is found
125 | if (suggest.indexOf(text) === 0) {
126 | if (performCycle) {
127 | if (text + selectionText === suggest) {
128 | foundAlreadySelectedValue = true;
129 | } else if (foundAlreadySelectedValue) {
130 | return suggest.substr(text.length);
131 | } else if (firstMatchedValue === null) {
132 | firstMatchedValue = suggest;
133 | }
134 | } else {
135 | return suggest.substr(text.length);
136 | }
137 | }
138 | }
139 | if (performCycle && firstMatchedValue) {
140 | return firstMatchedValue.substr(text.length);
141 | } else {
142 | return null;
143 | }
144 | };
145 |
146 | $area.updateSelection = function (completion) {
147 | if (completion) {
148 | var _selectionStart = $area.getSelection().start,
149 | _selectionEnd = _selectionStart + completion.length;
150 | if ($area.getSelection().text === "") {
151 | if ($area.val().length === _selectionStart) { // Weird IE workaround, I really have no idea why it works
152 | $area.setCaretPos(_selectionStart + 10000);
153 | }
154 | $area.insertAtCaretPos(completion);
155 | } else {
156 | $area.replaceSelection(completion);
157 | }
158 | $area.setSelection(_selectionStart, _selectionEnd);
159 | }
160 | };
161 |
162 | $area.unbind('keydown.asuggest').bind('keydown.asuggest', function (e) {
163 | if (e.keyCode === KEY.TAB) {
164 | if ($area.options.cycleOnTab) {
165 | var chunk = $area.getChunk();
166 | if (chunk.length >= $area.options.minChunkSize) {
167 | $area.updateSelection($area.getCompletion(true));
168 | }
169 | e.preventDefault();
170 | e.stopPropagation();
171 | $area.focus();
172 | $.asuggestFocused = this;
173 | return false;
174 | }
175 | }
176 | // Check for conditions to stop suggestion
177 | if ($area.getSelection().length &&
178 | $.inArray(e.keyCode, $area.options.stopSuggestionKeys) !== -1) {
179 | // apply suggestion. Clean up selection and insert a space
180 | var _selectionEnd = $area.getSelection().end +
181 | $area.options.endingSymbols.length;
182 | var _text = $area.getSelection().text +
183 | $area.options.endingSymbols;
184 | $area.replaceSelection(_text);
185 | $area.setSelection(_selectionEnd, _selectionEnd);
186 | e.preventDefault();
187 | e.stopPropagation();
188 | this.focus();
189 | $.asuggestFocused = this;
190 | return false;
191 | }
192 | });
193 |
194 | $area.unbind('keyup.asuggest').bind('keyup.asuggest', function (e) {
195 | var hasSpecialKeys = e.altKey || e.metaKey || e.ctrlKey,
196 | hasSpecialKeysOrShift = hasSpecialKeys || e.shiftKey;
197 | switch (e.keyCode) {
198 | case KEY.UNKNOWN: // Special key released
199 | case KEY.SHIFT:
200 | case KEY.CTRL:
201 | case KEY.ALT:
202 | case KEY.RETURN: // we don't want to suggest when RETURN key has pressed (another IE workaround)
203 | break;
204 | case KEY.TAB:
205 | if (!hasSpecialKeysOrShift && $area.options.cycleOnTab) {
206 | break;
207 | }
208 | case KEY.ESC:
209 | case KEY.BACKSPACE:
210 | case KEY.DEL:
211 | case KEY.UP:
212 | case KEY.DOWN:
213 | case KEY.LEFT:
214 | case KEY.RIGHT:
215 | if (!hasSpecialKeysOrShift && $area.options.autoComplete) {
216 | $area.replaceSelection("");
217 | }
218 | break;
219 | default:
220 | if (!hasSpecialKeys && $area.options.autoComplete) {
221 | var chunk = $area.getChunk();
222 | if (chunk.length >= $area.options.minChunkSize) {
223 | $area.updateSelection($area.getCompletion(false));
224 | }
225 | }
226 | break;
227 | }
228 | });
229 | return $area;
230 | };
231 | }(jQuery));
232 |
--------------------------------------------------------------------------------