基于AJAX和JSF打造丰富的互联网组件

2016-02-19 15:04 9 1 收藏

今天图老师小编给大家介绍下基于AJAX和JSF打造丰富的互联网组件,平时喜欢基于AJAX和JSF打造丰富的互联网组件的朋友赶紧收藏起来吧!记得点赞哦~

【 tulaoshi.com - Web开发 】

 

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  在本篇中,我们将向你展示怎样使用Mabon来创建一个简单而强有力的输入组件,它具有类似于Google Suggest所提供的内置的建议功能。为了使Web开发者更为容易地使用我们的JDJ InputSuggest组件,我们借助于Weblets开源工程来把外部资源,例如图标和JavaScript库,绑定到一个Java档案文件(JAR)中—由它来描述我们的JSF组件绑定。

 

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  一、创建支持AJAX的JSF HtmlInputSuggest组件

 

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

  这个JSF AJAX输入建议方案共包括四个类,见图1。

 

图1.类图:构建输入建议组件所需要的类

这些类分别是:

•HtmlInputSuggest—屏幕生成器特定的子类。

•HtmlRenderer—这是一个超类,它提供一些便利的方法来实现资源编码。

•HtmlInputSuggestRenderer—是你的新定制的屏幕生成器,它负责把标注生成到客户端屏幕上,包括需要的资源,例如JavaScript库和式样表等。

•HtmlInputSuggestTag是标签处理器。

在我们的输入建议解决方案中,我们实现了一个JavaScript库—inputSuggest.js—它包含利用Mabon从Web开发者的支持bean中检索数据的功能。在本文中,我们将详细讨论inputSuggest.js文件和HtmlInputSuggestRenderer—它们都受Mabon的影响并且提供了输入域(这些输入域都具有输入探测(type-ahead)和建议列表功能)。

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

二、输入建议JavaScript库

既然我们使用Mabon,因此不需要担心从支持bean中取回数据的问题。我们可以把这项任务交给Mabon来完成。然而,我们关心的是,如何处理XMLHttpRequest对象返回的数据,如何填充实际的建议列表以及如何处理用户交互。这个inputSuggest.js库中包含了大量的函数,用来处理键盘导航和鼠标交互。篇幅所限,在此我们将集中分析对该JSF HtmlInputSuggest组件有重大影响的函数。

(一)doKeyPress函数

显示于列表1中的doKeyPress函数负责处理键击事件并检查是否用户按下了TAB键。在正常情况下,这个TAB键将移出输入域并激发blur事件。对于本文中的输入建议解决方案来说,一次TAB键击也可以用于从建议列表中选择一个活动行。为此,我们需要跟踪TAB键,从建议列表中选择一行,把值添加到输入域,或者,如果没有列表数据可用的话,离开该输入域。如果发生控件导航,那么将激活doBlur()函数并关闭建议列表。

列表1—doKeyPress函数

projsf.jdj.doKeyPress = function(event){

var input = (event.srcElement || event.target);

var inputId = input.id;

var div = document.getElementById(inputId + "$suggest");

var divStyle = (div.currentStyle || div.style);

if (event.keyCode == 9 && divStyle.display == "block")

{

div.style.display = "none";

var activeRow = projsf.jdj._findActiveRow(div);

input.value = activeRow.innerHTML;

return false; //取消按Tab键离开输入域

}

return true; //继续:按Tab键离开输入域,它将调用doBlur()

}

列表2—doKeyUp函数

projsf.jdj.doKeyUp = function(event){

var input = (event.srcElement || event.target);

var inputId = input.id;

var div = document.getElementById(inputId + "$suggest");

if (event.keyCode == 9)//Tab键

{ return false; }

else if ((div.style.display == "block" || div.childNodes.length 0) &&

(event.keyCode == 40 || event.keyCode == 38))

{

if (div.style.display == "none")

{ div.style.display = "block"; }

else {

var activeRow = projsf.jdj._findActiveRow(div);

switch (event.keyCode) {

case 40: /向下箭头

if (activeRow.nextSibling)

{

activeRow.className = "HtmlInputSuggestRow";

activeRow = activeRow.nextSibling;

activeRow.className = "HtmlInputSuggestActiveRow";

}

break;

case 38: /向上箭头

if (activeRow.previousSibling)

{

activeRow.className = "HtmlInputSuggestRow";

activeRow = activeRow.previousSibling;

activeRow.className = "HtmlInputSuggestActiveRow";

}

break;

}

input.value = activeRow.innerHTML;

}

return false;

}

if (event.keyCode != 8)//不是一个Backspace键

{

input.blur();

input.focus();

}

if (input.value.length = 2)

div.style.display = "none";

}

 

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

 

 

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

列表3—doChange函数

projsf.jdj.doChange = function(event,doSuggestURL){

var input = (event.srcElement || event.target);

var inputId = input.id;

var context = { _inputId: inputId };

net.java.dev.mabon.send({ url: doSuggestURL,

args: [input.value],

callback: function(result) {

projsf.jdj._callback.call(context,result);} });

return true;

}

列表4:_callback函数

projsf.jdj._callback = function(results){

var inputId = this._inputId;

var input = document.getElementById(inputId);

var div = document.getElementById(inputId + "$suggest");

if (results.length = 1) {

div.style.display = "none";

return;

}

//从上下文中得到输入域ID

var input = document.getElementById(inputId);

div.style.width = input.offsetWidth;

while (div.firstChild) {

div.removeChild(div.firstChild);

}

for (var i=0; i results.length; i++) {

var row = document.createElement("div");

var span = document.createElement("span");

var text = document.createTextNode(results[i]);

row.className = "HtmlInputSuggestRow";

row.appendChild(text);

row.onmouseover = new Function("event",

"projsf.jdj._doMouseOver(event ||

window.event)");

row.onclick = new Function("event",

"projsf.jdj._doMouseClick(event ||

window.event)");

div.appendChild(row);

}

div.firstChild.className = "HtmlInputSuggestActiveRow";

div.style.display = "block";

window.setTimeout("projsf.jdj._selectText('" + inputId + "', " +

"'" + input.value + "', " +

"'" + results[0] + "')",

200);

}

列表5:_selectText函数

projsf.jdj._selectText=function(inputId,initialValue,suggestion){

var input = document.getElementById(inputId);

if (input.value != initialValue)

return;

if (input.value == suggestion) return;

if (input.createTextRange)//IE特定的

{

var selectionStart = input.value.length;

input.value = suggestion;

var range = input.createTextRange();

range.moveStart("character", selectionStart);

range.moveEnd("character", input.value.length);

range.select();

}

else //DOM兼容的

{

var selectionStart = input.value.length;

input.value = suggestion;

input.selectionStart = selectionStart;

input.selectionEnd = input.value.length;

}

}

列表6.HtmlInputSuggestRenderer的encodeBegin()方法

package com.apress.projsf.jdj.render.html;

Import ...//(省略)

/**

*HtmlInputSuggestRenderer用自动建议的行为生成一个传统的HtmlInputText域

*.

*/

public class HtmlInputSuggestRenderer extends HtmlRenderer{

//...

public static String TITLE_ATTR = "title";

public static String DO_SUGGEST_ATTR = "doSuggest";

public void encodeBegin(

FacesContext context,

UIComponent component) throws IOException

{

writeScriptResource(context,

"weblet://org.dojotoolkit.browserio/dojo.js");

writeScriptResource(context,

"weblet://net.java.dev.mabon/mabon.js");

writeScriptResource(context,

"weblet://com.apress.projsf.jdj/inputSuggest.js");

writeStyleResource(context,

"weblet://com.apress.projsf.jdj/inputSuggest.css");

}

 

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

 

 

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

列表7.HtmlInputSuggestRenderer的encodeEnd()方法

public void encodeEnd(

FacesContext context,

UIComponent component) throws IOException

{

String valueString = _getValueAsString(context, component);

String clientId = component.getClientId(context);

Map attrs = component.getAttributes();

String title = (String)attrs.get(TITLE_ATTR);

String onchange = (String)attrs.get(ONCHANGE_ATTR);

MethodBinding doSuggest = (MethodBinding)attrs.get(DO_SUGGEST_ATTR);

ResponseWriter out = context.getResponseWriter();

out.startElement("div", component);

if (title != null)

out.writeAttribute("title", title, TITLE_ATTR);

//
// value="[converted-value]" onchange="[onchange]" /

out.startElement("input", component);

out.writeAttribute("id", clientId, null);

out.writeAttribute("name", clientId, null);

if (valueString != null)

out.writeAttribute("value", valueString, null);

if (doSuggest != null)

{

//当使用服务器端建议时,禁止浏览器自动完成功能

out.writeAttribute("autocomplete", "off", null);

String expression = doSuggest.getExpressionString();

//从表达式中修整#{}

String bindingRef =

expression.substring(2, expression.length() - 1);

ViewHandler handler =

context.getApplication().getViewHandler();

String doSuggestURL =

handler.getResourceURL(context, "mabon:/" + bindingRef);

out.writeAttribute("onkeypress",

"return projsf.jdj.doKeyPress(event);", null);

out.writeAttribute("onkeyup",

"return projsf.jdj.doKeyUp(event);", null);

out.writeAttribute("onchange",

"projsf.jdj.doChange(event, '" + doSuggestURL

+ "');", null);

out.writeAttribute("onblur",

"return projsf.jdj.doBlur(event);", null);

}

out.endElement("input");

out.startElement("br", null);

out.endElement("br");

out.startElement("div", null);

out.writeAttribute("id", clientId + "$suggest", null);

out.writeAttribute("class", "HtmlInputSuggest", null);

out.endElement("div");

}

列表8.一个使用JSF HttpInputSuggest组件的JSP页面

<?xml version="1.0" encoding="UTF-8" ?>

<?XML:NAMESPACE PREFIX = JSP />
xmlns:jdj="http://projsf.apress.com/jdj"

xmlns:f="http://java.sun.com/jsf/core"

xmlns:h="http://java.sun.com/jsf/html"



<?XML:NAMESPACE PREFIX = F />











<?XML:NAMESPACE PREFIX = H />


title="Input Suggest Component"

value="#{backingBean.value}"

doSuggest="#{backingBean.doSuggest}" /









列表9:支持bean的value属性

package com.apress.projsf.jdj.application;

import java.util.ArrayList;

import java.util.List;

/**

*BackingBean是一个inputSuggest.jspx文档的支持bean。

*/

public class BackingBean{

public void setValue(Object value) { _value = value; }

public Object getValue() { return _value; }

列表10.支持bean的doSuggest()方法

public String[] doSuggest(String initialValue) {

List suggestions = new ArrayList();

for (int i=0; i _MASTER_LIST.length; i++) {

if (_MASTER_LIST[i].startsWith(initialValue))

suggestions.add(_MASTER_LIST[i]);

}

return suggestions.toArray(new String[0]);

}

private Object _value;

static private final String[] _MASTER_LIST = new String[]

{

"Pro JSF and Ajax",

"Pro Ajax",

"Pro JSP 2",

"Pro Jakarta",

"Pro J2EE 1.4"

};

}

 

 

(本文来源于图老师网站,更多请访问http://www.tulaoshi.com/webkaifa/)

一个JavaScript工具函数。我们可以使用这种Mabon协议来发送目标URL和需要的任何参数,然后异步地从托管bean中接收数据。

(七)Mabon和JSON

正如你所知,XMLHttpRequest提供了两种响应类型—responseText和responseXML—它们可以用于取回数据。你可能会问:我何时该使用哪一种响应类型?其实,这个问题的答案依赖于是否由你自己控制响应的语法。

responseXML类型返回一个完整的DOM对象(它提供多种方式来遍历这棵DOM树),从而允许你查找需要的信息并把所作变化应用到当前文档中。当你的组件有可能影响到周围的元素而且你不能控制响应时(例如,当你与一个Web服务进行通讯时),这是相当有用的。

对于本例中的输入建议组件,你的确要控制响应并且你只想从你的组件中取回数据,而不是修改整个页面的DOM结构。responseText类型返回普通的文本,这允许你利用JSON语法用于响应。为了在组件中利用AJAX技术,JSON是一种极其有用的数据交换格式,因为它可以轻易地使用eval()函数进行分析。

eval()函数仅使用一个参数(一个JavaScript代码字符串),并一次性分析和执行这个字符串而不是分析处理每一部分。这种方法要比任何其它类型的分析(例如XML DOM分析方法)快得多。

这正是为什么Mabon实现JSON的原因—你能够控制响应,而且JSON具有语法简单和分析速度快的特点。

(八)encodeEnd()方法

真正的工作是在encodeEnd()方法中完成的,见列表7。在encodeEnd()方法中,我们从HtmlInputSuggest组件得到属性的Map。这个组件的属性之一是doSuggest属性。通过这个属性,我们能够得到MethodBinding(如果有的话),并且从这个MethodBinding对象,我们能够得到实际的由Web开发者所定义的MethodBinding表达式(例如,#{backingBean.doSuggest})。然后,我们从表达式中修整#{}并且用类似mabon:/协议的语法来连接字符串的余下部分。最后,MabonViewHandler将识别这个字符串并返回一个资源URL—它将被写向客户端(例如,/context-root/mabon-servlet-mapping/backingBean.doSuggest)。

三、使用输入建议组件

创建一套AJAX方案并不是一项简单的任务,尽管有若干使得这类工作更为容易些的AJAX工具包可用(例如Dojo Toolkit,www.dojotoolkit.org)。相比之下,JSF提供的是一种更为简单的编程模型和一种为大量开发者所熟悉的工具:JSP和Java。为了完整地结束本文中所提供的Ajax解决方案,让我们分析一下你如何在一个JSF应用程序中使用这个输入建议组件,由列表8所示。

这个页面包含一个HtmlInputSuggest组件(),它把value属性设置为一个绑定表达式的值。这个表达式指向一个支持bean的value属性。doSuggest属性包含一个绑定表达式的方法—这个表达式指向在同一个支持bean上的doSuggest()方法。你可以在列表9中观察这个支持bean。

value属性仅是一个普通的JavaBean属性。但是,显示于列表10中的doSuggest()方法却值得引起你的注意。这个方法使用由用户输入的初始值,该值是从doChange()函数(见列表3)中经由Mabon传递给它的。然后,doSuggest()方法根据用户在客户端输入的初始值返回一个经过过滤的数组。值得注意的是,返回的值遵循支持的JSON语法。

这个HtmlInputSuggest组件的最后结果显示于图2中。

 

图2.在一个浏览器中生成HtmlInputSuggest组件

四、结论

从本文中,我们希望你已经理解了如何使用Mabon来实现你的JSF组件以支持基于Ajax技术的数据回取,以及怎样通过利用Weblets工程把你的JSF组件需要的外部资源打包到与你的Java类相同的文档中。

最后,既然你已经知道怎样利用JSF和AJAX技术创建可重用的丰富互联网应用程序,那么我们非常希望你能够利用你在本系列文章中所学的技术来创建自己的定制组件以构建丰富互联网应用程序(RIA)。

来源:http://www.tulaoshi.com/n/20160219/1608766.html

延伸阅读
为了对现阶段 互联网 金融的模式做一个清晰的界定,投融贷P2P网站工作人员调研走访,深度解析资讯,最终梳理出第三方支付、P2P网贷、大数据金融、众筹、信息化金融机构、互联网金融门户等六大互联网金融模式。 互联网金融模式1 :第三方支付 第三方支付(Third-Party Payment)狭义上是指具备一定实力和信誉保障的非银行机构,借助...
标签: 电脑入门
PowerPoint提供了强大的网络功能,能够帮助我们轻轻松松地召开网络会议,生动又有效率。 这需要用到Microsoft NetMeeting。这个程序和Microsoft Office的紧密结合给我们开联机会议提供了相当大的便利。只要在PowerPoint中打开工具→联机协作→现在开会命令,在出现的窗口中输入你的姓、名、电子邮件、位置和服务器名称,NetMeeting就...
标签: 网络
乐视员工获刑4年半 乐视云计算公司员工闫某,为倒卖流量牟取私利,在职期间受上家吴某的委托在公司的207台服务器上种植木马程序。日前,海淀法院以非法控制计算机信息系统罪判处吴某有期徒刑5年,罚金2万元;判处闫某有期徒刑4年6个月,罚金1万元。 信息风险 这一点应该也是很多人知道并且担心的,而且互联网的信息共享性也确实...
存款类 比如余额宝,由基金管理人运作,基金托管人保管资金的一种开放式基金模式,货币基金的具体收益受银行利率的影响,一旦银行采取降息,货币基金的收益也会受到重大波及。 网贷类 比如P2P网络借款,又称点对点网络借款,是一种将小额资金聚集起来借贷给有资金需求人群的一种民间小额借贷模式。P2P的收益普遍较高,但高收益必...
你家宝宝跟谁亲 网友提问 我家宝宝两个多月,一般都是晚上我带,白天婆婆带,今天婆婆有事,我带的,我跟宝宝正玩的好好的,婆婆回来了,本来宝宝没哭,婆婆一来宝宝就哭了,婆婆说宝宝想让她抱了,认人了,跟她亲,我……等我上班了宝宝跟我接触更少了,岂不是不亲了,我怀的我生的儿子难道真的不跟我亲了啊! 七...

经验教程

741

收藏

18
微博分享 QQ分享 QQ空间 手机页面 收藏网站 回到头部