亚洲日日做天天做日日谢,亚洲乱码一区二区三区国产精品,亚洲男人都懂得羞羞网站http://m.tkk7.com/Jiangzy/category/26628.html這個(gè)世界上只有兩樣?xùn)|西愈分享愈多,那就是智慧與愛。zh-cnSat, 26 Jan 2008 05:59:36 GMTSat, 26 Jan 2008 05:59:36 GMT60js壓縮http://m.tkk7.com/Jiangzy/archive/2008/01/25/177858.html飛雪(leo)飛雪(leo)Fri, 25 Jan 2008 15:11:00 GMThttp://m.tkk7.com/Jiangzy/archive/2008/01/25/177858.htmlhttp://m.tkk7.com/Jiangzy/comments/177858.htmlhttp://m.tkk7.com/Jiangzy/archive/2008/01/25/177858.html#Feedback0http://m.tkk7.com/Jiangzy/comments/commentRss/177858.htmlhttp://m.tkk7.com/Jiangzy/services/trackbacks/177858.html壓縮不僅僅可以提高用戶的下載速度,同時(shí)還可以加密代碼,下面說下一個(gè)常用的js壓縮方法:

首先使用dojo的工具shrinksafe(http://shrinksafe.dojotoolkit.org/)壓縮一下,dojo的這個(gè)工具會(huì)去掉注釋,他的壓縮不是簡(jiǎn)單的替換變量,而是利用了mozilla的一個(gè)工具,對(duì)js解析后才壓縮,確保壓縮后的代碼不會(huì)出錯(cuò)。

dojo壓縮后,并不會(huì)減少太多,下一步可以使用http://javascriptcompressor.com/這個(gè)站點(diǎn)進(jìn)行更高層次的壓縮,可惜只能登陸這個(gè)站點(diǎn)再壓縮,只能將你的js代碼復(fù)制的他的文本框,然后等他的壓縮輸出

經(jīng)過這2步,你的js會(huì)變得既安全,文件又小



飛雪(leo) 2008-01-25 23:11 發(fā)表評(píng)論
]]>
Struts2與ajax的組合 http://m.tkk7.com/Jiangzy/archive/2007/10/18/153730.html飛雪(leo)飛雪(leo)Wed, 17 Oct 2007 16:47:00 GMThttp://m.tkk7.com/Jiangzy/archive/2007/10/18/153730.htmlhttp://m.tkk7.com/Jiangzy/comments/153730.htmlhttp://m.tkk7.com/Jiangzy/archive/2007/10/18/153730.html#Feedback0http://m.tkk7.com/Jiangzy/comments/commentRss/153730.htmlhttp://m.tkk7.com/Jiangzy/services/trackbacks/153730.html

Struts2與ajax的組合

Struts2與ajax的組合
在當(dāng)今——Web 2.0概念鋪天蓋地的Internet環(huán)境下,簡(jiǎn)易的AJAX集成對(duì)于一個(gè)成功的WEB框架來說是不可或缺的。因此,Struts 2其中的一個(gè)重要的功能(Feature)就是“First-class AJAX support - Add interactivity and flexibility with AJAX tags that look and feel just like standard Struts tags(大意:一流的AJAX支持——通過AJAX標(biāo)志增加互動(dòng)性和靈活性,而且使用這些AJAX標(biāo)志與普通的Struts標(biāo)志同樣簡(jiǎn)單)”。
實(shí)現(xiàn)原理
基于不重新發(fā)明輪子的原則,Struts 2并沒有開發(fā)新的AJAX框架,而是使用時(shí)下Java EE平臺(tái)中比較流行的AJAX框架——Dojo和DWR。
最近在Musachy Barroso等同志的無私奉獻(xiàn)下,開發(fā)了Struts 2的JSON插件(Plugin),極大地方便了我們輸出JSON結(jié)果(Result)。
JSON插件(Plugin)
在Struts 2的showcase中的AJAX部分,JSON的結(jié)果輸出是通過Freemaker模板實(shí)現(xiàn)。這種方法在簡(jiǎn)易性和靈活性上都比不上JSON插件,所以JSON插件值得向大家五星推薦。
下面讓我們看一個(gè)JSON插件的例子。
首先到以下網(wǎng)址http://code.google.com/p/jsonplugin/downloads/list下載JSON插件的JAR包,并將其加入你的WebContent\WEB-INF\lib下。
接下是本例子的Action代碼:
package tutorial;

import java.util.ArrayList;
import java.util.List;

import com.googlecode.jsonplugin.annotations.JSON;
import com.opensymphony.xwork2.ActionSupport;

public class JsonPluginAction extends ActionSupport {
private static final long serialVersionUID = -6784977600668791997L;

private int bookId;
private String title;
private double price;
private List<String> comments;
private transient String secret1;
private String secret2;

@JSON(name="ISBN")
public int getBookId() {
return bookId;
}

public void setBookId(int bookId) {
this.bookId = bookId;
}

public List<String> getComments() {
return comments;
}

public void setComments(List<String> comments) {
this.comments = comments;
}

public double getPrice() {
return price;
}

public void setPrice(double price) {
this.price = price;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

@Override
public String execute() {
bookId = 15645912;
title = "Max On Java";
price = 0.9999d;
comments = new ArrayList<String>(3);
comments.add("It's no bad!");
comments.add("WOW!");
comments.add("No comment!");
secret1 = "You can't see me!";
secret2 = "I am invisible!";
return SUCCESS;
}
}
清單1 src/tutorial/JsonPluginAction.java
以上代碼值得注意的是,通過@JSON的JAVA注釋(Annotation),我們可以改變JSON結(jié)果的屬性名稱,另外帶有transient修飾符與沒有Getter方法的字段(field)都不會(huì)被串行化為JSON。
然后,我們來配置一下此Action,代碼如下:
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
<package name="Struts2_AJAX_DEMO" extends="json-default">
<action name="JsonPlugin" class="tutorial.JsonPluginAction">
<result type="json" />
</action>
</package>
</struts>
清單2 src/struts.xml
上面配置文件的“package”元素和以往不同的是,它擴(kuò)展了“json-default”而不是“struts-default”。“json-default”是在jsonplugin-0.11.jar包里的struts-plugin.xml中定義的。該文件同時(shí)定義了“json”的結(jié)果類型,有興趣的朋友可以打開此文件看看。
發(fā)布運(yùn)行應(yīng)用程序,在瀏覽器中鍵入:http://localhost:8080/Struts2_Ajax/JsonPlugin.action,出現(xiàn)下載文件對(duì)話框,原因是JSON插件將HTTP響應(yīng)(Response)的MIME類型設(shè)為“application/json”。把文件下載下來,用記事本打開,內(nèi)容如下:
{"ISBN":15645912,"comments":["It's no bad!","WOW!","No comment!"],"price":0.9999,"title":"Max On Java"}
清單3 例子1輸出的JSON串
當(dāng)然這還不是一個(gè)完整的AJAX的例子,下面讓我們寫一個(gè)HTML文件將其完成,HTML代碼如下:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>JSON Plugin</title>
<script type="text/javascript">
var bXmlHttpSupport = (typeof XMLHttpRequest != "undefined" || window.ActiveXObject);

if (typeof XMLHttpRequest == "undefined" && window.ActiveXObject) {
function XMLHttpRequest() {
var arrSignatures = ["MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0",
"MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP",
"Microsoft.XMLHTTP"];

for (var i=0; i < arrSignatures.length; i++) {
try {
var oRequest = new ActiveXObject(arrSignatures[i]);
return oRequest;
} catch (oError) { /*ignore*/ }
}

throw new Error("MSXML is not installed on your system.");
}
}

function retrieveBook() {
if(bXmlHttpSupport) {
var sUrl = 'JsonPlugin.action';
var oRequest = new XMLHttpRequest();
oRequest.onreadystatechange = function() {
if(oRequest.readyState == 4) {
var oBook = eval('(' + oRequest.responseText + ')');
var bookHolder = document.getElementById('bookHolder');
var sBook = '<p><b>ISBN: </b>' + oBook.ISBN + '</p>';
sBook += ('<p><b>Title: </b>' + oBook.title + '</p>');
sBook += ('<p><b>Price: </b>$' + oBook.price + '</p>');
sBook += ('<b><i>Comments: </i></b><hr/>');
for(i = 0; i < oBook.comments.length; i++) {
sBook += ('<p><b>#' + (i + 1) + ' </b>' + oBook.comments[i] + '</p>');
}
bookHolder.innerHTML = sBook;
}
};
oRequest.open('POST', sUrl);
oRequest.send(null);
}
}
</script>
</head>
<body>
<input type="button" value="Retrieve Book" onclick="retrieveBook()" />
<div id="bookHolder"></div>
</body>
</html>
清單4 WebContent/JsonPlugin.html
以上代碼中,我沒有使用任何的AJAX的Javascript包,而是參考《Professional Javascript For Web Developer》手工創(chuàng)建XHR(XMLHttpRequest),并在XHR完成后使用eval()方法將JSON字符串變?yōu)镴SON對(duì)象。需要注意的是,要調(diào)用eval函數(shù)時(shí),必須使用“(”和“)”將JSON字符串括起來,否則會(huì)出錯(cuò)的。
打開http://localhost:8080/Struts2_Ajax/JsonPlugin.html,點(diǎn)擊“Retrieve Book”按鈕,頁面如下圖所示:

圖1 JsonPlugin.html頁面輸出
Struts 2與Dojo
Dojo是開源Javascript工具包,它引了Widget的概念,方便了Javascript面向?qū)ο缶幊蹋∣OP),改進(jìn)Javascript的事件模型。在此我不打算對(duì)此進(jìn)行深入的講解,有興趣的朋友的可以找網(wǎng)上找一些關(guān)于Dojo的資料學(xué)習(xí)。
Struts 2基于Dojo編寫一些AJAX標(biāo)志(在Dojo中稱為Widget),要使用這些標(biāo)志的AJAX功能,需要將標(biāo)志的“theme”屬性設(shè)為“ajax”。同時(shí),亦需要將加入在<head>與</head>之間加入<s:head theme="ajax" />。當(dāng)使用這些標(biāo)志的AJAX功能,有些屬性可能會(huì)經(jīng)常用到,所以我會(huì)對(duì)這些屬性稍作解釋。
名稱 描述
href XHR(XMLHttpRequest)請(qǐng)求的地址
listenTopics 監(jiān)聽的Dojo話題(Topic)以觸發(fā)自身,如可以在可以通過發(fā)布(Publish)相應(yīng)的話題,通知<s:autocompleter />重新加載其備選項(xiàng)(Options)
notifyTopics 完成遠(yuǎn)程調(diào)用后,發(fā)出通知,觸發(fā)相應(yīng)的Javascript函數(shù)或Dojo Widget
formId 需要提交到服務(wù)器的表單的ID
formFilter 過濾表單字段的Javascript函數(shù)名稱
indicator 在XHR處理過程中,包含用戶提示的信息的HTML元素的ID,如圖片或DIV等
表1 常用的AJAX標(biāo)志屬性
這些標(biāo)志包括:<s:a />、<s: submit />、<s:autocompleter />和<s:tree />等,下面我將分別講解。
1、<s:a />和<s:submit />
這兩個(gè)標(biāo)志方便了我們的調(diào)用XHR實(shí)現(xiàn)AJAX,所以上面的HTML如果使用了這兩標(biāo)志將會(huì)變得更簡(jiǎn)單,因?yàn)槲覀儾挥迷偃ダ頃?huì)繁鎖的XHR創(chuàng)建和設(shè)定的工作。下面是示例代碼:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>JSON Plugin</title>
<s:head theme="ajax" />
<script type="text/javascript">
dojo.addOnLoad(function() {
dojo.event.topic.subscribe('retrieveBook', this, function(data, type, e){
if(type == 'load') {
showBook(data);
} else if(type == 'error') {
alert('Can not retrieve the book');
}
});
});

function showBook(strBook) {
var oBook = eval('(' + strBook + ')');
var bookHolder = document.getElementById('bookHolder');
var sBook = '<p><b>ISBN: </b>' + oBook.ISBN + '</p>';
sBook += ('<p><b>Title: </b>' + oBook.title + '</p>');
sBook += ('<p><b>Price: </b>$' + oBook.price + '</p>');
sBook += ('<b><i>Comments: </i></b><hr/>');
for(i = 0; i < oBook.comments.length; i++) {
sBook += ('<p><b>#' + (i + 1) + ' </b>' + oBook.comments[i] + '</p>');
}
bookHolder.innerHTML = sBook;
}
</script>
</head>
<body>
<s:url id="bookUrl" value="/JsonPlugin.action" />
<s:submit href="%{bookUrl}" theme="ajax" indicator="indicator"
value="Retrieve Book" align="left" notifyTopics="retrieveBook" />
<s:a theme="ajax" href="%{bookUrl}" indicator="indicator"
notifyTopics="retrieveBook">Retrieve Book</s:a>
<img id="indicator"
src="${pageContext.request.contextPath}/images/indicator.gif"
alt="Loading " style="display:none" />
<div id="bookHolder"></div>
</body>
</html>
清單5 WebContent/LinkButton.jsp
可能上述代碼還不夠簡(jiǎn)潔,因?yàn)槲覍TML格式化的工作都放在Javascript中完成。但如果你的XHR返回的是HTML片段,你可以簡(jiǎn)單地將<s:a />或<s:submit />的“targets”屬性設(shè)為“bookHolder”即可,詳情大家可以參考Struts 2 Showcase。至于返回HTML片段,可以通過Action + Freemaker完成。
2、<s:autocompleter />
Autocomplete是比較經(jīng)典的AJAX應(yīng)用,雖然谷歌已經(jīng)停止使用這一功能,但就Autocompleter自身而言的確是很酷的。下面是一個(gè)<s:autocompleter />的例子。
首先,我要偽造一些字符串?dāng)?shù)據(jù),代碼如下:
package tutorial;

import java.util.ArrayList;
import java.util.List;

public final class Datas {
public static final List<String> NAMES;
static {
NAMES = new ArrayList<String>();
NAMES.add("Alabama");
NAMES.add("Alaska");
NAMES.add("American Samoa");
NAMES.add("Arizona");
NAMES.add("Arkansas");
NAMES.add("Armed Forces Europe");
NAMES.add("Armed Forces Pacific");
NAMES.add("Armed Forces the Americas");
NAMES.add("California");
NAMES.add("Colorado");
NAMES.add("Connecticut");
NAMES.add("Delaware");
NAMES.add("District of Columbia");
NAMES.add("Federated States of Micronesia");
NAMES.add("Florida");
NAMES.add("Georgia");
NAMES.add("Guam");
NAMES.add("Hawaii");
NAMES.add("Idaho");
NAMES.add("Illinois");
NAMES.add("Indiana");
NAMES.add("Iowa");
NAMES.add("Kansas");
NAMES.add("Kentucky");
NAMES.add("Louisiana");
NAMES.add("Maine");
NAMES.add("Marshall Islands");
NAMES.add("Maryland");
NAMES.add("Massachusetts");
NAMES.add("Michigan");
NAMES.add("Minnesota");
NAMES.add("Mississippi");
NAMES.add("Missouri");
NAMES.add("Montana");
NAMES.add("Nebraska");
NAMES.add("Nevada");
NAMES.add("New Hampshire");
NAMES.add("New Jersey");
NAMES.add("New Mexico");
NAMES.add("New York");
NAMES.add("North Carolina");
NAMES.add("North Dakota");
NAMES.add("Northern Mariana Islands");
NAMES.add("Ohio");
NAMES.add("Oklahoma");
NAMES.add("Oregon");
NAMES.add("Pennsylvania");
NAMES.add("Puerto Rico");
NAMES.add("Rhode Island");
NAMES.add("South Carolina");
NAMES.add("South Dakota");
NAMES.add("Tennessee");
NAMES.add("Texas");
NAMES.add("Utah");
NAMES.add("Vermont");
NAMES.add("Virgin Islands, U.S.");
NAMES.add("Virginia");
NAMES.add("Washington");
NAMES.add("West Virginia");
NAMES.add("Wisconsin");
NAMES.add("Wyoming");
}
}
清單6 src/tutorial/Datas.java
然后是用于獲取和過濾數(shù)據(jù)的Action,代碼如下:
package tutorial;

import java.util.ArrayList;
import java.util.List;

import com.opensymphony.xwork2.ActionSupport;

public class AutocompleterAction extends ActionSupport {
private static final long serialVersionUID = -8201401726773589361L;

private List<String[]> names;
private String start;

public void setStart(String start) {
this.start = start;
}

public List<String[]> getNames() {
return names;
}

@Override
public String execute() {
names = new ArrayList<String[]>();
if(start == null || "".equals(start.trim())) {
start = "a";
}
for(String s : Datas.NAMES) {
if(s.toLowerCase().startsWith(start.toLowerCase())) {
names.add(new String[]{ s, s });
}
}
return SUCCESS;
}
}
清單7 src/tutorial/AutocmpleterAction.java
上述Action會(huì)以JSON的形式返回以start開頭的Datas.NAMES的中字符串,以下是此Action的配置:
<action name="Autocompleter" class="tutorial.AutocompleterAction">
<result type="json">
<param name="root">names</param>
</result>
</action>
清單8 Autocompleter Action的配置代碼片段
在JSON類型結(jié)果的參數(shù)中加入“root”參數(shù)可以設(shè)定輸出JSON結(jié)果的根,以上述情況為例,如果沒有“root”參數(shù),輸出將為“{ "names": [ ["xxx", "xxx"]...] }”,加了之后變就會(huì)成“[ ["xxx", "xxx"]...] ”。接下來,讓我們看看頁面的代碼:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Struts 2 AJAX - Autocompleter</title>
<s:head theme="ajax" />
</head>
<body>
<h2>
Autocompleter
</h2>
<s:form action="autocompleterForm">
<s:textfield label="abc" name="abc" />
<tr>
<td class="tdLabel">
<label class="label">
No AJAX Autocompleter:
</label>
</td>
<td>
<s:autocompleter theme="simple" name="user"
list="@tutorial.Datas@NAMES" />
</td>
</tr>
<tr>
<td class="tdLabel">
<label class="label">
AJAX Autocompleter:
</label>
</td>
<td>
<s:url id="dataUrl" value="/Autocompleter.action" />
<s:autocompleter theme="ajax" name="start" href="%{dataUrl}"
loadOnTextChange="true" loadMinimumCount="1" indicator="indicator"
autoComplete="false" showDownArrow="false" />
<img id="indicator"
src="${pageContext.request.contextPath}/images/indicator.gif"
alt="Loading " style="display:none" />
</td>
</tr>
</s:form>
</body>
</html>
清單9 WebContent/Autocompleter.jsp
上述頁面包含兩個(gè)<s:autocompleter />標(biāo)志,前者使用“simple”模板,所以不具有AJAX功能,它的數(shù)據(jù)將以HTML方式輸出到最終頁面里;而后者則使用了“ajax”模板,每當(dāng)輸入框的值發(fā)生改變時(shí),它都向URL“/Autocompleter.action”發(fā)送請(qǐng)求,Action根據(jù)請(qǐng)求中的start參數(shù)的值,返回相當(dāng)?shù)腏SON,在請(qǐng)求完成后頁面通過回調(diào)函數(shù)改變輸入框的下拉提示,效果如下圖所示:

圖2 Autocompleter.jsp頁面輸出
3、<s:tree />
樹是是比較常用的數(shù)據(jù)結(jié)構(gòu),因?yàn)樗梢院芎玫伢w現(xiàn)真實(shí)世界中對(duì)象之間的關(guān)系。<s:tree />的使用也相對(duì)簡(jiǎn)單,但需要說明的是——Struts 2.0.6 GA版本的<s:tree />是有BUG的,大家可以點(diǎn)擊這個(gè)鏈接https://issues.apache.org/struts/browse/WW-1813了解詳細(xì)的情況。這個(gè)BUG主要是在<s:tree />的通過“treeCollapsedTopic”、“treeExpandedTopic”和“treeSelectedTopic”設(shè)定的話題(Topic)都沒有起作用,上述鏈接相應(yīng)給出了解決方法,但我認(rèn)為該方法太麻煩(需要自己重新編譯和打包Struts 2),所以下面的例子,我將另辟?gòu)袕剑?qǐng)參考以下代碼。
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Struts 2 AJAX - Tree</title>
<s:head theme="ajax" debug="true" />
<script type="text/javascript">
function treeNodeSelected(arg) {
alert(arg.source.title + ' selected');
}
dojo.addOnLoad(function() {
var s = dojo.widget.byId('parentId').selector;
dojo.event.connect(s, 'select', 'treeNodeSelected');
});
</script>
</head>
<body>
<h2>
Tree
</h2>
<div style="float:left; margin-right: 50px;">
<s:tree label="parent" id="parentId" theme="ajax"
templateCssPath="/struts/tree.css" showRootGrid="true"
showGrid="true">
<s:treenode theme="ajax" label="child1" id="child1Id">
<s:treenode theme="ajax" label="grandchild1" id="grandchild1Id" />
<s:treenode theme="ajax" label="grandchild2" id="grandchild2Id" />
<s:treenode theme="ajax" label="grandchild3" id="grandchild3Id" />
</s:treenode>
<s:treenode theme="ajax" label="child2" id="child2Id" />
<s:treenode theme="ajax" label="child3" id="child3Id" />
<s:treenode theme="ajax" label="child4" id="child4Id" />
<s:treenode theme="ajax" label="child5" id="child5Id">
<s:treenode theme="ajax" label="gChild1" id="gChild1Id" />
<s:treenode theme="ajax" label="gChild2" id="gChild2Id" />
</s:treenode>
</s:tree>
</div>
</body>
</html>
清單10 WebContent/Tree.jsp
因?yàn)镈ojo的樹控件,即使在沒有設(shè)定“selector”情況下,也會(huì)自動(dòng)生成一個(gè)默認(rèn)的Selector,所以只要將其事件綁定到特定的事件處理函數(shù)即可。
打開http://localhost:8080/Struts2_Ajax/Tree.jsp,點(diǎn)擊任一樹節(jié)點(diǎn),頁面如下圖所示:

圖3 Tree.jsp頁面輸出
更多<s:tree />
在Struts 2的showcase中有兩個(gè)<s:tree />的例子,分別是靜態(tài)樹與動(dòng)態(tài)樹。所謂的靜態(tài)樹即是在編寫JSP代碼時(shí)通過<s:treenode />生成樹節(jié)點(diǎn)。我的上一篇文章的例子就是一個(gè)典型的靜態(tài)樹。而動(dòng)態(tài)樹則是在程序運(yùn)行期間,Struts 2 運(yùn)行時(shí)(Runtime)根據(jù)程序中的數(shù)據(jù)動(dòng)態(tài)創(chuàng)建樹節(jié)點(diǎn)。雖然在兩個(gè)例子中<s:tree />的theme屬性都為“ajax”,但是從嚴(yán)格意義上來說,這兩種樹都不屬于AJAX樹,因?yàn)樗鼈兌际窃谳敵鲰撁鏁r(shí)將全部節(jié)點(diǎn)加載到其中,而不是在父節(jié)點(diǎn)展開時(shí)通過XHR(XMLHttpRequest)獲取節(jié)點(diǎn)數(shù)據(jù)。
動(dòng)態(tài)樹
下面我們先看一下動(dòng)態(tài)樹的例子,接著再一步步地將其改造為名副其實(shí)的AJAX 樹。下例將會(huì)把WEB應(yīng)用程序的目錄樹展現(xiàn)在JSP頁面中。因此,我需要先包裝一下java.io.File 類,代碼如下:
package tutorial;

import java.io.File;

public class FileWrapper {
private File file;

public FileWrapper(String path) {
file = new File(path);
}

public FileWrapper(File file) {
this.file = file;
}

public String getId() {
return "file_" + file.hashCode();
}

public String getName() {
return file.getName();
}

public String getAbsolutePath() {
return file.getAbsolutePath();
}

public FileWrapper[] getChildren() {
File[] files = file.listFiles();
if(files != null && files.length > 0) {
int length = files.length;
FileWrapper[] wrappers = new FileWrapper[length];
for(int i = 0; i < length; ++i) {
wrappers[i] = new FileWrapper(files[i]);
}
return wrappers;
}
return new FileWrapper[0];
}
}
清單1 src/tutorial/FileWrapper.java
之所以需要對(duì)File類進(jìn)行如此包裝,是因?yàn)?lt;s:tree />用于動(dòng)態(tài)樹時(shí),rootNode、nodeIdProperty、nodeTitleProperty 和 childCollectionProperty等屬性都必填的。
然后是Action類的代碼如下:
package tutorial;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.interceptor.ServletRequestAware;

import com.opensymphony.xwork2.ActionSupport;

public class DynamicTreeAction extends ActionSupport implements ServletRequestAware {
private static final long serialVersionUID = 1128593047269036737L;

private HttpServletRequest request;
private FileWrapper root;

public void setServletRequest(HttpServletRequest request) {
this.request = request;
}

public FileWrapper getRoot() {
return root;
}

@Override
public String execute() {
root = new FileWrapper(request.getSession().getServletContext().getRealPath("/"));
return SUCCESS;
}
}
清單2 src/tutorial/DynamicTreeAction.java
上述代碼取得WEB應(yīng)用程序的根目錄的絕對(duì)路徑后,初始化FileWrapper對(duì)象root。該對(duì)象將為JSP頁面的<s:tree />的根節(jié)點(diǎn)。如下代碼所示:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Struts 2 AJAX - More Tree</title>
<s:head theme="ajax" debug="true" />
<script type="text/javascript">
/* <![CDATA[ */
function treeNodeSelected(arg) {
alert(arg.source.title + ' selected');
}

function treeNodeExpanded(arg) {
alert(arg.source.title + ' expanded');
}

function treeNodeCollapsed(arg) {
alert(arg.source.title + ' collapsed');
}

dojo.addOnLoad(function() {
var t = dojo.widget.byId('appFiles');
dojo.event.topic.subscribe(t.eventNames.expand, treeNodeExpanded);
dojo.event.topic.subscribe(t.eventNames.collapse, treeNodeCollapsed);

var s = t.selector;
dojo.event.connect(s, 'select', 'treeNodeSelected');
});
/* ]]> */
</script>
</head>
<body>
<h2>
Dynamic Tree Example
</h2>
<div style="float:left; margin-right: 50px;">
<s:tree id="appFiles" theme="ajax" rootNode="root"
nodeTitleProperty="name" nodeIdProperty="id"
childCollectionProperty="children" />
</div>
</body>
</html>
清單3 WebContent/Tree.jsp
因?yàn)?lt;s:tree />的treeCollapsedTopic和treeExpandedTopic屬性都沒有起作用,所以如果我們想要監(jiān)聽這兩個(gè)事件,就必須使用上述代碼的方法。
最后是struts.xml配置文件:
<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
<package name="Struts2_AJAX_DEMO" extends="struts-default">
<action name="DynamicTree" class="tutorial.DynamicTreeAction">
<result>Tree.jsp</result>
</action>
</package>
</struts>
清單4 src/struts.xml
發(fā)布運(yùn)行應(yīng)用程序,在瀏覽器地址欄中鍵入http://localhost:8080/Struts2_Ajax2/DynamicTree.action,有如下圖所示頁面:

圖1 動(dòng)態(tài)樹示例
AJAX 樹
正如我在文章開頭所說,Struts 2所提供的靜態(tài)樹和動(dòng)態(tài)樹都不是嚴(yán)格意義上的AJAX樹。下面就讓我們來實(shí)現(xiàn)一個(gè)如假包換的AJAX樹。首先要說明的是,Struts 2的<s:tree />默認(rèn)是不支持這種按需加載數(shù)據(jù)的AJAX樹。不過因?yàn)樗腔贒ojo的樹控件(Widget)所以要擴(kuò)展也很方便。
Dojo 通過名為“TreeRPCController”的控件實(shí)現(xiàn) AJAX 樹,它會(huì)監(jiān)聽被控制樹的事件。當(dāng)發(fā)生展開節(jié)點(diǎn)的事件時(shí),TreeRPCController就會(huì)向URL發(fā)送XHR請(qǐng)求,該URL由TreeRPCController的RPCUrl 屬性定義。XHR請(qǐng)求格式類似如下格式:
http://localhost:8080/Struts2_Ajax2/AjaxTree.action?action=getChildren&data={"node":{"widgetId":"file_226092423","objectId":"C:\\Program Files\\Tomcat 5.5\\webapps\\Struts2_Ajax2","index":0,"isFolder":true},"tree":{"widgetId":"appFiles","objectId":""}}&dojo.preventCache=1182913465392
清單5 XHR樣本
顯而易見,請(qǐng)求中包含三個(gè)參數(shù),分別是action為“getChildren”(固定值),data一個(gè)包含當(dāng)前節(jié)點(diǎn)與樹信息的JSON串和dojo.preventCache隨機(jī)串,用于緩存不同節(jié)點(diǎn)的請(qǐng)求響應(yīng)(父節(jié)點(diǎn)只會(huì)在第一次被展開時(shí)到服務(wù)器端加載數(shù)據(jù),之后都是從瀏覽器的緩存中讀取數(shù)據(jù),可以提高應(yīng)用程序性能)。
首先我要先寫一個(gè)加載樹節(jié)點(diǎn)數(shù)據(jù)的Action類,代碼如下:
package tutorial;

import java.util.Map;

import com.googlecode.jsonplugin.JSONExeption;
import com.googlecode.jsonplugin.JSONUtil;

public class AjaxTreeAction extends DynamicTreeAction {
private static final long serialVersionUID = 3970019751740942311L;

private String action;
private String data;
private FileWrapper[] wrappers;

public void setAction(String action) {
this.action = action;
}

public void setData(String data) {
this.data = data;
}

public FileWrapper[] getWrappers() {
return wrappers;
}

@Override
public String execute() {
if("getChildren".equals(action)) {
try {
Object o = JSONUtil.deserialize(data);
String path = ((Map) ((Map) o).get("node")).get("objectId").toString();
wrappers = new FileWrapper(path).getChildren();
} catch (JSONExeption e) {
e.printStackTrace();
}
return "ajax";
}
return super.execute();
}
}
清單6 src/tutorial/AjaxTreeAction.java
上述代碼可能需要解釋一下:
1. action屬性對(duì)應(yīng)于XHR中的action,如果它為“getChildren”時(shí),則需要進(jìn)行加載子節(jié)點(diǎn)操作。否則,會(huì)讀取樹的根節(jié)點(diǎn),并返回JSP頁面;
2. 通過上面XHR的分析,大家可以知道data是代表樹和當(dāng)前節(jié)點(diǎn)的JSON串,故應(yīng)將其反串行化為Map對(duì)象,并將其 objectId屬性取出。通常情況下,Dojo樹的objectId屬性代表服務(wù)器端的對(duì)象的標(biāo)識(shí),在本例中為文件夾的絕對(duì)路徑;
3. wrappers屬性表示當(dāng)前文件夾下的文件數(shù)組,它被傳送到Freemarker頁面,翻譯為Dojo樹節(jié)點(diǎn)數(shù)組的JSON串。
下面是Freemarker頁面的代碼:
[
<#list wrappers as r>
{ "title": "${r.name}", "isFolder": <#if r.children?size gt 0>true<#else>false</#if>, "id": "${r.id}", "objectId": "${r.absolutePath?js_string}" }<#if r_has_next>,</#if>
</#list>
]
清單7 WebContent/AjaxTree.ftl
以上代碼中<#list></#lsit>的寫法是Freemarker中遍歷集合的寫法;而<#if r.children?size gt 0>判斷“r”對(duì)象的children屬性是否為空;r.absolutePath?js_string 就是將“r”的absolutePath屬性的值輸出為Javascript 的字串符形式;<#if r_has_next></#if>判斷集合是否有下一項(xiàng)數(shù)據(jù)。如果希望更詳細(xì)地了解Freemarker的使用,請(qǐng)參考該手冊(cè)。
接下來,讓我們看看Action的配置代碼片段:
<action name="AjaxTree" class="tutorial.AjaxTreeAction">
<result>AjaxTree.jsp</result>
<result name="ajax" type="freemarker">AjaxTree.ftl</result>
</action>
清單8 src/struts.xml配置片段
最后是JSP頁面代碼:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Struts 2 AJAX - More Tree</title>
<s:head theme="ajax" debug="true" />
<script type="text/javascript">
/* <![CDATA[ */
function treeNodeSelected(arg) {
alert(arg.source.title + ' selected');
}

dojo.addOnLoad(function() {
var t = dojo.widget.byId('appFiles');
var s = t.selector;
dojo.event.connect(s, 'select', 'treeNodeSelected');
});
/* ]]> */
</script>
</head>
<body>
<h2>
AJAX Tree Example
</h2>
<div style="float:left; margin-right: 50px;">
<script type="text/javascript">
/* <![CDATA[ */
dojo.require("dojo.lang.*");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.Tree");
dojo.require("dojo.widget.TreeRPCController");
/* ]]> */
</script>
<div dojoType="TreeRPCController" widgetId="treeController"
DNDcontroller="create" RPCUrl="<s:url />"></div>
<div dojoType="Tree" widgetId="appFiles" toggle="fade" controller="treeController">
<div dojoType="TreeNode" title='<s:property value="root.name" />'
widgetId='<s:property value="root.id" />'
isFolder='<s:property value="root.children.length > 0" />'
objectId='<s:property value="root.absolutePath" />'>
</div>
</div>
</div>
</body>
</html>
清單9 WebContent/AjaxTree.jsp
由于上面所提及的原因,我在上述的代碼中并沒有使用<s:tree />標(biāo)志,而是使用了Dojo的寫法——?jiǎng)?chuàng)建 widgetId 為“treeController”的 TreeRPCController 并將設(shè)為樹的控制器。
發(fā)布運(yùn)行應(yīng)用程序,在瀏覽器地址欄中鍵入http://localhost:8080/Struts2_Ajax2/AjaxTree.action,點(diǎn)開某個(gè)節(jié)點(diǎn),在節(jié)點(diǎn)加載的過程中,加號(hào)圖標(biāo)變成時(shí)鐘狀圖標(biāo),如下圖所示頁面:

圖2 AJAX樹示例
自定義<s:tree />的AJAX的主題(theme)
Struts 2的標(biāo)志過人之外在于它允許開發(fā)人員自定義標(biāo)志的頁面輸出。要做到這一點(diǎn),你所需要做的只是創(chuàng)建一個(gè)自定義的theme并將其應(yīng)用到相應(yīng)標(biāo)志。下面就讓我自定義一個(gè)真正的AJAX的<s:tree/>的theme。
首先,你的源文件的根目錄下新建包“template.realajax”。
然后,在上一步所建的包中新建“tree.ftl”文件,內(nèi)容如下:
<script type="text/javascript">
/* <![CDATA[ */
dojo.require("dojo.lang.*");
dojo.require("dojo.widget.*");
dojo.require("dojo.widget.Tree");
dojo.require("dojo.widget.TreeRPCController"); <#-- Added by Max -->
/* ]]> */
</script>
<#-- Added by Max -->
<div dojoType="TreeRPCController"
widgetId="${parameters.id?html}_controller"
DNDcontroller="create"
RPCUrl="<@s.url />">
</div>
<#-- End -->
<div dojoType="Tree"
<#if parameters.blankIconSrc?exists>
gridIconSrcT="<@s.url value='${parameters.blankIconSrc}' encode="false" includeParams='none'/>"
</#if>
<#if parameters.gridIconSrcL?exists>
gridIconSrcL="<@s.url value='${parameters.gridIconSrcL}' encode="false" includeParams='none'/>"
</#if>
<#if parameters.gridIconSrcV?exists>
gridIconSrcV="<@s.url value='${parameters.gridIconSrcV}' encode="false" includeParams='none'/>"
</#if>
<#if parameters.gridIconSrcP?exists>
gridIconSrcP="<@s.url value='${parameters.gridIconSrcP}' encode="false" includeParams='none'/>"
</#if>
<#if parameters.gridIconSrcC?exists>
gridIconSrcC="<@s.url value='${parameters.gridIconSrcC}' encode="false" includeParams='none'/>"
</#if>
<#if parameters.gridIconSrcX?exists>
gridIconSrcX="<@s.url value='${parameters.gridIconSrcX}' encode="false" includeParams='none'/>"
</#if>
<#if parameters.gridIconSrcY?exists>
gridIconSrcY="<@s.url value='${parameters.gridIconSrcY}' encode="false" includeParams='none'/>"
</#if>
<#if parameters.gridIconSrcZ?exists>
gridIconSrcZ="<@s.url value='${parameters.gridIconSrcZ}' encode="false" includeParams='none'/>"
</#if>
<#if parameters.expandIconSrcPlus?exists>
expandIconSrcPlus="<@s.url value='${parameters.expandIconSrcPlus}' includeParams='none'/>"
</#if>
<#if parameters.expandIconSrcMinus?exists>
expandIconSrcMinus="<@s.url value='${parameters.expandIconSrcMinus?html}' includeParams='none'/>"
</#if>
<#if parameters.iconWidth?exists>
iconWidth="<@s.url value='${parameters.iconWidth?html}' encode="false" includeParams='none'/>"
</#if>
<#if parameters.iconHeight?exists>
iconHeight="<@s.url value='${parameters.iconHeight?html}' encode="false" includeParams='none'/>"
</#if>
<#if parameters.toggleDuration?exists>
toggleDuration=${parameters.toggleDuration?c}
</#if>
<#if parameters.templateCssPath?exists>
templateCssPath="<@s.url value='${parameters.templateCssPath}' encode="false" includeParams='none'/>"
</#if>
<#if parameters.showGrid?exists>
showGrid="${parameters.showGrid?default(true)?string}"
</#if>
<#if parameters.showRootGrid?exists>
showRootGrid="${parameters.showRootGrid?default(true)?string}"
</#if>
<#if parameters.id?exists>
id="${parameters.id?html}"
</#if>
<#if parameters.treeSelectedTopic?exists>
publishSelectionTopic="${parameters.treeSelectedTopic?html}"
</#if>
<#if parameters.treeExpandedTopic?exists>
publishExpandedTopic="${parameters.treeExpandedTopic?html}"
</#if>
<#if parameters.treeCollapsedTopic?exists>
publishCollapsedTopic="${parameters.treeCollapsedTopic?html}"
</#if>
<#if parameters.toggle?exists>
toggle="${parameters.toggle?html}"
</#if>
controller="${parameters.id?html}_controller" <#-- Added by Max -->
>
<#if parameters.label?exists>
<div dojoType="TreeNode" title="${parameters.label?html}"
<#if parameters.nodeIdProperty?exists>
id="${stack.findValue(parameters.nodeIdProperty)}"
<#else>
id="${parameters.id}_root"
</#if>
>
<#elseif parameters.rootNode?exists>
${stack.push(parameters.rootNode)}
<#-- Edited by Max -->
<div dojoType="TreeNode"
title="${stack.findValue(parameters.nodeTitleProperty)}"
widgetId="${stack.findValue(parameters.nodeIdProperty)}"
isFolder="<#if stack.findValue(parameters.childCollectionProperty)?size gt 0>true<#else>false</#if>"
objectId="${stack.findValue(parameters.nameValue)}">
</div>
<#-- End -->
<#assign oldNode = stack.pop()/> <#-- pop the node off of the stack, but don't show it -->
</#if>
清單10 src/template/realajax/tree.ftl
對(duì)上述稍作解釋,上述代碼主要在原版的src/template/ajax/tree.ftl的基礎(chǔ)上添加了TreeRPCController的控件,并只輸出根節(jié)點(diǎn)。由于<s:tree />沒有類似nodeObjectIdProperty的屬性,所以我用了value屬性表示objectId對(duì)應(yīng)的屬性名稱。
接著新建tree-close.ftl文件,內(nèi)容和原版的一樣,如下所示:
<#if parameters.label?exists></div></#if></div>
清單11 src/template/realajax/tree-close.ftl
再下來就應(yīng)該是將theme應(yīng)用到<s:tree />,如下代碼所示:
<%@ page language="java" contentType="text/html; charset=utf-8"
pageEncoding="utf-8"%>
<%@ taglib prefix="s" uri="/struts-tags"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Struts 2 AJAX - More Tree</title>
<s:head theme="ajax" debug="true" />
<script type="text/javascript">
/* <![CDATA[ */
function treeNodeSelected(arg) {
alert(arg.source.title + ' selected');
}

dojo.addOnLoad(function() {
var t = dojo.widget.byId('appFiles');
var s = t.selector;
dojo.event.connect(s, 'select', 'treeNodeSelected');
});
/* ]]> */
</script>
</head>
<body>
<h2>
AJAX Tree Example
</h2>
<div style="float:left; margin-right: 50px;">
<s:tree id="appFiles" theme="realajax" rootNode="root"
nodeTitleProperty="name" nodeIdProperty="id"
childCollectionProperty="children" value="absolutePath" />
</div>
</body>
</html>
清單12 WebContent/AjaxTreeTheme.jsp
上述代碼中<s:tree />的用法,除了theme改為“realajax”和多了value="absolutePath"外,幾乎和靜態(tài)樹中的一樣。
為了不影響前一個(gè)例子,我們?yōu)樵揓SP文件配置類型相同的Action,如下代碼所示:
<action name="AjaxTreeTheme" class="tutorial.AjaxTreeAction">
<result>AjaxTreeTheme.jsp</result>
<result name="ajax" type="freemarker">AjaxTree.ftl</result>
</action>
清單13 src/struts.xml配置片段
發(fā)布運(yùn)行應(yīng)用程序,在瀏覽器地址欄中鍵入http://localhost:8080/Struts2_Ajax2/AjaxTreeTheme.action,結(jié)果如圖2所示。
總結(jié)
通過上述例子,大家知道Struts 2 的AJAX 標(biāo)志是基于Dojo控件開發(fā)的,所以如果大家希望熟練地使用這些標(biāo)志,最好去了解一下Dojo。
本來還打算介紹一下Struts 2與DWR,不過看看文章的篇幅似乎足夠自成一篇了,因此DWR相關(guān)的內(nèi)容要留待下文繼續(xù)了。



飛雪(leo) 2007-10-18 00:47 發(fā)表評(píng)論
]]>
DOJO試用手記4--dojo基礎(chǔ) http://m.tkk7.com/Jiangzy/archive/2007/10/18/153729.html飛雪(leo)飛雪(leo)Wed, 17 Oct 2007 16:32:00 GMThttp://m.tkk7.com/Jiangzy/archive/2007/10/18/153729.htmlhttp://m.tkk7.com/Jiangzy/comments/153729.htmlhttp://m.tkk7.com/Jiangzy/archive/2007/10/18/153729.html#Feedback0http://m.tkk7.com/Jiangzy/comments/commentRss/153729.htmlhttp://m.tkk7.com/Jiangzy/services/trackbacks/153729.html DOJO試用手記4--dojo基礎(chǔ) 來源:原創(chuàng) 作者:zxub 發(fā)布時(shí)間:2006-04-06 17:05:00  

  前面說了dojo在ajax方面的一些個(gè)東西,感覺要理解透徹還有些dojo內(nèi)部的東西需要理解,所以想好好看一下dojo的東西,惡補(bǔ)一陣:-)
  看了會(huì)官方一些個(gè)文檔,有了些許體會(huì)。
  dojo.js被包含進(jìn)來后,一些對(duì)象和函數(shù)就可以用了,在用JSEclipse編輯的時(shí)候,可以看到一些,不過是包含在dojo.js中的,官網(wǎng)說還包括boostrap文件里的,我查了下,有bootstrap1.js和bootstrap2.js,不過那些對(duì)象直接顯示不出來,估計(jì)有什么地方要設(shè)置,弄清楚后再補(bǔ)上來。
  可用的東東有:
 ?。保?span id="ocitgly" class="pre">dojo.render對(duì)象:該對(duì)象存放了dojo運(yùn)行環(huán)境的一些信息。
  dojo.render.name:根據(jù)dojo.render.name = navigator.appName,可以知道這是瀏覽器的名稱,但是直接顯示出來是空的,估計(jì)還沒有被賦值,運(yùn)行

1 dojo.render.name = navigator.appName;
2 alert(dojo.render.name);


我的出來的是:Microsoft Internet Explorer。
  dojo.render.os:看名字就知道與操作系統(tǒng)有關(guān),事實(shí)確實(shí)如此。這個(gè)屬性直接打印出來是[object Object],可以知道是一個(gè)對(duì)象。查了下源代碼,發(fā)現(xiàn)這個(gè)對(duì)象有3個(gè)屬性:dojo.render.os.osx,當(dāng)操作系統(tǒng)為"MacOS"取值為true;dojo.render.os.linux,當(dāng)操作系統(tǒng)為"Linux"的時(shí)候?yàn)閠rue;dojo.render.os.win,Windows系統(tǒng)取值為true。3個(gè)屬性的默認(rèn)值都為false,一進(jìn)dojo,則某一個(gè)屬性被賦值為true,我的Windows系統(tǒng)當(dāng)然是dojo.render.os.win為true了。根據(jù)源碼,若不是這3種系統(tǒng),dojo.render.os.linux將賦值為true。
  dojo.render.ver,官網(wǎng)上說與dojo.version一樣,但我一打印發(fā)現(xiàn)不對(duì),查了下代碼,發(fā)現(xiàn)如下一段:dojo.render.ver = parseFloat(navigator.appVersion, 10),是與瀏覽器版本號(hào)有關(guān),我這里dojo.render.ver的值為4。再找dojo.version,發(fā)現(xiàn)這么一段:

dojo.version = {
    major: 
0, minor: 2, patch: 2, flag: "",
    revision: Number(
"$Rev: 2836 $".match(/[0-9]+/)[0]),
    toString: 
function() {
        
with (dojo.version) {
            
return major + "." + minor + "." + patch + flag + " (" + revision + ")";
        }
    }
};


將dojo.version打印一下,是0.2.2(2836),上面一段的結(jié)果。
  dojo.render.html,這也是一個(gè)對(duì)象,它有好幾個(gè)屬性。dojo.render.html.capable,宿主環(huán)境是否支持html,一般來說,都是true。其它幾個(gè)是與瀏覽器類型有關(guān)的,都是布爾類型。dojo.render.html.moz,當(dāng)瀏覽器為Mozilla或者M(jìn)ozilla核心的瀏覽器(例如 Firefox)時(shí)為true; dojo.render.html.safari,使用蘋果的Safari瀏覽器的時(shí)候?yàn)閠rue,dojo.render.html.ie,平常的機(jī)器這個(gè)屬性都是true,因?yàn)槲覀兓臼怯肕icrosoft Internet Explorer,即ie瀏覽器;dojo.render.html.opera,使用Opera瀏覽器的時(shí)候?yàn)閠rue;dojo.render.html.khtml,使用KHTML瀏覽器(例如Konqueror,但是我還就真沒聽過這種KHTML瀏覽器,其它的都知道,看來還是知識(shí)不夠,唉~)的時(shí)候?yàn)閠rue。dojo.render.html對(duì)象主要是用來判斷瀏覽器類型的。我的機(jī)器上dojo.render.html.ie為true。
  其它還有dojo.render.svg,dojo.render.vml,dojo.render.swf,dojo.render.swt,由上面的資料,可以知道是對(duì)SVG、VML、SWF、SWT的支持,它們都有個(gè)capable屬性,表示是否支持該技術(shù),ie5.0以上版本支持VML,所以我的dojo.render.vml.capable為true,SVG需要裝插件,所以不支持該項(xiàng),dojo.render.svg.capable為false,dojo.render.swf.capable也為false,這里的swf不是指flash的swf,而是Simple Web Framework,Simple Web Framework (SWF)是一個(gè)基于事件的web框架.它很適合于那些想要開發(fā)胖客戶端Web應(yīng)用程序但又不想轉(zhuǎn)向JSF的Struts開發(fā)人員。SWF跟Struts一樣也是構(gòu)建在Jakarta commons基礎(chǔ)之上,但使用一個(gè)不同的request processor。SWF事件模型支持基于XmlHttpRequest的事件提交。至于dojo.render.swt,不清楚了,難道與java中的SWT有關(guān)系?這四個(gè)對(duì)象的其它屬性,在源碼中居然沒看到相應(yīng)代碼??以后弄明白再回來補(bǔ)過。
  2.dojo.version對(duì)象。在上面已經(jīng)講過這個(gè)對(duì)象,是dojo庫文件的版本,沒啥好研究的了。
 ?。常甦ojo.hostenv對(duì)象,個(gè)人認(rèn)為里面的東西很有看頭,不過要慢慢講來也太費(fèi)時(shí)間了,具體可以去看源碼中那幾個(gè)hostenv_XXX.js文件,dojo.hostenv.getText函數(shù)和dojo.hostenv.println函數(shù)還有點(diǎn)意思,以后隨時(shí)補(bǔ)充吧。
  下面講一講dojo中的一些基本函數(shù)。
  



飛雪(leo) 2007-10-18 00:32 發(fā)表評(píng)論
]]>
Dojo學(xué)習(xí)筆記http://m.tkk7.com/Jiangzy/archive/2007/10/18/153726.html飛雪(leo)飛雪(leo)Wed, 17 Oct 2007 16:31:00 GMThttp://m.tkk7.com/Jiangzy/archive/2007/10/18/153726.htmlhttp://m.tkk7.com/Jiangzy/comments/153726.htmlhttp://m.tkk7.com/Jiangzy/archive/2007/10/18/153726.html#Feedback0http://m.tkk7.com/Jiangzy/comments/commentRss/153726.htmlhttp://m.tkk7.com/Jiangzy/services/trackbacks/153726.htmlDojo學(xué)習(xí)筆記2007年06月05日 星期二 17:18(1. 模塊與包)


Intro:

Dojo是一個(gè)非常強(qiáng)大的面向?qū)ο蟮腏avaScript的工具箱, 建議讀者能夠去補(bǔ)充一下JavaScript下如何使用OO進(jìn)行編程的, 這對(duì)于你以后閱讀Dojo Source有很大的用處

請(qǐng)大家下載dojo 0.3.1, 以下的說明均針對(duì)此版本

翻譯自http://manual.dojotoolkit.org/WikiHome/DojoDotBook/BookUsingDojo


Getting Started

1: 把Dojo加入到我們的Web程序中

1. 標(biāo)志

<script type="text/javascript">
djConfig = { isDebug: false };
</script>
djConfig是Dojo里的一個(gè)全局對(duì)象, 其作用就是為Dojo提供各種選項(xiàng), isDebug是最常用的屬性之一, 設(shè)置為True以便能夠在頁面上直接看到調(diào)試輸出, 當(dāng)然其中還有些屬性與調(diào)試有關(guān), 這里就不羅索了

2. 引用 dojo 的啟動(dòng)代碼

<script type="text/javascript" src="/yourpath/dojo.js" />
這樣你就引用了dojo的代碼, 并可以直接使用其中部分常用的對(duì)象, 下載下來的dojo.js是壓縮(remove comments and space)后的代碼, 要閱讀的話,建議閱讀dojo.js.uncompressed.js, dojo.js大概有127K, 而未壓縮前有211K, ok, 為什么會(huì)這么大呢, 原來其已經(jīng)把部分常用的模塊整合進(jìn)dojo.js里, 因此顯得大了一點(diǎn), build.txt里就說明了默認(rèn)的dojo.js包含了哪些模塊

3. 聲明你所要用到的包

<script type="text/javascript">
dojo.require("dojo.math");
dojo.require("dojo.io.*");
dojo.require("dojo.widget.*");
</script>
你就把這些代碼當(dāng)成是java的import語句或C#中的using語句一樣, 如果你不require的話, 而模塊本身又沒有整合在dojo.js中, 是會(huì)出現(xiàn)腳本錯(cuò)誤的喔

2. 針對(duì)不同需求提供的預(yù)整合包

Dojo本身是由許多模塊所組合而成的, 但是由于用戶需求的多樣性, dojo針對(duì)不同的需求而提供了不同的版本, 用戶在下載dojo的時(shí)候就看見可以選擇很多的版本, 比如Ajax版和Widget版, 每個(gè)版本最重要的區(qū)別就在于dojo.js文件, 但是除此之外, 每一個(gè)版本都是全功能的, dojo.js根據(jù)版本的不同而整合進(jìn)了不同的模塊

3. 直接獲取Dojo的最新源代碼

首先你必須安裝 Subversion, 當(dāng)Subversion在你的電腦上能夠正常工作后,你就可以通過如下命令下載dojo的源代碼:

svn co http://svn.dojotoolkit.org/dojo/trunk/
這會(huì)在你的當(dāng)前目錄下創(chuàng)建一個(gè) trunk 的目錄; 如果你希望直接Get到當(dāng)前目錄, 用這個(gè)命令:

svn co http://svn.dojotoolkit.org/dojo/trunk/ .
或者你希望Get到當(dāng)前目錄下的 MyDir 目錄, 用這個(gè)命令:

svn co http://svn.dojotoolkit.org/dojo/trunk/ MyDir

模塊與包

模塊

Dojo的代碼被劃分為邏輯單元稱之為模塊, 這有點(diǎn)類似于Java中的package,除了dojo的模塊能夠包含類 (類似于java中的classes)和簡(jiǎn)單函數(shù)

比如: 模塊"dojo.html"包含了一系列的函數(shù), 比如dojo.html.getContentBox(), 模塊"dojo.dnd"包含了一系列的HtmlDragObject的類

注意名稱約定, 函數(shù)的首字母為小寫字母,類的首字母為大寫

模塊也可以稱之為"命名空間"

在多數(shù)情況下, dojo的模塊只需要定義在一個(gè)文件就可以了, 但有時(shí), 一個(gè)模塊可能劃分到多個(gè)文件, 比如: 模塊dojo.html, 本來是定義在一個(gè)文件中, 可是由于功能的增強(qiáng), 文件逐漸變大, 我們不得不將其拆分為多個(gè)文件, 這主要是為性能考慮, 以便瀏覽器可以只下載其需要用到的代碼, 不幸的是其實(shí)現(xiàn)細(xì)節(jié)對(duì)于dojo的用戶看起來不那么透明, 你必須知道你想要用到的功能到底是包含在哪個(gè)文件, 然后才能require并使用它

這樣的每一個(gè)文件都稱之為一個(gè)包

dojo.require("dojo.html.extras")
將引用文件 src/html/extras.js, 這將定義模塊 dojo.html 的若干(并非所有)函數(shù)

據(jù)我所知, 盡管單個(gè)文件可以定義包里的多個(gè)類, 單個(gè)腳本文件不能定義多個(gè)模塊 (在Java可以等效于在一個(gè)文件中定義2個(gè)類), 并且, 包的名稱和模塊的名稱可以不同, 比如: 包dojo.widget.Button定義了dojo.widget.html.Button

基本上你應(yīng)該這樣認(rèn)為, 包和模塊盡管密切相關(guān), 但是是兩個(gè)完全不同的實(shí)體

為什么會(huì)有模塊和包這樣的概念?

為什么會(huì)有模塊和包這樣的概念? 為了滿足你的應(yīng)用程序只需要加載其所用到的東西的需求, 充分利用模塊化設(shè)計(jì)的優(yōu)點(diǎn), dojo維護(hù)了最小的足印以便仍能提供你所需要的功能, 為什么要你的用戶浪費(fèi)時(shí)間去下載用不到的JavaScript, 當(dāng)一個(gè)包就是一個(gè)js文件時(shí), 一個(gè)模塊本質(zhì)上就是一個(gè)命名空間, 比如: dojo.style 或 dojo.html.extras
多數(shù)簡(jiǎn)單情況下, 一個(gè)包包含了一個(gè)模塊, 但更常見的是, 一個(gè)模塊可能被拆分為幾個(gè)包文件

利用包和模塊, 將能確保你能夠交付最相關(guān)的功能代碼, 最小程度的減少代碼的膨脹和消除由此帶來的不好的用戶體驗(yàn),這就是模塊設(shè)計(jì)的主要目標(biāo), 通過模塊化, 你能夠引入自定義模塊(你自己擁有的 JavaScript 工具), 并且維護(hù)模塊對(duì)于核心代碼庫基本不會(huì)產(chǎn)生什么影響

另外, Dojo的模塊系統(tǒng)也提供了內(nèi)建的機(jī)制來使用代碼提供命名空間, 比如, 通過模塊dojo.event定義的Dojo的事件系統(tǒng)

怎樣引用

設(shè)置引用語句

你怎樣才能知道該引用哪個(gè)包到dojo.require()?

1. 模塊

首先, 確定你要使用什么模塊, 這個(gè)例子我們假定你要使用 dojo.lfx.html

2. 包

搜索代碼后你發(fā)現(xiàn)dojo.lfx.html定義在2個(gè)文件:

src/lfx/html.js
src/lfx/extras.js
根據(jù)你要用到的功能, 你可以

dojo.require("dojo.lfx.html");

dojo.require("dojo.lfx.html");
dojo.require("dojo.lfx.extras");

通配符

新用戶可能會(huì)對(duì)dojo.lfx.*這樣就可以替代上面2句而感到詫異, 實(shí)際上, __package__.js 中已經(jīng)定義了通配符可以代替的語句, 并且這樣可以讓dojo根據(jù)當(dāng)時(shí)的環(huán)境而決定加載具體的模塊

Dojo學(xué)習(xí)筆記(2. djConfig解說)


djConfig是dojo內(nèi)置的一個(gè)全局設(shè)置對(duì)象,其作用是可以通過其控制dojo的行為

首先我們需要在引用dojo.js前聲明djConfig對(duì)象,以便在加載dojo.js的時(shí)候才能夠取得所設(shè)置的值,雖然在0.3版本以后dojo支持在加載后設(shè)置,但是強(qiáng)烈建議你把聲明djConfig的代碼作為第一段script

一個(gè)完整的djConfig對(duì)象定義如下(值均為dojo的默認(rèn)值)

<script type="text/javascript">
var djConfig = {
isDebug: false,
debugContainerId: "",
bindEncoding: "",
allowQueryConfig: false,
baseScriptUri: "",
parseWidgets: true
searchIds: [],
baseRelativePath: "",
libraryScriptUri: "",
iePreventClobber: false,
ieClobberMinimal: true,
preventBackButtonFix: true,
};
</script>
isDebug是一個(gè)很有用的屬性,顧名思義,如果設(shè)置為真,則所有dojo.Debug的輸出有效,開發(fā)時(shí)應(yīng)該設(shè)置為true,發(fā)布時(shí)應(yīng)該設(shè)置為false

debugContainerId同樣也是與調(diào)試有關(guān)的,如果不指定的話,調(diào)試信息將會(huì)直接利用 document.write輸出,這樣可能會(huì)破壞頁面的整體布局,所以你可以指定任何一個(gè)可以作為容器的html元素的id作為調(diào)試信息輸出容器

allowQueryConfig,這個(gè)屬性指明 dojo是否允許從頁面url的參數(shù)中讀取djConfig中的相關(guān)屬性,當(dāng)值為true時(shí),dojo會(huì)優(yōu)先從url參數(shù)中讀取djConfig的其他屬性,比如: http://server/dojoDemo.htm?djConfig.debugContainerId=divDebug

baseScriptUri,一般不需要設(shè)置,dojo會(huì)自動(dòng)根據(jù)你引用dojo.js的路徑設(shè)置這個(gè)值,比如,<script type="text/javascript" src="../dojo/dojo.js"></script>,自動(dòng)獲取的值便是 ../dojo/
ps: 如果你有多個(gè)工程需要同時(shí)引用dojo.js的話,建議也把dojo當(dāng)作一個(gè)獨(dú)立的工程,引用的時(shí)候采用絕對(duì)路徑就可以了

parseWidgets,這個(gè)是可以控制dojo是否自動(dòng)解析具有dojoType的html元素為對(duì)應(yīng)的widget,如果你沒有使用任何Widget,建議設(shè)置為false以加快dojo的加載速度

searchIds,這是一個(gè)字符串?dāng)?shù)組,定義了所有需要解析為widget的html元素的ID,如果ID不在其中的html元素是不會(huì)被解析的,當(dāng)數(shù)組為空數(shù)組時(shí),則所有具有dojoType的元素都會(huì)被解析

還有一個(gè)bindEncoding,是用來設(shè)置默認(rèn)的bind請(qǐng)求的編碼方式

至于其它的屬性,不是用處不大,就是不知道有什么作用

在實(shí)際開發(fā)中,可以把djConfig的定義放在一個(gè)js文件里,并將其作為第一個(gè)引用的js文件,這樣應(yīng)該是最方便的。

Dojo學(xué)習(xí)筆記(3. Dojo的基礎(chǔ)對(duì)象和方法)

這里所說的基礎(chǔ)對(duì)象和方法是指的不Require任何包就能夠調(diào)用的對(duì)象和方法

匿名函數(shù)

在開始前,我想介紹一下js里的匿名函數(shù),這個(gè)在閱讀dojo的源代碼的時(shí)候,會(huì)發(fā)現(xiàn)到處都有匿名函數(shù)

;(function(){
alert(123);
})();
//前面的分號(hào)是一個(gè)空語句,是可以不要的
匿名函數(shù)。一個(gè)匿名函數(shù)就是一個(gè)沒有名字的函數(shù)。

你可以認(rèn)為他們是一次性函數(shù)。當(dāng)你只需要用一次某個(gè)函數(shù)時(shí),他們就特別有用。通過使用匿名函數(shù),沒有必要把函數(shù)一直放在內(nèi)存中,所以使用匿名函數(shù)更加有效率。

當(dāng)然你也可以根本不定義函數(shù),但是使用匿名函數(shù)可以把你的代碼分段,就像C#中的#region一樣

dojo.byId

非常有用的一個(gè)方法,與prototype.js的著名的$一樣

似乎以前的版本還有dojo.byIdArray, 不過最新的版本已經(jīng)找不到這個(gè)函數(shù)了(除了src\compat\0.2.2.js)

如果有多個(gè)元素具有指定的id,則返回的是一個(gè)集合

Usage Example:

dojo.byId("divTest");
dojo.byId("divTest", document);
dojo.byId(document.getElementById("divTest"));


dojo.version

dojo的版本,可以取得major, minor, patch, flag和revision

這個(gè)對(duì)象沒什么太大用處,除非你要根據(jù)dojo的版本選擇執(zhí)行你的代碼

dojo.raise

拋出一個(gè)異常

dojo.errorToString

將異常轉(zhuǎn)換為字符串

Usage Example:

try
{
dojo.raise("打印失敗", new Error("文件不存在"));
}
catch(e)
{
alert(dojo.errorToString(e));
}


dojo.render

系統(tǒng)環(huán)境對(duì)象

dojo.render.name 返回 browser ,說明是工作在瀏覽器下
dojo.render.ver 返回 4 ,似乎沒什么用
dojo.os.win 返回true說明操作系統(tǒng)是Windows
dojo.os.linux 返回true說明操作系統(tǒng)是Linux
dojo.os.osx 返回true說明操作系統(tǒng)是MacOS
dojo.html.ie 返回true說明瀏覽器是Internet Explorer
dojo.html.opera 返回true說明瀏覽器是Opera
dojo.html.khtml 返回true說明瀏覽器是Konqueror
dojo.html.safari 返回true說明瀏覽器是Safari
dojo.html.moz 返回true說明瀏覽器是Mozilla FireFox
dojo.svg.capable 返回true說明瀏覽器支持svg
dojo.vml.capable 返回true說明瀏覽器支持vml
dojo.swf.capable 返回true說明瀏覽器支持swf
dojo.swt.capable 返回true說明瀏覽器支持swt (IBM開發(fā)的Standard Widget Toolkit)
如果dojo.html.ie為true的話

dojo.html.ie50 返回true說明瀏覽器是IE 5.0
dojo.html.ie55 返回true說明瀏覽器是IE 5.5
dojo.html.ie60 返回true說明瀏覽器是IE 6.0
dojo.html.ie70 返回true說明瀏覽器是IE 7.0


dojo.addOnLoad

可以加載指定函數(shù)到window.load時(shí)執(zhí)行,好處就是可以很方便的在window.load時(shí)執(zhí)行多個(gè)函數(shù)

Usage Example:

dojo.addOnLoad(init); //init是一個(gè)函數(shù)
dojo.addOnLoad(myObject, init); //init是myObject對(duì)象的一個(gè)方法


dojo.require

如果你想調(diào)用一個(gè)模塊的對(duì)象的時(shí)候,你應(yīng)該首先用dojo.require來請(qǐng)求這個(gè)模塊,dojo會(huì)根據(jù)你的請(qǐng)求自動(dòng)取得相應(yīng)的js文件,并加載到內(nèi)存中,這樣你才能調(diào)用或創(chuàng)建其中的對(duì)象

dojo會(huì)自動(dòng)維護(hù)已加載的模塊列表,所以是不會(huì)重復(fù)加載模塊的

Usage Example:

dojo.require("dojo.event");
dojo.requireIf=dojo.requireAfterIf

可以根據(jù)指定的條件來決定是否加載指定的模塊

Usage Example:

dojo.requireIf(dojo.html.ie, "dojo.html"); //如果dojo.html.ie為true,才會(huì)加載dojo.html模塊


dojo.provide

除非你要開發(fā)自己的模塊,不然是用不到這個(gè)方法的,你可以這句看成是向系統(tǒng)注冊(cè)這個(gè)模塊名稱

Usage Example:

dojo.provide("dojo.custom");
dojo.exists

判斷指定對(duì)象是否具有指定名稱的方法

Usage Example:

dojo.exists(dojo, "exists"); //will return true


dojo.hostenv.getText

返回指定url的內(nèi)容

PS: 由于瀏覽器的安全限制,因此只能用于取得同域名的url的內(nèi)容,否則會(huì)報(bào)告權(quán)限不夠

Usage Example:

aSync = false; //同步,確保返回內(nèi)容不為null
silent = true; //不拋出錯(cuò)誤
s = dojo.hostenv.getText("http://www.google.com/", aSync, silent); //返回Google的首頁的HTML
alert(s);
dojo.debug

輸出調(diào)試信息,如果在djConfig中指定了debugContainerId,則輸出到指定的console容器中,否則直接document.write

所有的調(diào)試信息均以 DEBUG: 開頭

Usage Example:

dojo.debug("這是調(diào)試信息");


dojo.hostenv.println

與dojo.debug類似,不同的是,輸出內(nèi)容沒有 DEBUG:

Usage Example:

dojo.hostenv.println("這是一般的輸出信息");


dojo.debugShallow

輸出指定對(duì)象的全部信息(Shallow說明并不會(huì)遍歷到下一級(jí)別的對(duì)象屬性)以供調(diào)試

Usage Example:

dojo.debugShallow(dojo.render.html);
Dojo學(xué)習(xí)筆記(4. dojo.string & dojo.lang)

模塊:dojo.string.common / dojo.stringdojo.string.common 和 dojo.string 是一樣的,只要require其中一個(gè)就可以使用以下方法dojo.string.trim去掉字符串的空白Usage Example:s = " abc ";dojo.string.trim(s); //will return "abc"dojo.string.trim(s, 0); //will return "abc"dojo.string.trim(s, 1); //will return "abc "dojo.string.trim(s, -1);//will return " abc"
dojo.string.trimStart去掉字符串開頭的空白Usage Example:s = " abc ";dojo.string.trimStart(s); //will return "abc "dojo.string.trimEnd去掉字符串結(jié)尾的空白Usage Example:s = " abc ";dojo.string.trimEnd(s); //will return " abc"dojo.string.repeat生成由同一字符(串)重復(fù)組成的字符串Usage Example:dojo.string.repeat("a", 4); //will return "aaaa"dojo.string.repeat("1234", 3, "-"); //will return "1234-1234-1234"dojo.string.pad使用字符補(bǔ)齊字符串Usage Example:dojo.string.pad("100", 6); //will return "000100"dojo.string.pad("100", 6, "0", 1); //will return "000100"dojo.string.pad("100", 6, "0", -1); //will return "100000"dojo.string.padLeft使用字符補(bǔ)齊字符串開頭Usage Example:dojo.string.padLeft("100", 6); //will return "000100"dojo.string.padRight使用字符補(bǔ)齊字符串結(jié)尾Usage Example:dojo.string.padRight("100", 6); //will return "100000"
模塊:dojo.lang.common / dojo.langdojo.lang.common 和 dojo.lang 是一樣的,只要require其中一個(gè)就可以使用以下方法
dojo.lang.mixin將一個(gè)對(duì)象的方法和屬性增加到另一個(gè)對(duì)象上Usage Example:var s1 = {name: "TestObj", test1: function(){alert("this is test1!");}}var s2 = {value: 1000, test2: function(){alert("this is test2!");}}var d = {};dojo.lang.mixin(d, s1, s2); //執(zhí)行后d就具備了s1和s2的所有屬性和方法d.test1();dojo.lang.extend為指定類的原型擴(kuò)展方法與屬性Usage Example:TestClass = function() {};dojo.lang.extend(TestClass, {name: "demo", test: function(){alert("Test!");}});var o = new TestClass(); //TestClass本來是沒有test方法的,但是extend以后就有test方法了o.test();dojo.lang.find=dojo.lang.indexOf查找指定對(duì)象在指定數(shù)組中的位置Usage Example:var arr = [1,2,3,3,2,1];dojo.lang.find(arr, 2); //will return 1dojo.lang.find(arr, 2, true); //will return 1dojo.lang.find(arr, "2", true); //will return -1dojo.lang.find(arr, "2", false); //will return 1dojo.lang.find(arr, 2, true, true); //will return 4dojo.lang.findLast=dojo.lang.lastIndexOf查找指定對(duì)象在指定數(shù)組中的位置,從后往前查Usage Example:var arr = [1,2,3,3,2,1];dojo.lang.findLast(arr, 2); //will return 4dojo.lang.findLast(arr, 2, true); //will return 4dojo.lang.findLast(arr, "2", true); //will return -1dojo.lang.findLast(arr, "2", false); //will return 4dojo.lang.inArray查找指定對(duì)象是否在指定數(shù)組中Usage Example:var arr = [1,2,3];dojo.lang.inArray(arr, 1); //will return truedojo.lang.inArray(arr, 4); //will return falsedojo.lang.isObject判斷輸入的類型是否為對(duì)象Usage Example:dojo.lang.isObject(new String()); //will return truedojo.lang.isObject("123")); //will return falsedojo.lang.isArray判斷輸入的類型是否為數(shù)組Usage Example:dojo.lang.isArray({a:1,b:2}); //will return falsedojo.lang.isArray([1,2,3]); //will return truedojo.lang.isFunction判斷輸入的類型是否為函數(shù)Usage Example:dojo.lang.isFunction(function() {}); //will return truedojo.lang.isString判斷輸入的類型是否為字符串Usage Example:dojo.lang.isString(""); //will return truedojo.lang.isString(0); //will return falsedojo.lang.isAlien判斷輸入的類型是否為系統(tǒng)函數(shù)Usage Example:dojo.lang.isAlien(isNaN); //will return truedojo.lang.isBoolean判斷輸入的類型是否為布爾類型Usage Example:dojo.lang.isBoolean(2>1); //will return truedojo.lang.isNumber判斷輸入的類型是否為數(shù)值,根據(jù)注釋所說,此函數(shù)使用不太可靠,但是可替換使用的系統(tǒng)函數(shù)isNaN也不太可靠dojo.lang.isUndefined判斷輸入是否為未定義,根據(jù)注釋所說,此函數(shù)有可能會(huì)導(dǎo)致拋出異常,推薦使用 typeof foo == "undefined" 來判斷
模塊:dojo.lang.extrasdojo.lang.setTimeout延遲指定時(shí)間后執(zhí)行指定方法Usage Example:function onTime(msg){dojo.debug(msg)}dojo.lang.setTimeout(onTime, 1000, "test"); //1秒后會(huì)輸出調(diào)試信息"test"dojo.lang.setTimeout(dojo, "debug", 1000, "test"); //1秒后會(huì)輸出調(diào)試信息"test"dojo.lang.getNameInObj獲得指定項(xiàng)目在指定對(duì)象中的名稱Usage Example:dojo.lang.getNameInObj(dojo, dojo.debug); //will return "debug"dojo.lang.shallowCopy返回指定對(duì)象的淺表復(fù)制副本Usage Example:dojo.lang.shallowCopy({}); //will return a 空對(duì)象dojo.lang.firstValued返回第一個(gè)存在定義的參數(shù)Usage Example:var a;dojo.lang.firstValued(a,2,3); //will return 2以上全部是自己閱讀源代碼寫的總結(jié),如有錯(cuò)誤,還請(qǐng)指明。



飛雪(leo) 2007-10-18 00:31 發(fā)表評(píng)論
]]>
DOJO試用手記2--Event System http://m.tkk7.com/Jiangzy/archive/2007/10/18/153723.html飛雪(leo)飛雪(leo)Wed, 17 Oct 2007 16:28:00 GMThttp://m.tkk7.com/Jiangzy/archive/2007/10/18/153723.htmlhttp://m.tkk7.com/Jiangzy/comments/153723.htmlhttp://m.tkk7.com/Jiangzy/archive/2007/10/18/153723.html#Feedback0http://m.tkk7.com/Jiangzy/comments/commentRss/153723.htmlhttp://m.tkk7.com/Jiangzy/services/trackbacks/153723.html閱讀全文

飛雪(leo) 2007-10-18 00:28 發(fā)表評(píng)論
]]>
主站蜘蛛池模板: 一级做a爰片性色毛片免费网站| 亚洲邪恶天堂影院在线观看| 四虎永久免费影院| 免费看的黄色大片| 在线观看成人免费| 国产高清在线精品免费软件| 日韩一区二区三区免费体验| 国产高清在线精品免费软件| 免费一级毛片一级毛片aa| 免费少妇a级毛片人成网| 亚洲国产精品自产在线播放| 亚洲精品国产高清不卡在线| 亚洲综合色在线观看亚洲| 久久青青草原亚洲av无码| 国产成人精品日本亚洲专区61| 亚洲色成人WWW永久网站| 亚洲AV无码一区二区二三区软件| 亚洲AV乱码一区二区三区林ゆな| 久久精品国产亚洲AV无码麻豆| 337p欧洲亚洲大胆艺术| 国产色在线|亚洲| 亚洲AV日韩AV一区二区三曲| 特级毛片在线大全免费播放| 久久久久久久久久久免费精品| 男人进去女人爽免费视频国产| 亚洲国产精品免费在线观看| 免费看国产成年无码AV片| 热久久精品免费视频| 亚洲日本一区二区一本一道| 亚洲AV午夜成人片| 麻豆狠色伊人亚洲综合网站| 久久亚洲色WWW成人欧美| 成人A毛片免费观看网站| 黄网站免费在线观看| 久久受www免费人成_看片中文| 日韩一级免费视频| 情人伊人久久综合亚洲| 亚洲xxxxxx| 一级毛片完整版免费播放一区| 人人揉揉香蕉大免费不卡| 麻豆精品国产免费观看|