首先介绍下FineUI,FineUI 是基于 ExtJS 的专业 ASP.NET 2.0 控件库,FineUI的目标是创建 No JavaScript,No CSS,No UpdatePanel,No ViewState,No WebServices 的网站应用程序。如果你对FineUI还不熟悉的话,可以移步FineUI官方网站:http://fineui.com/
我们都知道FineUI是WebForm控件的集合,这也就意味着每次页面回发的代价比较大,需要重新构建页面中所有的控件并触发必要的事件。而对于自动补全这一常见功能来说,这种回发就显得没有必要了,因此我们可以通过一个ashx来取自动补全的数据。下面我们会通过一些例子详细演示如何在FineUI中集成jQuery UI的AutoComplete组件。
注:本文中的大部分例子和数据都来自jQuery UI官方网站。
示例一(内联数据):
这个例子的数据来自JavaScript,在文本框中任意输入一个字母,会出现一个选择编程语言的下拉列表,可以通过鼠标或者键盘选择需要的值,显示效果:
这个例子的完整代码如下:
1 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="inline.aspx.cs" Inherits="FineUI.Examples.autocomplete.inline" %>
2
3 <!DOCTYPE html>
4 <html>
5 <head runat="server">
6 <title></title>
7 <link href="../css/main.css" rel="stylesheet" type="text/css" />
8 <link rel="stylesheet" href="../jqueryui/css/ui-lightness/jquery-ui-1.9.2.custom.min.css" />
9 </head>
10 <body>
11 <form id="form1" runat="server">
12 <x:PageManager ID="PageManager1" runat="server" />
13 <x:SimpleForm ID="SimpleForm1" runat="server" Width="600px" BodyPadding="5px" EnableBackgroundColor="true"
14 Title="简单表单">
15 <Items>
16 <x:TextBox ID="TextBox1" runat="server" ShowLabel="false" EmptyText="输入字母 a 试试">
17 </x:TextBox>
18 </Items>
19 </x:SimpleForm>
20 </form>
21 <script src="../jqueryui/js/jquery-1.8.3.min.js" type="text/javascript"></script>
22 <script src="../jqueryui/js/jquery-ui-1.9.2.custom.min.js" type="text/javascript"></script>
23 <script type="text/javascript">
24
25 function onReady() {
26 var textbox1ID = '<%= TextBox1.ClientID %>';
27
28 var availableTags = [
29 "ActionScript",
30 "AppleScript",
31 "Asp",
32 "BASIC",
33 "C",
34 "C++",
35 "Clojure",
36 "COBOL",
37 "ColdFusion",
38 "Erlang",
39 "Fortran",
40 "Groovy",
41 "Haskell",
42 "Java",
43 "JavaScript",
44 "Lisp",
45 "Perl",
46 "PHP",
47 "Python",
48 "Ruby",
49 "Scala",
50 "Scheme"];
51
52 $('#' + textbox1ID).autocomplete({
53 source: availableTags
54 });
55
56 }
57
58 </script>
59 </body>
60 </html>
关键步骤:
- 首先在<head>标签中引入jQuery UI的CSS库;
- 在</form>标签后面引入jQuery和jQuery UI两个JavaScript库;
- 将所有实现代码放在 onReady 函数中,这个onReady函数会在所有的FineUI组件渲染完毕后由FineUI负责点调用;
- 通过 <%= TextBox1.ClientID %>
了解这些基本步骤后,后面的示例就轻松多了。
示例二(自动补全邮件地址):
很多邮件服务商或者邮件客户端都会提供这个功能,当你输入邮件前缀时会自动补全邮件后缀,显示效果如下:
关键代码如下:
1 function onReady() {
2 var textbox1ID = '<%= TextBox1.ClientID %>';
3
4 var availableTags = [
5 "qq.com",
6 "163.com",
7 "gmail.com",
8 "outlook.com",
9 "126.com",
10 "sina.com",
11 "yahoo.com",
12 "sohu.com",
13 "foxmail.com",
14 "live.com",
15 "mail.ustc.edu.cn"];
16
17
18 function getFullEmails(name) {
19 var emails = [];
20 for (var i = 0, count = availableTags.length; i < count; i++) {
21 emails.push(name + "@" + availableTags[i]);
22 }
23 return emails;
24 }
25
26 $('#' + textbox1ID).autocomplete({
27 source: function (request, response) {
28 if (request.term.indexOf('@') === -1) {
29 response(getFullEmails(request.term));
30 }
31 }
32 });
33
34 }
示例三(多行补全数据):
就是补全数据的每一项都显示标题和描述,可能还有其他信息,效果如下:
当选中一项时,可以把相关数据放到对应的文本输入框中:
关键代码:
1 function onReady() {
2 var textbox1ID = '<%= TextBox1.ClientID %>';
3 var textbox2ID = '<%= TextBox2.ClientID %>';
4 var textbox3ID = '<%= TextBox3.ClientID %>';
5
6 var projects = [
7 {
8 value: "jquery",
9 label: "jQuery",
10 desc: "the write less, do more, JavaScript library"
11 },
12 {
13 value: "jquery-ui",
14 label: "jQuery UI",
15 desc: "the official user interface library for jQuery"
16 },
17 {
18 value: "sizzlejs",
19 label: "Sizzle JS",
20 desc: "a pure-JavaScript CSS selector engine"
21 }
22 ];
23
24 $('#' + textbox1ID).autocomplete({
25 minLength: 0,
26 source: projects,
27 select: function (event, ui) {
28 var $this = $(this);
29 $this.val(ui.item.label);
30 $('#' + textbox2ID).val(ui.item.value);
31 $('#' + textbox3ID).val(ui.item.desc);
32 return false;
33 }
34 }).data("autocomplete")._renderItem = function (ul, item) {
35 return $("<li>").data("item.autocomplete", item)
36 .append("<a><span class='autocomplete-item-title'>" + item.label + "</span><br/>" + item.desc + "</a>")
37 .appendTo(ul);
38 };
39
40 }
代码中出现了一个自动的CSS类 autocomplete-item-title,因此还需要在 <head> 标签中加入CSS定义:
1 <style>
2 .autocomplete-item-title
3 {
4 font-weight: bold;
5 }
6 </style>
示例四(输入逗号分隔的多个值):
这个例子稍微有点复杂,不过都是jQuery UI的调用代码,并且代码中我都加上了中文注释,应该比较容易看懂:
1 function onReady() {
2 var textbox1ID = '<%= TextBox1.ClientID %>';
3
4 var availableTags = [
5 "ActionScript",
6 "AppleScript",
7 "Asp",
8 "BASIC",
9 "C",
10 "C++",
11 "Clojure",
12 "COBOL",
13 "ColdFusion",
14 "Erlang",
15 "Fortran",
16 "Groovy",
17 "Haskell",
18 "Java",
19 "JavaScript",
20 "Lisp",
21 "Perl",
22 "PHP",
23 "Python",
24 "Ruby",
25 "Scala",
26 "Scheme"
27 ];
28
29 // 将字符串 val 以逗号空格作为分隔符,分隔成数组
30 function split(val) {
31 return val.split(/,\s*/);
32 }
33
34 // 取得以逗号空格为分隔符的最后一个单词
35 // 比如,输入为 "C++, C#, JavaScript" 则输入出 "JavaScript"
36 function extractLast(term) {
37 return split(term).pop();
38 }
39
40 $('#' + textbox1ID).bind("keydown", function (event) {
41 // 通过 Tab 选择一项时,不会使当前文本框失去焦点
42 if (event.keyCode === $.ui.keyCode.TAB &&
43 $(this).data("autocomplete").menu.active) {
44 event.preventDefault();
45 }
46 }).autocomplete({
47 minLength: 0,
48 source: function (request, response) {
49 // 将最后一个单词作为输入值,从列表中过滤出备选项
50 response($.ui.autocomplete.filter(
51 availableTags, extractLast(request.term)));
52 },
53 focus: function () {
54 // 阻止某一项获得焦点时,更新文本框的值
55 return false;
56 },
57 select: function (event, ui) {
58 var terms = split(this.value);
59 // 移除用户正在输入项
60 terms.pop();
61 // 添加用户选择的项
62 terms.push(ui.item.value);
63 // 添加占位符,确保字符串的最后以逗号空格结束
64 terms.push("");
65 this.value = terms.join(", ");
66 return false;
67 }
68 });
69
70 }
示例五(远程服务器取数据,客户端缓存):
上面几个例子的自动补全数据全在JavaScript中,这个例子我们将从服务器获取数据,准备一个ashx文件:
1 using System;
2 using System.Collections.Generic;
3 using System.Web;
4 using Newtonsoft.Json;
5 using Newtonsoft.Json.Linq;
6
7 namespace FineUI.Examples.autocomplete
8 {
9 /// <summary>
10 /// search 的摘要说明
11 /// </summary>
12 public class search : IHttpHandler
13 {
14 private static readonly string[] LANGUAGES = new string[]{
15 "ActionScript",
16 "AppleScript",
17 "Asp",
18 "BASIC",
19 "C",
20 "C++",
21 "Clojure",
22 "COBOL",
23 "ColdFusion",
24 "Erlang",
25 "Fortran",
26 "Groovy",
27 "Haskell",
28 "Java",
29 "JavaScript",
30 "Lisp",
31 "Perl",
32 "PHP",
33 "Python",
34 "Ruby",
35 "Scala",
36 "Scheme"
37 };
38
39 public void ProcessRequest(HttpContext context)
40 {
41 //System.Threading.Thread.Sleep(2000);
42
43 String term = context.Request.QueryString["term"];
44 if (!String.IsNullOrEmpty(term))
45 {
46 term = term.ToLower();
47
48 JArray ja = new JArray();
49 foreach (string lang in LANGUAGES)
50 {
51 if (lang.ToLower().Contains(term))
52 {
53 ja.Add(lang);
54 }
55 }
56
57
58 context.Response.ContentType = "text/plain";
59 context.Response.Write(ja.ToString());
60 }
61
62 }
63
64 public bool IsReusable
65 {
66 get
67 {
68 return false;
69 }
70 }
71 }
72 }
这个 search.ashx 文件会根据传入的 term 参数,查询出符合条件的自动补全数据,并作为 JSON 数组的形式返回给jQuery UI的Autocomplete组件。
看下客户端的调用代码:
1 function onReady() {
2 var textbox1ID = '<%= TextBox1.ClientID %>';
3
4 var cache = {};
5
6 $('#' + textbox1ID).autocomplete({
7 minLength: 2,
8 source: function (request, response) {
9 var term = request.term;
10 if (term in cache) {
11 response(cache[term]);
12 return;
13 }
14
15 $.getJSON("search.ashx", request, function (data, status, xhr) {
16 cache[term] = data;
17 response(data);
18 });
19 }
20 });
21
22 }
需要说明的两点:
- 在JavaScript端声明了一个局部变量 var cache = {}; 用来缓存服务器端返回的数据,从而有效地提高性能。
- 通过 minLength 来限制自动补全所需的最小字符数。对于这个例子,如果只输入一个字符是不会出现自动补全下拉列表的。
最终的显示效果:
小结:
FineUI 经过4 年的发展,100多个版本的锤炼,目前已经相当的稳定。下一步我会尽可能多的考虑将更多的其他组件集成进来,包括前一段时间集成的 FCEditor、CKEditor以及百度的UEditor,让程序员能够把更多的精力放到业务实现上去,而不是纠结于技术细节,从而提供开发效率。
下载全部源代码:
这些例子最终会加入FineUI v3.2.3中(尚未发布),不过你现在就可以下载 FineUI 全部源代码,自己编译运行这些例子