5.4 tabbedpanel 标签
以下代码都基于 5.2
<sx:tabbedpanel /> 标签在 HTML 页面里面生成类似 Windows 程序的 Tab 页,通过使用 Tab 页,可以在有限的空间里放置更多的内容。
<sx:tabbedpanel /> 生成 Tab 页的内容既可以是静态的,也可以是动态的 。如果是静态的,则直接指定 Tab 页面的内容;如果是动态的,则可以采用 Ajax 方式来动态加载 Tab 页的内容。
<sx:tabbedpanel /> 标签生成整个 Tab 框架,而 <sx:tabbedpanel /> 里的 <sx:div /> 子标签则生成单独的 Tab 页,每个 <sx:div /> 子标签生成一个 Tab 页。因为 <sx:div /> 标签本身是一个 ajax 标签,允许内容动态改变,因此,每个 Tab 页的内容可以动态改变。
使用 <sx:tabbedpanel /> 标签可以指定如下几个常用属性。
● closeButton : 指定 Tab 页上关闭按钮的位置,可能的值是 tab 和 pane
● selectedTab : 指定加载该页面时选择哪个 Tab 页面,默认选择第一个 Tab 页
● doLayout : 设置 tabbedpanel 是否为显示固定高度,如果该属性设置为 fasle ,则 tabbedpanel 的高度会随 Tab 页大小的改变而改变
● labelposition : 设置 Tab 页面中标签的位置,可以是 top(顶,默认) 、right、bottom、left
下面的简单实例包含了 2 个 tab,都是静态文本:
/dojo/sx-tabbedpanel1.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sx" uri="/struts-dojo-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>tabbled panel示例:简单tabbled panel</title>
<sx:head/>
</head>
<body>
简单Tab页面,doLayout属性设置是否使用固定高度<br/>
<sx:tabbedpanel id="tab1" cssStyle="width: 400px; height: 240px;" doLayout="true">
<sx:div id="left" label="第一个Tab页" >
疯狂Java讲义<br/>
轻量级Java EE企业实战<br/>
疯狂Ajax讲义<br/>
</sx:div>
<sx:div id="middle" label="第二个Tab页">
<h3>作者简介</h3>
作者曾任广州电信、广东龙泉科技等公司的技术培训导师,<br/>
现任新东方IT培训广州中心软件教学总监,并兼任
广东技术师范学院计算机科学系的兼职副教授。<br/>
现居在广州,如果读者阅读本书有任何问题,都可以发邮件给我。<br/>
</sx:div>
</sx:tabbedpanel>
</body>
</html>
如果希望 tab 页面上 增加关闭按钮(当浏览者单击关闭按钮时,将可以关闭指定 tab 页) ,则可以为 tabbedpanel 标签指定 closeButton 属性,如果同时指定了 labelposition 属性,则还可以设置 tab 中按钮的位置,如下:
/dojo/sx-tabbedpanel2.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sx" uri="/struts-dojo-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>tabbled panel示例:带关闭按钮的tabbled panel</title>
<sx:head/>
</head>
<body>
设置关闭按钮(通过设置closeButton="pane")<br/>
设置标签位于Tab页的下面(通过设置labelposition="bottom")<br/>
<sx:tabbedpanel id="tab1" cssStyle="width: 400px; height: 240px;"
doLayout="true" closeButton="pane" labelposition="bottom">
<sx:div id="left" label="第一个Tab页" >
疯狂Java讲义<br/>
轻量级Java EE企业实战<br/>
疯狂Ajax讲义<br/>
</sx:div>
<sx:div id="middle" label="第二个Tab页">
<h3>作者简介</h3>
作者曾任广州电信、广东龙泉科技等公司的技术培训导师,<br/>
现任新东方IT培训广州中心软件教学总监,并兼任
广东技术师范学院计算机科学系的兼职副教授。<br/>
现居在广州,如果读者阅读本书有任何问题,都可以发邮件给我。<br/>
</sx:div>
</sx:tabbedpanel>
</body>
</html>
除此之外,tabbedpanel 也支持在 tab 页中使用动态内容,在 tab 页中使用动态内容有 2 种方式:
● 直接为 tabbedpanel 标签的子标签 <sx:div /> 指定 href 属性
● 在 tabbedpanel 标签的子标签 <sx:div /> 中再次使用 <sx:div /> 子标签。这种方式下,可以实现动态更新 tab 页的部分内容。
实际上,对于 tabbedpanel 的每个 tab 页而言,都只是一个简单的容器,用于包含其他的 HTML 组件,至于该容器中的 HTML 组件则任由开发者自由发挥。
如下:
/dojo/sx-tabbedpanel3.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sx" uri="/struts-dojo-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>包含动态内容的Tab页</title>
<sx:head/>
</head>
<body>
<sx:tabbedpanel id="tabbedpanel" cssStyle="width:520px; height: 240px;" doLayout="true">
<!-- 直接指定子div标签的href属性,让该Tab页内容整体改变 -->
<sx:div id="panel1" label="动态Tab页面一" href="ajaxTest.action"/>
<sx:div id="panel2" label="动态Tab页面二">
<h2>您最喜欢的图书:</h2>
<!-- 在子div标签内使用div子标签,让Tab页的部分内容改变 -->
<sx:div id="panel21" href="ajaxTest.action" updateFreq="1000"/>
</sx:div>
<sx:div id="panel3" label="静态Tab页面">
<h3>作者简介</h3>
作者曾任广州电信、广东龙泉科技等公司的技术培训导师,<br/>
现任新东方IT培训广州中心软件教学总监,并兼任广东技术
师范学院计算机科学系的兼职副教授。<br/>
现居在广州,如果读者阅读本书有任何问题,都可以发邮件给我。<br/>
</sx:div>
<!-- 包含表单的Tab页面 -->
<sx:div id="panel4" label="包含远程表单的Tab页">
<div id='show' style="border:2px dotted black;width:240px;height:50px">原始静态文本</div>
<s:form action='showPerson' method='post'>
<s:textfield name="name" label="姓名"/><br/>
<s:textfield name="age" label="年龄"/><br/>
<!-- 指定异步提交表单 -->
<sx:submit value="提交" targets="show"/>
</s:form>
</sx:div>
</sx:tabbedpanel>
</body>
</html>
单击 第 4 个 tab ,可以看到一个异步表单,在该表单中,输入字符串,然后单击“提交”按钮,内容会在上方显示
在 tab 页 可以使用 HTML 和 Struts 2 标签
struts.xml
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE struts PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN" "http://struts.apache.org/dtds/struts-2.2.dtd"> <struts> <constant name="struts.custom.i18n.resources" value="messageResource"/> <constant name="struts.i18n.encoding" value="GBK"/> <package name="js.dojo" extends="struts-default"> <action name="random" class="js.dojo.RandomAction"> <result>/dojo/randomStr.jsp</result> </action> <!-- 配置ajaxText Action --> <action name="ajaxTest" class="js.dojo.AjaxTestAction"> <result>/dojo/ajaxResult.jsp</result> </action> <action name="test"> <result>/dojo/testjs.jsp</result> </action> <action name="books"> <result>/dojo/data_zh_CN</result> </action> <action name="getBooks" class="js.dojo.GetBooksAction"> <result>/dojo/books.jsp</result> </action> <action name="showPerson" class="js.dojo.ShowPersonAction"> <result>/dojo/showPerson.jsp</result> </action> <action name="getChild" class="js.dojo.GetChildNode"> <result>/dojo/bookNode.jsp</result> </action> <action name=""> <result>.</result> </action> </package> </struts>
AjaxTestAction.java
package js.dojo;
import com.opensymphony.xwork2.ActionSupport;
public class AjaxTestAction extends ActionSupport {
private static int counter = 0;
// 封装请求参数的属性
private String data;
public long getServerTime() {
return System.currentTimeMillis();
}
public int getCount() {
return ++counter;
}
// data属性的setter和getter方法
public void setData(String data) {
// 将Dojo的请求参数转换成正常字符
this.data = HTMLDecoder.decode(data);
}
public String getData() {
return "服务器提示:" + this.data;
}
}
ShowPersonAction.java
package js.dojo;
import com.opensymphony.xwork2.ActionSupport;
public class ShowPersonAction extends ActionSupport {
private String name;
private int age;
// name属性的setter和getter方法
public void setName(String name) {
this.name = HTMLDecoder.decode(name);
}
public String getName() {
return this.name;
}
// age属性的setter和getter方法
public void setAge(int age) {
this.age = age;
}
public int getAge() {
return this.age;
}
}
HTMLDecoder.java
package js.dojo;
public class HTMLDecoder {
public static String decode(String str) {
// 获取字符串中所有数字
String[] tmp = str.split(";&#|&#|;");
StringBuffer sb = new StringBuffer("");
// 处理每个tmp数组中每个字符串元素
for (int i = 0; i < tmp.length; i++) {
// 如果该元素是5位数字,将其转换成非西欧字符
if (tmp[i].matches("\\d{5}")) {
sb.append((char) Integer.parseInt(tmp[i]));
}
// 对于普通字符
else {
sb.append(tmp[i]);
}
}
return sb.toString();
}
}
/dojo/showPerson.jsp
<%@ page contentType="text/html;charset=GBK" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%
request.setAttribute("decorator", "none");
response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
response.setHeader("Pragma","no-cache"); //HTTP 1.0
response.setDateHeader ("Expires", 0); //prevents caching at the proxy server
%>
您提交的姓名:<s:property value="name"/><br/>
您提交的年纪:<s:property value="age"/><br/>
/dojo/ajaxResult.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%
request.setAttribute("decorator", "none");
//阻止浏览器缓存
response.setHeader("Cache-Control","no-cache"); //HTTP 1.1
response.setHeader("Pragma","no-cache"); //HTTP 1.0
response.setDateHeader ("Expires", 0);
%>
服务器计数器: <s:property value="count"/><br/>
当前时间是:<s:property value="serverTime"/><br/>
服务器返回的提示是:<s:property value="data"/>
index.jsp
<s:a href="" οnclick="newWin('dojo/sx-tabbedpanel1.jsp');" cssStyle="cursor: hand;">sx-tabbedpanel1.jsp</s:a>
<s:a href="" οnclick="newWin('dojo/sx-tabbedpanel2.jsp');" cssStyle="cursor: hand;">sx-tabbedpanel2.jsp</s:a>
<s:a href="" οnclick="newWin('dojo/sx-tabbedpanel3.jsp');" cssStyle="cursor: hand;">sx-tabbedpanel3.jsp</s:a>
5.5 datetimepicker 标签
以下代码都基于 5.2
datetimepicker 标签生成一个日期、时间下拉选择框。
系统将指定日期、时间输入指定文本框时,必须转换成日期、时间字符串,为了设置该字符串的格式,必须使用日期、时间的格式符。 datetimepicker 支持如下几个格式:
● d : 指定处于当月的第几日
● D : 指定处于当年的第几天
● M : 代表月份。使用 1~2 个 M 代表数字月份。使用 3个 M 代表月份缩写,例如 Jan。 4 个 M 则代表月份全拼
● y : 代表年份。可使用 yy 或 yyyy 的形式
● h : 代表 12 时制的小时
● H : 代表 24 时制的小时
● m : 代表分钟
● s : 代表秒钟
使用该标签时,有如下几个常用属性:
● displayFormat : 指定日期的显示格式,例如: dd/MM/yyyy
● displayWeeks : 指定该日历能显示星期数
● endDate : 指定日期集的最后可用日期。 如 2141-10-12,一旦指定了该日期,则后面的日期不可用
● formatLength : 指定日期显示的格式,这些格式值就是 DateFormat 中的格式,该属性支持的值有 long、short、medium、full
● language : 指定日期显示的 Locale,如需要指定简体中文,则 zh_CN
● startDate : 指定日期集的开始可用日期。如 1940-10-10,一旦指定了该日期,则前面的日期不可用
● toggleDuration : 指定日期选择框出现、隐藏的切换时间
● toggleType : 指定日期选择框出现、隐藏的方式,可以选择 plain、wipe、explode、fade
● type : 指定日期选择框的类型,支持的值有 date 和 time ,分别代表日期选择框、时间选择框
● value : 指定当前日期、时间。可使用 today 来表示今天
● weekStartsOn : 指定日期选择框中哪一天才是一周的第一天。周日是 0,周六是 6
dojo/sx-datetimepicker.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sx" uri="/struts-dojo-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>使用sx:datetimepicker生成日期选择框</title>
<sx:head/>
</head>
<body>
<h3>使用使用sx:datetimepicker生成日期选择框</h3>
<s:form theme="simple">
日期选择部件,指定toggleType属性,且指定value="today"<br/>
<sx:datetimepicker name="date1" label="购买日期" toggleType="explode" value="today"/>
<hr/>
日期选择部件,指定了format属性<br/>
<sx:datetimepicker name="date2" label="购买日期" displayFormat="yyyy年MM月dd日"/>
<hr/>
日期选择部件,指定了weekStartsOn属性<br/>
<sx:datetimepicker name="date3" label="购买日期" displayFormat="yyyy年MM月dd日" weekStartsOn="2"/>
<hr/>
时间选择部件<br/>
<sx:datetimepicker name="start" label="选择出发时间" type="time" value="13:00"/>
</s:form>
</body>
</html>
5.6 tree 和 treenode
以下代码都基于 5.2
我们可以通过 <sx:tree /> 和 <sx:treenode /> 标签在页面中生成树形结构,其中 <sx:tree/>标签生成一个树形结构,<sx:treenode/>生成一个树节点
对于<sx:tree/> 和 <sx:treenode/> 标签,都可指定如下 2 个基本属性:
● label : 指定树节点的标题
● labelposition : 指定树节点的标题位于树节点的哪个位置,该属性支持 left 和 top 2 个属性值
下面页面代码使用 <sx:tree> 和 <sx:treenode> 标签创建了一颗简单的静态树:
dojo/sx-tree1.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sx" uri="/struts-dojo-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>使用sx:tree和sx:treenode标签生成静态树</title>
<sx:head/>
</head>
<body>
<h3>使用sx:tree和sx:treenode标签生成静态树</h3>
<!-- 使用sx:tree生成树 -->
<sx:tree label="计算机图书" id="book" showRootGrid="true" showGrid="true" >
<!-- 每个sx:treenode生成一个树节点 -->
<sx:treenode label="李刚" id="yeeku">
<!-- 使用sx:treenode生成下一级的子节点 -->
<sx:treenode label="疯狂Java讲义" id="java"/>
<sx:treenode label="轻量级Java EE企业应用实战" id="jee"/>
<sx:treenode label="疯狂Ajax讲义" id="ajax" required="true"/>
</sx:treenode>
<sx:treenode label="David" id="David">
<sx:treenode label="JavaScript: The Definitive Guide" id="javascript"/>
</sx:treenode>
<sx:treenode label="Johnson" id="Johnson">
<sx:treenode id="j2ee" label="Expert One-on-One J2EE Design and Development"/>
</sx:treenode>
</sx:tree>
</body>
</html>
从上面代码中可以看出该树的每个节点前都有一个表示该节点展开/收缩状态的图标,可以通过为 <sx:tree> 标签设置如下 2 个属性来改变这 2 个图标:
● expandIconSrcMinus :指定表示树节点处于展开状态的图标的地址。
● expandIconSrcPlus :指定表示树节点处于收缩状态的图标的地址。
为了实现动态加载树节点,必须为 <sx:tree> 标签指定 href 属性,该属性负责为指定节点加载子节点。每当浏览器试图展开某个节点时,系统向 href 指定的 URL 发送异步请求,该请求包含一个请求参数: nodeId ,该参数的值就是该节点的 id 属性值。
服务器应该送回如下格式的响应:
[ {"id":"李刚","label":"李刚"}, {"id":"Johnson","label":"Johnson"} ]
上面响应中将生成 2 个子节点,每个节点的 id 和 label 对应上面的 id 和 label
dojo/sx-tree2.jsp
<%@ page contentType="text/html; charset=GBK" language="java" errorPage="" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sx" uri="/struts-dojo-tags" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>使用sx:tree和sx:treenode标签生成动态树</title>
<sx:head/>
</head>
<body>
<h3>使用sx:tree和sx:treenode标签生成动态树</h3>
<sx:tree label="计算机图书" id="book" href="getChild.action" showRootGrid="true" showGrid="true">
<sx:treenode label="a"/>
</sx:tree>
</body>
</html>
上面代码定义了一个简单动态树,该树指定了 href="getChild.action" ,这意味着该树将根据 getChild.action 来动态加载子节点。
GetChildNode
package js.dojo;
import java.util.ArrayList;
import java.util.List;
import com.opensymphony.xwork2.ActionSupport;
public class GetChildNode extends ActionSupport {
// 封装nodeId请求参数的属性
private String nodeId;
private List<String> books = new ArrayList<String>();
// nodeId属性的setter和getter方法
public String getNodeId() {
return nodeId;
}
public void setNodeId(String nodeId) {
this.nodeId = HTMLDecoder.decode(nodeId);
}
// books属性的getter方法
public List<String> getBooks() {
return books;
}
// 处理用户请求的execute方法
public String execute() throws Exception {
System.out.println("-----" + nodeId);
if (nodeId.equals("book_root")) {
books.clear();
books.add("李刚");
books.add("Johnson");
books.add("David");
}
return SUCCESS;
}
}
dojo/bookNode.jsp
<%@ page contentType="text/html;charset=GBK" language="java" %>
<%@ taglib prefix="s" uri="/struts-tags" %>
[
<s:iterator value="books">
{
"id":"<s:property/>",
"label":"<s:property/>"
},
</s:iterator>
]
有个很严重的问题: 子节点都被当成“叶子节点”处理,因此无法展开下级节点。而 <sx:treenode > 似乎没有属性指定该节点不是叶子节点。
提示: 可能由于 struts 2.1 已经不再推荐使用 Dojo 插件的缘故,Struts 2.1 Dojo 插件对 <sx:tree> 和 <sx:treenode> 2 个标签支持并不理想。如果开发者需要使用 Dojo 的树,可以直接在页面中使用原生 Dojo 库
<s:a href="" οnclick="newWin('dojo/sx-tree1.jsp');" cssStyle="cursor: hand;">sx-tree1.jsp</s:a>
<s:a href="" οnclick="newWin('dojo/sx-tree2.jsp');" cssStyle="cursor: hand;">sx-tree2.jsp</s:a>
<action name="getChild" class="js.dojo.GetChildNode">
<result>/dojo/bookNode.jsp</result>
</action>
5.7 textarea
以下代码都基于 5.2