使用 JSF 組件的樣式屬性
幾乎每個 JSF HTML 組件都有兩個可選屬性,分別為 style
和 styleClass
,這兩個屬性在 HTML 輸出中呈現為 style
和 class
屬性。一些組件,比如 <h:dataTable>
和 <h:panelGrid>
,還有針對于其 facet 的額外樣式屬性。本節討論與 CSS 相關的 JSF HTML 庫屬性。
將 CSS 文件鏈接到 JSF 頁面
如果 Web 頁面具有獨特的樣式,可以在頁面頁眉的 <style>
元素內定義樣式規則。也可以使用 style
屬性為單個 JSF 組件指定樣式信息。但在大多數情況下,您可能更愿意在單獨的 CSS 文件中包含樣式規則,以便可以將這些樣式規則應用到多個頁面。可以使用 <link>
標記將外部樣式表鏈接到一個 Web 頁面,如清單 1 所示:
清單 1. 使用 <link> 標記
<link rel="stylesheet" type="text/css"
href="${pageContext.request.contextPath}/MyStyles.css">
<link rel="stylesheet" type="text/css"
href="<%=request.getContextPath()%>/styles/MoreStyles.css">
|
|
使用 MyFaces Tomahawk
如果更愿意使用 JSF 組件,而非 HTML 標記,則可以使用 MyFaces Tomahawk 的 <t:stylesheet> 組件,該組件可以呈現 <link> 標記。
|
|
在清單 1 中,href
屬性包含絕對 URI。也可以為 CSS 文件使用相對鏈接,但如果 JSF 頁面包含 /faces/
前綴,最好是在上下文路徑中包含 ${pageContext.request.contextPath}
或 <%=request.getContextPath()%>
。在這種情況下,任何鏈到 CSS 文件、圖像或其他資源的相對鏈接都將導致一個包含 /faces/
前綴的 HTTP 請求,這意味著非 JSF 文件將由 Faces servlet 處理。這雖然可以工作,但效率并不高。若使用 .faces
后綴請求 JSF 頁面,則盡可以放心地在基于 JSF 的應用程序中使用相對鏈接,因為這樣可以消除上述問題。
定義和使用樣式規則
CSS 文件包含一些樣式表規則,這些規則可以應用于 JSF 組件能夠呈現的 HTML 元素,也可以被簡單地包含在 JSF 頁面的組件之間。比如,如果希望只有將鼠標放到鏈接上時才出現下劃線,則可以使用如下規則(參見清單 2):
清單 2. 鏈接的樣式規則
a { text-decoration: none; }
a:hover { text-decoration: underline; }
|
這些規則可應用于任何鏈接,無論 <a>
元素是直接包含在 JSF 頁面還是由諸如 <h:commandLink>
這樣的 JSF 組件生成(參見清單 3):
清單 3. HTML 和 JSF 鏈接
<a href="LinkStyles.faces">HTML Link</a>
<h:commandLink value="JSF Link"/>
|
清單 4 給出了如何為 JSF 組件指定內聯樣式。
清單 4. 具有樣式屬性的 JSF 組件
<h:commandLink value="Red Link" style="color: red"/>
|
然而在大多數情況下,都是在 CSS 文件中定義樣式類(參見清單 5),以便可以將相同的樣式規則應用于多個組件。
清單 5. 樣式類示例
.GreenClass { color: green; }
|
此樣式類的名稱將會通過 styleClass
屬性提供給 JSF 組件,如清單 6 所示。
清單 6. 具有 styleClass 屬性的 JSF 組件
<h:commandLink value="Green Link" styleClass="GreenClass"/>
|
清單 1-6 的代碼可以從本文的示例代碼鏈接給出的 LinkStyles.jsp
和 LinkStyles.css
文件中找到(參見 下載)。
具有多個樣式類的 JSF 組件
正如之前所提到的,一些 JSF 組件具有多個樣式屬性。例如,<h:message>
和 <h:messages>
就有如下所示的 10 個與 CSS 相關的屬性:
-
style
-
styleClass
-
errorClass
-
errorStyle
-
fatalClass
-
fatalStyle
-
infoClass
-
infoStyle
-
warnClass
-
warnStyle
根據所呈現的消息的嚴重程度,只有兩個屬性會應用到每個消息。UISelectOne
和 UISelectMany
組件的 JSF 標記接受所呈現的列表項的 enabledClass
和 disabledClass
屬性。<h:dataTable>
和 <h:panelGrid>
標記 則有針對主表、頁眉、頁腳、行和列的類屬性。下面的示例展示了如何使用與 CSS 相關的數據表屬性,這個數據表在下面的屏幕截圖中給出。
圖 1. TableStyles 示例
首先,需要為這個表組件建立數據模型。OrderBean
類(如清單 7 所示)擴展了 javax.faces.model.ArrayDataModel
。實際的應用程序會從數據庫中獲得模型的數據,但為了簡便起見,OrderBean
將由一個靜態數組初始化。
清單 7. OrderBean 示例
package jsfcssjs;
import javax.faces.model.ArrayDataModel;
public class OrderBean extends ArrayDataModel {
private static ItemBean items[] = new ItemBean[] {
new ItemBean("Domain Name", 3, 7.99f),
new ItemBean("SSL Certificate", 1, 119.00f),
new ItemBean("Web Hosting", 1, 19.95f),
new ItemBean("Email Box", 20, 0.15f),
new ItemBean("E-Commerce Setup", 1, 25.00f),
new ItemBean("Technical Support", 1, 50.00f)
};
public OrderBean(){
super(items);
}
public float getTotalPrice(){
float total = 0;
for (int i = 0; i < items.length; i++)
total += items[i].getItemPrice();
return total;
}
}
|
ItemBean
類(參見清單 8)具有三個讀/寫屬性(description
、quantity
、unitPrice
)和一個只讀屬性(itemPrice
)。
清單 8. ItemBean 示例
package jsfcssjs;
public class ItemBean implements java.io.Serializable {
private String description;
private int quantity;
private float unitPrice;
public ItemBean(){
}
public ItemBean(String description, int quantity, float unitPrice){
this.description = description;
this.quantity = quantity;
this.unitPrice = unitPrice;
}
...
public float getItemPrice(){
return unitPrice * quantity;
}
}
|
TableStyles.css
文件(如清單 9 所示)包含用于此數據表的樣式。
清單 9. TableStyles.css 示例
body { font-family: Arial; }
.tablebg { background-color: #D0D0A0; }
.header { font-weight: bold; }
.footer { font-weight: bold; }
.text { text-align: left; }
.number { text-align: right; }
.graybg { background-color: #DDDDDD; }
.whitebg { background-color: #FFFFFF; }
|
TableStyles.jsp
示例(參見清單 10)包含一個 JSF 表組件,該組件使用在 TableStyles.css
中定義的樣式類。styleClass
屬性的值用于 <table>
元素。headerClass
和 footerClass
屬性為此表的頁眉和頁腳單元格指定樣式。columnClasses
屬性包含用于數據單元格的 <td>
元素的類的列表(用逗號分隔)。
另外一個類的列表通過 rowClasses
屬性指定。這些類用于此表的 <tr>
元素。在 TableStyles.jsp
示例中,只有兩個行類,但此表卻有 6 行。<h:dataTable>
組件的 JSF 呈現器會交替使用這兩個樣式類,為第一、三和五行使用 graybg
類,為第二、四和六行使用 whitebg
類。var
屬性定義一個變量,稱為 row
,可用來在呈現期間訪問當前行的數據。全部數據從 orderBean
模型獲得,該模型通過 value
屬性綁定到此表。
清單 10. TableStyles.jsp 示例
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<f:view>
<html>
<head>
<title>Order Table</title>
<link rel="stylesheet" type="text/css"
href="<%=request.getContextPath()%>/styles/TableStyles.css">
</head>
<body>
<h1>Order Table</h1>
<h:dataTable id="table" var="row" value="#{orderBean}"
styleClass="tablebg" headerClass="header" footerClass="footer"
columnClasses="text,number,number,number"
rowClasses="graybg,whitebg" border="0" cellpadding="5">
<h:column>
<f:facet name="header">
<h:outputText value="Description"/>
</f:facet>
<h:outputText value="#{row.description}"/>
<f:facet name="footer">
<h:outputText value="Total Price"/>
</f:facet>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Quantity"/>
</f:facet>
<h:outputText value="#{row.quantity}"/>
</h:column>
<h:column>
<f:facet name="header">
<h:outputText value="Unit Price"/>
</f:facet>
<h:outputText value="#{row.unitPrice}">
<f:convertNumber type="currency" currencyCode="USD"
minFractionDigits="2" maxFractionDigits="2"/>
</h:outputText>
</h:column>
<h:column footerClass="footer number">
<f:facet name="header">
<h:outputText value="Item Price"/>
</f:facet>
<h:outputText value="#{row.itemPrice}">
<f:convertNumber type="currency" currencyCode="USD"
minFractionDigits="2" maxFractionDigits="2"/>
</h:outputText>
<f:facet name="footer">
<h:outputText value="#{orderBean.totalPrice}">
<f:convertNumber type="currency" currencyCode="USD"
minFractionDigits="2" maxFractionDigits="2"/>
</h:outputText>
</f:facet>
</h:column>
</h:dataTable>
</body>
</html>
</f:view>
|
清單 11 給出了由 TableStyles.jsp
頁面生成的 HTML。
清單 11. 由 TableStyles.jsp 生成的 HTML
<html>
<head>
<title>Order Table</title>
<link rel="stylesheet" type="text/css"
href="/jsf12css/styles/TableStyles.css">
</head>
<body>
<h1>Order Table</h1>
<table id="table" class="tablebg" border="0" cellpadding="5">
<thead>
<tr>
<th class="header" scope="col">Description</th>
<th class="header" scope="col">Quantity</th>
<th class="header" scope="col">Unit Price</th>
<th class="header" scope="col">Item Price</th>
</tr>
</thead>
<tfoot>
<tr>
<td class="footer">Total Price</td>
<td class="footer"></td>
<td class="footer"></td>
<td class="footer number">$240.92</td>
</tr>
</tfoot>
<tbody>
<tr class="graybg">
<td class="text">Domain Name</td>
<td class="number">3</td>
<td class="number">$7.99</td>
<td class="number">$23.97</td>
</tr>
<tr class="whitebg">
<td class="text">SSL Certificate</td>
<td class="number">1</td>
<td class="number">$119.00</td>
<td class="number">$119.00</td>
</tr>
<tr class="graybg">
...
</tr>
<tr class="whitebg">
...
</tr>
<tr class="graybg">
...
</tr>
<tr class="whitebg">
...
</tr>
</tbody>
</table>
</body>
</html>
|
TableStyles.jsp
示例中的 JSF 表的最后一個 <h:column>
組件使用 footerClass
屬性為顯示訂單總額的頁腳單元格指定兩個類。footer
和 number
類將會用于頁腳單元格的 <td>
元素。<h:column>
組件的 footerClass
屬性只在 JSF 1.2 中可用。如果使用的是較早的 JSF 版本,則必須包裝能在 <div>
元素內呈現總額的 <h:outputText>
組件,以便可以添加 number
類的對齊效果(參見清單 12)。源代碼的壓縮文件包含針對 JSF 1.1 和 JSF 1.2 的代碼示例。
清單 12. JSF 1.1 版本的 TableStyles.jsp 示例
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<f:view>
...
<h:dataTable ...>
...
<h:column>
...
<f:facet name="footer">
<h:panelGroup>
<f:verbatim><div class="number"></f:verbatim>
<h:outputText value="#{orderBean.totalPrice}">
<f:convertNumber type="currency" currencyCode="USD"
minFractionDigits="2" maxFractionDigits="2"/>
</h:outputText>
<f:verbatim></div></f:verbatim>
</h:panelGroup>
</f:facet>
</h:column>
</h:dataTable>
...
</f:view>
|
為 JSF 組件設置默認樣式
在構建具有很多 JSF 頁面的大型應用程序時,您可能不喜歡手動設置每個組件實例的 styleClass
屬性。標準的 JSF HTML 組件沒有默認樣式,但是您將在本節中看到,可以遍歷此 JSF 組件樹并程序化地設置默認的樣式類。要實現此操作,需要知道這些樹是如何創建的以及此 HTML 是如何生成的。
理解 JSF 組件樹如何構建
所有的 face 請求均由 Faces Servlet 截獲,這是在每個基于 JSF 的 Web 應用程序的 web.xml
描述符中配置的。對于每個請求,Faces Servlet 都會初始化 javax.faces.context.FacesContext
對象并調用 javax.faces.lifecycle.Lifecycle
實例的 execute()
和 render()
方法。execute()
方法處理 JSF 請求處理生命周期中除最后一個階段(Render Response)之外的每個階段,最后的這個階段由 render()
方法執行。
|
狀態保存方法
根據 javax.faces.STATE_SAVING_METHOD 上下文參數的值(可在 web.xml 文件中設置),組件樹或者保存于服務器或者保存于客戶機。JSF 實現可以使用 session 范圍在服務器端保存此組件樹。此方法很有效,但若用戶單擊了瀏覽器的后退
按鈕返回到已經提交的表單,此 JSF
框架就會陷入困惑。最好是在客戶機端保存每個組件樹,客戶機端的一個隱藏的表單元素保存與此頁面實例相關的樹的序列化后的副本。在客戶機端保存組件樹會增
加流量,并且需要額外的 CPU 資源來對對象樹進行序列化和去序列化,但是與使用 session 范圍相比,這種方法更加可靠。
|
|
在第一個階段(名為 Restore View),JSF 實現獲取應用程序的視圖處理程序,它是一個 javax.faces.application.ViewHandler
實例,如果請求是一個 post back(比如,用戶單擊了提交按鈕),還會調用 restoreView()
方法。在這種情況下,此組件樹應該在處理之前的 Faces 請求期間構造和保存(參見側欄 狀態保存方法)。
如果當前的請求不是一個 post back(比如,用戶單擊了一個 Faces 鏈接),JSF 實現調用當前 FacesContext
的 renderResponse()
方法和 ViewHandler
實例的 createView()
方法。renderResponse()
調用會指導 JSF 實現由當前的 Restore View 階段跳到 Render Response 階段。默認視圖處理程序的 createView()
方法只創建一個 javax.faces.component.UIViewRoot
組件。此樹的其余部分將會在 Render Response 階段創建,在該階段 JSF 實現調用視圖處理程序的 renderView()
方法。
不管是恢復還是創建組件樹,JSF 實現都會在 renderView()
方法執行期間的某個階段將 HTTP 請求轉發給相關的 JSF 頁面。比如,如果請求 /MyApp/MyPage.faces
或 /MyApp/faces/MyPage.jsp
,那么所執行的 JSF 頁面的 URI 就是 /MyApp/MyPage.jsp
。
任何 JSF 頁面都包含組件標記,比如 <f:view>
和 <h:form>
,這些標記都受 JSP 標記處理程序支持。這是一些 Java™ 類,它們實現在 javax.servlet.jsp.tagext
包中定義的接口。當執行此頁時,JSP 容器會創建標記處理程序的實例并調用它們的方法。JSF 1.2 組件的所有標記處理程序都擴展了 javax.faces.webapp.UIComponentELTag
。如果使用的是 JSF 1.1 API,則此標記處理程序類擴展 javax.faces.webapp.UIComponentTag
或
javax.faces.webapp.UIComponentBodyTag
。不管使用的是哪個 JSF 版本,如果組件樹沒有在 Restore View 階段恢復,JSF 標記處理程序將會在 Render Response 階段創建組件實例。
您可能會嘗試通過實現 javax.faces.event.PhaseListener
來設置默認的樣式,但當用戶以單擊鏈接或在 Web 瀏覽器中輸入 URL 的方式請求頁面時,這種方法不會生效。在這種情況下,JSF
實現不能恢復組件樹,此樹必須在 Render Response
階段創建。在最后階段之前,組件樹并不存在,在呈現了響應之后再更新組件樣式就太晚了,因為 HTML
輸出已經生成。因此,默認的樣式必須在呈現組件之前的 Render Response 階段執行期間設置。
在呈現之前遍歷組件樹
JSF 組件有一個有趣的只讀屬性,稱為 rendersChildren
。如果該屬性為 false
,只有 encodeBegin()
和 encodeEnd()
方法會被調用來呈現此組件。如果 getRendersChildren()
返回 true
,那么 encodeChildren()
也會在 Render Response 階段被調用。這些方法通常會將呈現指派給另一個類,該類必須實現 javax.faces.render.Renderer
接口,但 JSF 組件也可以生成 HTML,無需使用呈現器。
當使用 JSF 1.1 時,編碼方法最初都由標記處理程序方法調用。但是,如果組件呈現自身的子組件,那么嵌套組件的所有標記處理程序都會停止調用編碼方法,因為呈現將會由另一些組件負責,這些組件的 getRendersChildren()
方法返回 true
。這種在 JSF 1.1 中實現的呈現過程十分有效,因為它將緩沖降到了最低,但它需要應用程序開發人員在 <f:verbatim>
組件中包含 HTML 內容。在 JSF 1.2 中,由于呈現只會在整個組件樹創建之后才執行,所以不需要使用 <f:verbatim>
。
不管使用的是 JSF 1.1 還是 1.2,只要調用了 encodeChildren()
,嵌套組件都會被完全初始化并準備好被呈現。因此,此時就是設置默認樣式的最佳時機。接下來,您會看到如何創建一個定制組件來為它的所有嵌套組件設置 styleClass
屬性,遞歸遍歷 JSF 組件樹。
這里所展示的技巧可以用來設置 JSF 組件的任何屬性,而不僅僅是默認的樣式。因而,最好是創建一個可重用的通用基類。SetupComponent
類擴展 JSF API 的 UIComponentBase
類,并定義一個名為 setup()
的抽象方法,可以對支持呈現的每個嵌套組件調用該方法。setupTree()
方法(如清單 13 所示)執行 JSF 組件樹的遞歸遍歷。
清單 13. SetupComponent 類的 setup() 和 setupTree() 方法
package jsfcssjs;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.context.FacesContext;
...
public abstract class SetupComponent extends UIComponentBase {
protected abstract void setup(FacesContext ctx, UIComponent comp);
protected void setupTree(FacesContext ctx, UIComponent comp){
if (!comp.isRendered())
return;
setup(ctx, comp);
for (UIComponent child : comp.getChildren())
setupTree(ctx, child);
}
...
}
|
繼承自 UIComponentBase
的 getRendersChildren()
方法(參見清單 14)被覆蓋以返回 true
,以便設置組件能夠控制其子組件的呈現。
清單 14. SetupComponent 類的 getRendersChildren()方法
public abstract class SetupComponent extends UIComponentBase {
...
public boolean getRendersChildren(){
return true;
}
...
}
|
清單 15 中所示的 encodeChildren()
方法被覆蓋,以便在為每個子組件調用 encodeTree()
之前調用 setupTree()
。
清單 15. SetupComponent 類的 encodeChildren() 方法
public abstract class SetupComponent extends UIComponentBase {
...
public void encodeChildren(FacesContext ctx)
throws IOException {
if (!isRendered())
return;
setupTree(ctx, this);
for (UIComponent child : getChildren())
encodeTree(ctx, child);
}
...
}
|
encodeTree()
方法(參見清單 16)為當前組件調用編碼方法,如果 getRendersChildren()返回 false
,則還會為子組件遞歸調用此方法。
清單 16. SetupComponent 類的 encodeTree() 方法
public abstract class SetupComponent extends UIComponentBase {
...
protected void encodeTree(FacesContext ctx, UIComponent comp)
throws IOException {
if (!comp.isRendered())
return;
comp.encodeBegin(ctx);
if (comp.getRendersChildren())
comp.encodeChildren(ctx);
else
for (UIComponent child : comp.getChildren())
encodeTree(ctx, child);
comp.encodeEnd(ctx);
}
}
|
創建和配置一個定制組件
清單 17 中所示的 DefaultStylesComponent
類擴展 SetupComponent
并實現 setup()
方法,以設置 styleClass
屬性,此屬性的值構建在組件系列的名稱和呈現器的名稱之上。
清單 17. DefaultStylesComponent 類
package jsfcssjs;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import java.util.Map;
public class DefaultStylesComponent extends SetupComponent {
protected void setup(FacesContext ctx, UIComponent comp){
Map<String, Object> attrMap = comp.getAttributes();
if (attrMap.get("styleClass")!= null)
return;
String familyName = getLastName(comp.getFamily());
String rendererName = getLastName(comp.getRendererType());
if (familyName == null || rendererName == null)
return;
String className = "Default" + familyName;
if (!familyName.equals(rendererName))
className += rendererName;
attrMap.put("styleClass", className);
}
protected String getLastName(String fullName){
if (fullName == null)
return null;
int dotIndex = fullName.lastIndexOf('.');
if (dotIndex != -1)
return fullName.substring(dotIndex+1);
else
return fullName;
}
public String getFamily(){
return "DefaultStyles";
}
}
|
DefaultStylesComponent
在 faces-config.xml
中配置,如清單 18 所示。
清單 18. 在 faces-config.xml 中配置 DefaultStylesComponent
<faces-config ...>
...
<component>
<component-type>DefaultStylescomponent</component-type>
<component-class>jsfcssjs.DefaultStylesComponent</component-class>
<component-extension>
<component-family>DefaultStyles</component-family>
</component-extension>
</component>
</faces-config>
|
實現定制標記
DefaultStylesTag
類(參見清單 19)擴展由 JSF 1.2 API 定義的
UIComponentELTag
類,并實現 getComponentType()
和 getRendererType()
方法以分別返回 DefaultStylesComponent
和 null
。如果使用的是 JSF 1.1,標記類必須擴展 UIComponentTag
,而非 UIComponentELTag
。
清單 19. DefaultStylesTag 類
package jsfcssjs;
import javax.faces.webapp.UIComponentELTag;
public class DefaultStylesTag extends UIComponentELTag {
public String getComponentType(){
return "DefaultStylesComponent";
}
public String getRendererType(){
return null;
}
}
|
css.tld
文件(如清單 20 所示)定義了定制標記的 defaultStyles
名稱和屬性。對 id
、binding
和 rendered
屬性的支持均繼承自 UIComponentELTag
。
清單 20. 用于 JSF 1.2 和 JSP 2.1 的 css.tld 文件
<?xml version="1.0" encoding="UTF-8" ?>
<taglib xmlns="http://java.sun.com/xml/ns/javaee" ... version="2.1">
<tlib-version>1.0</tlib-version>
<short-name>css</short-name>
<uri>/css.tld</uri>
<tag>
<name>defaultStyles</name>
<tag-class>jsfcssjs.DefaultStylesTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>id</name>
<required>false</required>
<rtexprvalue>true</rtexprvalue>
</attribute>
<attribute>
<name>binding</name>
<required>false</required>
<deferred-value>
<type>jsfcssjs.DefaultStylesComponent</type>
</deferred-value>
</attribute>
<attribute>
<name>rendered</name>
<required>false</required>
<deferred-value>
<type>boolean</type>
</deferred-value>
</attribute>
</tag>
</taglib>
|
如果使用的是 JSF 1.1,TLD 文件應該遵從 JSP 1.2 規范定義的語法(參見清單 21)。
清單 21. 用于 JSF 1.1 和 JSP 1.2 的 css.tld 文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE taglib
PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.2//EN"
"http://java.sun.com/dtd/web-jsptaglibrary_1_2.dtd">
<taglib>
<tlib-version>1.0</tlib-version>
<jsp-version>1.2</jsp-version>
<short-name>css</short-name>
<uri>/css.tld</uri>
<tag>
<name>defaultStyles</name>
<tag-class>jsfcssjs.DefaultStylesTag</tag-class>
<body-content>JSP</body-content>
<attribute>
<name>id</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>binding</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
<attribute>
<name>rendered</name>
<required>false</required>
<rtexprvalue>false</rtexprvalue>
</attribute>
</tag>
</taglib>
|
在 JSF 頁使用定制組件
|
developerWorks Ajax 資源中心
訪問 Ajax 資源中心,這是一個一站式中心,其中包含開發 Ajax 應用程序所需的免費工具、代碼和信息。活躍 Ajax 社區論壇 可能有針對您的問題的答案,該論壇由 Ajax 專家 Jack Herrington 主持。
|
|
本節中給出的 JSF 示例展示了如何使用背景顏色和邊框來增強 JSF 組件的外觀。
圖 2. DefaultStyles 示例
清單 22 展示的是 DefaultStyles.css
文件,該文件定義了幾個用于 DefaultStyles.jsp
示例的樣式類。
清單 22. DefaultStyles.css 示例
.DefaultForm {}
.DefaultPanelGrid { background-color: #FFFFFF; }
.DefaultInputText { background-color: #FFDDDD;
border-style: ridge; border-width: thin; }
.DefaultInputTextarea { background-color: #DDFFDD;
border-style: groove; border-width: thick; }
.DefaultSelectOneMenu { background-color: #DDDDFF;
border-style: inset; border-width: medium; }
.DefaultCommandButton { background-color: #DDDDDD;
border-style: outset; border-width: medium; }
.SpecialInputText { background-color: #DDFFFF;
border-style: double; border-width: thick; }
.EnabledOption { color: #FF0000; }
.DisabledOption { color: #0000FF; }
|
DefaultStyles.jsp
示例 (參見清單 23)使用了 <css:defaultStyles>
組件為不具有 styleClass
屬性的 JSF 組件設置默認樣式。其中的一個組件使用 SpecialInputText
樣式類。EnabledOption
和 DisabledOption
類用于下拉列表項。
清單 23. DefaultStyles.jsp 示例
<%@ taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
<%@ taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
<%@ taglib prefix="css" uri="/css.tld" %>
<f:view>
<html>
<head>
<title>Default Styles</title>
<link rel="stylesheet" type="text/css"
href="<%=request.getContextPath()%>/styles/DefaultStyles.css">
</head>
<body>
<h1>Default Styles</h1>
<css:defaultStyles>
<h:form id="form">
<h:panelGrid columns="1" border="0" cellspacing="5">
<h:inputText id="text" size="30" value="default text style"/>
<h:inputText id="special" size="30" value="special text style"
styleClass="SpecialInputText"/>
<h:selectOneMenu id="menu" enabledClass="EnabledOption"
disabledClass="DisabledOption">
<f:selectItem itemValue="First" itemLabel="First"/>
<f:selectItem itemValue="Second" itemLabel="Second"/>
<f:selectItem itemValue="Third" itemLabel="Third"
itemDisabled="true"/>
</h:selectOneMenu>
<h:inputTextarea id="area" rows="5" cols="30"
value="default text area style"/>
<h:commandButton id="button" value="Submit"/>
</h:panelGrid>
</h:form>
</css:defaultStyles>
</body>
</html>
</f:view>
|
清單 24 給出了由 DefaultStyles.jsp
頁面產生的 HTML。您將注意到所有的表單元素都有一個 class
屬性。以 Default
開始的那些類名均由 <css:defaultStyles>
組件設置。
清單 24. DefaultStyles.jsp 產生的 HTML
<html>
<head>
<title>Default Styles</title>
<link rel="stylesheet" type="text/css"
href="/jsf12css/styles/DefaultStyles.css">
</head>
<body>
<h1>Default Styles</h1>
<form id="form" ... class="DefaultForm" ...>
<input type="hidden" name="form" value="form" />
<table class="DefaultPanelGrid" border="0" cellspacing="5">
<tbody>
<tr>
<td><input id="form:text" type="text" ...
class="DefaultInputText" .../></td>
</tr>
<tr>
<td><input id="form:special" type="text" ...
class="SpecialInputText" .../></td>
</tr>
<tr>
<td><select id="form:menu" ... class="DefaultSelectOneMenu" ...>
<option value="First" class="EnabledOption">First</option>
<option value="Second" class="EnabledOption">Second</option>
<option value="Third" disabled="disabled"
class="DisabledOption">Third</option>
</select></td>
</tr>
<tr>
<td><textarea id="form:area" ...
class="DefaultInputTextarea" ...> ... </textarea></td>
</tr>
<tr>
<td><input id="form:button" type="submit" ...
class="DefaultCommandButton" /></td>
</tr>
</tbody>
</table>
<input type="hidden" ... id="javax.faces.ViewState" value="..." />
</form>
</body>
</html>
|
結束語
本文討論了標準 JSF 組件提供的 CSS 支持。簡單的組件只有兩個可選屬性,分別為 style
和 styleClass
。
更復雜的組件,比如網格和數據表,則會有針對其 facet 和元素的額外的 CSS 屬性。本系列的這一部分還介紹了 JSF
如何構建組件樹,以及如何在組件呈現之前遍歷這些組件樹以便可以添加特性,比如默認樣式。請繼續留意本系列的第 2 部分,在該部分您將會獲得可以讓
JSF 表單更加動態的基于 JavaScript 的技巧。
下載
描述 | 名字 | 大小 | 下載方法 |
本文的示例應用程序 |
jsfcssjs_part1_src.zip |
25KB |
HTTP |
參考資料
學習
獲得產品和技術