跳轉到內容

ZK/操作指南/概念與技巧

來自 Wikibooks,開放世界中的開放書籍

概念與技巧

[編輯 | 編輯原始碼]

引數和事件監聽器

[編輯 | 編輯原始碼]

使用 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 等)
  • 如果文字框包含在一個單元格中,使用者就無法選擇其內容。

為什麼在 BeanShell 中訪問 value 屬性時使用 alert 而不是錯誤框

[編輯 | 編輯原始碼]

在下面的程式碼片段中,沒有顯示錯誤框。相反,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 會拉伸框。 變通方案

更改或自定義 FCKeditor 中的工具欄

[編輯 | 編輯原始碼]

自 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 中看到您修改後的工具欄集。

如何在啟動時開啟 treeitem

[編輯 | 編輯原始碼]

請嘗試使用最新版本作為變通方案。

...

 
</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>


如何以程式設計方式建立一個帶有 onClick zscript 的按鈕?

[編輯 | 編輯原始碼]

此程式碼不適用於 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?

[編輯 | 編輯原始碼]

重要的是要注意,您用 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 變數值傳遞給 ZK 伺服器

[編輯 | 編輯原始碼]

有時我們需要編寫一些瀏覽器端 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' 中使用 'self' 事件處理程式

[編輯 | 編輯原始碼]

使用 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>




IE 相對定位 DIV 的溢位滾動

[編輯 | 編輯原始碼]

溢位錯誤有很好的記錄,並且存在於 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>

如何停用 ZK 的進度條

[編輯 | 編輯原始碼]

將以下程式碼新增到您的 zul 頁面中。

<script type="text/javascript"><![CDATA[
window.Boot_progressbox = function (){}
]]></script>

如何在 zul 中不使用 zscript 訪問類的靜態成員欄位

[編輯 | 編輯原始碼]

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

[編輯 | 編輯原始碼]

Firebug 被認為是降低 Javascript 效能的原因。這是一種檢測使用者是否啟用 Firebug 的方法。這是一段 Javascript 程式碼。

  if(window.console && window.console.firebug){
      // Do something Javascript code.
  }

如何在將 ZK 和 JSP 整合時解決 IE6&7 中 CSS 未載入的問題。

[編輯 | 編輯原始碼]

據我所知,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”中,但我認為我會把它放到論壇中,這樣如果有人搜尋“如何將引數傳遞給宏”,它就會出現。

華夏公益教科書