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
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
;
16 timeout
= setTimeout(later
, wait
- last
);
19 result
= func
.apply(context
, args
);
20 context
= args
= null;
29 timeout
= setTimeout(later
, wait
);
35 function Adapter () {}
37 $.extend(Adapter
.prototype, {
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.
50 initialize: function (element
, completer
, option
) {
52 this.$el
= $(element
);
53 this.id
= completer
.id
+ this.constructor.name
;
54 this.completer
= completer
;
57 if (this.option
.debounce
) {
58 this._onKeyup
= debounce(this._onKeyup
, this.option
.debounce
);
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
;
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
;
97 // Focus on the element.
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
) {
124 if (clickEvent
.ctrlKey
) switch (clickEvent
.keyCode
) {
132 $.fn
.textcomplete
.Adapter
= Adapter
;