forked from RubyLouvre/avalon
-
Notifications
You must be signed in to change notification settings - Fork 0
/
avalon.autocomplete.js
134 lines (126 loc) · 5.48 KB
/
avalon.autocomplete.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
134
define(["avalon"], function(avalon) {
var defaults = {
items: 8
}
avalon.ui.autocomplete = function(element, id, vmodels, opts) {
var $element = avalon(element),
refreshList,
tempValue = "",
model
//处理配置
var options = avalon.mix({}, defaults, opts, $element.data())
var source = options.source || []
var sourceList = document.createElement("div")
sourceList.innerHTML = '<ul class="ui-autocomplete ui-front ui-menu ui-widget ui-widget-content ui-corner-all" ms-each-presentation="matcher" ms-visible="show" >' +
'<li class="ui-menu-item" ><a class="ui-corner-all" tabindex="-1" ms-mouseover="get" ms-hover="ui-state-focus" ms-class="ui-state-focus:matcher[selectedIndex] === presentation " >{{presentation}}</a></li>' +
'</ul>'
for (var i = 0, node; node = element.attributes[i++]; ) {
var name = node.name
if (name.indexOf("ms-ui") === 0) {
element.removeAttribute(name)//防止死循环
break
}
}
sourceList = sourceList.firstChild
$element.bind("blur", function() {
setTimeout(function() {
refreshList = model.show = false //隐藏datalist
}, 250)
})
avalon.bind(sourceList, "click", function() {
model.value = model.overvalue
})
$element.bind("keyup", function(e) {
if (/\w/.test(String.fromCharCode(e.which))) { //如果是字母数字键
refreshList = true //这是方便在datalist显示时,动态刷新datalist
model.value = element.value //触发$watch value回调
} else {
refreshList = false
switch (e.which) {
case 8:
refreshList = true//回退键可以引发列表刷新
break
case 13:
tempValue = model.value
refreshList = model.show = false
break
case 38:
// up arrow
--model.selectedIndex
if (model.selectedIndex === -2) {
model.selectedIndex = model.matcher.length - 1
}
var value = model.matcher[model.selectedIndex]
model.value = value === void 0 ? tempValue : value
break
case 40:
// down arrow
++model.selectedIndex
if (model.selectedIndex === model.matcher.length) {
model.selectedIndex = -1
}
var value = model.matcher[model.selectedIndex]
model.value = value === void 0 ? tempValue : value
break
}
}
})
model = avalon.define(id, function(vm) {
vm.show = false
vm.selectedIndex = -1
vm.value = element.value
vm.matcher = []
vm.overvalue = ""
vm.get = function() {
vm.overvalue = this.$vmodel.presentation
}
vm.$watch("value", function(value) {
if (refreshList !== false) { //flagKeyup是控制datalist的刷新
model.show = true
tempValue = value
var lower = []
var matcher = source.filter(function(el) {
if (el.indexOf(value) === 0) {
return el //最精确
}
if (el.toLowerCase().indexOf(value.toLowerCase()) === 0) {
lower.push(el) //不区分大小写
}
})
lower = matcher.concat(lower)
var query = value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&')
var strongRegExp = new RegExp('(' + query + ')', 'ig')
if (lower.length) {
vm.matcher = lower.slice(0, options.items)
} else { //模糊匹配,只要它中间有这些字母就行
vm.matcher = source.filter(function(el) {
return strongRegExp.test(el)
})
}
}
})
})
avalon.ready(function() {
// console.log(model)
element.setAttribute("ms-duplex", "value")
document.body.appendChild(sourceList)
adjustPosition()
var models = [model].concat(vmodels)
avalon.scan(element, models)
avalon.scan(sourceList, models)
})
function adjustPosition() {
var offset = $element.offset()
sourceList.style.width = element.clientWidth + "px"
sourceList.style.left = offset.left + "px"
sourceList.style.top = offset.top + element.offsetHeight + "px"
sourceList.style.zIndex = 9999
if (avalon(document).height() - 200 > offset.top) {
var pageY = sourceList.offsetHeight + parseFloat(sourceList.style.top)
window.scrollTo(pageY + 50, 0)
}
}
$element.bind("focus", adjustPosition)
}
return avalon
})