jiapeng 8 years ago
parent
commit
d314e417d4
6 changed files with 376 additions and 9 deletions
  1. 5 5
      css/common.css
  2. 2 2
      html/model/sys/user/index.html
  3. 68 0
      html/test.html
  4. 6 1
      js/codehtml.js
  5. 2 1
      js/model/sys/user/index.js
  6. 293 0
      js/typeahead.js

+ 5 - 5
css/common.css

@ -2152,7 +2152,7 @@ a cite {
2152 2152
2153 2153
.form-item.select {}
2154 2154
2155
.form-item > a.dd-hand, .form-item.text > input, .form-item.textarea > textarea {
2155
.form-item > a.dd-hand, .form-item.typeahead>input,.form-item.text > input, .form-item.textarea > textarea {
2156 2156
    display: block;
2157 2157
    width: 100%;
2158 2158
    padding: 6px 6px;
@ -2177,11 +2177,11 @@ a cite {
2177 2177
    transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
2178 2178
}
2179 2179
2180
.form-item.invalid > a.dd-hand, .form-item.text.invalid > input, .form-item.textarea.invalid > textarea {
2180
.form-item.invalid > a.dd-hand,.form-item.typeahead.invalid > input, .form-item.text.invalid > input, .form-item.textarea.invalid > textarea {
2181 2181
	border: 1px solid red;
2182 2182
}
2183 2183
2184
.form-item.select > a.dd-hand, .form-item.text > input, .form-item.date > a.dd-hand {
2184
.form-item.select > a.dd-hand, .form-item.typeahead > input, .form-item.text > input, .form-item.date > a.dd-hand {
2185 2185
    height: 34px;
2186 2186
    white-space: nowrap;
2187 2187
}
@ -2273,7 +2273,7 @@ a cite {
2273 2273
    content: '\e64e';
2274 2274
}
2275 2275
2276
.form-item .dd-drop .select-item {
2276
.form-item .dd-drop .select-item{
2277 2277
    display: list-item;
2278 2278
    cursor: pointer;
2279 2279
    padding: 5px 10px;
@ -2286,7 +2286,7 @@ a cite {
2286 2286
    -webkit-touch-callout: none;
2287 2287
}
2288 2288
2289
.form-item .dd-drop .select-item:hover {
2289
.form-item .dd-drop .select-item:hover,.form-item .dd-drop .select-item.active {
2290 2290
    color: #fff;
2291 2291
    background-color: #3280fc;
2292 2292
}

+ 2 - 2
html/model/sys/user/index.html

@ -6,9 +6,9 @@
6 6
		<div class="row">
7 7
			<div class="col-2 item-caption">名称</div>
8 8
			<div class="col-4">
9
				<div class="form-item text" defVal="" name="name"></div>
9
				<div class="form-item text trim " defVal="" name="name"></div>
10 10
			</div>
11
			<div class="col-2 item-caption ">是否有效</div>
11
			<div class="col-2 item-caption">是否有效</div>
12 12
			<div class="col-4">
13 13
				<div class="form-item select bool" dictCode="bool" defVal="" name="actived"></div>
14 14
			</div>

+ 68 - 0
html/test.html

@ -0,0 +1,68 @@
1
<!DOCTYPE html>
2
<html>
3

4
	<head>
5
		<meta charset="utf-8" />
6
		<meta http-equiv="X-UA-Compatible" content="IE=edge" />
7
		<title></title>
8
		<link href="../css/common.css" rel="stylesheet" type="text/css" />
9
		<style>
10

11
		</style>
12
	</head>
13

14
	<body>
15
		<div class="container dt-form">
16
			<div class="row">
17
				<div class="col-2 item-caption">名称</div>
18
				<div class="col-4">
19
					<div class="form-item text trim " defVal="" name="name"></div>
20
				</div>
21
				<div class="col-2 item-caption">是否有效</div>
22
				<div class="col-4">
23
					<div class="form-item typeahead" uri="../ajax/test/typeahead?s=15&q=" name="qq"></div>
24
				</div>
25
			</div>
26
		</div>
27

28
		<div id='g_info'>
29
			<div id='g_err'></div>
30
			<div id='g_warn'></div>
31
			<div id='g_msg'></div>
32
		</div>
33
		<div id='g_loading' style="display: none;">
34
			<div>
35
				<i class='icon icon-spin icon-spinner-snake'></i>
36
			</div>
37
		</div>
38

39
	</body>
40
	<script type="text/javascript" src="../js/jquery-1.12.4.js"></script>
41
	<script type="text/javascript" src="../js/common.js"></script>
42
	<script type="text/javascript" src="../js/form.js"></script>
43
	<script type="text/javascript" src="../js/dict.js"></script>
44
	<script type="text/javascript" src="../js/text.js"></script>
45
	<script type="text/javascript" src="../js/textarea.js"></script>
46
	<script type="text/javascript" src="../js/dropdown.js"></script>
47
	<script type="text/javascript" src="../js/select.js"></script>
48
	<script type="text/javascript" src="../js/date.js"></script>
49
	<script type="text/javascript" src="../js/pager.js"></script>
50
	<script type="text/javascript" src="../js/codehtml.js"></script>
51
	<script type="text/javascript" src="../js/datagrid.js"></script>
52
	<script type="text/javascript" src="../js/pageDataGrid.js"></script>
53
	<script type="text/javascript" src="../js/spa.js"></script>
54
	<script type="text/javascript" src="../js/upload.js"></script>
55
	<script type="text/javascript" src="../js/dyn-select.js"></script>
56
	<script type="text/javascript" src="../js/validate.js"></script>
57
	<script type="text/javascript" src="../js/typeahead.js"></script>
58

59
	<script>
60
		$(function() {
61
			$.use(["spa", "util", "form"], function(spa, util, fb) {
62
				fb.build($(".dt-form"));
63

64
			});
65
		});
66
	</script>
67

68
</html>

+ 6 - 1
js/codehtml.js

@ -18,7 +18,12 @@ $.define(["jQuery", "doc", "body", "util"], "code", function($, doc, $body, util
18 18
				var v = env.cd;
19 19
				if(v) v = this.k ? v[this.k] : v;
20 20
				if(v) return v;
21
				return "";
21
				return 0===v?"0":"";
22
			},
23
			"cp":function(env){
24
				var v = env.cd;
25
				if(v) return v;
26
				return 0===v?"0":"";
22 27
			},
23 28
			"_index": function(env) {
24 29
				return env.ci+1;

+ 2 - 1
js/model/sys/user/index.js

@ -1,10 +1,11 @@
1 1
;
2 2
spa_define(function() {
3
	return $.use(["spa", "pagedatagrid", "util"], function(spa, pdgf, util) {
3
	return $.use(["spa", "pagedatagrid", "util", "validate"], function(spa, pdgf, util, validate) {
4 4
		return {
5 5
			main: function() {
6 6
				var root = spa.findInMain(".sys_user_index");
7 7
				var pdg = pdgf.build(root);
8
//				validate.form(pdg.form, { name: { required: "not null", len: { val: 5, msg: "我的中国心" } } });
8 9
				root.find(".opt-query").on("click", function() {
9 10
					pdg.load();
10 11
				});

+ 293 - 0
js/typeahead.js

@ -0,0 +1,293 @@
1
$.use(["jQuery", "form", "doc", "util", "dropdown", "code"], function($, form, doc, util, dd, code) {
2
	var m_rd = "必选的",
3
		modelName = 'typeahead',
4
		placeholder = "placeholder",
5
		required = "required",
6
		typeahead = function() {
7
			this.ve = null;
8
			this.minLength = 1;
9
			this.maxShowCount = 10;
10
			this.keyPressInterval = 500;
11
			this.caption = "";
12
			this.autoselect = true;
13
		};
14
	typeahead.prototype = defCfg = {};
15

16
	defCfg.source = function(query, hand) {
17
	//	console.log("source:" + query)
18
		var self = this;
19
		this.lastQuerying = query;
20
		setTimeout(function() {
21
			if((query === self.lastQuerying) && (query !== self.lastQueryed)) {
22
				self.doQuery(query, hand);
23
			}
24
		}, this.keyPressInterval || 500);
25
	};
26
	defCfg.doQuery = function(query, hand) {
27
		var self = this;
28
		this.lastQueryed = query;
29
	//	console.log("doQuery:" + query);
30
		util.get(this.quri + encodeURIComponent(query), null, function(data) {
31
			if(self.lastQueryed === query) {
32
				if(self.transfer) {
33
					data = self.transfer(data);
34
				}
35
//				console.log("doHand:" + query);
36
				hand(data);
37
			}
38
		}, this.ajaxEH, this.ajaxCfg);
39
	};
40
	defCfg.blur = function() {
41
		var self = this;
42
		setTimeout(function() {
43
			self.hide();
44
		}, 150);
45
	};
46
	defCfg.keydown = function(e) {
47
		this.suppressKeyPressRepeat = [40, 38, 9, 13, 27].indexOf(e.keyCode) >= 0;
48
		this.move(e);
49
	};
50
	defCfg.move = function(e) {
51
		if(!this.shown) return;
52
		switch(e.keyCode) {
53
			case 9: // tab
54
			case 13: // enter
55
			case 27: // escape
56
				e.preventDefault();
57
				break;
58
			case 38: // up arrow
59
				e.preventDefault();
60
				this.prev();
61
				break;
62
			case 40: // down arrow
63
				e.preventDefault();
64
				this.next();
65
				break;
66
		}
67
		e.stopPropagation();
68
	};
69
	defCfg.keypress = function(e) {
70
		if(this.suppressKeyPressRepeat) return;
71
		this.move(e);
72
	};
73
	defCfg.keyup = function(e) {
74
		var self = this;
75
		switch(e.keyCode) {
76
			case 40: // down arrow
77
			case 38: // up arrow
78
				break;
79
			case 9: // tab
80
			case 13: // enter
81
				if(!self.shown) return;
82
				self.select();
83
				break;
84
			case 27: // escape
85
				if(!self.shown) return;
86
				self.hide();
87
				break;
88
			default:
89
				self.lookup();
90
		}
91
		e.stopPropagation();
92
		e.preventDefault();
93
	};
94
	defCfg.click = function(e) {
95
		e.stopPropagation();
96
		e.preventDefault();
97
		this.select();
98
	};
99
	defCfg.mouseenter = function(e) {
100
		this.ctn.find('.active').removeClass('active');
101
		$(e.currentTarget).addClass('active');
102
	};
103
	defCfg.prev = function(e) {
104
		var active = this.ctn.find('.active').removeClass('active');
105
		var prev = active.prev();
106
		if(!prev.length) {
107
			prev = this.ctn.find('li').last();
108
		}
109
		prev.addClass('active');
110
	};
111
	defCfg.next = function(e) {
112
		var active = this.ctn.find('.active').removeClass('active');
113
		var next = active.next();
114
		if(!next.length) {
115
			next = this.ctn.find('li').first();
116
		}
117
		next.addClass('active');
118
	};
119
	defCfg.render = function(items) {
120
		var lis = [];
121
		items.forEach(function(item) {
122
			var pc = String(item.code || item);
123
			var pt = String(item.caption || item);
124

125
			lis.push({
126
				tn: "li",
127
				attrs: [{
128
					an: "code",
129
					av: pt
130
				}, {
131
					an: "caption",
132
					av: pt
133
				}, {
134
					an: "class",
135
					av: "select-item"
136
				}],
137
				chs: [pt]
138
			});
139
		});
140
		if(this.autoselect) {
141
			lis[0].attrs[2].av = " active select-item";
142
		}
143
		this.menu.empty();
144
		util.appendChild(this.menu[0], lis);
145
		return this;
146
	};
147
	defCfg.lookup = function(event) {
148
		var self = this;
149
		console.log("lookup")
150
		self.query = self.ve.val();
151

152
		if(!self.query || self.query.length < self.minLength) {
153
			return self.shown ? self.hide() : self
154
		}
155

156
		if(self.source instanceof Function) {
157
			self.source(self.query, function() {
158
				self.process.apply(self, arguments);
159
			});
160
		} else {
161
			self.process(self.source);
162
		}
163

164
		return self;
165
	};
166
	defCfg.process = function(items) {
167
		if(items && items.length) {
168
			this.render(items.slice(0, this.maxShowCount));
169
			this.show();
170
		}
171
	};
172
	defCfg.show = function() {
173
		this.shown = true;
174
		this.ctn.addClass("open");
175
	};
176
	defCfg.hide = function() {
177
		this.shown = false;
178
		this.ctn.removeClass("open");
179
		var v = this.ve.val();
180
		if(v) {
181
			if(v !== this.caption) {
182
				this.ve.val(this.caption);
183
			}
184
		} else {
185
			this.rv = "";
186
			this.caption = "";
187
		}
188
		this.lastQuerying = null;
189
		this.lastQueryed = null;
190
	};
191
	defCfg.select = function() {
192
		if(this.shown) {
193
			var item = this.menu.find(".active");
194
			this.rv = item.attr('code');
195
			this.caption = item.attr("caption");
196
			this.ve.val(this.caption);
197
			return this.hide();
198
		}
199
	};
200
	defCfg.init = function($e) {
201
		var self = this;
202
		this.ctn = $e;
203
		var ve = $e.children(".dd-drop");
204
		if(ve.length && ve.children("ul").length === 1) {
205
			var rc = code.parseCode(ve);
206
			rc.empty();
207
			this.render = function(items) {
208
				rc.val(items);
209
			}
210
		} else {
211
			$("<div class='dd-drop'><ul></ul></div>").appendTo($e);
212
		}
213
		this.menu = $e.find(".dd-drop>ul");
214
		ve = this.ve = $("<input type='text'/>");
215
		var tmp = $e.attr(placeholder);
216
		if(tmp) ve.attr(placeholder, tmp);
217
		$e.addClass("dd-ctn").append(ve).removeClass("dd-clean");
218
		this.shown = false;
219
		this.quri = this.quri || $e.attr("uri");
220
		this.minLength == this.minLength || parseInt($e.attr("minQueryLen") || "1");
221
		this.maxShowCount = this.maxShowCount || parseInt($e.attr("minQueryLen") || "1");
222
		this.keyPressInterval = this.keyPressInterval || parseInt($e.attr("keyPressInterval") || "500");
223
		ve.on("blur", function(e) {
224
			self.blur(e);
225
		});
226
		ve.on("keypress", function(e) {
227
			self.keypress(e);
228
		});
229
		ve.on("keyup", function(e) {
230
			self.keyup(e);
231
		});
232
		ve.on("keydown", function(e) {
233
			self.keydown(e);
234
		});
235
		$e.children(".dd-drop").on("click", function(e) {
236
			self.click(e);
237
		});
238
		$e.children(".dd-drop").on("mouseenter", "li", function(e) {
239
			self.mouseenter(e);
240
		});
241
	};
242

243
	form.register(function($e, options) {
244
		var cls = util.classCheck($e[0], [modelName, required]),
245
			config;
246
		if(cls[modelName]) {
247
			var n = $e.attr("name") || $e.attr("id"),
248
				ve, rules = [];
249
			if(!n) {
250
				throw "Attribute[name] is invalid";
251
			}
252
			config = $.extend(new typeahead(), options ? options[n] || {} : {});
253
			config.dv = $e.attr("defVal") || "";
254
			config.rv = config.dv;
255
			if(!config.rules) {
256
				config.rules = [];
257
			}
258
			config.init($e);
259
			return {
260
				name: n,
261
				get: function() {
262
					return config.rv;
263
				},
264
				set: function(data) {
265
					config.rv = data;
266
				},
267
				validate: function() {
268
					if(cls[required]) {
269
						if(!config.rv) {
270
							this.invalid(m_rd);
271
							return m_rd;
272
						}
273
					}
274
					return util.validate(config.rules, this);
275
				},
276
				addRules: function(rule) {
277
					util.addRules(config.rules, rule);
278
				},
279
				reset: function() {
280
					this.set(dv);
281
				},
282
				valid: function() {
283
					util.valid($e);
284
				},
285
				invalid: function(reson) {
286
					util.invalid($e);
287
					util.error(reson);
288
				}
289
			};
290
		}
291

292
	});
293
});