在同一ZUML页面内和XUL组件一起使用HTML标签有几种方式。你可以根据需求选择任意一个。
首先,你可以使用html组件嵌入HTML标签。使用此方法,HTML标签仅简单的为html
组件的内容。它们会直接被送至客户端,对于ZK来说它们没有具体的意义。
第二,你可以使用XHTML(http://www.w3.org/1999/xhtml
) 命名空间来从XHTML组件集内指定一个组件。换句话说, XHTML命名空间代表的相关XML元素为XHTML 组件集内的组件。就像ZUL组件集(http://www.zkoss.org/2005/zul
),ZK为ZUML页面内每个XML元素创建一个实例。
第三,你可以使用本地命名空间(http://www.zkoss.org/2005/zk/native
) 来代表将一个HTML标签直接送至客户端,而不是为它们创建ZK组件。这种方法更有效,但是不能动态改变。
最后一种但并非最不重要,你可以使用 inclusion (include
) 和 inline frames (iframe
) 嵌入一个ZUL页面,理论上可以是任何内容(不限于HTML标签)。
最简单的方式是使用称为html
[43] 的XUL组件,在其中嵌入你想直接发送至浏览器的HTML标签。为了避免ZK解释HTML标签,通常要使用<![CDATA
[ and ]]>将HTML标签围入其中。换言之,他们并不是子组件。而是被存储在content
属性[44]内。注意在其中可以使用EL表达式。
<window title="Html Demo"> <html><![CDATA[ <h4>Hi ${parent.title}</h4> <p>It is the content of the html component. </p> ]]></html> </window>
在此处将会成为元素的内容(又见org.zkoss.zul.Html
类的getContent
方法)。
提示: 你可以使用attribute 元素来指定XHTML片段,以代替 CDATA,如下。
<html <attribute name="content"> <h4>Hi, ${parent.title}</h4> <p>It is the content of the html component.</p> </attribute> </html
参考ZK用户界面标记语言一章attribute
元素一节。
html
组件会产生 HTML SPAN 标签来包围这些内容。换句话说,当提交到浏览器是时会产生下列的HTML标签。
<span id="z_4a_3"> <h4>Hi, Html Demo</h4> <p>It is the content of the html component.</p> </span>
html
组件会产生 HTML SPAN
标签来包围这些内容。因此,你可以像使用其它的XUL组件一样使用它。例如,我们可以指定CSS样式,动态的改变它的内容。
<html id="h" style="border: 1px solid blue;background: yellow"><![CDATA[ <ul> <li>Native browser content</li> </ul> ]]></html> <button label="change" onClick="l.setContent("Hi Update")"/>
注意,由于SPAN
用于包围嵌入的HTML标签,下面的语句是错误的。
<html><![CDATA[ <ul> <li> <!-- incorrect since <ul><li> is inside <span> --> ]]></html> <textbox/> <html><![CDATA[ </li> </ul> ]]</html>
如果你需要直接产生嵌入的HTML标签,而不用SPAN
包围,你可以使用native命名空间,如下所示。
使用Native 命名空间,表示ZUML页面内的XML元素会被直接送至浏览网而不会成为ZK组件。例如,
<n:ul xmlns:n="http://www.zkoss.org/2005/zk/native"> <n:li> <textbox/> </n:li> <n:li> <textbox/> </n:li> </n:ul>
会产生下面的HTML标签送至浏览器:
<ul> <li> <input id="z_a3_2"/> </li> <li> <input id="z_a3_5"/> </li> </ul>
此处,<input>
为由textbox
产生的HTML标签。不同于上例中的textbox
,ZK加载器并不会为每个ul
和li
[45]
创建一个组件。而是,它们直接被送至客户端。当然,它们必须是被客户端可识别的。对于HTML浏览器,它们必须为合法的HTML标签。
由于与Native关联的元素会直接被送至客户端,所以它们不是ZK组件,且在客户端没有对应部分。优点是根据内存和处理事件来看都有更好的性能。而缺点是你不能够动态的改变它们。例如,下面的代码片断是错误的,因为没有名为x
的组件。
<n:ul id="x" xmlns:n="http://www.zkoss.org/2005/zk/native"/> <button label="add" onClick="new Li().setParent(x)"/>
若你想动态改变它们,则可以按如下章节描述的那样指定XHTML 命名空间。
若你想生成另一个命名空间至输出,则可以使用另一种格式作为Native命名空间的URI。
native:URI-of-another-namespace
例如,若你想直接输出SVG标签之客户端,则可以指定native:native:http://www.w3.org/2000/svg
,如下。
<window> <svg width="100%" height="100%" version="1.1" xmlns="native:http://www.w3.org/2000/svg"> <ellipse cx="240" cy="100" rx="220" ry="30" style="fill:purple"/> </svg> </window>
那么,客户端接受到的内容如下:
<div id="z_lx_0c" z.type="zul.wnd.Wnd"> <svg width="100%" height="100%" version="1.1" xmlns="http://www.w3.org/2000/svg"> <ellipse cx="240" cy="100" rx="220" ry="30" style="fill:purple"/> </svg> </div>
XHTML表示XHTML组件集,就像ZUL命名空间(http://www.zkoss.org/2005/zul)代表ZUL组件集一样。因此,使用XHTML命名空间指定的一个XML元素表示此组件的创建将会基于定义在XHTML组件集内的组件。例如,下面的代码基于XHTML组件集创建了一个ul
实例:
<h:ul xmlns:h="http://www.w3.org/1999/xhtml">
换言之,ZK加载器将会在XHTML 组件集内寻找组件定义ul
,然后基于它创建一个实例。
下面是一个更完整的例子。
<window title="mix HTML demo" xmlns:h="http://www.w3.org/1999/xhtml"> <h:table border="1"> <h:tr id="row1"> <h:td>column 1</h:td> <h:td> <listbox id="list" mold="select"> <listitem label="AA"/> <listitem label="BB"/> </listbox> </h:td> </h:tr> </h:table> <button label="add" onClick="new org.zkoss.zhtml.Td().append(row1)"/> </window>
不同于html
组件,ZK加载器会为存储在content
属性内HTML标签创建ZK组件。优点是你可以动态的操作每个HTML标签,就像在上面例子中描述的那样(add按钮)。缺点是需要花费更长的处理事件及更多的空间来维护。
[提示]: 不同于XHTML命名空间,Native并不代表另一种组件集。它只是一个保留的命名空间,用于告诉ZK加载器将它们直接送至客户端,以取得更好的性能。
include
组件用于包含由另一个servlet 产生的输出。servlet可以是任何页面,包括JSF,JSP,甚至另一个ZUML页面。
<window title="include demo" border="normal" width="300px"> Hello, World! <include src="/userguide/misc/includedHello.zul"/> <include src="/html/frag.html"/> </window>
就像所有的其它属性,你可以在运行时动态的改变src属性包括来自于不同servlet的输出。
若被包括的输出是另一个ZUML,开发人员被允许访问此ZUML的组件,就好像它们是包含(containing)页面的一部分。
有两种方式将值传递至包含页面。一,你可以使用查询字符串。
<include src="mypage?some=something"/>
然后,在包含页面内,你可以使用Execution
或ServletRequest
接口的getParameter
方法来访问它们。在EL表达式(包含页面内的)中,你可以使用param
变量来访问它们。但是,使用查询字符串,你仅能传递字符串类型的值。
${param.some}
另一种方式,你可以利用setDynamicProperty
方法所谓的动态属性,或者ZUL内的一个动态属性来传递任意值,如下:
<include src="mypage" some="something" another="${expr}"/>
使用动态属性,你可以传递非字符串类型的值。在包含页面内,可以使用Execution
或ServletRequest
接口的getAttribute
方法来访问它们。在EL表达式(包含页面内的)中,你可以使用requestScope
变量来访问它们。
${requestScope.some}
如果include
组件被用于包含一个ZUML页面,那么被包含的页面会成为桌面的一部分。但是,直到请求被完全处理被包含页面才会可见。换言之,仅当下列的事件被用户或计时器(timer)触发时被包含页面才会可见。
理由是include组件到页面响应阶段[46](the Rendering phase)才会包含一个页面。另外zscript 发生在组件创建阶段(the Component Creation phase), onCreate 发生在事件处理阶段(the Event Processing Phase)。它们都在包含前执行。
<window onCreate="desktop.getPages()"> <!-- the included page not available --> <include src="/my.zul"/> <zscript> desktop.getPages(); //the included page not available yet </zscript> <button label="Hit" onClick="desktop.getPages()"/> <!-- Yes, the included page is available when onClick is received --> </window>
若你想浏览被包含页面的组件,宏(macro)组件通常是更好的选择。参考ZK用户界面标记语言一章中宏组件一节。
style
组件被用于在ZUML页面中指定CSS样式。最简单的格式如下。
<style> .blue { color: white; background-color: blue; } </style> <button label="OK" sclass="blue"/>
提示:为整个应用程序配置样式表,可以在zk.xm内指定theme
-uri
,参考国际化一章中主题一节或the Developer's Reference中的附录B(Appendix B) 获取细节。 为一中语言配置样式表,可以使用语言插件(language addon),参考 the Component Development Guide。
有时将所有的CSS定义放在一个单独的文件中是更好的选择,例如my.css
。然后,我们可以使用style组件来引用它,如下。
<style src="/my.css"/>
上面的语句实际下列的HTMl标签[47]送至服务器,所以指定的文件必须是可被浏览器访问的。
<link rel="stylesheet" href="/css/mystyles.css"/>
换言之,你不能指定"/WEB-INF/xx"
或
"
C:/xx/yy
"
。
就像其它的URI,style
接受"*"来加载浏览器和本地化(Locale dependent)样式表。参考国际化一章中浏览器和本地化URI一节获取细节。
script
组件用于指定运行在浏览器的脚本代码。注意,不同于zscript
,脚本代码运行在浏览器。通常由大多数浏览器支持的JavaScript编写。最简单的格式如下。
<script type="text/javascript"> function myfunc() { $e("${win.uuid}").style.backgroundColor = "blue"; } </script>
如上所示,你可以在脚本代码内使用EL表达式 (${win.uuid
})。
当然,你可以使用src
属性引用额外的JavaScript文件,如下。
<script src="/js/super.js" type="text/javascript"/>
由于ZK应用程序运行在服务器端(使用你最喜欢的语言执行),开发人员很少需要使用JavaScript代码来执行。它们通常定制ZK客户端引擎的行为,或运行遗留下来的JavaScript库。
iframe
组件使用HTML IFRAME标签将显示的一部分委托(delegate)给另一个URL。尽管外观看起来与include
组件相似,但是iframe
组件的概念及意义是不同的。
被include
组件包含的内容是整个HTML页面的片断。由于内容是HTML页面的一部分,所以也是桌面的一部分,你可以访问include
组件内的任何组件。包含是在服务器进行的,浏览器并不知道。这意味着src
属性指定的URL可以是任何内部资源。
iframe
组件的内容是由浏览器加载的,作为一个单独的页面。由于是作为单独的页面被加载,所以内容的格式可以不同于HTML。例如,你可以嵌入一个PDF文件。
<iframe src="/my.pdf"/> ...other HTML content
提示: 默认没有边框。若想启用,使用style属性指定,例如, <iframe style="border:1px inset" src="http://www.zkoss.org"
/>
当解释包含IFRAME的标签时,embedding是被浏览器处理的。这也暗示着URL必须为从浏览器可访问的资源。
就像image
和 audio
组件[48],你可以动态指定生成的内容。典型的例子是使用JasperReport[49]生成一个PDF报告,以二进制数组或流格式,然后将结果包装成org.zkoss.util.media.AMedia
类传递给iframe
组件。
在下面的例子中,我们说明,你可以使用iframe
嵌入任何内容,只要客户端支持内容的格式。
<window title="iframe demo" border="normal"> <iframe id="iframe" width="95%"/> <separator bar="true"/> <button label="Upload"> <attribute name="onClick">{ Object media = Fileupload.get(); if (media != null) iframe.setContent(media); }</attribute> </button> </window>
|
用户上传一个Microsoft PowerPoint文件 ,这张图片描述了上传后的外观。 |
当用户操作iframe
组件指向另一个URL(或bookmark签)时,org.zkoss.zk.ui.event.URIEvent
类的一个对象会被发送至iframe
组件。这个事件通常被用于标记(bookmark)iframe
组件的状态,这样之后正确的内容会被修复(be restored)。
若iframe
组件包含一个非ZK页面,则onURIChange
事件不会被发送。例如,若包含一个PDF页面,此事件就不会被发送。
另一方面,如果你使用了其它技术将ZK页面置于一个iframe
内,可以编写一个叫做onIframeChange
的JavaScript方法监视URL。
//Part of your, say, PHP page <script type="text/script"> function onIframeChange(uuid, url) { do_whatever_you_need_in_the_technology_you_use(uuid, url); } </script>
这里uuid
是你使用document.getElementById
获取的元素的ID,url
是iframe
要浏览的一个新URL。注意,url
包含上下文路径(context path),而URIEvent.getURI()
不包含。
[43] html元素内的文本实际上是由html组件的content属性赋值的(而不是成为一个子标签)。
[44] 若你不熟悉XML, 参考ZK用户界面标记语言一章中XML一节。
[45] ZK实际上创建了一个特殊的组件来表示尽可能多的使用Native命名空间的XML元素。
[46] 参考组件活动周期(Component Lifecycle )一章获取细节。
[47] 实际的结果取决于Web应用程序的配置。
[48] 在许多方面,iframe
类似于image
和 audio
。你可以将iframe
当成一个可以包含任意内容的组件。
[49] http://jasperreports.sourceforge.net