ZK/操作指南/概念與技巧
使用 Execution.getParameter() 或 EL 中的 ${param[key]} 訪問引數很簡單,如下所示。
<button label="${param['what']}"/>
但是,您無法在事件監聽器中訪問它。例如,在下面的示例中,按鈕的標籤一旦按下就會變為空。
<button label="${param['what']}" onClick="doIt()"/>
<zscript>
void doIt() {
self.label= Executions.getCurrent().getParameter("what");
}
為什麼?
引數對映僅在頁面評估時可用。而且,當用戶點選按鈕時,會生成另一個 URL,之前的引數就消失了。
解決方案
<button label="${param['what']}" onClick="doIt()"/>
<zscript>
tmp = Executions.getCurrent().getParameter("what");
void doIt() {
self.label= tmp;
}
網格 和 列表框 都支援多列和多行。它們看起來很像。應該使用哪一個?列表框和網格中也使用組合框。onopen() 用於在執行時在列表框和組合框中建立資料庫記錄;
- 主要用途:表格形式的資料呈現。
- 每個單元格可能彼此大不相同
- 要實現選擇,開發人員必須為每一行新增一個複選框。沒有簡單的方法來實現單選(使用單選按鈕)。
- 主要用途:可選擇的資料
- 選擇直接支援(透過使用 getSelectedItem 等)
- 如果文字框包含在一個單元格中,使用者就無法選擇其內容。
在下面的程式碼片段中,沒有顯示錯誤框。相反,ZK 將其視為程式設計錯誤(透過使用 JavaScript 的 alert 顯示異常)
<zk> <textbox id="box" constraint="no empty"/> <button label="cause validation error" onClick="alert(box.value)"/> </zk>
為什麼?BeanShell 攔截所有異常,並使用它自己的異常來表示它們。因此,ZK 不知道它實際上是由 WrongValueException 引起的。
解決方案:使用 getValue() 和 setValue() 而不是直接訪問屬性名。
<zk> <textbox id="box" constraint="no empty"/> <button label="cause validation error" onClick="alert(box.getValue())"/> </zk>
如果您有一個具有許多(例如 1,000,000 個)專案的列表框,則不能使用列表框的內部分頁機制(換句話說,您不能設定 '分頁' 模具)。原因是內部分頁機制將建立與專案數量一樣多的列表項。
由分頁控制的列表框將始終顯示從偏移量“頁大小 * 活動頁面計數”到“頁大小 * (活動頁面計數 + 1)”的列表項。因此,您必須 *不* 將列表項數量與實際元素數量不匹配的列表框與分頁元素關聯起來。換句話說,不要讓列表框成為分頁元素的被控物件。相反,建立一個單獨的分頁元素,如下所示
<vbox> <listbox id="box" /> <paging id="paging" /> </vbox>
將實際專案的數量設定為分頁控制器的“totalSize”
paging.setTotalSize(1000000);
現在,您必須攔截“onPaging”事件
paging.addEventListener("onPaging", new EventListener() {
public void onEvent(Event e) {
PagingEvent pe = (PagingEvent)e;
int desiredPage = pe.getActivePage();
// now retrieve items desiredPage * pagesize .. (desiredPage+1) * pagesize
// and assign their content to listitem 0 .. pagesize
}
});
因此,始終只有與當前顯示的列表項一樣多的列表項。
請注意,此技術的缺點是您必須將分頁控制器放置在列表框之外。您不能將此分頁控制器新增到列表框,因為列表框會檢查是否添加了最多一個 org.zkoss.zul.Paging 例項的子項,以防它與內部分頁元件發生衝突。第二個缺點是您不能使用 “box.getPageSize()” 方法,該方法依賴於內部分頁。您必須改為使用 “paging.getPageSize()”。另外,如果您使用此技術,請確保 *不* 呼叫 box.setPaginal(paging)。
在 ZK 中使用帶百分比的 width= 屬性需要小心,因為它的含義與其他框架不同。一方面,ZK 努力成為一個與瀏覽器無關的框架。另一方面,在渲染 HTML 時,ZK 經常將 width= 屬性傳遞給它使用的 HTML 元素,這會導致意想不到的效果。原因是,傳遞 width= 屬性的 HTML 元素形成的層次結構不同於它們起源的 ZUL 元素。
為了理解這一點,請考慮以下場景
<hbox width="100%">
<div width="50%" style="background-color: blue;"> Left </div>
<div width="50%" style="background-color: green;"> Right </div>
</hbox>
此處,目的是讓父 hbox 佔用其父元素(可能是視窗)的 100%,讓每個 'div' 子元素佔用其父元素的 50%。在 CSS 中,[W3C], width 屬性指的是包含塊。
但是,ZK 粗略地將上述內容渲染為以下內容
<table width="100%">
<tr>
<td>
<div style="width:50%"> Left </div>
</td>
<td>
<div style="width:50%"> Right </div>
</td>
</tr>
</table>
熟悉 CSS 的使用者會注意到,width:50% 屬性現在不再是指用於渲染 'hbox' 的 'table' 元素,而是指 ZK 插入的 'td' 元素!'td' 元素的預設寬度為表格的 50%(因為有兩個 'td' 元素),因此 'div' 元素的實際寬度為表格的 25%。很明顯,為了正確使用 width=,必須瞭解 ZK 如何在 ZUL 和 HTML 之間進行轉換(與 ZK 開發人員的意圖相反)。
為了解決這個問題,ZK 為框元素提供了“widths”屬性。'widths' 屬性允許將 'width:' 屬性分配給構成框的 'td' 元素。為了達到預期效果,您必須使用
<hbox widths="50%,50%" width="100%">
<div width="100%" style="background-color: blue;"> Left </div>
<div width="100%" style="background-color: green;"> Right </div>
</hbox>
它將被渲染為
<table width="100%">
<tr>
<td style="width:50%">
<div style="width:100%"> Left </div>
</td>
<td style="width:50%">
<div style="width:100%"> Right </div>
</td>
</tr>
</table>
因此,表格佔據其父元素的 100%,每個 'td' 元素佔據表格寬度的 50%,每個 'td' 中的 'div' 元素佔據整個空間 (100%)。
屬性 'widths' 為盒子提供了一種變通方案,但不幸的是,它沒有提供通用的解決方案。透過將 'width=' 屬性傳遞給 HTML 元素,ZK 使渲染依賴於所使用的瀏覽器,從而將 ZK 使用者暴露於所有與寬度相關的渲染錯誤。此外,這些錯誤很難除錯,因為它們需要 ZK 使用者瞭解 ZK 的渲染過程,才能開始解決導致這些錯誤的瀏覽器特性。
例如,將寬度指定為 100% 給 <textbox> 將導致將樣式 "width:100%" 應用於 <input type="text"> 元素,這會觸發不同瀏覽器的錯誤 - 例如,當放置在文字框中的值大於框時,IE 會忽略寬度限制。在這種情況下,IE 會拉伸框。 變通方案
自 2007 年 3 月 13 日起,FCKeditor 支援新的方法 setCustomConfigurationsPath(String url),您可以指定自定義配置 .js 檔案的 url。您不再需要修改 fckez.jar 中的 fckconfig.js。有關可自定義內容的詳細資訊,請參閱 FCKeditor 配置檔案
以下是如何為 FCKeditor 建立一個新的工具欄集。
1. 建立一個 JavaScript .js 自定義配置檔案,例如,將 myconfig.js 放置在您的 Web 路徑中的某個位置。為了便於描述,本示例將將其放在根路徑下;即 "/myconfig.js"。
2. 在檔案中建立一個新的工具欄集 "Simple" (myconfig.js)。例如:
FCKConfig.ToolbarSets["Simple"] = [ ['Bold','Italic','Underline','StrikeThrough','-','TextColor','BGColor'] ];
3. 要使用此 /myconfig.js,您必須在 <fckeditor> 標籤中指定它
<fckeditor customConfigurationsPath="/myconfig.js" toolbarSet="Simple"/>
或透過 Java 方法
FCKeditor myFCKeditor = new FCKeditor();
myFCKeditor.setCustomConfigurationsPath("/myconfig.js");
myFCKeditor.setToolbarSet("Simple");
4. 好了。您完成了。
以下是需要您修改 fckez.jar 中的 fckconfig.js 的舊方法
要更改 FCKeditor 中的工具欄或建立一個新的工具欄,必須修改 fckez.jar 檔案中的 fckconfig.js 檔案。
1. 在出現任何錯誤時,備份 fckez.jar 檔案。
2. 將 fckez.jar 檔案重新命名為 fckez.zip (jar 檔案只是 zip 檔案,所以這可以正常工作)
3. 將 fckez.zip 檔案解壓縮到某個位置。建議建立一個新目錄。
4. 找到 fckconfig.js 並開啟它進行編輯。它應該位於 \web\js\ext\FCKeditor\fckconfig.js
5. 找到工具欄部分。以下是基本部分。
FCKConfig.ToolbarSets["Basic"] = [ ['Bold','Italic','-','OrderedList','UnorderedList','-','Link','Unlink','-','About'] ] ;
6. 要建立一個新的 ToolbarSet,請複製 FCKConfig.ToolbarSets... 之間的全部內容到分號 ;
7. 將其貼上到分號之後,並更改名稱。
FCKConfig.ToolbarSets["Simple"] = [ ['Bold','Italic','-','OrderedList','UnorderedList','-','Link','Unlink','-','About'] ] ;
8. 根據需要更改 Toolset。按鈕在單引號中定義。'-' 是工具欄分隔符。讓我們刪除連結和取消連結按鈕。
FCKConfig.ToolbarSets["Simple"] = [ ['Bold','Italic','-','OrderedList','UnorderedList','-','About'] ] ;
9. 儲存檔案並退出編輯器程式。
10. 向上導航目錄樹,直到您到達 web 資料夾級別,並將整個樹放入 zip 檔案中。(這將保留修改後的檔案在目錄結構中的位置。)
11. 將 zip 檔案重新命名回 fckez.jar,並將 jar 檔案放入與其他 zk jar 檔案相同的 tomcat shared/lib 目錄中。
12. 更改您在 zk 應用程式中呼叫 FCKeditor 的程式碼,以使用 'Simple' 工具欄集。
FCKeditor myFCKeditor = new FCKeditor();
myFCKeditor.setToolbarSet("Simple");
13. 啟動 Tomcat,並使用瀏覽器檢視您的應用程式。您應該在 FCKeditor 中看到您修改後的工具欄集。
請嘗試使用最新版本作為變通方案。
...
</treecols>
</tree>
<zscript>
int[] path ={0};
tree.renderItemByPath(path);
int[] path ={1};
tree.renderItemByPath(path);
</zscript>
... 另外,請參考 javadoc- treemodel 獲取有關路徑的詳細資訊,
請隨時在 sourceforge 上的 ZK 論壇上釋出更多問題
由於某些規範變更,3.0.3 之後,請參考以下內容:...
</treecols>
</tree>
<zscript>
int[] path ={0.0};
tree.renderItemByPath(path);
int[] path ={1.0};
tree.renderItemByPath(path);
</zscript>
... 這是一個用來練習的演示程式碼
<?xml version="1.0" encoding="UTF-8"?>
<zk xmlns="http://www.zkoss.org/2005/zul">
<window title="Dynamically Change by Model">
<zscript><![CDATA[
class MySimpleTreeNode extends SimpleTreeNode {
private String myData = null;
public MySimpleTreeNode(String data, List children) {
super(data, children);
myData = data.toString();
}
public String toString() {
return "Node: " + myData;
}
public void append(String data) {
myData = myData + data;
}
public Object getData() {
return myData;
}
}
List aChildren = new ArrayList();
List empty = new ArrayList();
List a2Children = new ArrayList();
MySimpleTreeNode a20 = new MySimpleTreeNode("A2-0", empty);
MySimpleTreeNode a21 = new MySimpleTreeNode("A2-1", empty);
MySimpleTreeNode a22 = new MySimpleTreeNode("A2-2", empty);
a2Children.add(a20);
a2Children.add(a21);
a2Children.add(a22);
MySimpleTreeNode a0 = new MySimpleTreeNode("A0", empty);
MySimpleTreeNode a1 = new MySimpleTreeNode("A1", empty);
MySimpleTreeNode a2 = new MySimpleTreeNode("A2", a2Children);
aChildren.add(a0);
aChildren.add(a1);
aChildren.add(a2);
List children = new ArrayList();
MySimpleTreeNode a = new MySimpleTreeNode("A", aChildren);
children.add(a);
List bbChildren = new ArrayList();
MySimpleTreeNode b00 = new MySimpleTreeNode("B0-0", empty);
bbChildren.add(b00);
List bChildren = new ArrayList();
MySimpleTreeNode b0 = new MySimpleTreeNode("B0", bbChildren);
MySimpleTreeNode b1 = new MySimpleTreeNode("B1", empty);
MySimpleTreeNode b2 = new MySimpleTreeNode("B2", empty);
bChildren.add(b0);
bChildren.add(b1);
bChildren.add(b2);
MySimpleTreeNode b = new MySimpleTreeNode("B", bChildren);
children.add(b);
List rList = new ArrayList();
rList.add(a);
rList.add(b);
MySimpleTreeNode r = new MySimpleTreeNode("Root", rList);
List rootList = new ArrayList();
rootList.add(r);
MySimpleTreeNode root = new MySimpleTreeNode("Root", rootList);
SimpleTreeModel stm = new SimpleTreeModel(root);
public void renderByPath(Object obj){
int[] result = stm.getPath(root,obj);
for(int i =0; i < result.length;i++)
{
System.out.println(result[i]);
}
tree.renderItemByPath(result);
}
public void renderByPathMul(){
int l = tree.getTreechildren().getChildren().size();
System.out.println(l);
for(int i=0; i<l; i++) {
int[] path ={0,i};
tree.renderItemByPath(path);
}
}
]]></zscript>
<vbox>
<tree model="${stm}" id="tree" width="700PX">
</tree>
<hbox>
<button label='renderByPath A2' onClick='renderByPath(a2)' />
<button label='renderByPath B0-0' onClick='renderByPath(b00)' />
<button label='renderByPath A2-1' onClick='renderByPath(a21)' />
<button label='renderByPath Root' onClick='renderByPath(r)' />
<button label='renderByPath A' onClick='renderByPath(a)' />
</hbox>
</vbox>
</window>
</zk>
此程式碼不適用於 ZK 3.5.1!
點選演示頁面上的 "Try Me!" 按鈕檢視原始碼面板。剪下並貼上以下示例,然後再次點選 "Try Me!" 載入示例。然後點選按鈕檢視程式碼執行效果。
<window title="My First Window" border="normal" width="200px">
<vbox id="myVbox">
<button label="create new button">
<attribute name="onClick">
<![CDATA[
deleteButton = new Button("Click me!");
// Store an arbitary piece of data in my button (e.g. some data primary key of the some object to delete)
deleteButton.setAttribute("myDeleteButtonAttribute", "mary had a little lamb");
cond = new org.zkoss.zk.ui.util.Condition(){
boolean isEffective(Component comp) {return true;}
boolean isEffective(Page page){return true;}
};
// here the script just does a serverside alert showing the silly text but you could call a
// business delegate function to delete something from the database.
zscript = new org.zkoss.zk.ui.metainfo.ZScript("java", "alert(self.getAttribute(\"myDeleteButtonAttribute\"));", cond);
eventHandler = new org.zkoss.zk.ui.metainfo.EventHandler( zscript, cond);
deleteButton.addEventHandler("onClick", eventHandler);
myVbox.appendChild(deleteButton);
]]>
</attribute>
</button>
</vbox>
</window>
重要的是要注意,您用 zscript 編寫的事件處理程式和函式在伺服器上執行,而不是在瀏覽器中執行。有一個名為 "客戶端操作" 的功能,您可以讓瀏覽器並行執行一些 JavaScript 函式以響應您的伺服器端事件處理程式。客戶端操作非常適合瀏覽器的圖形效果。在瀏覽器中執行的 JavaScript 客戶端操作無法訪問您的伺服器端業務物件、整個 Java JDK 和包含豐富 XUL 物件的伺服器端 ZK 桌面。伺服器端 zscript 可以直接訪問所有這些內容,您可以使用包括 JavaScript 在內的多種語言。
此程式碼展示瞭如何在伺服器端事件 zscript 處理程式中選擇使用 JavaScript 而不是解釋型 Java (BeanShell)
<?page zscript-language="javascript"?>
<window>
<zscript>
// this is a JavaScript function that creates a JavaScript object literal
// on the server and runs the server-side alert function
function hello(){
var now = new java.util.Date(); // you can script pure Java objects!
var myMessage = {msg:'hello world '+now}; // pure JavaScript
alert(myMessage.msg); // JavaScript calling a Java method
// Rhino = JavaScript on Java (http://www.mozilla.org/rhino/doc.html)
}
</zscript>
<button label="Say hello world">
<attribute name="onClick">
hello();
</attribute>
</button>
</window>
您可以在 zkoss.org 網站的演示頁面上執行該示例。只需按下 "Try Me!" 按鈕顯示編輯器,貼上示例,然後再次按下 "Try Me!" 載入示例,然後按下 "Say hello world" 按鈕檢視其執行效果。
您不能期望做的事情是寫類似於
window.setTimeout("alert('hello');", 1000);在伺服器端 JavaScript 函式中。為什麼?因為 'window' 只是瀏覽器 JavaScript 執行時中的一個隱式物件引用。由於事件處理程式在伺服器上執行,因此您無法直接訪問瀏覽器中的物件。伺服器端 ZK 中沒有名為 'window' 的隱式物件引用。我們可以給 xul 視窗標籤和 id 賦予 "window",然後我們可以對其進行指令碼化。將以下示例剪下並貼上到 zkoss.org 演示的 "Try Me!" 程式碼編輯器中,然後再次點選 "Try Me!" 載入它
<?page zscript-language="javascript"?>
<window id="window" title="This is my window title">
<zscript>
// this is a JavaScript function that manipulates the
// desktop object that is assigned the ID "window"
function changeWindowTitle(title){
window.title = title;
}
</zscript>
<label value="New title:"/>
<textbox id="new_title" value="edit me..."/>
<button label="Change the window title.">
<attribute name="onClick">
changeWindowTitle(new_title.value);
</attribute>
</button>
</window>
我們在那裡給視窗物件賦予了 'window' 的 ID,以便我們可以在 zscript 中透過該名稱引用它並更改其標題。我們仍然不能呼叫 "window.setTimeout()",因為 ZK Window 元件上沒有名為 setTimeout 的方法。ZKOSS 網站上的 JavaDoc 檢視 Window 和其他元件有哪些方法。我們在上一個示例中隱式地使用了 setTitle,當時我們在 zscript 中為 window.title 設定了一個新值。
人們一直使用的一個瀏覽器方法是
document.getElementById('some_id');這不會奏效,因為 'document' 是瀏覽器中的一個隱式物件,它不存在於伺服器端 ZK 中。但不要失望!ZK 除了 76 種 XUL 物件型別外,還有 86 種不同型別的 XHTML 物件。它將在伺服器上構建一個混合的 XHTML 和 XUL "DOM",稱為桌面。以下示例使用 JavaScript zscript 操作一些 XHTML
<?page zscript-language="javascript"?>
<zk xmlns:h="http://www.w3.org/1999/xhtml">
<window id="window">
<zscript>
function changeParagraph(){
// this script code changes the xhtml objects on the server
myParagraph.children.get(1).value = 'goodbye world';
}
</zscript>
<!--
The following are XHTML elements. If you don't like the prefix 'h' see the DevGuide
about how to set the default namespace to be html.
-->
<h:p id="myParagraph">
<h:img src="https://wikibook.tw/skins-1.5/common/images/button_bold.png"></h:img>
hello world <!-- "hello world" is in an implicit Text element -->
</h:p>
<!-- This is a XUL button that has an onClick that changes an XHTML element -->
<button label="Change hello to goodbye">
<attribute name="onClick">
changeParagraph();
</attribute>
</button>
</window>
</zk>
您無法更改 XHTML IMG 元素的 src 屬性。請改用 ZUL IMAGE 元素。同樣,如果您想設定 IFRAME 的源,請使用 ZUL 元素,而不是 XHTML 元素。為什麼?因為這樣,當您在 zscript 中直接訪問您的業務邏輯後更改它們在伺服器上的狀態時,ZK 將自動更新瀏覽器中相應的 DOM 元素。ZUL 元素已記錄在 此處,ZHTML 元素已記錄在 此處。
有時我們需要編寫一些瀏覽器端 JavaScript 函式來完成某些操作。我們可以使用 CSA (客戶端操作) 來觸發操作,沒有問題。但是,JavaScript 執行完成後,我們可能需要從 zscript 函式 (在伺服器端執行的程式碼) 中訪問 JavaScript 變數的值。這是一個實現此目的的技巧。基本上,我們準備一個 "代理" 文字框。將 JavaScript 值複製到文字框的值並模擬 "onChange" 事件,以便真正將值傳送回伺服器。以下是示例程式碼
<zk>
<script type="text/JavaScript">
<![CDATA[
function test(tbxsss) {
var sssval = "Time: "+(new Date());
tbxsss.value = sssval;
if (document.createEvent) {
var evt = document.createEvent('HTMLEvents');
evt.initEvent( 'blur', false, false);
tbxsss.dispatchEvent(evt);
var evt2 = document.createEvent('HTMLEvents');
evt2.initEvent( 'change', false, false);
tbxsss.dispatchEvent(evt2);
} else if (document.createEventObject) {
tbxsss.fireEvent('onblur');
tbxsss.fireEvent('onchange');
}
}
]]>
</script>
<window id="win" title="My First Window" border="normal" width="200px">
<textbox id="sss" value="test" onChange="alert(self.getValue());" visible="false"/>
<button id="btn" label="Invoke JS" action="onclick:test(#{sss})"/>
</window>
</zk>
點選按鈕時,會執行 JavaScript 函式 test()。然後,它將新的字串“abc”複製到文字框的值中,並模擬 onblur 和 onchange 事件。這將導致 ZK JavaScript 引擎將新值“abc”傳遞迴伺服器端,更新 Textbox 物件的值屬性,並觸發“onChange”ZK 事件。現在,您可以從這個“代理”文字框訪問該值。如果您仔細閱讀示例程式碼,您應該注意到文字框在瀏覽器中是“不可見”的(visible = “false”),因此它不會干擾您的佈局。玩得開心!
使用 forEach 動態構建使用者介面非常有用。如果您的 forEach 中有事件處理程式,您可以使用 'self' 來引用發生事件的元件。您也可以使用 'self' 從發生事件的元件開始遍歷元件範圍。
<window>
<zscript><![CDATA[
/**
* in a real application we would use something like
* List iterateOverMe = sessionScope.get("searchResults");
*/
String[][] iterateOverMe = {
{"Fred","Flintstone"}
,{"Wilma","Flintstone"}
,{"Barney","Rubble"}
,{"Betty","Rubble"}
};
void doRespondToClick(){
String message = "I am "+self.id;
List people = self.parent.children;
for( Iterator i = people.iterator(); i.hasNext(); ){
Object person = i.next();
if( person.id != self.id ) message += "\nI am next to "+person.id;
}
alert(message);
}
]]></zscript>
<vbox>
<!--
Here I know that ${each} is a String[] so I pull out its first and second element.
A more realistic example would be to access arbitrary getters on a POJO
domain model object e.g. I could call:
com.your.Person.getFirstName()
simply by using:
${each.firstName}
such that the label below would be defined as
label="Click Me ${each.firstName} ${each.lastName}"
-->
<button forEach="${iterateOverMe}"
id="${each[0]} ${each[1]}"
label="Click Me ${each[0]} ${each[1]}"
onClick="doRespondToClick()"/>
</vbox>
</window>
溢位錯誤有很好的記錄,並且存在於 IE6 或 IE7 中。因此,在這種情況下,我們必須在外部標籤中指定“position:relative”。例如,
<window title="tree demo" border="normal">
<div style="overflow:auto;position:relative" width="300px"
height="100px">
<tree id="tree" width="90%" rows="5">
<treecols sizable="true">
<treecol label="Name" />
<treecol label="Description" />
</treecols>
<treechildren>
<treeitem>
<treerow>
<treecell label="Item 1" />
<treecell label="Item 1 description" />
</treerow>
</treeitem>
<treeitem>
<treerow>
<treecell label="Item 2" />
<treecell label="Item 2 description" />
</treerow>
<treechildren>
<treeitem>
<treerow>
<treecell label="Item 2.1" />
</treerow>
<treechildren>
<treeitem>
<treerow>
<treecell label="Item 2.1.1" />
</treerow>
</treeitem>
<treeitem>
<treerow>
<treecell label="Item 2.1.2" />
</treerow>
</treeitem>
</treechildren>
</treeitem>
<treeitem>
<treerow>
<treecell label="Item 2.2" />
<treecell
label="Item 2.2 is something who cares" />
</treerow>
</treeitem>
</treechildren>
</treeitem>
<treeitem label="Item 3" />
</treechildren>
</tree>
</div>
</window>
我們需要捕獲 onFocus 事件來記錄現在誰獲得了焦點。例如,
<zk>
<zscript>
Component current;
void changeFocus(Component t){
current = t;
}
</zscript>
<window title="My First Window" border="normal" width="300px">
<hbox>Window 1 : <textbox id="First" onFocus="changeFocus(self)"/></hbox>
</window>
<window title="My Second Window" border="normal" width="300px">
<hbox>Window 2 : <textbox id="Second" onFocus="changeFocus(self)"/></hbox>
</window>
<window title="My Third Window" border="normal" width="300px">
<hbox>Window 3 : <textbox id="Third" onFocus="changeFocus(self)"/></hbox>
</window>
<window title="My Fourth Window" border="normal" width="300px">
<hbox>Window 4 : <textbox id="Fourth" onFocus="changeFocus(self)"/></hbox>
</window>
<button label="Show" onClick="alert(current.id)"/>
</zk>
將以下程式碼新增到您的 zul 頁面中。
<script type="text/javascript"><![CDATA[
window.Boot_progressbox = function (){}
]]></script>
ZUL 的 EL 支援標籤庫,因此我們可以編寫一個 util 標籤庫函式來從 zul 訪問靜態成員欄位。(或任何其他靜態函式)
Note: ZK 3.0 introduced the xel-method directive to declare a static method directly in a ZUL page (without TLD). <?xel-method prefix="c" name="forName" class="java.lang.Class" signature="java.lang.Class forName(java.lang.String)"?> Use TLD as described below if you want to manage the declarations in a single TLD file (rather than scattering around ZUL files), or you want to be compatible with ZK 2.x.
步驟 1. 編寫標籤庫,我將此欄位放在 src/metainfo/tld/myutil.tld 中
<?xml version="1.0" encoding="ISO-8859-1" ?>
<taglib>
<uri>http://mytld/util</uri>
<description>
</description>
<function>
<name>sf</name>
<function-class>mytld.Util</function-class>
<function-signature>
java.lang.String getStaticField(java.lang.String name)
</function-signature>
<description>
</description>
</function>
</taglib>
步驟 2. 編寫標籤庫配置,此檔案必須放在 src/metainfo/tld/config.xml 中
<?xml version="1.0" encoding="UTF-8"?>
<config>
<version>
<version-class>org.zkoss.zk.Version</version-class>
<version-uid>3.0.1</version-uid>
</version>
<taglib>
<taglib-uri>http://mytld/util</taglib-uri>
<taglib-location>/metainfo/tld/myutil.tld</taglib-location>
</taglib>
</config>
步驟 3. 標籤庫實現
public class Util {
static public String getStaticField(String name){
try{
int i = name.lastIndexOf(".");
String field = name.substring(i+1,name.length());
name = name.substring(0,i);
Class clz = Class.forName(name);
Object obj = clz.getField(field).get(null);
if(obj!=null){
return obj.toString();
}
return null;
}catch(Exception x){
throw new RuntimeException(x);
}
}
}
步驟 4. 在 zul 中訪問標籤庫。(sf 是在步驟 1 中宣告的函式名稱)
<?taglib uri="http://mytld/util" prefix="t" ?> <window id="${t:sf('mytld.CompIds.ID1')}" title="title"> <button label="click" onClick="alert(self.parent.id)"/> </window>
Firebug 被認為是降低 Javascript 效能的原因。這是一種檢測使用者是否啟用 Firebug 的方法。這是一段 Javascript 程式碼。
if(window.console && window.console.firebug){
// Do something Javascript code.
}
據我所知,ZK CSS 檔案無法在 IE6&7 上的 JSP 中載入,因此您必須在 JSP 檔案中新增以下頁面定義。
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> ... //Your JSP content ...
如果您有一個宏元件,並且您在視窗中使用該宏,則以下內容顯示了將引數傳遞給宏的確切語法(這在開發人員指南中,但沒有實際示例)以及如何在宏中使用它們
這是宏元件
<hbox valign="center">
<button id="pmminusButton"/>
<progressmeter width="${arg.width}" value="${arg.initialValue}" id="dhProgressMeter" />
<button id="pmplusButton"/>
</hbox>
這是我視窗檔案頂部的 include 語句,我在其中指定要傳遞的引數
<?component name="dhProgressMeter" inline="true" macro-uri="/macros/dhProgressMeter.zul" width="90px" initialValue="20" ?>
這裡重要的內容是,我聲明瞭兩個要傳遞給宏元件的變數,“width”和“initialValue”。
在宏本身中,您可以看到我是使用 ${arg.width} 和 ${arg.initialValue} 獲取這些引數的值的。
這很簡單,我認為可以放到“how-to”中,但我認為我會把它放到論壇中,這樣如果有人搜尋“如何將引數傳遞給宏”,它就會出現。