
借助 jMaki,Java 开发人员可以在基于 Java 的应用程序中将 JavaScript 作为 JSP 标记库或 JSF 组件使用。jMaki 融合了 Java 和 JavaScript 的优势,旨在交付富 Ajax 样式的部件。目前,jMaki 为许多组件提供了引导部件,这些组件包括 Dojo、Script.aculo.us、Yahoo UI 部件、Spry、DHTML Goodies 和 Google。jMaki 为这些部件库提供了一个公共接口并允许开发人员在同一个页面一起使用这些库。
您将通过本动手实验室了解如何使用 jMaki 部件开发基于 AJAX 的、快速响应的交互式 Web 应用程序。本文档旨在帮助您尽快入门。
预计时间:120 分钟
本动手实验室假定您拥有以下技术的基本知识或者具备相关编程经验:
在开始之前,您需要在计算机上安装以下软件。请注意本实验室要求的软件版本是 NetBeans IDE 5.5。如果您的计算机上只有 NetBeans IDE 5.0,就需要安装 NetBeans 5.5。在安装 NetBeans IDE 5.5 之前不必卸载 NetBeans IDE 5.0。NetBeans IDE 5.0 和 NetBeans IDE 5.5 可以共存在一台计算机上而不会有任何问题。
在本练习中,先要安装 jMaki NetBeans 插件。也要将 Mozilla Firefox 浏览器配置为 NetBeans IDE 的缺省浏览器。在开始之前,要保证您已经下载并安装了 上述软件。
















在本练习中,将构建和运行一个 jMaki 演示应用程序,您可以从中使用并探究各种由 jMaki 技术所支持的部件。此应用程序可以从 此处 在线访问。
0. 启动 NetBeans 5.5 IDE(如果尚未这样做)
1. 创建一个新的 jMaki NetBeans 项目





2. 运行项目。


在本步骤中,将使用 DHTML Goodies 部件。










| { "columns": { "title" : "Title", "author":"Author", "isbn": "ISBN #", "description":"Description"}, "rows":[ ['Life is good', 'Doris Chen','441234', 'You must be kidding!'], ['Save the earth', 'Me','441322', 'Some long description'], ['The Sun rises again','Whoever', '441234','Yes, indeed'], ['javapassion.com', 'Sang Shin', '441335', 'Some long description'], ['passion', 'Sang Shin', '451335', 'Some long description'] ] } |



| <%@ taglib prefix="a" uri="http://java.sun.com/jmaki" %> <h2>Dojo Fish Eye List Test</h2> <a href="index.jsp">Back to Samples</a> <hr> <a:ajax name="dojo.fisheye" args="{items:[ {iconSrc:'images/JayashriVisvanathan.jpg',caption:'Jayashri', index:1}, {iconSrc:'images/chinnici.jpg',caption:'Roberto',index:2}, {iconSrc:'images/blog_murray.jpg',caption:'Greg',index:3}, {iconSrc:'images/edburns.jpg',caption:'Ed',index:4}, {iconSrc:'images/icon_browser.png',caption:'You are here!',index:5}, {iconSrc:'images/icon_calendar.png',caption:'my caption2',index:6}, {iconSrc:'images/icon_update.png',caption:'passion',index:7} ]}" /> <script type="text/javascript"> function fisheyeListener(item) { var targetDiv = document.getElementById("newpage"); var responseText = ""; var index = Number(item.index); switch(index){ case 1: responseText += '<img src="images/JayashriVisvanathan.jpg"/><p>I am Jayashri Visvanathan and I work on Java Studio Creator. My area of interest/expertise is JSF components. Before I joined Creator team, I used to work on the JSF Reference Implementation (RI). I have been part of JSF team since its inception and have contributed to various releases including the current release JSF 1.2. I was also managing the JSF project on java.net since its launch. Prior to joining the JSF team, I worked on various client and server side web products/technologies within Sun including Mozilla, WebTop Registry Server and HotJava Browser.'; break; case 2: responseText +='<img src="images/chinnici.jpg"/><p>Roberto Chinnici is a senior staff engineer at Sun Microsystems, Inc. where he works on the Java Platform, Enterprise Edition, with particular focus on Web Services and Ease of Development. He is the specification lead for the JAX-RPC 1.1 and JAX-WS 2.0 technologies, both developed under the Java Community Process. He is also Sun\'s principal representative in the Web Services Description Working Group at W3C and has been a member of the WS-I Basic Profile Working Group. Mr. Chinnici holds an M.S. in Computer Science from the University of Milan, Italy.'; break; case 3: responseText += '<img src="images/blog_murray.jpg"/><p>Appointed as AJAX Architect for Sun Microsystems, Greg Murray is deeply involved in the AJAX movement through his participation in the OpenAJAX Alliance and contributions to the Dojo Foundation\'s open-source JavaScript toolkit. Within Sun, Greg lead a grass roots effort advancing the integration of client-side scripting with Java technologies and is the creator and principal architect of Project jMaki. jMaki uses the best parts of Java and the best parts of JavaScript to deliver rich AJAX style widgets through a singe, easy-to-use interface that accesses components from popular widget libraries such as Dojo, Script.aculo.us, Yahoo\'s UI Library, Spry, DHTML Goodies, and Google\'s Web Toolkit. Greg recently contributed to the design and development of the AJAX-based Java Pet Store 2.0 Demo and helped create Java BluePrints solutions for using AJAX with Java technologies.'; break; case 4: responseText += '<img src="images/edburns.jpg"/><p>Ed Burns is a senior staff engineer at Sun Microsystems. Ed has worked on a wide variety of client and server side web technologies since 1994, including NCSA Mosaic, Mozilla, the Sun Java Plugin, Jakarta Tomcat and, most recently JavaServer Faces. Ed is currently the co-spec lead for JavaServer Faces. Ed has contributed JSF support to jMaki in the form of bug-fixes, nags, and tersely worded emails.</p>'; break; default: responseText += '单击 on one of the photos above'; break; } targetDiv.innerHTML = responseText; } jmaki.subscribe("/dojo/fisheye", fisheyeListener); </script> <p> <h3><div id="newpage"></div></h3> |

在本练习中,您构建和运行了 jMaki 演示应用程序,并通过该应用程序探讨了各种部件的用法。您也了解了这些部件如何由 JSP 和 JSF 标签来表现。
返回顶部
在本练习中,您将使用包括 Dojo Fish Eye List 在内的 jMaki 部件构建一个 Web 应用程序。您将了解如何使用部件定制器来配置部件。以及如何为应用程序选择 CSS 布局。
0. 如果尚未启动 NetBeans IDE 请启动它。
1. 创建一个新的 jMaki NetBeans 项目

图 2.10:创建 Web Application 项目




3. 将 images 目录从 jMakiDemo 项目复制到 jMakFisheye 项目中。


| <%@ taglib prefix="a" uri="http://java.sun.com/jmaki" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <link rel="stylesheet" href="jmaki-standard-no-sidebars.css" type="text/css"></link> <html> <head> <title>Page Title</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <body> <div class="outerBorder"> <div class="header"> <div class="banner">Application Name</div> <div class="subheader"> <div> <a href="mailto:feedback@youraddress">Feedback</a> | <a href="#">Site Map</a> | <a href="#">Home</a> </div> </div> <!-- subheader --> </div> <!-- header --> <div class="main"> <div class="content" style="height:400px"> Main Content Area <a:ajax name="dojo.fisheye" args="{items:[ {iconSrc:'images/icon_browser.png',caption:'browser', index:1}, {iconSrc:'images/icon_calendar.png',caption:'calendar', index:2}, {iconSrc:'images/icon_email.png',caption:'email',index:3}, {iconSrc:'images/icon_texteditor.png',caption:'text editor',index:4}, {iconSrc:'images/icon_update.png',caption:'update',index:5} ]}"/> </div> <!-- content --> </div> <!-- main --> </div> <!-- outerborder --> </body> </html> |

在本步骤中,您将了解如何通过部件定制器对每个部件进行配置
1. 右键单击部件标签中任意位置并选择 jMaki。(如下图 2.20 所示)

图 2.20:了解 Dojo Fish Eye List 部件的 jMaki 定制器
2. 注意到出现了 dojo.fisheye Customizer 对话框的 属性 窗格。阅读每个参数的 Description。(如图 2.21 所示)

图 2.21:dojo.fisheye Customizer, Properties
3. 单击 Usage标签。(下图 2.22 所示)

图 2.22:dojo.fisheye 的用法






在本练习中,您构建和运行了几个使用不同 jMaki 部件的示例应用程序,这些部件可从 jMaki NetBeans 插件中获得。您也尝试了不同的 CSS 布局。
在本练习中,您将了解如何通过使用 jMaki 框架的 "发布和订阅" 机制对应用程序的 jMaki 部件事件进行响应,从而实现部件处理程序。在本练习中,先要修改您在 练习 2 中创建的 fisheye 部件,其中,它将自己作为主题发布给能够订阅它的独立应用程序。稍后您将在应用程序中订阅该主题。
<致谢> 该练习基于 "Handling jMaki Widget Events Using the Publish and Subscribe Mechanism" 一文 发布于 java.net。
本步骤假定您已经如 练习 2 步骤 1 所述创建了 jMakiFisheye 项目。 如果 jMakiFisheye 项目已经处于打开状态,刚完成练习 2 时即如此,那么略过这一步到步骤 3.1。
0. 启动 NetBeans IDE。1. 选择 文件->打开项目(Ctrl+Shift+O)。此时将出现 打开项目 对话框。2. 向下浏览至在 练习2 中创建的 jMakiFisheye 项目的目录中。3. 选择 jMakiFisheye.
4. 单击 打开项目文件夹。
,来发布合适内容到主题。针对 fisheye 部件,需要指定用户选定的图标,以便应用程序能够对用户单击图标这一事件进行适当的响应。| dojo.require("dojo.widget.FisheyeList"); // define the namespaces if (!jmaki.widgets.dojo) { jmaki.widgets.dojo = {}; } jmaki.widgets.dojo.fisheye = {}; jmaki.widgets.dojo.fisheye.Widget = function(wargs) { // create the top level widget var container = document.getElementById(wargs.uuid); var dynaCallback = null; if (typeof _globalScope.DynaFaces != 'undefined') { // Find the form for this widget var containerForm = container; while (null != containerForm && -1 == containerForm.tagName.toLowerCase().indexOf("form")) { containerForm = containerForm.parentNode; } // Save it on the widget so we have access to it in the listener. wargs.form = containerForm; } var orientation = "horizontal"; var labelEdge = "bottom"; var items = ["item1","item2","item3"]; if (typeof wargs.args != "undefined") { if (typeof wargs.args.orientation != "undefined"){ orientation = wargs.args.orientation; if (orientation == "vertical") { labelEdge = "right"; } } if (typeof wargs.args.labelEdge != "undefined"){ labelEdge = wargs.args.labelEdge; } if (typeof wargs.args.topic != "undefined") { topic = wargs.args.topic; } if (typeof wargs.args.items != "undefined") { items = wargs.args.items; } } var fishEye = dojo.widget.createWidget("FishEyeList", { orientation : orientation, itemWidth:50, itemHeight:50, itemMaxWidth:200, itemMaxHeight:200, effectUnits:2, itemPadding:10, attachEdge:"top", labelEdge:labelEdge, enableCrappySvgSupport:false }, container); // default topic var topic = "/dojo/fisheye"; // default values // programtically add FisheyeListItem children to the widget var counter = 0; while (true) { var i = items[counter++]; if (i == null) break; var icon = dojo.widget.createWidget("FisheyeListItem", i); icon.on单击 = function () { //jmaki.publish(topic, {target:this, wargs:wargs}); jmaki.publish(topic, this); } fishEye.addChild(icon); } this.destroy = function() { if (dynaCallback != null) { jmaki.unsubscribe("/dojo/fisheye", dynaCallback); } } } |
函数中,脚本调用了 publish 方法来传递主题,即 "dojo/fisheye",图标部件对单击的图标进行响应。包含所有传自标签的属性的图标正是发布的内容。onClick 事件做出响应。 方法订阅该主题,该方法传入该主题的名称 "/dojo/fisheye" 和监听器的名称 fisheyeListener。| <%@ taglib prefix="a" uri="http://java.sun.com/jmaki" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <link rel="stylesheet" href="jmaki-standard-no-sidebars.css" type="text/css"></link> <html> <head> <title>Page Title</title> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> </head> <body> <div class="outerBorder"> <div class="header"> <div class="banner">Application Name</div> <div class="subheader"> <div> <a href="mailto:feedback@youraddress">Feedback</a> | <a href="#">Site Map</a> | <a href="#">Home</a> </div> </div> <!-- subheader --> </div> <!-- header --> <div class="main"> <div class="content" style="height:400px"> Main Content Area <a:ajax name="dojo.fisheye" args="{items:[ {iconSrc:'images/icon_browser.png',caption:'You are here!', index:1}, {iconSrc:'images/icon_calendar.png',caption:'my caption2', index:2}, {iconSrc:'images/icon_email.png',caption:'email',index:3}, {iconSrc:'images/icon_texteditor.png',caption:'text editor',index:4}, {iconSrc:'images/icon_update.png',caption:'passion',index:5} ]}"/> <script type="text/javascript"> function fisheyeListener(item) { var targetDiv = document.getElementById("newpage"); var responseText = ""; var index = Number(item.index); var caption = item.caption; switch(index){ case 1: responseText += '<img src="images/icon_browser.png"/><p>Caption is '+caption+'!'; break; case 2: responseText += '<img src="images/icon_calendar.png"/><p>Caption is '+caption+'!'; break; case 3: responseText += '<img src="images/icon_email.png"/><p>Caption is '+caption+'!'; break; case 4: responseText += '<img src="images/icon_texteditor.png"/><p>Caption is '+caption+'!'; break; case 5: responseText += '<img src="images/icon_update.png"/><p>Caption is '+caption+'!'; break; default: responseText += '单击 on one of the photos above'; break; } targetDiv.innerHTML = responseText; } jmaki.subscribe("/dojo/fisheye", fisheyeListener); </script> <h3><div id="newpage"></div></h3> </div> <!-- content --> </div> <!-- main --> </div> <!-- outerborder --> </body> </html> |

div 标签。
在本练习中,您将构建和运行一个使用 List 部件的 jMaki 示例应用程序。然后将介绍 List 部件的构成。本练习选择 List 部件是因为它是最简单的部件之一。在练习 5,您将构建自己的 HelloWorld 部件。
0. 如果尚未启动 NetBeans IDE 请启动它。
1. 创建一个新的 jMaki NetBeans 项目。







| .plain { color: yellow; height:25px; font-size:18px; font-weight: bold; font-family: Arial; background: blue; } .over { color: white; height:25px; font-size:18px; font-weight: bold; font-family: Arial; background: #0099FF; cursor: pointer; } .listDiv { color: blue; position: relative; width: 300px; height: 275px; overflow: auto; } .listContainer { width: 300px; height: 275px; } |

| <div id="${uuid}" class="listContainer"> <form onsubmit="jmaki.attributes.get('${uuid}').submitData(); return false;"> <input id="${uuid}_entryField" type="text" size="20" value="Enter new Value"> <input type="button" onclick="jmaki.attributes.get('${uuid}').submitData(); return false;" value="Add to List"> </from> <div id="${uuid}_list" class="listDiv"></div> </div> |
| // define the namespaces if (!jmaki.widgets.jmaki) { jmaki.widgets.jmaki = {}; } jmaki.widgets.jmaki.list = {}; jmaki.widgets.jmaki.list.Widget = function(wargs) { // The uuid variable contains uuid value of the widget instance var uuid = wargs.uuid; // The service variable contains the value of the service attribute specified, listService.jsp, for example var service = wargs.service; // Create XMLHttpRequest differently depending on the browser type function getXHR(url) { if (window.XMLHttpRequest) { return new XMLHttpRequest(); } else if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP"); } } // submitData() function submits the data entered to the // service, listService.jsp. this.submitData = function() { var list = document.getElementById(uuid + "_list"); var req = getXHR(service); req.onreadystatechange = function() { if (req.readyState == 4) { if (req.status == 200) { list.innerHTML = req.responseText; } } }; req.open("POST", service, true); var entryField = document.getElementById(uuid + "_entryField"); req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); req.send("command=add&entry=" + entryField.value + "&uuid=" + uuid); } // removeItem() function sends the index of the item // for removal. this.removeItem = function(index) { var list = document.getElementById(uuid + "_list"); var req = getXHR(service); req.onreadystatechange = function() { if (req.readyState == 4) { if (req.status == 200) { list.innerHTML = req.responseText; } } }; req.open("POST", service, true); req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); req.send("command=remove&index=" + index + "&uuid=" + uuid); } } |
| <%@ taglib prefix="a" uri="http://java.sun.com/jmaki" %> <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <h1>JSP Page</h1> <a:ajax name="jmaki.list" service="listService.jsp" /> </body> </html> |
| <%@ taglib prefix="a" uri="http://java.sun.com/jmaki" %> <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <h1>JSP Page</h1> <a:ajax name="jmaki.list" service="myOwnlistService.jsp" /> </body> </html> |

| <ol> <% java.util.ArrayList list = (java.util.ArrayList)session.getAttribute("list"); String command = request.getParameter("command"); String uuid = request.getParameter("uuid"); String service = request.getParameter("service"); if (list == null) { list = new java.util.ArrayList(); session.setAttribute("list", list); } if ("add".equals(command)) { String item = request.getParameter("entry"); // list.add(item); list.add(item.toUpperCase()); } if ("remove".equals(command)) { String indexString = request.getParameter("index"); if (indexString != null) { int index = Integer.valueOf(indexString); list.remove(index); } } java.util.Iterator it = list.iterator(); int counter=0; while(it.hasNext()) { out.println("<li><div class=\"plain\" onmouseover=\"this.className ='over';\" onmouseout=\"this.className ='plain';\" onclick=\"jmaki.attributes.get('" + uuid + "').removeItem('" + counter++ + "')\">" + it.next() + "</div></li>"); } %> </ol> |

在本练习中,您先使用 List 部件构建和运行了一个简单的 jMaki 应用程序。然后了解到部件由三个文件组成 —— component.css 用于风格、component.htm 用于显示和 component.js 用于行为。也了解了如何改变一个现有的部件。在下一个练习中,您将创建自己的部件。
在本练习中,您将创建一个属于您自己的简单 "HelloWorld" jMaki 部件。"HelloWorld" jMaki 部件是一个具有 AJAX 行为的输入文本字段 —— 无论您在该文本字段中输入什么,都会几乎立即重新显示为 "Hello, <whatever-you-typed>!"。





| <form> <input id="${uuid}_name" type="text" size="20" value="Enter your name" onkeyup="jmaki.attributes.get('${uuid}').submitData()"> </from> <div id="${uuid}_hello" class="helloDiv"></div> </div> |

| .plain { color: black; height:25; font-size:18px; font-weight: bold; font-family: Arial; background: white; } .over { color: white; height:25; font-size:18px; font-weight: bold; font-family: Arial; background: blue; cursor: pointer; } .helloDiv { position: relative; width: 400px; height: 300px; overflow: auto; } |
| // define the namespaces if (!jmaki.widgets.jmaki) { jmaki.widgets.jmaki = {}; } jmaki.widgets.jmaki.helloworld = {}; jmaki.widgets.jmaki.helloworld.Widget = function(wargs) { // The jMaki framework must have created widget JavaScript object. var uuid = wargs.uuid; var service = wargs.service; function getXHR(url) { if (window.XMLHttpRequest) { return new XMLHttpRequest(); } else if (window.ActiveXObject) { return new ActiveXObject("Microsoft.XMLHTTP"); } } // This function gets called when a user typed some characters // in the input text field whose id is set as ${uuid}_hello in // component.htm template file. this.submitData = function() { var target = document.getElementById(uuid + "_hello"); var req = getXHR(service); req.onreadystatechange = function() { if (req.readyState == 4) { if (req.status == 200) { target.innerHTML = req.responseText; } } }; req.open("POST", service, true); var name= document.getElementById(uuid + "_name"); req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); req.send("name=" + name.value + "&uuid=" + uuid); } } |

| <ol> <% String name= request.getParameter("name"); out.println("Hello, " + name + "!"); %> </ol> |
| <%@page contentType="text/html"%> <%@page pageEncoding="UTF-8"%> <%@ taglib prefix="a" uri="http://java.sun.com/jmaki" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <h1>Use my own HelloWorld jMaki widget</h1> <a:ajax name="jmaki.helloworld" service="helloService.jsp" /> </body> </html> |


