-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathautocompletion.js
133 lines (133 loc) · 4.28 KB
/
autocompletion.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
(function($, window, document, undefined) {
"use strict";
var plugin_name = "autocompletion", defaults = {
caching: true,
container: '<div class="autocompletion"></div>',
item: '<p class="autocompletion-item"></p>',
source: []
};
function Plugin(element, options) {
this.options = $.extend({}, defaults, options);
this.customize = this.options.customize || this.customize;
this.fill = this.options.fill || this.fill;
this.$container = $(this.options.container);
this.$element = $(element);
this._attr_value = "data-item-value";
this._cache = {};
this._class_current = "current";
this._defaults = defaults;
this._name = plugin_name;
this.init();
}
Plugin.prototype = {
init: function() {
this.bind();
},
bind: function() {
var that = this, item_selector = "[" + this._attr_value + "]";
this.$element.on("blur", $.proxy(this.blur, this)).on("keyup", $.proxy(this.keyup, this));
this.$container.on("mouseenter", function() {
that.mousein = true;
}).on("mouseleave", function() {
that.mousein = false;
}).on("mouseenter", item_selector, function(e) {
that.$container.find("." + that._class_current).removeClass(that._class_current);
$(e.currentTarget).addClass(that._class_current);
}).on("click", item_selector, $.proxy(this.click, this));
},
blur: function() {
// Hide only when cursor outside of the container.
// This is to ensure that the browser did not hide container before the clue clicked.
if (!this.mousein) {
this.hide();
}
},
keyup: function() {
this.q = this.$element.val();
this.q_lower = this.q.toLowerCase();
if (!this.q) {
return this.hide();
}
if (this.options.caching && this._cache[this.q_lower]) {
// pass to render method directly
this.render(this._cache[this.q_lower]);
} else if ($.isFunction(this.options.source)) {
// if it's a function, then run it and pass context
this.options.source(this.q, $.proxy(this.suggest, this));
} else {
this.suggest(this.options.source);
}
},
click: function(e) {
e.stopPropagation();
e.preventDefault();
this.select();
},
suggest: function(items) {
var that = this,
filtered_items = $.grep(items, function(item) {
return item.toLowerCase().indexOf(that.q_lower) !== -1;
});
// cache if needed
if (this.options.caching) {
this._cache[this.q_lower] = filtered_items;
}
this.render(filtered_items);
},
render: function(items) {
if (!items.length) {
return this.hide();
}
var that = this,
items_dom = $.map(items, function(item) {
return $(that.options.item).attr(that._attr_value, item).html(that.highlight(item))[0];
}), position = this.$element.position();
// render container body
this.customize(this.$container.css({
left: position.left + "px",
top: position.top + this.$element.outerHeight() + "px"
}).html(items_dom)[0]);
this.$container.insertAfter(this.$element);
this.show();
},
highlight: function(item) {
var q = this.q.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
return item.replace(new RegExp("(" + q + ")", "ig"), function($1, match) {
return "<strong>" + match + "</strong>";
});
},
customize: function(clues) {
return;
},
select: function() {
var $el = this.$container.find("." + this._class_current),
value = $.proxy(this.fill, $el[0], $el.attr(this._attr_value), $.proxy(this.hide, this))();
if (value) {
this.hide();
this.$element.val().change();
}
},
fill: function(value) {
return value;
},
show: function() {
if (!this.visible) {
this.visible = true;
this.$container.show();
}
},
hide: function() {
if (this.visible) {
this.visible = false;
this.$container.hide();
}
}
};
$.fn[plugin_name] = function(options) {
return this.each(function() {
if (!$.data(this, "plugin_" + plugin_name)) {
$.data(this, "plugin_" + plugin_name, new Plugin(this, options));
}
});
};
})(jQuery, window, document);