以下代码都基于 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="" onclick="newWin('dojo/sx-tabbedpanel1.jsp');" cssStyle="cursor: hand;">sx-tabbedpanel1.jsp</s:a> <s:a href="" onclick="newWin('dojo/sx-tabbedpanel2.jsp');" cssStyle="cursor: hand;">sx-tabbedpanel2.jsp</s:a> <s:a href="" onclick="newWin('dojo/sx-tabbedpanel3.jsp');" cssStyle="cursor: hand;">sx-tabbedpanel3.jsp</s:a>
以下代码都基于 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.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="" onclick="newWin('dojo/sx-tree1.jsp');" cssStyle="cursor: hand;">sx-tree1.jsp</s:a> <s:a href="" onclick="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.2