1、第十章:输入前提示,输入前提示 在客户端缓存搜索结果 Rico库 Prototype库 Javascript apply()函数 将组件参数化,10.1考察输入前提示应用,由于Ajax变得越来越流行,输入前提示已经成为最受欢迎的程序之一,人们在创建输入前提示功能时,大量的解决方案存在缺陷,部分存在过度设计的问题。,10.1.1输入前提示的常见特征,1、在页面中输入字符 2、输入前提示功能发送请求到服务器 3、服务器返回数据给客户端 4、客户端得到数据并将结果显示在表格、层、文本框或其他格式中。,存在的问题:,1、每次按键都回送 2、没有数据缓存 3、56k的调制解调器 4、返回太多的结果 5、
2、界面太华丽 6、快速的打字员,10.1.2 Google Suggest,将显示结果限制为10条 使用定时器来为快速打字员计数,10.1.3实战开发Ajax输入前提示,该输入前提示功能将努力限制对于服务器的影响,小型网站没有均衡设备和多台服务器,节约带宽,降低成本。 仅仅在需要更新数据库时才会访问服务器。 客户端和服务器端使用一脚本为中心的交互,服务器返回的是文本+识别字段。,10.2 服务器端框架:C#,服务器、数据库和客户端。 利用XMLHttpRequest从客户端发送一个请求到服务器,查询数据库动态创建一个文档(包括JavaScript代码和包含数据的数组)。 见 typeAheadD
3、ata.aspx.cs,10.2.2 测试服务器端代码,测试方法: 从客户端发送一个请求。 在服务器端采用硬编码的方式。 string strQuery =“a”; string strAny = “%“;,10.3 客户端框架,客户端的框架包括Ajax的XMLHttpRequest对象和大量的DHTML。,10.3.1 HTML, AutoComplete Text Box: 关闭自动完成功能 txtIgnore的存在防止按回车键提交表单 txtUserValue获得输入的值,10.3.2 JavaScript,主要任务: 1、监控键盘和鼠标的行为 2、向服务器发送数据,并且从服务器接收数据
4、 3、生成用户可以交互的HTML内容,监视按键 加载文本和JavaScript代码 创建提示列表 为输入字母加上下划线,1、添加外部的JavaScript文件,2、输出span元素,使用页面的onload事件处理函数将span元素动态的添加到页面中,这样可以避免每次想要使用脚本时不得不手工将标签添加到页面中。 为span添加了样式CSS类,通过设置和改变display属性可以隐藏和显示span.,3、将输入前提示功能分配给文本框,为了解决在多个表单中使用输入前提示功能,应该开发出为不同元素分配不同属性的方法。需要定制一个对象,见 SetProperties()函数的定义。,SetPropert
5、ies(xElem,xHidden,xserverCode,xignoreCase,xmatchAnywhere,xmatchTextBoxWidth,xshowNoMatchMessage,xnoMatchingDataMessage,xuseTimeout, xtheVisibleTime),xElem:要分配输入前提示功能的文本框。 xHidden:保存值的hedden元素。 xserverCode:服务器的地址。 xignoreCase:忽略大小写的布尔值。 xmatchAnywhere:在字符串中匹配任意位置的文本的布尔值。 xmatchTextBoxWidth:匹配文本框宽度的布尔
6、值。 xshowNoMatchMessage:显示无匹配消息的布尔值。 xnoMatchingDataMessage:显示的消息。 xuseTimeout:显示一段时间是否隐藏。 xtheVisibleTime:保持打开的时间。,document.Form1.txtUserInput.obj =SetProperties(document.Form1.txtUserInput,document.Form1.txtUserValue,typeAheadXML.aspx,true,true,true,true, “No matchingData“,false,null);,4、事件处理函数,为了能
7、够为输入前提示功能确定用户在文本框中的操作,需要为表单添加事件处理函数,主要是键盘的输入和用户是否离开了文本字段。,Var isOpera=(navigator.userAgent.toLowerCase().indexOf(“opera“)!= -1);function AddHandler(objText)objText.onkeyup = GiveOptions;objText.onblur = function()if(this.obj.useTimeout)StartTimeout();if(isOpera)objText.onkeypress =GiveOptions;,5、处理用
8、户按键,GiveOptions()函数在按键事件触发时会被调用,根据按下的键确定需要执行的操作:确定需要使用Ajax从服务器获取数据,还是使用已经拥有的数据。,10.3.3访问服务器,function TypeAhead(xStrText) var strParams = “q=“ + xStrText +“,当结果从服务器返回时,BuildChoices()函数被调用。 function BuildChoices()var strText = this.req.responseText;eval(strText);BuildList(strLastValue);bMadeRequest =
9、false;,1、创建结果span 2、动态设置元素的位置。 3、使用正则表达式 4、操作字符串 5、突出显示选项 6、设置选中的值 7、使用JavaScript定时器,10.4 添加功能:包含不同查询的多个元素。,多个元素需要使用输入前提示功能时,只需要为每个元素添加SetProperties(),必需不同的服务器页面。 解决的办法:在定制的对象上添加额外的参数,然后发送到服务器。,在服务器端使用if-else语句。,function TypeAhead(xStrText)var strParams = “q=“ + xStrText +“,10.5 重构,现在已经实现了输入前提示的所有功能
10、,应考虑如何封装这些功能,提供给Web开发者更容易使用。 -生成一个组件,重构任务,1、该组件与HTML标记协同工作,不需要修改任何标记,允许修改head部分。 2、组件支持在同一个页面中多次实例化 3、每个组件能够按照行为和样式配置 4、不使用全局变量 5、组件应该为所有的配置选项提供默认值。 6、组件必须在IE和Firefox中都能工作 7、组件使用开源框架,减少所需的编码工作量,提高解决方案的质量和健壮性。,10.5.1开发TextSuggest组件的游戏计划,如何提高生产力?采用别人的成果,此处使用开源的Rico和prototype框架。 Rico提供了一些Ajax基础框架、效果和工具
11、方法,可以提高开发速度。 Prototype提供了一些支持优雅编程语法的基础架构,可以使代码更加清晰,减少开发时间。,Prototype框架,Prototype提供了一些对核心JavaScript对象的扩展,以及获得漂亮代码风格的一些函数。 (1)class对象负责创建能够拥有任意多个方法的实例。见prototype.js var TextSuggest=Class .create();TextSuggest .prototype= initialize:function(p1, p2,p3); Var textSuggest=new TextSuggest(p1,p2,p3);,extend
12、()方法,prototype库扩展了JavaScript的基对象(Object对象),并且为它添加了一个extend()方法,因此这个方法对于所有的对象都是可用的。 extend()方法以基对象和扩展基对象的对象为参数,扩展对象的属性将被遍历并复制到基对象中,这样就形成了一种以对象的每个实例为基础的扩展机制。,bind/bindAsEventListener,这两种方法提供了优雅的创建函数闭包的语法。 oThis=this; this.onclick=function()oThis.call() 使用bind()方法: this.onclick=this.call.bind(this); bi
13、ndAsEventListener()将Event对象传入该方法。并且在启动时对IE和W3C标准之间的差异进行了规范化。,$方法,在JavaScript中可以使用某种特殊字符来命名方法,例如可以采用$基于元素的id从文档获取一个元素。 $(textFild).value=aNewValue;,2、Rico库,Rico拥有一组丰富的行为、拖放功能及影片播放效果。 Rico的Ajax功能通过一个名为ajaxEngine的文档中有说明的Singleton对象发布的。 ajaxEngine这个API支持为请求注册逻辑名,和注册知道如何处理Ajax相应的对象。,ajaxEngine.registerRe
14、quest(getInvoiceData,someLongGnarlyUrl.do); ajaxEngine. registerAjaxObject(xyz,someObject); 第一行代码为可能很丑陋的URL注册一个逻辑名,在发送请求时可以使用这个逻辑名,而不必记住URL,registerAjaxObject()方法用来注册一个Ajax处理对象。对象引用someObject将在响应中通过逻辑名xyz来引用。,10.5.2创建TextSuggest清晰而且可配置,现在我们有了一个很好的技术平台,可以开始编写组件。 要求1:组建必须与现有的HTML标记协同工作并且不需要修改任何标记,允许简单
15、地修改head部分来注册组件的行为。 见typeAheadXML_refactored.htm 见suggest.js,suggestDivClassName:指定保存提示的div元素的CSS类名。 suggestionClassName:指定保存每一条提示的span元素的CSS类名。 matchClassName:指定用来保存用户输入内容span元素的CSS类名。 matchTextWidth:指定生成的div的宽度是否与文本字段宽度匹配。 selectionColor:为选定的提示背景颜色制定一个十六进制的值。 matchAnywhere : false,ignoreCase : fals
16、e,count : 10,10.5.3 支持Ajax,见initAjax() 在客户端必须做两件事情:发送请求和处理响应。,1、文本提示-发送Ajax请求,文本输入框必需生成一个将要监听的onChange事件,并且有条件地为提示发送请求。 见sendRequestForSuggestions(),2、文本提示-处理Ajax响应,见ajaxUpdate(),10.5.4 处理事件,见this.injectSuggestBehavior(),10.5.5 提示的弹出界面,1、创建弹出界面。这意味着需要为提示创建div,并且为每个提示创建span 2、定位弹出框 3、使用提示填充弹出列表 4、显示和
17、隐藏提示的弹出列表,1、创建提示的弹出框,injectSuggestBehavior: function() this.createSuggestionsDiv(); createSuggestionsDiv()方法创建了提示弹出框的容器div的最外层,这个div是程序生成的所有图形界面的容器,是考察界面代码的合理起点。 见createSuggestionsDiv();,2、定位弹出框,见positionSuggestionsDiv(),3、创建弹出框的内容,见updateSuggestionsDiv(),4、显示和隐藏弹出框,见showSuggestions,10.6 小结,本章主要考察了一些输入前提示的实现中存在的缺陷,并且创建了一个应用,通过在客户端完成大部分工作来消除任何不必要向服务器的回送。,