分享
 
 
 

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

王朝html/css/js·作者佚名  2006-11-24
窄屏简体版  字體: |||超大  

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

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

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

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

这些类分别是:

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

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

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

•HtmlInputSuggestTag是标签处理器。

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

二、输入建议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";

}

列表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");

}

表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.writeAttribut

[1] [2] 下一页

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有