jquery-textcomplete
Version:
[](http://badge.fury.io/js/jquery-textcomplete) [](http://badge.fury.io/bo/jquery-textcomplete) [ • 3.74 kB
JavaScript
+function ($) {
'use strict';
var now = Date.now || function () { return new Date().getTime(); };
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
// `wait` msec.
//
// This utility function was originally implemented at Underscore.js.
var debounce = function (func, wait) {
var timeout, args, context, timestamp, result;
var later = function () {
var last = now() - timestamp;
if (last < wait) {
timeout = setTimeout(later, wait - last);
} else {
timeout = null;
result = func.apply(context, args);
context = args = null;
}
};
return function () {
context = this;
args = arguments;
timestamp = now();
if (!timeout) {
timeout = setTimeout(later, wait);
}
return result;
};
};
function Adapter () {}
$.extend(Adapter.prototype, {
// Public properties
// -----------------
id: null, // Identity.
completer: null, // Completer object which creates it.
el: null, // Textarea element.
$el: null, // jQuery object of the textarea.
option: null,
// Public methods
// --------------
initialize: function (element, completer, option) {
this.el = element;
this.$el = $(element);
this.id = completer.id + this.constructor.name;
this.completer = completer;
this.option = option;
if (this.option.debounce) {
this._onKeyup = debounce(this._onKeyup, this.option.debounce);
}
this._bindEvents();
},
destroy: function () {
this.$el.off('.' + this.id); // Remove all event handlers.
this.$el = this.el = this.completer = null;
},
// Update the element with the given value and strategy.
//
// value - The selected object. It is one of the item of the array
// which was callbacked from the search function.
// strategy - The Strategy associated with the selected value.
select: function (/* value, strategy */) {
throw new Error('Not implemented');
},
// Returns the caret's relative coordinates from body's left top corner.
getCaretPosition: function () {
var position = this._getCaretRelativePosition();
var offset = this.$el.offset();
// Calculate the left top corner of `this.option.appendTo` element.
var $parent = this.option.appendTo;
if ($parent) {
if (!($parent instanceof $)) { $parent = $($parent); }
var parentOffset = $parent.offsetParent().offset();
offset.top -= parentOffset.top;
offset.left -= parentOffset.left;
}
position.top += offset.top;
position.left += offset.left;
return position;
},
// Focus on the element.
focus: function () {
this.$el.focus();
},
// Private methods
// ---------------
_bindEvents: function () {
this.$el.on('keyup.' + this.id, $.proxy(this._onKeyup, this));
},
_onKeyup: function (e) {
if (this._skipSearch(e)) { return; }
this.completer.trigger(this.getTextFromHeadToCaret(), true);
},
// Suppress searching if it returns true.
_skipSearch: function (clickEvent) {
switch (clickEvent.keyCode) {
case 9: // TAB
case 13: // ENTER
case 40: // DOWN
case 38: // UP
case 27: // ESC
return true;
}
if (clickEvent.ctrlKey) switch (clickEvent.keyCode) {
case 78: // Ctrl-N
case 80: // Ctrl-P
return true;
}
}
});
$.fn.textcomplete.Adapter = Adapter;
}(jQuery);