struts系列學習(tiles標籤庫四)

Tiles的使用(四)-遺補和總結

                                 
一.) Tiles配置
要正常使用tiles,必須在Structs配置文件中加入下列代碼:
 

 <plug-in className="org.apache.struts.tiles.TilesPlugin" >
 <set-property property="definitions-config" value="/WEB-INF/tiles-defs.xml, /WEB-INF/tiles-tests-defs.xml,/WEB-INF/tiles-tutorial-defs.xml,
 /WEB-INF/tiles-examples-defs.xml" />
 <set-property property="moduleAware" value="true" />
 <set-property property="definitions-parser-validate" value="true" />
 </plug-in>


1.definitions-factory-class:(可選)
        definition factory類的名稱,可以使用自己編寫definition factory。如果不指定,使用國際化factory。
2.definitions-config:(可選)
       指定tiles的配置文件, 可以是多個,中間用逗號隔開。每個文件按次序被讀取,遇到definition就添加進definition factory中。如果產生重名,後面的definition將替代前面的。
3.moduleAware:(可選)
       如果是true(默認值),一個Struts module就會有一個factory;如果是false,多個Struts module分享單獨的一個factory。
4.definitions-parser-validate:(可選)
        如果是true(默認值),validate.DTD會在文件頭中被指定;如果是false,沒有validation。

 
二.) 把Definition's名稱做爲Struts Forward
如果用Tiles' servlet替代Struts' servlet,那麼你可以使用Tiles配置文件中的definition名稱來替代URL。你Struts Action的配置像下面一樣:
 <action path="/tutorial/testAction2" type="org.apache.struts.example.tiles.tutorial.ForwardExampleAction">
 <forward name="failure" path="forward.example.failure.page"/>
 <forward name="success" path="forward.example.success.page"/>
 </action>

在這裏你的Action代碼和以前一樣,但forward mapping現在被指定爲一個definition名稱,當action forward碰到definition名稱時,它就裝載definition,創建並初始化Tile's attributes相關的內容,再插回到definition中。
 
三.) 爲View準備數據:添加一個控制器(controller)
       我們常常需要給Jsp頁面傳遞一些計算好的數據。MVC框架中,控制器用來做這個事情。要解析Tiles和Struts,我們可以用一個Struts Action作爲controller,一個JSP頁面作爲一個view,然後在Tile中將兩者組合。所以當你插入Tile時,在Jsp頁面顯示前Action會先被調用。
       Tils可以通過controller(每個Tile對應一個sub-controller)產生,再合成的一個完整的web頁面。這個方法比用一個單獨的controller來控制所有Tile的頁面要好,因爲它允許獨立的構建Tile,而不用擔心怎樣傳遞數據。
有幾種方法能夠把Action和一個View做爲一個Tile:
    1. 在<insert>或<definition>中使用Action類名或Action URL。
    2. 讓struts-config.xml中的Action指向一個definition名稱。在tiles-onfig.xml文件中指定一個含URL的difinition和一個含有view的difinition。第一個difinition作爲一個完整的Tile difinition(action+view),第二個difinition作爲view difinition。
    3. 可以讓多個view和一個controller結合。選擇一個恰當的controller,對於有main view和error view來說是很有用的。和以前一樣,但可以多個forward到一個view definition。

       將controller放入中Tile最簡單的方法是在<insert>和<definition>中指定,可以是本地URL或一個類。在Jsp頁面顯示前controller被調用。controller使用共享的Tile內容填充Jsp頁面,所以它可以讀取、修改和添加Tile屬性。controller一般用來做這麼幾件事情:model的數據被傳遞到view前進行處理;屬性傳遞到view前對其進行修改或添加。
       你可以使用當前web應用程序的Structs Action URL來做爲controller,你的action可以擴展org.apache.struts.action.TilesAction,來替代Structs Action類。TilesAction繼承原來的execute()方法。還提供了一個新的execute()方法,這個方法多了"tileContext"參數,當你需要處理Tile的屬性是很有用。

 <tiles:insert page="layout.jsp" controllerUrl="myAssociatedAction.do” >
 <tiles:put name="title" value="Test controller set in insert" />
 <tiles:put name="header" value="header.jsp" />
 <tiles:put name="body" value="body.jsp" />
 </tiles:insert>

Structs Action中的描述:
 <action path="/myAssociatedAction" type="org.apache.struts.example.tiles.MyAssociatedAction">
 </action>

Action中的描述:
 public final class MyAssociatedAction extends TilesAction {
  public ActionForward execute( ComponentContext context,ActionMapping mapping,ActionForm form,
                                               HttpServletRequest request, HttpServletResponse response)
  throws IOException, ServletException{
     String title = (String)context.getAttribute( "title" );
     System.out.println( "Original title" + title );
     context.putAttribute( "title", "New Title" );
     return null;
 }
}


如果你使用類名做爲controller,就必須繼承下面基類或接口中的一個:
        org.apache.struts.tiles.Controller:這是個controller接口定義了cintorller方法。這些方法接收包含當前Tile內容的參數和普通的servlet參數(request、response和servletContext)。
        org.apache.struts.tiles.ControllerSupport:這是個底層類,沒有方法。
 <tiles:insert page="layout.jsp" controllerClass="org.apache.struts.example.tiles.test.TestTileController" >
 <tiles:put name="title" value="Test controller set in insert" />
 <tiles:put name="header" value="header.jsp" />
 <tiles:put name="body" value="body.jsp" />
 </tiles:insert>

在definition中使用的例子:
 <definition name="tileWithActionAsController" path="/actionAsController.do" >
 <put name="title" value="Title" />
 <put name="anAttribute" value="aValue" />
 </definition>

Action被用作controller:
 <action path="/ actionAsController " type="org.apache.struts.example.tiles.ActionAsController">
 <forward name="failure" path="/failurePage.jsp"/>
 <forward name="success" path="success.definition"/>
 </action>

四.) 舉個例子:RssChannel

在這個例子中,我們將創建一個Tile,通過指定的URL讀取Rss channel的內容,再使用一個合適的layout把內容顯示出來。Tile產生一個controller和view,controller從XML文件中讀取channel內容,然後創建一個容易被view調用的bean做爲model。channel feed的URL被當作Tile 的屬性值。
這樣做的優點是:

    1. 能夠在頁面的任何地方插入Tile。
    2. 可以在同一個Tile頁面中插入多個不同的channel。
    3. 只需要簡單的修改view就能更改channel。
    4. 每個Tile可以放置幾個channel,方便使用。

注:在jakarta-struts-1.2.2中的tiles-documentation.war有相關的代碼。
Definition:

tiles-examples-defs.xml
------------------------------------------------------------------------------------------------------------------------------------------ 
<definition name="examples.rssChannel.body" path="/examples/tiles/rssChannels.jsp" 
 controllerUrl="/examples/controller/rssChannel.do" >
    <putList name="urls" >
     <!--<add value="
http://www.newsforge.com/newsforge.rss" /> -->
     <add value="
http://xmlhack.com/rss.php" />
     <add value="
http://lwn.net/headlines/rss" />
   </putList>
  </definition>

控制器是一個Action URL,在Structs配置文件中有聲明:
stucts-examples-config.xml
------------------------------------------------------------------------------------------------------------------------------------------ 
 <action    path="/controller/rssChannel"
                type="org.apache.struts.webapp.tiles.rssChannel.RssChannelsAction">
 </action>
這個Action沒有forward到一個view,相關的view是一個Tile definition。

Contorller:
controller就是一個java類。它從Tile putList 屬性中接收channel URL列表,用RSSDigester類來解析channel的內容。然後把bean中的相關內容做爲model,通過Tile 屬性傳遞給view。

 public final class RssChannelsAction extends TilesAction {

    private static Log log = LogFactory.getLog(RssChannelsAction.class);
    public static final String CHANNELS_KEY = "CHANNELS";
    public static final String CHANNEL_URLS_KEY = "urls";
    public static final String CHANNEL_URL_KEY = "url";

    public ActionForward execute(ComponentContext context,ActionMapping mapping, ActionForm form,
                                                 HttpServletRequest request,HttpServletResponse response)
        throws Exception {
        log.debug("Enter Rss Channel Action");
        ActionMessages errors = new ActionMessages();
        // -- Retrieve parameters --
        // Urls can come from a list, or from a single attribute.
        List channels = (List) context.getAttribute(CHANNEL_URLS_KEY);
        if (channels == null) {
            Object url = context.getAttribute(CHANNEL_URL_KEY);
            channels = new ArrayList(1);
            channels.add(url);
        }
        log.debug("urls count" + channels.size());
        // -- Loop through channels --
        List channelBeans = new ArrayList(channels.size());
        try {
            for (int i = 0; i < channels.size(); i++) {
                RSSDigester digester = new RSSDigester();
                String url = (String) channels.get(i);
                // Add application path if needed
                if (url.startsWith("/")) {
                    url = toFullUrl(request, url);
                }
                log.debug("Channel url=" + url);
                Channel obj = (Channel) digester.parse(url);
                log.debug("Channel:" + obj);
                channelBeans.add(obj);
            }
           
        } catch (Throwable t) {
            errors.add(ActionMessages.GLOBAL_MESSAGE, new ActionMessage("rss.access.error"));
            servlet.log(t.toString());
        }

        // -- Handle Errors ---
        if (!errors.isEmpty()) {
            this.saveErrors(request, errors);
            // If no input page, use error forwarding
            log.debug("Exit Rss Channel Action : error");
            return null;
        }

        // -- Save Bean, and Continue  ---
        log.debug("Exit Rss Channel Action");

        // Use Tile context to pass channels
        context.putAttribute(CHANNELS_KEY, channelBeans);

        return null;
    }

    /**
     * Compute Full local url from an url starting with "/".
     */
    private String toFullUrl(HttpServletRequest request, String url) {
        StringBuffer buff = new StringBuffer();
        buff.append(request.getScheme()).append("://").append(request.getServerName());
        if (request.getServerPort() != 80) {
            buff.append(":").append(request.getServerPort());
        }
        buff.append(request.getContextPath()).append(url);
        return buff.toString();
    }
}


View:
把Tile的CHANNELS屬性中得到數據迭代顯示出來。
<%--
/**
* Summarize channels as unadorned HTML.
*
* @param CHANNELS List of channels
*/
--%>
<%@ page language="java" %>
<%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
<%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>
<div align="center"><font size="+1"><b>
<tiles:importAttribute name="CHANNELS" scope="page"/>
<logic:iterate name="CHANNELS" id="CHANNEL" >
<TABLE border="0" cellspacing="0" cellpadding="4" width="100%" align="center" >
<TR>
<TD class="spanhd" ><logic:present name="CHANNEL" property="image">
<a href="<bean:write name="CHANNEL" property="link"/>">
<img src="<bean:write name="CHANNEL" property="image.URL"/>"></logic:present></a>
</TD>
<TD class="spanhd" width="100%"><bean:write name="CHANNEL" property="title"/> <a
href="<bean:write name="CHANNEL" property="link"/>">[home]</a></TD>
</TR>
<TD class="yellow" colspan="2"><bean:write name="CHANNEL" property="description"/></TD>
</TR>
<TR>
<TD class="datagrey" colspan="2">
<logic:iterate name="CHANNEL" property="items" id="ITEM">
<br><b><bean:write name="ITEM" property="title"/></b>
<br><bean:write name="ITEM" property="description"/>
<br>&nbsp;&nbsp;[ <a href="<bean:write name="ITEM" property="link"/>">more</a> ]
<br>
</logic:iterate>
</TD>
</TR>
</TABLE>
<br>
</logic:iterate>
</b></font></div>

從這個例子中可以看到,要更換channel,只需改變Tile definition中<putList>的值。

總結篇

一.) 常用到的layout
Tiles有個令人感興趣的地方,它可以複用現有的layout,定義一個新的layout,簡單改變一下屬性設置就可以擴展一個layout。對於一個layout,只不過是以現有頁面爲基礎,抽取並提供一些屬性的描述。
注:在jakarta-struts-1.2.2中的tiles-documentation.war有相關的代碼。

    1. Classic layout
      這個layout經常會被web站點採用。它提供典型的"header, menu, body ,footer",用<header>和<body>做爲HTML頁面的骨架,在恰當的地方放置header、menu、body、footer。
      • 所需屬性:
        tiltle - String類型;
        header、menu、body、footer - URL或definition名稱。
      • 調用layout的代碼:
         <tiles:insert page="/layouts/classicLayout.jsp" flush="true">
         <tiles:put name="title" value="Browser Title" />
         <tiles:put name="header" value="/header.jsp" />
         <tiles:put name="footer" value="/footer.jsp" />
         <tiles:put name="menu" value="/menu.jsp" />
         <tiles:put name="body" value="definition.name" />
         </tiles:insert>

        也能夠在definition中調用:
         <definition name="mainLayout" path="/layouts/classicLayout.jsp">
         <put name="title" value="Browser Title" />
         <put name="header" value="/header.jsp" />
         <put name="footer" value="/footer.jsp" />
         <put name="menu" value="menu.main" />
         <put name="body" value="main.portal.body" />
         </definition>

      • layout的代碼:
         <HTML>
         <HEAD>
         <link rel=stylesheet href="<%=request.getContextPath()%>/layouts/stylesheet.css" type="text/css">
         <title><tiles:getAsString name="title"/></title>
         </HEAD>
         <body bgcolor="#ffffff" text="#000000" link="#023264" alink="#023264" vlink="#023264">
         <table border="0" width="100%" cellspacing="5">
         <tr><td colspan="2"><tiles:insert attribute="header" /></td>
         </tr>
         <tr><td width="140" valign="top"><tiles:insert attribute='menu'/></td>
         <td valign="top" align="left"><tiles:insert attribute='body' /></td>
         </tr>
         <tr><td colspan="2"><tiles:insert attribute="footer" /></td>
         </tr>
         </table></body></html>

    2. Menu Layout
      這個layout用於帶有鏈接的菜單。一個菜單需要一個"item" bean列表,每個"item"包含一個子菜單的數據。可以用一個屬性相同的menu layout來代替另一種menu layout(例如可以用vbox layout構建一個垂直的menu,下面會講到)。
      • 所需屬性
        title - String類型,做爲菜單標題(可選)。
        items - List類型,Items 是帶有vlaue、link、tooltip、icon參數的bean。
      • 調用layout的代碼:
         <definition name="examples.menu.settings" path="/layouts/menu.jsp" >
         <put name="title" value="Preferences" />
         <putList name="items" >
         <item value="my Portal Settings" link="/examples/myPortalSettings.jsp" classtype="org.apache.struts.tiles.beans.SimpleMenuItem" />
         <item value="my Menu Settings" link="/examples/myMenuSettings.jsp" classtype="org.apache.struts.tiles.beans.SimpleMenuItem" />
         </putList>
         </definition>

        definition中描述了兩個屬性:tilte和list。list是一個item bean 列表,每個item相當於菜單中的一個選項,包含一些參數,value表示選項的標題,link表示鏈接。
      • layout的代碼:
         <%@ taglib uri="/WEB-INF/struts-logic.tld" prefix="logic" %>
         <%@ taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
         <%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>
         <%@ page import="java.util.Iterator" %>

         <%-- Push tiles attributes in page context --%>
         <tiles:importAttribute /><table>
         <logic:present name="title">
         <tr><th colspan=2>
         <div align="left"><strong><tiles:getAsString name="title"/></strong></div></th>
         </tr>
         </logic:present>
         <%-- iterate on items list --%>
         <logic:iterate id="item" name="items" type="org.apache.struts.tiles.beans.MenuItem" >
         <% // Add site URL if link starts with "/"
         String link = item.getLink();
         if(link.startsWith("/") ) link = request.getContextPath() + link;
         %>
         <tr><td width="10" valign="top" ></td>
         <td valign="top" ><font size="-1"><a href="<%=link%>">
         <logic:notPresent name="item" property="icon"><%=item.getValue()%></logic:notPresent>
         <logic:present name="item" property="icon">
         <% // Add site URL if link starts with "/"
         String icon = item.getIcon();
         if(icon.startsWith("/") ) icon = request.getContextPath() + icon;
         %>
         <img src='<%=request.getContextPath()%><bean:write name="item" property="icon" scope="page"/>'
         alt='<bean:write name="item" property="tooltip" scope="page" ignore="true"/>' />
         </logic:present></a></font></td>
         </tr>
         </logic:iterate></table>

    3. VBox 或 VStack Layout
      這個layout用於垂直的顯示Tile列表,常被菜單條或multi - columns layout採用。
      • 所需屬性
        list - 要插入的列表名稱或URL
      • 調用的layout代碼:
         <definition name="examples.menu.bar" path="/layouts/vboxLayout.jsp" >
         <putList name="list" >
         <add value="examples.userMenu" />
         <add value="examples.menu.links" />
         <add value="doc.menu.links" />
         <add value="examples.menu.settings" />
         <add value="doc.menu.taglib.references" />
         <add value="doc.menu.printer.friendly" />
         <add value="examples.menu.admin" />
         </putList>

      • layout代碼:
         <%@ page import="java.util.Iterator"%>
         <%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>
         <tiles:useAttribute id="list" name="list" classname="java.util.List" />
         <%  // 用Tile 屬性初始化一個腳本變量。
               // 這裏不使用<logic:iterate>標籤,因爲在JSP1.1不允許這麼做。
         <%
         Iterator i=list.iterator();
         while( i.hasNext() )
         {
         String name= (String)i.next();
         %>
         <tiles:insert name="<%=name%>" flush="true" />
         <br>
         <%
         } // end loop
         %>

    4. Multi-columns Layout
      這個layout垂直顯示Tile多行列表。每一行代表一個列表,常用來構建多個Tile主體的入口。
      • 所需屬性
        numCols - 行數
        list1 - 第一個Tile列表
        list2、list3、listn - 第n個Tile類別(可選)
      • 調用的代碼:
         <definition name="examples.portal.body" path="/layouts/columnsLayout.jsp" controllerUrl="/portal/myPortal.do" >
         <put name="numCols" value="2" />
         <putList name="list0" >
         <add value="/examples/tiles/portal/login.jsp" />
         <add value="/examples/tiles/portal/messages.jsp" />
         <add value="/examples/tiles/portal/newsFeed.jsp" />
         </putList>
         <putList name="list1" >
         <add value="/examples/tiles/portal/advert3.jsp" />
         <add value="/examples/tiles/portal/stocks.jsp" />
         <add value="/examples/tiles/portal/whatsNew.jsp" />
         <add value="/examples/tiles/portal/advert2.jsp" />
         </putList>
         </definition>

      • layout的代碼:
         <tiles:useAttribute id="numColsStr" name="numCols" classname="java.lang.String" />
         <table>
         <tr>
         <%
         int numCols = Integer.parseInt(numColsStr);
         ComponentContext context = ComponentContext.getContext( request );
         for( int i=0; i<numCols; i++ )
         {
         java.util.List list=(java.util.List)context.getAttribute( "list" + i );
         pageContext.setAttribute("list", list );
         if(list==null)
         System.out.println( "list is null for " + i );
         %>
         <td valign="top">
         <tiles:insert page="/layouts/vboxLayout.jsp" flush="true" >
         <tiles:put name="list" beanName="list" beanScope="page" />
         </tiles:insert>
         </td>
         <%
         } // end loop
         %>
         </tr>
         </table>

        這邊同樣也不能使用<logic:iterate>標籤,在JSP1.1不允許在一個標記體內插入另一個頁面。
    5. Center Layout
      這個layout常由"top, left, center, right, bottom"組成,left和right部分是可選的。
      • 所需屬性
        header、body、footer - 用difinition名稱或URL顯示相應的部分。
        right、left - 用difinition名稱或URL顯示相應的部分(可選)。
      • 調用layout的代碼:和classic layout類似
         <tiles:insert page="/layouts/centerLayout.jsp" flush="true">
         <tiles:put name="header" value="/header.jsp" />
         <tiles:put name="footer" value="/footer.jsp" />
         <tiles:put name="right" value="/menu.jsp" />
         <tiles:put name="left" value="/menuLeft.jsp" />
         <tiles:put name="body" value="definition.name" />
         </tiles:insert>

        也可以忽略left和right部分:
         <tiles:insert page="/layouts/centerLayout.jsp" flush="true">
         <tiles:put name="header" value="/header.jsp" />
         <tiles:put name="footer" value="/footer.jsp" />
         <tiles:put name="body" value="definition.name" />
         </tiles:insert>

      • layout的代碼:
         <%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>
         <table border="0" width="100%" cellspacing="5">
         <tr>
         <td colspan="3"><tiles:insert attribute="header" /></td>
         </tr>
         <tr>
         <td width="140" valign="top">
         <tiles:insert attribute=right ignore='true'/>
         </td>
         <td valign="top" align="left">
         <tiles:insert attribute='body' />
         </td>
         <td valign="top" align="left">
         <tiles:insert attribute='left' ignore='true'/>
         </td>
         </tr>
         <tr>
         <td colspan="3">
         <tiles:insert attribute="footer" />
         </td>
         </tr>
         </table>

    6. Tabs Layout
      這個layout用表格的形式來呈現Tile類表。Tabs Layout有一個body區域,用來顯示當前被選中的Tile;還有一個索引區域,顯示可用的表格或Tile。
      • 所需屬性
        tabList - 列表的URL或definition名稱,我們用MenuItem來存儲數據。
        selectedIndex - 默認被選中的表格
        parameterName - HTTP參數名,在HTTP request中存儲選中的Tile信息。
      • 調用layout的代碼:創建了帶有三個索引的tab layout
         <definition name="examples.tabs.body" path="/layouts/tabsLayout.jsp" >
         <put name="selectedIndex" value="0" />
         <put name="parameterName" value="selected" />
         <putList name="tabList" >
         <item value="Doc Home" link="/index.jsp" classtype="org.apache.struts.tiles.beans.SimpleMenuItem" />
         <item value="Quick overview" link="/doc/quickOverview.jsp" classtype="org.apache.struts.tiles.beans.SimpleMenuItem" />
         <item value="Tutorial" link="/doc/tutorial.jsp" classtype="org.apache.struts.tiles.beans.SimpleMenuItem" />
         </putList>
         </definition>

      • layout的代碼:
         <%@ taglib uri="/WEB-INF/tiles.tld" prefix="tiles" %>
         <tiles:useAttribute name="parameterName" classname="java.lang.String" />
         <tiles:useAttribute id="selectedIndexStr" name="selectedIndex" ignore="true" classname="java.lang.String" />
         <tiles:useAttribute name="tabList" classname="java.util.List" />
         <%
         String selectedColor="#98ABC7";
         String notSelectedColor="#C0C0C0";
         int index = 0; // Loop index
         int selectedIndex = 0;
         // Check if selected come from request parameter
         try {
         selectedIndex = Integer.parseInt(selectedIndexStr);
         selectedIndex = Integer.parseInt(request.getParameter( parameterName ));
         }
         catch( java.lang.NumberFormatException ex )
         { // do nothing
         }
         // Check selectedIndex bounds
         if( selectedIndex < 0 || selectedIndex >= tabList.size() ) selectedIndex = 0;
         String selectedBody =
         ((org.apache.struts.tiles.beans.MenuItem)tabList.get(selectedIndex)).getLink(); // Selected body
         %><table border="0" cellspacing="0" cellpadding="0">
         <%-- Draw tabs --%>
         <tr><td width="10"">&nbsp;</td>
         <td>
         <table border="0" cellspacing="0" cellpadding="5">
         <tr><logic:iterate id="tab" name="tabList" type="org.apache.struts.tiles.beans.MenuItem" >
         <% // compute href
         String href = request.getRequestURI() + "?"+parameterName + "=" + index;
         String color = notSelectedColor;
         if( index == selectedIndex )
         {
         selectedBody = tab.getLink();
         color = selectedColor;
         } // enf if
         index++;
         %>
         <td bgcolor="<%=color%>"><a href="<%=href%>" /><%=tab.getValue()%></a></td>
         <td width="1" ></td>
         </logic:iterate>
         </tr></table></td>
         <td width="10" >&nbsp;</td></tr>
         <tr><td height="5" bgcolor="<%=selectedColor%>" colspan="3" >&nbsp;</td></tr>
         <%-- Draw body --%>
         <tr><td width="10" bgcolor="<%=selectedColor%>">&nbsp;</td>
         <td><tiles:insert name="<%=selectedBody%>" flush="true" /></td>
         <td width="10" bgcolor="<%=selectedColor%>">&nbsp;</td></tr>
         <tr><td height="5" bgcolor="<%=selectedColor%>" colspan="3" >&nbsp;</td>
         </tr></table>

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章