Import source for “1.7.1” from upstream tarball.
[debian_jquery-textcomplete.git] / src / adapter.js
blob858f256f67ff271d1e7177d3550cb3f1de52a07a
1 +function ($) {
2 'use strict';
4 var now = Date.now || function () { return new Date().getTime(); };
6 // Returns a function, that, as long as it continues to be invoked, will not
7 // be triggered. The function will be called after it stops being called for
8 // `wait` msec.
9 //
10 // This utility function was originally implemented at Underscore.js.
11 var debounce = function (func, wait) {
12 var timeout, args, context, timestamp, result;
13 var later = function () {
14 var last = now() - timestamp;
15 if (last < wait) {
16 timeout = setTimeout(later, wait - last);
17 } else {
18 timeout = null;
19 result = func.apply(context, args);
20 context = args = null;
24 return function () {
25 context = this;
26 args = arguments;
27 timestamp = now();
28 if (!timeout) {
29 timeout = setTimeout(later, wait);
31 return result;
35 function Adapter () {}
37 $.extend(Adapter.prototype, {
38 // Public properties
39 // -----------------
41 id: null, // Identity.
42 completer: null, // Completer object which creates it.
43 el: null, // Textarea element.
44 $el: null, // jQuery object of the textarea.
45 option: null,
47 // Public methods
48 // --------------
50 initialize: function (element, completer, option) {
51 this.el = element;
52 this.$el = $(element);
53 this.id = completer.id + this.constructor.name;
54 this.completer = completer;
55 this.option = option;
57 if (this.option.debounce) {
58 this._onKeyup = debounce(this._onKeyup, this.option.debounce);
61 this._bindEvents();
64 destroy: function () {
65 this.$el.off('.' + this.id); // Remove all event handlers.
66 this.$el = this.el = this.completer = null;
69 // Update the element with the given value and strategy.
71 // value - The selected object. It is one of the item of the array
72 // which was callbacked from the search function.
73 // strategy - The Strategy associated with the selected value.
74 select: function (/* value, strategy */) {
75 throw new Error('Not implemented');
78 // Returns the caret's relative coordinates from body's left top corner.
79 getCaretPosition: function () {
80 var position = this._getCaretRelativePosition();
81 var offset = this.$el.offset();
83 // Calculate the left top corner of `this.option.appendTo` element.
84 var $parent = this.option.appendTo;
85 if ($parent) {
86 if (!($parent instanceof $)) { $parent = $($parent); }
87 var parentOffset = $parent.offsetParent().offset();
88 offset.top -= parentOffset.top;
89 offset.left -= parentOffset.left;
92 position.top += offset.top;
93 position.left += offset.left;
94 return position;
97 // Focus on the element.
98 focus: function () {
99 this.$el.focus();
102 // Private methods
103 // ---------------
105 _bindEvents: function () {
106 this.$el.on('keyup.' + this.id, $.proxy(this._onKeyup, this));
109 _onKeyup: function (e) {
110 if (this._skipSearch(e)) { return; }
111 this.completer.trigger(this.getTextFromHeadToCaret(), true);
114 // Suppress searching if it returns true.
115 _skipSearch: function (clickEvent) {
116 switch (clickEvent.keyCode) {
117 case 9: // TAB
118 case 13: // ENTER
119 case 40: // DOWN
120 case 38: // UP
121 case 27: // ESC
122 return true;
124 if (clickEvent.ctrlKey) switch (clickEvent.keyCode) {
125 case 78: // Ctrl-N
126 case 80: // Ctrl-P
127 return true;
132 $.fn.textcomplete.Adapter = Adapter;
133 }(jQuery);