admin 管理员组文章数量: 887021
DOJO API 中文参考手册
Dojo 体系架构总体上来看是一个分层的体系架构。最下面的一层是包系统,Dojo API 的结构与 Java 很类似,它把所有的 API 分成不
同的包(package),当您要使用某个 API 时,只需导入这个 API 所在的包。包系统上面一层是语言库,这个语言库里包含一些语言工具 API,类似于 Java
的 util 包。再上一层是环境相关包,这个包的功能是处理跨浏览器的问题。Dojo 体系架构图
Dojo 大部分代码都位于应用程序支持库,由于太小限制,图中没有列出所有的包。开发人员大部分时候都在调用这个层中的 API,比如,用 IO 包可以进行Ajax 调用。
最上面的一层是 Dojo 的 Widget 系统,Widget 指的是用户界面中的一个元素,比如按钮、进度条和树等。 Dojo 的 Widget 基于 MVC 结构。它的视图作为一个 Template(模板)来进行存放,在 Template 中放置着 HTML 和 CSS 片段,而控制器来对该 Template 中的元素进行操作。 Widget 不仅支持自定义的样式表,并且能够对内部元素的事件进行处理。用户在页面中只需要加入简单的标签就可以使用。在这一层中,存在数百个功能强大的 Widget 方便用户使用,包括表格、树、菜单等。
常用包介绍
Dojo 1.1.1 提供了上百个包,这些包分别放入三个一级命名空间:Dojo,Dijit和 DojoX 。其中 Dojo 是核心功能包 , Dijit 中存放的是 Dojo 所有的Widget 组件,而 DojoX 则是一些扩展或试验功能,DojoX 中的试验功能在成熟之后有可能在后续版本中移入到 Dojo 或 Dijit 命名空间中。
由于 Dojo 包种类繁多,下面只列举了最常用的一些包及其功能,以方便读者有个初步了解或供以后查阅。
包名 | 功能 |
dojo.io | 不同的 IO 传输方式。 script、IFrame 等等; |
dojo.dnd | 拖放功能的辅助 API 。 |
dojo.string | 这个包可以对字符串进行如下的处理:修整、转换为大写、 |
| 编码、esacpe、填充(pad)等等; |
dojo.date | 解析日期格式的有效助手; |
dojo.event | 事件驱动的 API,支持 AOP 开发,以及主题 / 队列的功能; |
dojo.back | 用来撤销用户操作的栈管理器; |
dojo.rpc | 与后端服务(例如理解 JSON 语法的 Web 服务)进行通信; |
dojo.colors | 颜色工具包; |
dojo.data | Dojo 的统一数据访问接口,可以方便地读取 XML、JSON 等不同格式的数据文件; |
dojo.fx | 基本动画效果库; |
dojo.regexp | 正则表达式处理函数库; |
dijit.forms | 表单控件相关的 Widget 库; |
dijit.layout | 页面布局 Widget 库; |
dijit.popup | 这个包用于以弹出窗口方式使用 Widget ; |
dojox.charting | 用于在页面上画各种统计图表的工具包; |
dojox.collections | 很有用的集合数据结构(List、Query、Set、Stack、Dictionary...); |
dojox.encoding | 实现加密功能的 API(Blowfish、MD5、Rijndael、SHA...); |
dojox.math | 数学函数(曲线、点、矩阵); |
dojo.reflect | 提供反射功能的函数库; |
dojox.storage | 将数据保存在本地存储中(例如,在浏览器中利用 Flash的本地存储来实现); |
dojox.xml | XML 解析工具包; |
djConfig
是 dojo 内置的一个全局设置对象,其作用是可以通过其控制 dojo 的行为
首先我们需要在引用 dojo.js 前声明 djConfig 对象,以便在加载 dojo.js 的时候才能够取得所设置的值,虽然在 0.3 版本以后 dojo
支持在加载后设置,但是强烈建议你把声明 djConfig 的代码作为第一段 script
一个完整的 djConfig 对象定义如下(值均为 dojo 的默认值)
<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 是一个很有用的属性,顾名思义,如果设置为真,则所有 dojo.Debug 的输出有效,开发时应该设置为 true,发布时应
该设置为 false
debugContainerId 同样也是与调试有关的,如果不指定的话,调试信息将会直接利用 document.write 输出,这样可能会破坏页
面的整体布局,所以你可以指定任何一个可以作为容器的 html 元素的 id 作为调试信息输出容器
allowQueryConfig,这个属性指明 dojo 是否允许从页面 url 的参数中读取 djConfig 中的相关属性,当值为 true 时,dojo 会优先
从 url 参数中读取 djConfig 的其他属性,比如: http://server/dojoDemo.htm?djConfig.debugContainerId=divDebug
baseScriptUri,一般不需要设置,dojo 会自动根据你引用 dojo.js 的路径设置这个值,比如,<script type="text/javascript"
src="../dojo/dojo.js"></script>,自动获取的值便是 ../dojo/
ps: 如果你有多个工程需要同时引用 dojo.js 的话,建议也把 dojo 当作一个独立的工程,引用的时候采用绝对路径就可以了
parseWidgets,这个是可以控制 dojo 是否自动解析具有 dojoType 的 html 元素为对应的 widget,如果你没有使用任何 Widget,
建议设置为 false 以加快 dojo 的加载速度
searchIds,这是一个字符串数组,定义了所有需要解析为 widget 的 html 元素的 ID,如果 ID 不在其中的 html 元素是不会被解
析的,当数组为空数组时,则所有具有 dojoType 的元素都会被解析
还有一个 bindEncoding,是用来设置默认的 bind 请求的编码方式
至于其它的属性,不是用处不大,就是不知道有什么作用
在实际开发中,可以把 djConfig 的定义放在一个 js 文件里,并将其作为第一个引用的 js 文件,这样应该是最方便的。
preventBackButtonFix 在 djConfig 中设置 preventBackButtonFix: false。这样保证了隐藏的表单
(hidden IFRAME)将会添加到页面当中,如果不加入这段,dojo.undo.browser 不会正常工
作。
译者注:设置方法就是在 header 中加入如下代码:
<script language="JavaScript" type="text/javascript">
djConfig = { isDebug: true, preventBackButtonFix: false };
</script>
djConfig
是 dojo 内置的一个全局设置对象,其作用是可以通过其控制 dojo 的行为
首先我们需要在引用 dojo.js 前声明 djConfig 对象,以便在加载 dojo.js 的时候才能够取得所设置的值,
虽然在 0.3 版本以后 dojo 支持在加载后设置,但是强烈建议你把声明 djConfig 的代码作为第一段 s cript
一个完整的 djConfig 对象定义如下(值均为 dojo 的默认值)
<s cript type="text/javas cript">
var djConfig = {
isDebug: false,
debugContainerId: "",
allowQueryConfig: false,
bases criptUri: "",
parseWidgets: true
searchIds: [],
baseRelativePath: "",
librarys criptUri: "",
iePreventClobber: false,
ieClobberMinimal: true,
preventBackButtonFix: true,
};
</s cript>
isDebug 是一个很有用的属性,顾名思义,如果设置为真,则所有 dojo.Debug 的输出有效,开发时应该
设置为 true,发布时应该设置为 false
debugContainerId 同样也是与调试有关的,如果不指定的话,调试信息将会直接利用 document.write 输出,
这样可能会破坏页面的整体布局,所以你可以指定任何一个可以作为容器的 html 元素的 id 作为调试信息
输出容器
allowQueryConfig,这个属性指明 dojo 是否允许从页面 url 的参数中读取 djConfig 中的相关属性,当值为
true 时,dojo 会优先从 url 参数中读取 djConfig 的其他属性,比
如: http://server/dojoDemo.htm?djConfig.debugContainerId=divDebug
bases criptUri,一般不需要设置,dojo 会自动根据你引用 dojo.js 的路径设置这个值,比如,<s
cript type="text/javas cript" src="../dojo/dojo.js"></s cript>,自动获取的值便是 ../dojo/
ps: 如果你有多个工程需要同时引用 dojo.js 的话,建议也把 dojo 当作一个独立的工程,引用的时候采用
绝对路径就可以了 parseWidgets,这个是可以控制 dojo 是否自动解析具有 dojoType 的 html 元素为对
应的 widget,如果你没有使用任何 Widget,建议设置为 false 以加快 dojo 的加载速度
searchIds,这是一个字符串数组,定义了所有需要解析为 widget 的 html 元素的 ID,如果 ID 不在其中的
html 元素是不会被解析的,当数组为空数组时,则所有具有 dojoType 的元素都会被解析
至于其它的属性,不是用处不大,就是不知道有什么作用
在实际开发中,可以把 djConfig 的定义放在一个 js 文件里,并将其作为第一个引用的 js 文件,这样应该
是最方便的。
实现功能:在一个容器里点击一个链接,在另外一个容器中显示这个链接所指向页面的内容。
<html>
<head>
<script src="./dojo/dojo.js">
</script>
<script>
dojo.require("dojo.widget.ContentPane");
var links = null, display = null;
dojo.addOnLoad(init);
function init(){
links = dojo.widget.byId("links");
display = dojo.widget.byId("display");
// listen to links domNode for onclick event
// lowercased on all DOM events as opposed to widget events
//"onclick",必须是小写的
dojo.event.connect(links.domNode, "onclick", 'relayClicks');
}
// finds out if this is a link event
function relayClicks(evt){
var node = evt.target;//取得事件源
if(node.nodeName.toLowerCase() == "a"){
// it is a link, prevent the browser from unloading the page
evt.preventDefault();
// change page in display pane
display.setUrl(node.href);
}
}
</script>
</head>
<body>
<h1>Example on how to easily relay <a href="someurl.html" target="display"> clicks</h1>
<div dojoType="ContentPane"
widgetId="links"
style="float:left ; width: 200px; height: 400px; border: 1px solid red;"
>
<a href="link1.html">Link 1</a><br/>
<a href="link2.html">Link 2</a><br/>
<a href="link3.html">Link 3</a><br/>
</div>
<div dojoType="ContentPane"
widgetId="display" name="display" id ="display"
style="width: 600px; height: 400px; border: 1px solid blue;"
></div>
</body>
</html>
dojo.addOnLoad
可以加载指定函数到 window.load 时执行,好处就是可以很方便的在 window.load 时执行多个函数
Usage Example:
dojo.addOnLoad(init); //init 是一个函数
dojo.addOnLoad(myObject, init); //init 是 myObject 对象的一个方法
dojo.require
如果你想调用一个模块的对象的时候,你应该首先用 dojo.require 来请求这个模块,dojo 会根据你的请求自动取得相应的 js 文
件,并加载到内存中,这样你才能调用或创建其中的对象
dojo 会自动维护已加载的模块列表,所以是不会重复加载模块的
Usage Example:
dojo.require("dojo.event");
dojo.requireIf=dojo.requireAfterIf
可以根据指定的条件来决定是否加载指定的模块
Usage Example:
dojo.requireIf(dojo.html.ie, "dojo.html"); //如果 dojo.html.ie 为 true,才会加载 dojo.html 模块
dojo.provide
除非你要开发自己的模块,不然是用不到这个方法的,你可以这句看成是向系统注册这个模块名称
Usage Example:
dojo.provide("dojo.custom");
dojo.exists
判断指定对象是否具有指定名称的方法
Usage Example:
dojo.exists(dojo, "exists"); //will return true
模块:dojo.io.IO
dojo.io.bind
处理请求取回需要的数据并处理
这个函数是 AJAX 中最为重要和有用的函数,dojo.io.bind 这个类是用来处理客户端与服务器
间通讯的,需要通讯的参数由对象 dojo.io.Request 所定义,具体通讯的方法则由另外一个对
象 Transport 所提供。 因此,我们如果需要与服务器通讯,则应该定义一个 Request 对象,
其中包括服务器地址及回调函数,例子中 Requset 都是以匿名对象方式定义的
虽然我们可以定义一个自己的 Transport,但是显然不如直接利用现成的 Transport 方便。
Dojo 里提供了一个同时兼容 IE 和 Firefox 的 dojo.io.XMLHTTPTransport,但是这个对象位于
dojo.io.BrowserIO,因此,一般 require dojo.io.IO 时,还应该 require dojo.io.BrowserIO
Usage Example
dojo.io.bind({
url: "http://localhost/test.html", //要请求的页面地址
mimetype: "text/html", // 请 求 的 页 面 的 类 型 , 应 该 设 置 为 与 你 请 求 页 面 类 型 对 应 的
mimetype,默认为 "text/plain"
method:"GET", //默认为"GET"
sync: false, //默认为异步执行
useCache: false, //默认为不使用页面缓存,注意这里的缓存并不是浏览器的缓存,而是 Dojo
自身所维护的页面缓存
preventCache: false, //默认为启用浏览器缓存,否则将通过自动增加不同的参数来确保浏
览器缓存失效
timeoutSeconds: 3000, //3 秒后超时,如果为 0 则永不超时
load: function(type, data, evt) { alert(data); }, //type should be "load", data is that we wanted
error: function(type, error) { alert(error.message); }, //error is dojo.io.Error
timeout: function(type) { alert("请求超时!"); }
});
你也可以用一个 handle 来处理所有的事件
dojo.io.bind({
url: "http://localhost/test.html", //要请求的页面地址
mimetype: "text/html", // 请 求 的 页 面 的 类 型 , 应 该 设 置 为 与 你 请 求 页 面 类 型 对 应 的
mimetype
timeoutSeconds: 3000, //3 秒后超时,如果为 0 则永不超时
handle: function(type, data, evt){
if(type == "load") { alert(data); } //data is that we wanted
else if (type == "error") { alert(data.message); } //data is the error object
else { ; } //other events maybe need handled
}
});
如果没有在 Request 中指定所用的 transport,则 Dojo 会自动的在已注册的 transports 中寻
找能够处理这个 Request 的 transport,如果不能找到,则返回指定的 Request。下面是一个
指定了 transport 的例子:
dojo.io.bind({
url: "http://localhost/test.html", //要请求的页面地址
mimetype: "text/html", // 请 求 的 页 面 的 类 型 , 应 该 设 置 为 与 你 请 求 页 面 类 型 对 应 的
mimetype
timeoutSeconds: 3000, //3 秒后超时,如果为 0 则永不超时
transport: "XMLHTTPTransport",
load: function(type, data, evt) { alert(data); }, //type should be "load", data is that we wanted
error: function(type, error) { alert(error.message); }, //error is dojo.io.Error
timeout: function(type) { alert("请求超时!"); }
});
你还可以利用 bind 来得到一个 Javas cript 所定义的对象(注意 mimetype 必须要定义为
"text/javas cript")
testObj = dojo.io.bind({
url: "http://localhost/test.js", //test.js 里定义了一个对象
mimetype: "text/javas cript", //请求的页面的类型,应该设置为与你请求页面类型对应的
mimetype
timeoutSeconds: 3000, //3 秒后超时,如果为 0 则永不超时 handle: function(type, data, evt){
if(type == "load") { alert(data); } //data is a object or value
else if (type == "error") { alert(data.message); } //data is the error object
else { ; } //other events maybe need handled
}
});
下面是一个 Post 的例子:
dojo.io.bind({
url: "http://localhost/test.aspx", //要提交的页面地址
mimetype: "text/html", //请求的页面的类型,应该设置为与你请求页面类型对应的
mimetype
timeoutSeconds: 3000, //3 秒后超时,如果为 0 则永不超时
method: "POST",
formNode: dojo.byId("myForm"), //指定提交的 Form 名称
load: function(type, data, evt) { alert(data); }, //type should be "load", data
is that we wanted
error: function(type, error) { alert(error.message); }, //error is dojo.io.
Error
timeout: function(type) { alert("请求超时!"); }
});
另一个 Post 的例子(without Form to post):
dojo.io.bind({
url: "http://localhost/test.aspx", //要提交的页面地址
mimetype: "text/html", // 请 求 的 页 面 的 类 型 , 应 该 设 置 为 与 你 请 求 页 面 类 型 对 应 的
mimetype
timeoutSeconds: 3000, //3 秒后超时,如果为 0 则永不超时
method: "POST",
content: {a: 1, b: 2}, //要提交的数据
load: function(type, data, evt) { alert(data); }, //type should be "load", data is that we wanted
error: function(type, error) { alert(error.message); }, //error is dojo.io.Error
timeout: function(type) { alert("请求超时!"); }
});
dojo.io.queueBind
有时,我们需要一次发出多个网页请求,则应该使用 dojo.io.queueBind,因为浏览器可能
只允许同时发出有限个数的请求,如果是使用 dojo.io.bind 的话,则有可能会申请不到新的
XMLHttp 对象而导致出错。
用法与 dojo.io.bind 是一样的。
dojo.io.argsFromMap
用来把对象转换为 URL 的参数形式
Usage Example:
dojo.io.argsFromMap({a:1,b:2,c:3}); //will return "c=3&b=2&a=1"
dojo.io.argsFromMap({name:"名称",value:"值
"},"utf"); //will return "value=å\u8364X¼&name=å��称&", 有中文的话应该指定 utf 格式,否则
dojo.string.encodeAscii 返回的编码是很怪异的
dojo.io.argsFromMap({a:1,b:2,c:3}, "utf", "c"); //will return "b=2&a=1&c=3",最后一个参
数可以控制指定名称的值出现在最后
dojo.io.setIFrameSrc
设置 IFrame 的 Src
Usage Example:
dojo.io.setIFrameSrc(dojo.byId("myFrame"), "http://localhost/test.htm"); //myFrame 打
开指定的网页
dojo.io.setIFrameSrc(dojo.byId("myFrame"), "http://localhost/test.htm", true); //myFra
me 打开指定的网页,并覆盖浏览器的历史记录
模块:dojo.io.BrowserIO
基本上就提供了 dojo.io.XMLHTTPTransport 这个对象
XMLHTTPTransport 一般能够满足我们的需求,但是其有几个限制:它不能传输文件,不能够成功执行
跨域名的远程请求,并且不支持 file:// 这样的协议
因此,根据应用要求,我们可能会需要选用其它的
transport: dojo.io.IframeTransport, dojo.io.repubsubTranport, dojo.io.s
criptSrcTransport, ShortBusTransport
dojo.io.IframeTransport,用法与 xmlhttp 是一样的,其优点就是可以跨域,不存在任何的安全问题
如果 Request 指定的 mimetype 是 text 或 javas cript,返回的内容应该是放在第一个 textarea 里的
内容,如果指定的 mimetype 是 html,则 IFrame 里的 html 则是需要的内容。因为浏览器兼容的原因,
IframeTransport 不能正确处理返回类型为 XML 的请求。
关于 Rpc,这个类似于 Remoting 的东西,也将在以后对其进行介绍。
模块:dojo.string.extras
模块:dojo.stringmon
模块:dojo.string
dojo.stringmon 和 dojo.string 是一样的,只要 require 其中一个就可以使用以下方法
dojo.string.capitalize
把每一个单词的首字母大写
Usage Example:
dojo.string.capitalize("show me love"); //will return "Show Me Love"
dojo.string.isBlank
判断输入字符串是否为空或全是空白字符,如果传入对象为非字符串则也会返回 true
Usage Example:
dojo.string.isBlank(" 1 "); //will return false
dojo.string.escape
参数 1 为 type,可传值为: xml/html/xhtml, sql, regexp/regex, javas cript/js cript/js, ascii
将按照所传 type 对字符串进行编码
Usage Example:
dojo.string.escape("html", "<input type='text' value='' />"); //will return "<input
type='text' value='' />"
dojo.string.encodeAscii
dojo.string.escapeXml
dojo.string.escapeSql
dojo.string.escapeRegExp
dojo.string.escapeJavas cript
dojo.string.escapeString
这些函数也就是 dojo.string.escape 所调用的,这里无需多说
dojo.string.summary
取得输入字符串的缩略版本
Usage Example:
dojo.string.summary("1234567890", 5); //will return "12345..."
dojo.string.endsWith
判断输入字符串是否以指定的字符串结尾
Usage Example:
dojo.string.endsWith("abcde", "E"); //will return false
dojo.string.endsWith("abcde", "E", true); //will return true
dojo.string.endsWithAny
判断输入字符串是否以指定的任意字符串结尾
Usage Example:
dojo.string.endsWithAny("abcde", "E", "e"); //will return true
dojo.string.startsWith
判断输入字符串是否以指定的字符串开头
Usage Example:
dojo.string.startsWith("abcde", "A"); //will return false
dojo.string.startsWith("abcde", "A", true); //will return true
dojo.string.startsWithAny
判断输入字符串是否以指定的任意字符串开头
Usage Example:
dojo.string.startsWithAny("abcde", "A", "a"); //will return true
dojo.string.has
判断输入字符串是否含有任意指定的字符串
Usage Example:
dojo.string.has("abcde", "1", "23", "abc"); //will return true
dojo.string.normalizeNewlines
按要求转换回车换行的格式
Usage Example:
dojo.string.normalizeNewlines("a\r\nb\r\n", "\r"); //will return "a\rb\r"
dojo.string.splitEscaped
将字符串按分隔符转换为数组
Usage Example:
dojo.string.splitEscaped("a\\_b_c", '_'); //will return ["a\\_b", "c"]
dojo.string.trim
去掉字符串的空白
dojo.require("dojo.string");
defined in dojo/string.js
This version of trim() was taken from Steven Levithan’s blog. The short
yet performant version of this function is dojo.trim(), which is part of
Dojo base.
Usage
var foo=dojo.string.trim(str: String); (view source)
str
parameter
type
String
description
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
去掉字符串结尾的空白
Usage Example:
s = " abc ";dojo.string.trimEnd(s); //will return " abc"
dojo.string.repeat
生成由同一字符(串)重复组成的字符串
Usage Example:
dojo.string.repeat("a", 4); //will return "aaaa"
dojo.string.repeat("1234", 3, "-"); //will return "1234-1234-1234"
dojo.string.pad
使用字符补齐字符串
dojo.require("dojo.string");
defined in dojo/string.js
Pad a string to guarantee 保证 that it is at least 最小的 size length by filling 装填 with the
character ch at either the start or end of the string. Pads at the start, by default.
Usage
var foo=dojo.string.pad(text: String, size: Integer, ch: String?, end: Boolean?);
parameter type description
text
size
ch
end
String the string to pad
Integer length to provide padding
String Optional. character to pad, defaults to ‘0’
Boolean Optional. adds padding at the end if true, otherwise pads at start
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
使用字符补齐字符串开头
Usage Example:
dojo.string.padLeft("100", 6); //will return "100000"
dojo.string.padRight
使用字符补齐字符串结尾
Usage Example:
dojo.string.padRight("100", 6); //will return "100000"
dojo.string.substituteParams
dojo.string.substitute
类似 C#中的 String.Format 函数
%{name}要保证与传入的对象的名称大小写一致,否则会出异常
dojo.require("dojo.string");
defined in dojo/string.js
For example,
dojo.string.substitute("File '${0}' is not found in directory
'${1}'.",["foo.html","/temp"]);
dojo.string.substitute("File '${name}' is not found in directory
'${info.dir}'.",
{name: "foo.html", info: {dir: "/temp"}});
both return
"File 'foo.html' is not found in directory '/temp'."
Usage
var foo=dojo.string.substitute(template: String, map: Object|Array, transform: Function?,
thisObject: Object?);
parameter
type
description
template String
a string with expressions in the form ${key} to be replaced or
${key:format} which specifies a format function.
map
Object|Array hash to search for substitutions
transform Function
thisObject Object
Usage Example:
Optional. a function to process all parameters before substitution
takes place, e.g. dojo.string.encodeXML
Optional. where to look for optional format function; default to the
global namespace
dojo.string.substituteParams("%{0} - %{1} - %{2}", "a", "b", "c"); //will return "a - b - c"
dojo.string.substituteParams("%{name}: %{value}", {name:"名称",value:"值"}); //will return "名称: 值"
模块:dojo.langmon / dojo.lang
dojo.langmon 和 dojo.lang 是一样的,只要 require 其中一个就可以使用以下方法
dojo.lang.inherits
dojo.inherits
dojo.inherits = dojo.lang.inherits;
function(/*Function*/subclass, /*Function*/superclass){
// summary: Set up inheritance 继承 between two classes.
dojo.lang.mixin
dojo.mixin
dojo.mixin = dojo.lang.mixin;
将一个对象的方法和属性增加到另一个对象上
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); //执行后 d 就具备了 s1 和 s2 的所有属性和方法 d.test1();
dojo.lang.extend
dojo.extend
dojo.extend = dojo.lang.extend;
为指定类的原型扩展方法与属性
function(/*Object*/ constructor, /*Object...*/ props){
// summary:
//Adds all properties and methods of props to constructor's
//prototype, making them available to all instances created with
//constructor.
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
dojo.lang.indexOf = dojo.lang.find;
dojo.lang.find = function(/*Array*/ array, /*Object*/ value, /*Bollean*/ indentity, /*Boolean*/ findLast)
// summary:
//
Return the index of value in array, returning -1 if not found.
// array: just what you think
// value: the value to locate
// identity:
//
//
If true, matches with identity comparison (===). If false, uses
normal comparison (==).
// findLast:
//
//
//
If true, returns index of last instance of value.
// examples:
find(array,value[, identity [findLast]]) // recommended
find(value, array[, identity [findLast]]) // deprecated
// support both (array, value) and (value, array)
查找指定对象在指定数组中的位置
返回值在数组中的索引值,-1 为未发现。
Indentity 为 true 匹配模式为(===),反正为(==)
findLast 为 true 返回最后一个匹配值的索引。
Usage Example:
var arr = [1,2,3,3,2,1];dojo.lang.find(arr, 2);//will return 1
dojo.lang.find(arr, 2, true);//will return 1
dojo.lang.find(arr, "2", true);//will return -1
dojo.lang.find(arr, "2", false);//will return 1
dojo.lang.find(arr, 2, true, true); //will return 4
dojo.lang.findLast
dojo.lang.lastIndexOf
dojo.lang.lastIndexOf = dojo.lang.findLast;
function(/*Array*/array, /*Object*/value, /*boolean?*/identity){
// summary:
//
//
//
//
//
Return index of last occurance of value in array, returning -1 if
not found. This is a shortcut for dojo.lang.find() with a true
value for its "findLast" parameter.
// identity:
If true, matches with identity comparison (===). If false, uses
normal comparison (==).
查找指定对象在指定数组中的位置,从后往前查
Usage Example:
var arr = [1,2,3,3,2,1];dojo.lang.findLast(arr, 2);//will return 4
dojo.lang.findLast(arr, 2, true);//will return 4
dojo.lang.findLast(arr, "2", true);//will return -1
dojo.lang.findLast(arr, "2", false);//will return 4
dojo.lang.inArray
function(array /*Array*/, value /*Object*/){
// summary: Return true if value is present in array.
查找指定对象是否在指定数组中
Usage Example:
var arr = [1,2,3];
dojo.lang.inArray(arr, 1);//will return true
dojo.lang.inArray(arr, 4);//will return false
dojo.lang.isObject
function(/*anything*/ it){
// summary: Return true if it is an Object, Array or Function.
判断输入的类型是否为对象
Usage Example:
dojo.lang.isObject(new String()); //will return true
dojo.lang.isObject("123")); //will return false
dojo.lang.isArray
function(/*anything*/ it){
// summary: Return true if it is an Array.
判断输入的类型是否为数组
Usage Example:
dojo.lang.isArray({a:1,b:2}); //will return false
dojo.lang.isArray([1,2,3]); //will return true
dojo.lang.isArrayLike
function(/*anything*/ it){
// summary:
//Return true if it can be used as an array (i.e. is an object with
//an integer length property).
dojo.lang.isFunction
function(/*anything*/ it){
// summary: Return true if it is a Function.
判断输入的类型是否为函数
Usage Example:
dojo.lang.isFunction(function() {}); //will return true
dojo.lang.isString
判断输入的类型是否为字符串
function(/*anything*/ it){
// summary: Return true if it is a String.
Usage Example:
dojo.lang.isString(""); //will return true
dojo.lang.isString(0); //will return false
dojo.lang.isAlien
判断输入的类型是否为系统函数
function(/*anything*/ it){
// summary: Return true if it is not a built-in function. False if not.
Usage Example:
dojo.lang.isAlien(isNaN); //will return true
dojo.lang.isBoolean
判断输入的类型是否为布尔类型
function(/*anything*/ it){
// summary: Return true if it is a Boolean.
Usage Example:
dojo.lang.isBoolean(2>1); //will return true
下面的 is***()函数有点不安全
dojo.lang.isNumber
判断输入的类型是否为数值,根据注释所说,此函数使用不太可靠,但是可替换使用的系统函数 isNaN 也
不太可靠
// summary: Return true if it is a number.
// description:
//
WARNING - In most cases, isNaN(it) is sufficient to determine whether or not
// something is a number or can be used as such. For example, a number or string
// can be used interchangably when accessing array items (array["1"] is the same as
// array[1]) and isNaN will return false for both values ("1" and 1). However,
// isNumber("1") will return false, which is generally not too useful.
// Also, isNumber(NaN) returns true, again, this isn't general y useful, but there
// are corner cases (like when you want to make sure that two things are really
// the same type of thing). That is really where isNumber "shines".
//
// Recommendation - Use isNaN(it) when possible
dojo.lang.isUndefined
判断输入是否为未定义,根据注释所说,此函数有可能会导致抛出异常,推荐使
用 typeof foo == "undefined" 来判断
// summary: Return true if it is not defined.
// description:
//
WARNING - In some cases, isUndefined will not behave as you
// might expect. If you do isUndefined(foo) and there is no earlier
// reference to foo, an error will be thrown before isUndefined is
// called. It behaves correctly if you scope yor object first, i.e.
// isUndefined(foo.bar) where foo is an object and bar isn't a
//
//
propertyof the object.
// Recommendation - Use typeof foo == "undefined" when possible
模块:dojo.lang.array
处理数组相关 api
dojo.lang.has
判断对象是否具有指定属性,不过这个方法有用吗,不如直接使用 if(name in obj)
function(/*Object*/obj, /*String*/name)
// summary: is there a property with the passed name in obj?
Usage Example:
dojo.lang.has(dojo.lang, "has"); //will return true
dojo.lang.isEmpty
判断对象或数组是否为空
function(/*Object*/obj)
// summary:
//
//
//
//
//
//
can be used to determine 求出 if the passed object is "empty". In
the case of array-like objects, the length, property is
examined 检查, but for other types of objects iteration 重复 is used to
examine the iterable "surface area" to determine if any
non-prototypal properties have been assigned 分配. This iteration is
prototype-extension safe.
Usage Example:
dojo.lang.isEmpty({a: 1}); //will return false
dojo.lang.isEmpty([]); //will return true
dojo.lang.map
调用指定的方法处理指定的数组或字符串
function(/*Array*/arr, /*Object|Function*/obj, /*Function?*/unary_func)
// summary:
//
//
//
//
//
//
returns a new array constituded from the return values of
passing each element of arr into unary_func. The obj parameter
may be passed to enable the passed function to be called in
that scope. In environments that support JavaScript 1.6, this
function is a passthrough to the built-in map() function
provided by Array instances. For details on this, see:
// http://developer.mozilla/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:map
// examples:
//dojo.lang.map([1, 2, 3, 4], function(item){ return item+1 });
// returns [2, 3, 4, 5]
Usage Example:
dojo.lang.map([1,2,3,4,5], function(x) { return x * x;}); //will return [1,4,9,16,25]
dojo.lang.reduce
function(/*Array*/arr, initialValue, /*Object|Function*/obj, /*Function*/binary_func)
// summary:
//
//
//
//
//
//
//
//
//
//
similar to Python's builtin reduce() function. The result of
the previous 前面的 computation 计算 is passed as the first argument 争论 to
binary_func along with the next value from arr. The result of
this call is used along with the subsequent 后来的 value from arr, and
this continues until arr is exhausted. The return value is the
last result. The "obj" and "initialValue" parameters may be
safely omitted and the order of obj and binary_func may be
reversed. The default order of the obj and binary_func argument
will probably be reversed in a future release, and this call
order is supported today.
// examples:
//
//
dojo.lang.reduce([1, 2, 3, 4], function(last, next){ return last+next});
returns 10
dojo.lang.forEach
遍历指定的数组或字符串,并对其中的元素调用指定的方法
function(/*Array*/anArray, /*Function*/callback, /*Object?*/thisObject)
// summary:
//
for every item in anArray, call callback with that item as its
//
//
//
only parameter. Return values are ignored 忽略. This funciton
corresponds 协调(and wraps) the JavaScript 1.6 forEach method. For
more details, see:
//http://developer.mozilla/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:forEach
Usage Example:
dojo.lang.forEach("abc", function(x) { alert(x); });
dojo.lang.every
检查指定的数组是否全部满足指定方法的条件
function(/*Array*/arr, /*Function*/callback, /*Object?*/thisObject)
// summary:
//
//
//
//
//
//
determines 决定 whether or not every item in the array satisfies 符合 the
condition 条件 implemented by callback. thisObject may be used to
scope the call to callback. The function signature 特征 is derived 起源
from the JavaScript 1.6 Array.every() function. More
information on this can be found here:
http://developer.mozilla/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:every
// examples:
//
//
//
//
dojo.lang.every([1, 2, 3, 4], function(item){ return item>1; });
// returns false
dojo.lang.every([1, 2, 3, 4], function(item){ return item>0; });
// returns true
Usage Example:
dojo.lang.every([1,-2,3], function(x) { return x > 0; }); //指定的数组不是全大于 0 的,因此返回 false
dojo.lang.some
检查指定的数组是否部分满足指定方法的条件
function(/*Array*/arr, /*Function*/callback, /*Object?*/thisObject)
// summary:
//
//
determines whether or not any item in the array satisfies the
condition 条件 implemented by callback. thisObject may be used to
//
//
//
//
scope the call to callback. The function signature is derived
from the JavaScript 1.6 Array.some() function. More
information on this can be found here:
http://developer.mozilla/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:some
// examples:
//
//
//
//
dojo.lang.some([1, 2, 3, 4], function(item){ return item>1; });
// returns true
dojo.lang.some([1, 2, 3, 4], function(item){ return item<1; });
// returns false
Usage Example:
dojo.lang.some([1,-2,3], function(x) { return x > 0; }); //指定的数组有大于 0 的元素,因此返回 true
dojo.lang.filter
根据指定的方法来过滤指定的数组
function(/*Array*/arr, /*Function*/callback, /*Object?*/thisObject)
// summary:
//
//
//
//
//
//
returns a new Array with those items from arr that match the
condition implemented by callback.thisObject may be used to
scope the call to callback. The function signature is derived
from the JavaScript 1.6 Array.filter() function, although
special accomidation is made in our implementation for strings.
More information on the JS 1.6 API can be found here:
//http://developer.mozilla/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Array:filter
// examples:
//
dojo.lang.some([1, 2, 3, 4], function(item){ return item>1; });
// returns [2, 3, 4]
Usage Example:
dojo.lang.filter([1,-2,3], function(x) { return x > 0; }); //will return [1, 3]
dojo.lang.unnest
把指定的参数或数组转换为一维数组
function(/* ... */){
// summary:
//
//
// usage:
//
//
Creates a 1-D array out of all the arguments passed,
unravelling any array-like objects in the process
unnest(1, 2, 3) ==> [1, 2, 3]
unnest(1, [2, [3], [[[4]]]]) ==> [1, 2, 3, 4]
Usage Example:
dojo.lang.unnest(1, 2, 3); //will return [1, 2, 3]
dojo.lang.unnest(1, [2, [3], [[[4]]]]); //will return [1, 2, 3, 4]
dojo.lang.toArray
将输入转换为数组
function(/*Object*/arrayLike, /*Number*/startOffset){
// summary:
//
//
Converts an array-like object (i.e. arguments, DOMCollection)
to an array. Returns a new Array object.
Usage Example:
function test()
{
return dojo.lang.toArray(arguments, 1);
}
test(1,2,3,4,5); //will return [2,3,4,5]
模块:dojo.lang.extras
dojo.lang.setTimeout
延迟指定时间后执行指定方法
function(/*Function*/func, /*int*/delay /*, ...*/){
// summary:
//
Sets a timeout in milliseconds to execute a function in a given
//
// usage:
//
//
context with optional arguments.
dojo.lang.setTimeout(Object context, function func, number delay[, arg1[, ...]]);
dojo.lang.setTimeout(function func, number delay[, arg1[, ...]]);
Usage Example:
function onTime(msg){dojo.debug(msg)}dojo.lang.setTimeout(onTime, 1000, "test"); //1 秒后会输出调试
信息"test"dojo.lang.setTimeout(dojo, "debug", 1000, "test"); //1 秒后会输出调试信息"test"
dojo.lang.clearTimeout
function(/*int*/timer){
// summary: clears timer by number from the execution queue 排列
// FIXME:
//
//
//
why do we have this function? It's not portable outside of browser
environments and it's a stupid wrapper on something that browsers
provide anyway.
dojo.lang.getNameInObj
获得指定项目在指定对象中的名称
function(/*Object*/ns, /*unknown*/item)
// summary:
//
//
looks for a value in the object ns with a value matching item and
returns the property name
// ns: if null, dj_global is used
// item: value to return a name for
Usage Example:
dojo.lang.getNameInObj(dojo, dojo.debug); //will return "debug"
dojo.lang.shallowCopy
返回指定对象的浅表复制副本
function(/*Object*/obj, /*Boolean?*/deep)
// summary:
//
copies object obj one level deep, or full depth if deep is true
Usage Example:
dojo.lang.shallowCopy({}); //will return a 空对象
dojo.lang.firstValued
返回第一个非定义的参数
function(/* ... */){
// summary: Return the first argument that isn't undefined
Usage Example:
var a;dojo.lang.firstValued(a,2,3); //will return 2
dojo.lang.getObjPathValue
function(/*String*/objpath, /*Object?*/context, /*Boolean?*/create){
// summary:
//
//
Gets a value from a reference specified as a string descriptor,
(e.g. "A.B") in the given context.
// context: if not specified, dj_global is used
// create: if true, undefined objects in the path are created.
dojo.lang.setObjPathValue
function(/*String*/objpath, /*anything*/value, /*Object?*/context, /*Boolean?*/create)
// summary:
//
//
//
//
Sets a value on a reference specified as a string descriptor.
(e.g. "A.B") in the given context. This is similar to straight
assignment, except that the object structure in question can
optionally be created if it does not exist.
// context: if not specified, dj_global is used
// create: if true, undefined objects in the path are created.
// FIXME: why is this function valuable? It should be scheduled for
// removal on the grounds that dojo.parseObjPath does most of it's work and
// is more straightforward and has fewer dependencies. Also, the order of
// arguments is bone-headed. "context" should clearly come after "create".
// *sigh*
模块:dojo.lang.func
dojo.lang.hitch
将指定的方法挂在指定的对象下并返回该方法
function(/*Object*/thisObject, /*Function|String*/method /*, ...*/)
// summary:
//
//
//
Returns a function that will only ever execute in the a given scope
(thisObject). This allows for easy use of object member functions
in callbacks and other places in which the "this" keyword may
//
//
//
//
//
otherwise not reference the expected scope. Any number of default
positional arguments may be passed as parameters beyond "method".
Each of these values will be used to "placehold" (similar to curry)
for the hitched function. Note that the order of arguments may be
reversed in a future version.
// thisObject: the scope to run the method in
// method:
//
//
// usage:
//
//
a function to be "bound" to thisObject or the name of the method in
thisObject to be used as the basis for the binding
dojo.lang.hitch(foo, "bar")(); // runs foo.bar() in the scope of foo
dojo.lang.hitch(foo, myFunction); // returns a function that runs myFunction in the scope of foo
Usage Example:
func = {test: function(s) {alert(s)}};
dojo.lang.mixin(func, {demo: dojo.lang.hitch(func, "test")});
func.demo("demo and test are same method");
dojo.lang.nameAnonFunc
function(/*Function*/anonFuncPtr, /*Object*/thisObj, /*Boolean*/searchForNames){
// summary:
//
//
//
//
//
//
Creates a reference to anonFuncPtr in thisObj with a completely
unique name. The new name is returned as a String. If
searchForNames is true, an effort will be made to locate an
existing reference to anonFuncPtr in thisObj, and if one is found,
the existing name will be returned instead. The default is for
searchForNames to be false.
dojo.lang.forward
返回自身对象的指定名称的方法引用
function(funcName){
// summary:
//
//
//
Returns a function that forwards a method call to
this.funcName(...). Unlike dojo.lang.hitch(), the "this" scope is
not fixed on a single object. Ported from Mochi
Usage Example:
func = {test: function(s) {alert(s)}, demo: dojo.lang.forward("test")};
func.demo("demo and test are same method");
dojo.lang.curry
What is curry? 请参阅这篇文章:http://www.svendtofte/code/curried_javas cript/
function(thisObj, func /* args ... */)
// summary:
//
//
//
//
//
//
//
//
//
similar to the curry() method found in many functional programming
environments, this function returns an "argument accumulator"
function, bound to a particular scope, and "primed" with a variable
number of arguments. The curry method is unique in that it returns
a function that may return other "partial" function which can be
called repeatedly. New functions are returned until the arity of
the original function is reached, at which point the underlying
function (func) is called in the scope thisObj with all of the
accumulated arguments (plus any extras) in positional order.
// examples:
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
assuming a function defined like this:
var foo = {
bar: function(arg1, arg2, arg3){
dojo.debug.apply(dojo, arguments);
}
};
dojo.lang.curry() can be used most simply in this way:
tmp = dojo.lang.curry(foo, foo.bar, "arg one", "thinger");
tmp("blah", "this is superfluous");
// debugs: "arg one thinger blah this is superfluous"
tmp("blah");
// debugs: "arg one thinger blah"
tmp();
// returns a function exactly like tmp that expects one argument
other intermittent functions could be created until the 3
positional arguments are filled:
//
//
//
//
//
//
//
//
//
//
//
//
//
//
//
tmp = dojo.lang.curry(foo, foo.bar, "arg one");
tmp2 = tmp("arg two");
tmp2("blah blah");
// debugs: "arg one arg two blah blah"
tmp2("oy");
// debugs: "arg one arg two oy"
curry() can also be used to call the function if enough arguments
are passed in the initial invocation:
dojo.lang.curry(foo, foo.bar, "one", "two", "three", "four");
// debugs: "one two three four"
dojo.lang.curry(foo, foo.bar, "one", "two", "three");
// debugs: "one two three"
// FIXME: the order of func and thisObj should be changed!!!
Usage Example:
function add(a, b)
{
return a + b;
}
dojo.lang.curry(null, add, 2, 3); //will return 5
dojo.lang.curry(null, add, 2)(3); //will return 5
dojo.lang.curry(null, add)(2)(3); //will return 5
dojo.lang.curry(null, add)()(2)(3); //will return 5
dojo.lang.curryArguments
与 dojo.lang.curry 类似,但是可以选择忽略掉前 n 个参数
function(/*Object*/thisObj, /*Function*/func, /*Array*/args, /*Integer, optional*/offset)
// summary:
//
//
//
//
similar to dojo.lang.curry(), except that a list of arguments to
start the curry with may be provided as an array instead of as
positional arguments. An offset may be specified from the 0 index
to skip some elements in args.
Usage Example:
function add(a, b)
{
return a + b;
}
dojo.lang.curryArguments(null, add, [1,2,3,4,5], 2); //will return 7 (= 3 + 4)
dojo.lang.tryThese
测试参数指定所有函数,并返回第一个返回值不为 0 的函数值,没看懂这个函数哪里用得着
function(/*...*/){
// summary:
//
//
//
executes each function argument in turn, returning the return value
from the first one which does not throw an exception in execution.
Any number of functions may be passed.
from seno:
dojo.lang.tryThese 方法和 prototype 中的 Try.these()方法是一样的,
xmlNode.text 在一些浏览器中好用,但是 xmlNode.textContent 在另一些浏览器中正常工作。 使用
Try.these()方法我们可以得到正常工作的那个方法的返回值。
<script>
function getXmlNodeValue(xmlNode){
return Try.these(
function() {return xmlNode.text;},
function() {return xmlNode.textContent;)
);
}
dojo.lang.delayThese
没看懂这个函数怎么用
function(/*Array*/farr, /*Function, optional*/cb, /*Integer*/delay, /*Function,
optional*/onend)
// summary:
//
//
//
//
//
/**
executes a series of functions contained in farr, but spaces out
calls to each function by the millisecond delay provided. If cb is
provided, it will be called directly after each item in farr is
called and if onend is passed, it will be called when all items
have completed executing.
* alternate: (array funcArray, function callback, function onend)
* alternate: (array funcArray, function callback)
* alternate: (array funcArray)
*/
模块:dojo.eventmon
dojo.event.connect
绑定指定的方法到指定的对象的方法上
function(/*...*/)
// summary:
//
//
//
//
//
//
//
//
//
//
//
dojo.event.connect is the glue that holds most Dojo‐based
applications together. Most combinations of arguments are
supported, with the connect() method attempting to disambiguate
the implied types of positional parameters. The following will
all work:
dojo.event.connect("globalFunctionName1", "globalFunctionName2");
dojo.event.connect(functionReference1, functionReference2);
dojo.event.connect("globalFunctionName1", functionReference2);
dojo.event.connect(functionReference1, "globalFunctionName2");
dojo.event.connect(scope1, "functionName1", "globalFunctionName2");
dojo.event.connect("globalFunctionName1", scope2, "functionName2");
//
"functionName2");
dojo.event.connect(scope1,
"functionName1",
scope2,
//
"functionName2");
//
"functionName2");
//
//
//
//
//
//
dojo.event.connect("after", scope1, "functionName1", scope2,
dojo.event.connect("before", scope1, "functionName1", scope2,
dojo.event.connect("around", scope1, "functionName1",
scope2, "functionName2",
aroundFunctionReference);
dojo.event.connect("around", scope1, "functionName1",
scope2, "functionName2",
scope3,
"aroundFunctionName");
//
//
"functionName2",
//
dojo.event.connect("before‐around", scope1, "functionName1",
scope2,
aroundFunctionReference);
// dojo.event.connect("after‐around",
//
"functionName2",
scope1, "functionName1",
scope2,
//
aroundFunctionReference);
// dojo.event.connect("after‐around",
//
"functionName2",
//
"aroundFunctionName");
scope1, "functionName1",
scope2,
scope3,
true, 30);
//
//
//
//
//
//
dojo.event.connect("around", scope1, "functionName1",
scope2, "functionName2",
scope3, "aroundFunctionName",
dojo.event.connect("around", scope1, "functionName1",
scope2, "functionName2",
scope3, "aroundFunctionName",
null, null, 10);
// adviceType:
//
//
// srcObj:
//
//
//
//
//
Optional. String. One of "before", "after", "around",
"before‐around", or "after‐around". FIXME
the scope in which to locate/execute the named srcFunc. Along
with srcFunc, this creates a way to dereference the function to
call. So if the function in question is "foo.bar", the
srcObj/srcFunc pair would be foo and "bar", where "bar" is a
string and foo is an object reference.
// srcFunc:
//
//
//
//
the name of the function to connect to. When it is executed,
the listener being registered with this call will be called.
The adviceType defines the call order between the source and
the target functions.
// adviceObj:
//
the scope in which to locate/execute the named adviceFunc.
// adviceFunc:
//
the name of the function being conected to srcObj.srcFunc
// aroundObj:
//
the scope in which to locate/execute the named aroundFunc.
// aroundFunc:
//
//
//
//
//
//
//
//
the name of, or a reference to, the function that will be used
to mediate the advice call. Around advice requires a special
unary function that will be passed a "MethodInvocation" object.
These objects have several important properties, namely:
‐ args
a mutable array of arguments to be passed into the
wrapped function
‐ proceed
//
//
//
//
// once:
//
//
//
// delay:
//
//
// rate:
//
//
//
a function that "continues" the invocation. The result
of this function is the return of the wrapped function.
You can then manipulate this return before passing it
back out (or take further action based on it).
boolean that determines whether or not this connect() will
create a new connection if an identical connect() has already
been made. Defaults to "false".
an optional delay (in ms), as an integer, for dispatch of a
listener after the source has been fired.
an optional rate throttling parameter (integer, in ms). When
specified, this particular connection will not fire more than
once in the interval specified by the rate
// adviceMsg:
//
//
/*
*/
Usage Example:
简单绑定 1
function doOnClick1()
{
alert( "Clicked!");
}
boolean. Should the listener have all the parameters passed in
as a single argument?
ao.adviceType = args[0];
ao.srcObj = args[1];
ao.srcFunc = args[2];
ao.adviceObj = args[3]
ao.adviceFunc = args[4];
ao.aroundObj = args[5];
ao.aroundFunc = args[6];
ao.once = args[7];
ao.delay = args[8];
ao.rate = args[9];
ao.adviceMsg = args[10];
ao.maxCalls = args[11];
dojo.event.connect(dojo.byId("inputTest"),"onclick","doOnClick1");
简单绑定 2
obj = { doOnClick2: function(){ alert("Clicked!");}}
dojo.event.connect(dojo.byId("inputTest"),"onclick",obj,"doOnClick2");
如果存在需要进行多个事件的绑定的时候,你就会看到 dojo 的方便之处了
obj2 = { doOnClick2: function(){alert("Clicked!");}}
dojo.event.connect(dojo.byId("inputTest"),"onclick",obj,"doOnClick2");
dojo.event.connect(dojo.byId("inputTest"),"onclick",obj2,"doOnClick2");
connect 可以对任何对象的方法进行绑定,而不是只能针对 DOM 对象
dojo.event.connect(obj,"doOnclick2","doOnClick1"); //在调用 obj.doOnclick2()后调用 doOnClick1()
dojo.event.log
function(/*object or funcName*/ a1, /*funcName*/ a2)
// summary:
//
//
//
//
// a1:
//
//
// a2:
//
a function that will wrap and log all calls to the specified
a1.a2() function. If only a1 is passed, it'll be used as a
function or function name on the global context. Logging will
be sent to dojo.debug
if a2 is passed, this should be an object. If not, it can be a
function or function name.
a function name
dojo.event.connectBefore
function()summary:
//
//
takes the same parameters as dojo.event.connect(), except that
the advice type will always be "before"
dojo.event.connect 默认是后绑定,connectBefore 则是早绑定,绑定的方法将在指定方法前执行,用法与 connect 一致
dojo.event.connectAround
summary:
//
//
takes the same parameters as dojo.event.connect(), except that
the advice type will always be "around"
Usage Example:
function aroundTest(invocation){
//此处可以增加代码,比如检查参数(invocation.args)
var result = invocation.proceed();
//此处可以增加代码,比如修改结果(result)
return result;
}
dojo.event.connectAround(dojo.byId("inputTest"),"onclick","aroundTest");
dojo.event.connectOnce
function()
summary:
//
//
takes the same parameters as dojo.event.connect(), except that
the "once" flag will always be set to "true"
说起这个函数,还真的是让我想了半天,直觉上我就把它想象成 executeOnce,结果测试的结
果让我差点想不通
connectOnce 就是指保证只绑定一次,来避免重复绑定会导致的重复执行的问题
dojo.event.connectRunOnce
summary:
//
//
takes the same parameters as dojo.event.connect(), except that
the "maxCalls" flag will always be set to 1
dojo.event.kwConnect
kwConnect 可以做到更加灵活的绑定,比如可以设置延迟执行绑定
function(/*Object*/ kwArgs)
summary:
//
A version of dojo.event.connect() that takes a map of named
//
//
//
//
parameters instead of the positional parameters that
dojo.event.connect() uses. For many advanced connection types,
this can be a much more readable (and potentially faster)
alternative.
// kwArgs:
//
//
//
//
//
//
//
//
//
//
//
//
//
//
An object that can have the following properties:
‐ adviceType
‐ srcObj
‐ srcFunc
‐ adviceObj
‐ adviceFunc
‐ aroundObj
‐ aroundFunc
‐ once
‐ delay
‐ rate
‐ adviceMsg
As with connect, only srcFunc and adviceFunc are generally
required
Usage Example:
dojo.event.kwConnect({
srcObj: dojo.byId("inputTest"),
srcFunc: "onclick",
adviceObj: obj,
adviceFunc: "doOnclick2",
type: "before", //默认为"after",可选: "before", "around",注意:type 是用来决定 adviceFunc 的行为的,如果为"ar
ound",则 aroundFunc 将失效
aroundObj: null,
aroundFunc: null, //如果指定了 aroundFunc,则其将对 adviceFunc 进行拦截,但是当 type 为 "around"时,则 aroun
dFunc 将不会执行
once: false, //默认为 false,允许重复绑定
delay: 3000, //延时 3 秒后执行 adviceFunc
rate: 0, //这个从源代码没有看懂起什么作用
adviceMsg: false //这个从源代码没有看懂起什么作用
});
dojo.event.kwDisconnect
用来解除使用 kwConnect 指定的绑定
模块:dojo.event.topic
Topic 机制与 Advice 机制都能够实现事件的绑定,但是显然,Topic 更适合处理多重绑定。
发布主题,然后由用户订阅的机制就是一个典型的观察者模式
dojo.event.disconnect
解除绑定,调用参数与 connect 一致,即可解除之前的绑定操作
summary:
//
//
//
//
Takes the same parameters as dojo.event.connect() but destroys
an existing connection instead of building a new one. For
multiple identical connections, multiple disconnect() calls
will unroll one each time it's called.
这里所说的基础对象和方法是指的不 Require 任何包就能够调用的对象和方法
匿名函数
在开始前,我想介绍一下 js 里的匿名函数,这个在阅读 dojo 的源代码的时候,会发现到处都有匿名
函数
;(function(){
alert(123);
})();
//前面的分号是一个空语句,是可以不要的
匿名函数。一个匿名函数就是一个没有名字的函数。
你可以认为他们是一次性函数。当你只需要用一次某个函数时,他们就特别有用。通过使用匿名函数,
没有必要把函数一直放在内存中,所以使用匿名函数更加有效率。
当然你也可以根本不定义函数,但是使用匿名函数可以把你的代码分段,就像 C#中的#region 一样
dojo.event.MethodInvocation
function(/*dojo.event.MethodJoinPoint*/join_point, /*Object*/obj, /*Array*/args){
// summary:
//
//
a class the models the call into a function. This is used under the
covers for all method invocations on both ends of a
//
//
connect()‐wrapped function dispatch. This allows us to "pickle"
calls, such as in the case of around advice.
// join_point:
//
// obj:
//
// args:
//
a dojo.event.MethodJoinPoint object that represents a connection
the scope the call will execute in
an array of parameters that will get passed to the callee
dojo.event.MethodInvocation.protot
ype.proceed
// summary:
//
//
proceed with the method call that's represented by this invocation
object
模块:dojo.event.browser
dojo.event.browser.clean
function(/*DOMNode*/node)
summary:
//
//
//
// node:
//
removes native event handlers so that destruction of the node
will not leak memory. On most browsers this is a no‐op, but
it's critical for manual node removal on IE.
A DOM node. All of it's children will also be cleaned
dojo.event.browser.addClobberNode
function(/*DOMNode*/node)
summary:
//
// node:
//
register the passed node to support event stripping
A DOM node
dojo.event.browser.addClobberNodeA
ttrs
function(/*DOMNode*/node, /*Array*/props)
summary:
//
// node:
//
// props:
//
register the passed node to support event stripping
A DOM node to stip properties from later
A list of propeties to strip from the node
dojo.event.browser.removeListener
function( /*DOMNode*/ node,
/*String*/ evtName,
/*Function*/fp,
/*Boolean*/ capture)
// summary:
//
clobbers the listener from the node
// evtName:
//
// node:
//
// fp:
//
the name of the handler to remove the function from
DOM node to attach the event to
the function to register
// capture:
//
Optional. should this listener prevent propigation?
清除监听器(这个方法似乎是无效的)
dojo.event.browser.addListener
function(/*DOMNode*/node, /*String*/evtName, /*Function*/fp, /*Boolean*/capture,
/*Boolean*/dontFix){
// summary:
//
adds a listener to the node
// evtName:
//
//
// node:
//
// fp:
//
the name of the handler to add the listener to can be either of
the form "onclick" or "click"
DOM node to attach the event to
the function to register
// capture:
//
Optional. Should this listener prevent propigation?
// dontFix:
//
//
//
增加监听器
Usage Example:
function listener()
{
alert( "ok");
}
Optional. Should we avoid registering a new closure around the
listener to enable fixEvent for dispatch of the registered
function?
dojo.event.browser.addListener(document, 'mousedown', listener); //事件名称可以加上"on",
也可以没有"on"
dojo.event.browser.addListener(document, 'onmousedown', listener, true); //capture 为真表
示不受上层元素的事件控制
dojo.event.browser.isEvent
function(/*Object*/obj){
// summary:
//
Tries to determine whether or not the object is a DOM event.
// FIXME: event detection hack ... could test for additional attributes
// if necessary
判断指定对象是否为 event 对象
Usage Example:
dojo.event.browser.isEvent(dojo.event.browser.currentEvent); //当 dojo.event.browser.currentEvent 不为 null 时返回 t
rue
dojo.event.browser.callListener
function(/*Function*/listener, /*DOMNode*/curTarget){
// summary:
//
//
calls the specified listener in the context of the passed node
with the current DOM event object as the only parameter
// listener:
//
the function to call
// curTarget:
//
调用监听器
Usage Example:
the Node to call the function in the scope of
dojo.event.browser.callListener(listener, document);
dojo.event.browser.fixEvent
function(/*Event*/evt, /*DOMNode*/sender){
// summary:
//
//
normalizes properties on the event object including event
bubbling methods, keystroke normalization, and x/y positions
// evt: the native event object
// sender: the node to treat as "currentTarget"
dojo.event.browser.stopEvent
function(/*Event*/evt){
// summary:
//
//
prevents propigation and clobbers the default action of the
passed event
// evt: Optional for IE. The native event object.
dojo.event.browser.stopPropagation
阻止 Event 传播
Usage Example:
dojo.event.browser.stopPropagation();
dojo.event.browser.preventDefault
将当前事件的返回值设置为 false
Usage Example:
dojo.event.browser.preventDefault();
dojo.event.browser.keys
键定义:
KEY_BACKSPACE: 8,
KEY_TAB: 9,
KEY_ENTER: 13,
KEY_SHIFT: 16,
KEY_CTRL: 17,
KEY_ALT: 18,
KEY_PAUSE: 19,
KEY_CAPS_LOCK: 20,
KEY_ESCAPE: 27,
KEY_SPACE: 32,
KEY_PAGE_UP: 33,
KEY_PAGE_DOWN: 34,
KEY_END: 35,
KEY_HOME: 36,
KEY_LEFT_ARROW: 37,
KEY_UP_ARROW: 38,
KEY_RIGHT_ARROW: 39,
KEY_DOWN_ARROW: 40,
KEY_INSERT: 45,
KEY_DELETE: 46,
KEY_LEFT_WINDOW: 91,
KEY_RIGHT_WINDOW: 92,
KEY_SELECT: 93,
KEY_F1: 112,
KEY_F2: 113,
KEY_F3: 114,
KEY_F4: 115,
KEY_F5: 116,
KEY_F6: 117,
KEY_F7: 118,
KEY_F8: 119,
KEY_F9: 120,
KEY_F10: 121,
KEY_F11: 122,
KEY_F12: 123,
KEY_NUM_LOCK: 144,
KEY_SCROLL_LOCK: 145
dojo.event.browser.currentEvent
最近一次的 Event,其属性包括:
altKey //检查 alt 键的状态,当 alt 键按下时,值为 true
button //检查按下的鼠标键,0 没按键,1 按左键,2 按右键,3 按左右键,4 按中间键,5 按左键和中间键,6 按右
键和中间键,7 按所有的键
//这个属性仅用于 onmousedown, onmouseup, 和 onmousemove 事件。对其他事件,不管鼠标状态如何,都返回
0(比如 onclick)
clientX //返回鼠标在窗口客户区域中的 X 坐标
clientY //返回鼠标在窗口客户区域中的 Y 坐标
ctrlKey //检查 ctrl 键的状态,当 ctrl 键按下时,值为 true
fromElement //检测 onmouseover 和 onmouseout 事件发生时,鼠标所离开的元素
keyCode //检测键盘事件相对应的内码,仅当 type 为 keydown,keyup,keypress 时才有效
offsetX //检查相对于触发事件的对象,鼠标位置的水平坐标
offsetY //检查相对于触发事件的对象,鼠标位置的垂直坐标
propertyName //设置或返回元素的变化了的属性的名称,你可以通过使用 onpropertychange 事件,得到 propertyNa
me 的值
screenX //检测鼠标相对于用户屏幕的水平位置
screenY //检测鼠标相对于用户屏幕的垂直位置
shiftKey //检查 shift 键的状态,当 shift 键按下时,值为 true
srcElement //返回触发事件的元素
srcFilter //返回触发 onfilterchange 事件的滤镜
toElement //检测 onmouseover 和 onmouseout 事件发生时,鼠标所进入的元素
type //返回没有“on”作为前缀的事件名,比如 click, mousedown
x //返回鼠标相对于 css 属性中有 position 属性的上级元素的 x 轴坐标。如果没有 css 属性中有 position 属性的上级元
素,默认以 BODY 元素作为参考对象
y //返回鼠标相对于 css 属性中有 position 属性的上级元素的 y 轴坐标。如果没有 css 属性中有 position 属性的上级元
素,默认以 BODY 元素作为参考对象
target //同 srcElement
currentTarget
layerX //同 offsetX
layerY //同 offsetY
pageX //无水平滚动条的情况下与 clientX 同
pageY //无水平滚动条的情况下与 clientY 同
relatedTarget // 仅当 type 为 mouseover,mouseout 时才有效
keys //与 dojo.event.browser.keys 相同,仅当 type 为 keydown,keyup,keypress 时才有效
charCode //键值,仅当 type 为 keypress 时才有效
dojo.byId
非常有用的一个方法,与 prototype.js 的著名的$一样
似乎以前的版本还有 dojo.byIdArray, 不过最新的版本已经找不到这个函数了(除了
src\compat\0.2.2.js)
如果有多个元素具有指定的 id,则返回的是一个集合
Usage Example:
dojo.byId("divTest");
dojo.byId("divTest", document);
dojo.byId(document.getElementById("divTest"));
dojo.version
dojo 的版本,可以取得 major, minor, patch, flag 和 revision
这个对象没什么太大用处,除非你要根据 dojo 的版本选择执行你的代码
dojo.raise
抛出一个异常
dojo.errorToString
将异常转换为字符串
Usage Example:
try
{
dojo.raise("打印失败", new Error("文件不存在"));
}
catch(e)
{
alert(dojo.errorToString(e));
}
dojo.render
系统环境对象
dojo.render.name 返回 browser ,说明是工作在浏览器下
dojo.render.ver 返回 4 ,返回 dojo 版本
dojo.os.win 返回 true 说明操作系统是 Windows
dojo.os.linux 返回 true 说明操作系统是 Linux
dojo.os.osx 返回 true 说明操作系统是 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 开发的 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
可以加载指定函数到 window.load 时执行,好处就是可以很方便的在 window.load 时执行多个函数
Usage Example:
dojo.addOnLoad(init); //init 是一个函数
dojo.addOnLoad(myObject, init); //init 是 myObject 对象的一个方法
dojo.require
如果你想调用一个模块的对象的时候,你应该首先用 dojo.require 来请求这个模块,dojo 会根据
你的请求自动取得相应的 js 文件,并加载到内存中,这样你才能调用或创建其中的对象
dojo 会自动维护已加载的模块列表,所以是不会重复加载模块的
Usage Example:
dojo.require("dojo.event");
dojo.requireIf=dojo.requireAfterIf
可以根据指定的条件来决定是否加载指定的模块
Usage Example:
dojo.requireIf(dojo.html.ie, "dojo.html"); //如果 dojo.html.ie 为 true,才会加载 dojo.html 模
块
dojo.provide
除非你要开发自己的模块,不然是用不到这个方法的,你可以这句看成是向系统注册这个模块名称
Usage Example:
dojo.provide("dojo.custom");
dojo.exists
判断指定对象是否具有指定名称的方法
Usage Example:
dojo.exists(dojo, "exists"); //will return true
dojo.hostenv.getText
返回指定 url 的内容
PS: 由于浏览器的安全限制,因此只能用于取得同域名的 url 的内容,否则会报告权限不够
Usage Example:
aSync = false; //同步,确保返回内容不为 null
silent = true; //不抛出错误
s = dojo.hostenv.getText("http://www.google/", aSync, silent); //返回 Google 的首页的
HTML
alert(s);
dojo.debug
输出调试信息,如果在 djConfig 中指定了 debugContainerId,则输出到指定的 console 容器
中,否则直接 document.write
所有的调试信息均以 DEBUG: 开头
Usage Example:
dojo.debug("这是调试信息");
dojo.hostenv.println
与 dojo.debug 类似,不同的是,输出内容没有 DEBUG:
Usage Example:
dojo.hostenv.println("这是一般的输出信息");
dojo.debugShallow
输出指定对象的全部信息(Shallow 说明并不会遍历到下一级别的对象属性)以供调试
Usage Example:
dojo.debugShallow(dojo.render.html);
以上全部是自己阅读源代码写的总结,如有错误,还请指明。
模块:dojo.validate.creditCard
DOJO 常用的验证函数,dojo 提供了几乎全方位的验证函数
dojo.provide("dojo.validatemon");
dojo.validate.isValidCreditCard
dojo.validate.isValidCreditCard (/*String|Int*/value, /*String*/ccType);
Summary:
checks if type matches the # scheme, and if Luhn checksum is accurate (unless its an Enroute card,
the checkSum is skipped)
Value: Boolean
dojo.validate.isValidCreditCardNum
ber
dojo.validate.isValidCreditCardNumber (/*String|Int*/value,/*String?*/ccType)
//Summary:
// checks if the # matches the pattern for that card or any card types if none is specified
// value == CC #, white spaces and dashes are ignored
// ccType is of the values in cardinfo ‐‐ if Omitted it it returns a | delimited string of
matching card types, or false if no matches found
//Value: Boolean
dojo.validate.isValidCvv
dojo.validate.isValidCvv (/*String|Int*/value, /*String*/ccType);
//Summary:
// returns true if the security code (CCV) matches the correct format for supplied ccType
//Value: Boolean
模块:dojo.validatemon
dojo.validate.isText
dojo.validate.isText (/*String*/value, /*Object?*/flags):
isText accepts a parameter, and determines if it is a string
value:
value to test.
returns:
Boolean
// summary:
// Checks if a string has non whitespace characters.
// Parameters allow you to constrain the length.
//
// value: A string
// flags: {length: Number, minlength: Number, maxlength: Number}
// flags.length If set, checks if there are exactly flags.length number of characters.
// flags.minlength If set, checks if there are at least flags.minlength number of characters.
// flags.maxlength If set, checks if there are at most flags.maxlength number of characters.
dojo.validate.isInteger
dojo.validate.isInteger (/*String*/value, /*Object?*/flags):
isInteger accepts a parameter, and determines if it is an integer. Note that this returns true is it is string integer, or a number
integer.
value:
value to test.
returns:
Boolean
// summary:
// Validates whether a string is in an integer format
//
// value A string
// flags {signed: Boolean|[true,false], separator: String}
// flags.signed The leading plus-or-minus sign. Can be true, false, or [true, false].
// Default is [true, false], (i.e. sign is optional).
// flags.separator The character used as the thousands separator. Default is no separator.
// For more than one symbol use an array, e.g. [",", ""], makes ',' optional.
dojo.validate.isRealNumber
dojo.validate.isRealNumber (/*String*/value, /*Object?*/flags):
isNumber accepts a parameter, and determines if it is a number. Note that this also returns true is it is string number.
value:
value to test.
returns:
Boolean
// summary:
// Validates whether a string is a real valued number.
// Format is the usual exponential notation.
//
// value: A string
// flags: {places: Number, decimal: String, exponent: Boolean|[true,false], eSigned: Boolean|[true,false], ...}
// flags.places The integer number of decimal places.
// If not given, the decimal part is optional and the number of places is unlimited.
// flags.decimal The character used for the decimal point. Default is ".".
// flags.exponent Express in exponential notation. Can be true, false, or [true, false].
// Default is [true, false], (i.e. the exponential part is optional).
// flags.eSigned The leading plus-or-minus sign on the exponent. Can be true, false,
// or [true, false]. Default is [true, false], (i.e. sign is optional).
// flags in regexp.integer can be applied.
dojo.validate.isCurrency
dojo.validate.isCurrency (/*String*/value, /*Object?*/flags)
// summary:
// Validates whether a string denotes a monetary value.
// value: A string
// flags: {signed:Boolean|[true,false], symbol:String, placement:String, separator:String,
// fractional:Boolean|[true,false], decimal:String}
//
//
//
//
//
flags.signed The leading plus‐or‐minus sign. Can be true, false, or [true, false].
Default is [true, false], (i.e. sign is optional).
flags.symbol A currency symbol such as Yen "�", Pound "�", or the Euro sign "�".
Default is "$". For more than one symbol use an array, e.g. ["$", ""], makes $ optional.
flags.placement The symbol can come "before" the number or "after". Default is
"before".
//
//
flags.separator The character used as the thousands separator. The default is ",".
flags.fractional The appropriate number of decimal places for fractional currency (e.g.
cents)
//
//
Can be true, false, or [true, false]. Default is [true, false], (i.e. cents are optional).
flags.decimal The character used for the decimal point. Default is ".".
dojo.validate.isInRange
dojo.validate.isInRange (/*String*/value, /*Object?*/flags)
//summary:
// Validates whether 是否 a string denoting 表示 an integer,
// real number, or monetary 货币 value is between a max and min.
//
// value: A string
// flags: {max:Number, min:Number, decimal:String}
//
flags.max A number, which the value must be less than or equal <= to for the validation
to be true.
//
flags.min A number, which the value must be greater than or equal >= to for the
validation to be true.
//
flags.decimal The character used for the decimal point. Default is ".".
例如:dojo.validate.isInRange("‐1", {max:100, min:1, decimal: "."})
dojo.validate.isNumberFormat
dojo.validate.isNumberFormat = function(/*String*/value, /*Object?*/flags)
// summary:
// Validates any sort of number based format
//
// description:
// Use it for phone numbers, social security numbers, zip‐codes, etc.
// The value can be validated against one format or one of multiple formats.
//
// Format
//
//
#
?
Stands 容忍 for a digit, 0‐9.
Stands 容忍 for an optional digit, 0‐9 or nothing.
//
//
All other characters must appear literally in the expression.
// Example
//
//
//
//
//
"(###) ###‐####" ‐> (510) 542‐9742
"(###) ###‐#### x#???" ‐> (510) 542‐9742 x153
"###‐##‐####" ‐> 506‐82‐1089
"#####‐####" ‐> 98225‐1649
i.e. social security number
i.e. zip code
// value: A string
// flags: {format:String}
//
flags.format A string or an Array of strings for multiple formats.
dojo.validate.isValidLuhn
dojo.validate.isValidLuhn (/*String*/value)
//summary: Compares 比较 value against the Luhn algorithm 算法 to verify 验证 its integrity 完
整
模块:dojo.validate.check
dojo.validate.check
dojo.validate.check (/*HTMLFormElement*/form, /*Object*/profile)
// summary: validates user input of an HTML form based on input profile
//
// description:
// returns an object that contains several methods summarizing the results of the
validation
//
// form: form to be validated
// profile: specifies how the form fields are to be validated
// {trim:Array, uppercase:Array, lowercase:Array, ucfirst:Array, digit:Array,
// required:Array, dependencies:Object, constraints:Object, confirm:Object}
// Essentially private properties of results object
dojo.validate.evaluateConstraint
dojo.validate.evaluateConstraint (profile, /*Array*/constraint, fieldName, elem)
// summary:
// Evaluates dojo.validate.check() constraints that are specified as array
// arguments
//
// description: The arrays are expected to be in the format of:
//
//
//
constraints:{
fieldName: [functionToCall, param1, param2, etc.],
fieldName: [[functionToCallFirst,
param1],[functionToCallSecond,param2]]
//
//
}
// This function evaluates a single array function in the format of:
//
//
[functionName, argument1, argument2, etc]
// The function will be parsed out and evaluated against the incoming parameters.
//
// profile: The dojo.validate.check() profile that this evaluation is against.
// constraint: The single [] array of function and arguments for the function.
// fieldName: The form dom name of the field being validated.
// elem: The form element field.
模块: dojo.datemon
dojo.date.setDayOfYear
dojo.date.setDayOfYear(/*Date*/dateObject, /*Number*/dayOfYear)
summary: sets dateObject according to day of the year (1..366)
dojo.date.getDayOfYear
dojo.date.getDayOfYear (/*Date*/dateObject)
summary: gets the day of the year as represented by dateObject
dojo.date.setWeekOfYear
dojo.date.setWeekOfYear (/*Date*/dateObject, /*Number*/week, /*Number*/firstDay)
dojo.date.getWeekOfYear
dojo.date.getWeekOfYear(/*Date*/dateObject, /*Number*/firstDay)
dojo.date.setIsoWeekOfYear
dojo.date.setIsoWeekOfYear (/*Date*/dateObject, /*Number*/week, /*Number*/firstDay)
dojo.date.getIsoWeekOfYear
dojo.date.getIsoWeekOfYear (/*Date*/dateObject, /*Number*/firstDay)
模块:dojo.data
模块:dojo.validate.datetime
dojo.validate.isValidTime
dojo.validate.isValidTime(value, flags);
Validates a time value in any International format.
The value can be validated against one format or one of multiple formats.
Format
h
hh
H
HH
m
mm
s
ss
12 hour, no zero padding.
12 hour, has leading zero.
24 hour, no zero padding.
24 hour, has leading zero.
minutes, no zero padding.
minutes, has leading zero.
seconds, no zero padding.
seconds, has leading zero.
All other characters must appear literally in the expression.
Example
"h:m:s t" ‐> 2:5:33 PM
"HH:mm:ss" ‐> 14:05:33
@param value A string.
@param flags An object.
flags.format A string or an array of strings. Default is "h:mm:ss t".
flags.amSymbol The symbol used for AM. Default is "AM".
flags.pmSymbol The symbol used for PM. Default is "PM".
@return true or false
dojo.validate.is24HourTime
is24HourTime(value):
is24HourTime accepts a parameter, and determines if it is a valid 24 hour
time.
value:
value to test.
returns:
Boolean
Validates 24-hour military time format.
Zero-padding is required for hours, minutes, and seconds.
Seconds are optional.
@param value A string.
@return true or false
dojo.validate.is12HourTime
is12HourTime(value):
is12HourTime accepts a parameter, and determines if it is a valid 12 hour
time.
value:
value to test.
returns:
Boolean
Validates 12-hour time format.
Zero-padding is not allowed for hours, required for minutes and seconds.
Seconds are optional.
@param value A string.
@return true or false
dojo.validate.isValidDate
isValidDate(dateValue, format):
isValidate determines if a date is valid under the specified format, or a default format of MM/DD/YYYY if not is specified.
dateValue:
value to test.
format:
format to test
Accepts many format types, including ISO8601 and RFC3339. Al characters in the format string are treated literally except the
following tokens: YYYY - matches a 4 digit year M - matches a non zero-padded month MM - matches a zero-padded month D
- matches a non zero-padded date DD - matches a zero-padded date DDD - matches an ordinal date, 1-365, and 366 on
leapyear ww - matches week of year, 1-53 d - matches day of week, 1-7
Examples: These are all equivalent to October 19, 2005:
Date Format 2005-W42-3 YYYY-Www-d 2005-292 YYYY-DDD 20051019 YYYYMMDD 10/19/2005 M/D/YYYY 19.10.2005
D.M.YYYY
returns:
boolean
模块:dojo.validate.web
dojo.validate.isIpAddress
isIpAddress(value):
isIpAddress accepts a parameter, and determines if it is a valid IP address.
(IPv6 is not currently supported)
value:
value to test.
returns:
Boolean
dojo.validate.isUrl
isUrl(value):
isUrl accepts a parameter, and determines if it is a valid url, based on
either a domain name or IP address. (IPv6 is not currently supported)
value:
value to test.
returns:
boolean
dojo.validate.isEmailAddress
isEmailAddress(value, allowLocal, allowCruft):
isEmailAddress determines if value is an email address, with various levels of strictness in its validation.
value:
value to test.
allowLocal:
boolean. if true, values such as foo@localhost will return true. allowCruft:
boolean. if true, values such as mailto:foo@dojotoolkit and <mailto:foo@dojotoolkit> will return true.
returns:
boolean
dojo.validate.isEmailAddressList
isEmailAddressList(value, allowLocal, allowCruft):
isEmailAddress determines if a list of potential values are email addresses, with various levels of strictness in its validation.
value:
comma separated list of values to test.
allowLocal:
boolean. if true, values such as foo@localhost will return true.
allowCruft:
boolean. if true, values such as mailto:foo@dojotoolkit and <mailto:foo@dojotoolkit> will return true.
returns:
Boolean
dojo.validate.getEmailAddressList
summary: Check if value is an email address list. If an empty list
is returned, the value didn't pass the test or it was empty.
value: A string
flags: An object (same as dojo.validate.isEmailAddressList)
模块:dojo.validate.us
dojo.validate.us.isCurrency
isCurrency accepts a parameter, and determines if it is a valid US currency.
Supports optional plus/minus sign, optional dollar-sign, optional cents, optional commas.
value:
value to test.
returns:
boolean
dojo.validate.us.isPhoneNumber
dojo.validate.us.isPhoneNumber(“314-1234-234”);
isPhoneNumber accepts a parameter, and determines if it is a valid US
phone number. Support 4 common separators (none, space, -, and .). Need to add support for extensions.
value:
value to test.
returns:
boolean
dojo.validate.us.isSocialSecurityN
umber
isSocialSecurityNumber(value):
isSocialSecurityNumber accepts a parameter, and determines if it is a valid
US Social Security Number. Supports space, -, or no separator.
value:
value to test.
returns:
boolean
dojo.validate.us.isZipCode
isZipCode(value):
isZipCode accepts a parameter, and determines if it is a valid US zip code.
Supports space, -, or no separator between base and optional +4 portion of US zip code.
value:
value to test.
returns:
boolean
dojo.validate.us.isState
isState accepts a two character parameter, and determines if it is a valid
postal abbreviation for a US state or territory.
value:
value to test, 2 digit character representing a postal abbreviation.
returns:
boolean
模块:dojo.dom
dojo.dom.isNode
dojo.dom.isNode (/* object */wh)
summary:
//
checks to see if wh is actually a node.
测试指定对象是否为节点
Usage Example:
dojo.dom.isNode(dojo.byId('edtTitle'));
dojo.dom.getUniqueId
//summary:
//returns a unique string for use with any DOM element
取得唯一 id
Usage Example:
dojo.dom.getUniqueId(); //will return dj_unique_#
dojo.dom.firstElement
dojo.dom.getFirstChildElement
function(/* Element */parentNode, /* string? */tagName)
取得指定节点下的第一个满足指定 Tag 条件的子节点
Usage Example:
dojo.dom.firstElement(parentNode, 'SPAN');
dojo.dom.firstElement = dojo.dom.getFirstChildElement
dojo.dom.lastElement
dojo.dom.getLastChildElement
function(/* Element */parentNode, /* string? */tagName)
// summary:
//
returns the last child element matching tagName
取得指定节点下的最后一个满足指定 Tag 条件的子节点
Usage Example:
dojo.dom.lastElement(parentNode, 'SPAN');
dojo.dom.nextElement
dojo.dom.getNextSiblingElement
function(/* Node */node, /* string? */tagName)
returns the next sibling element matching tagName
dojo.dom.nextElement = dojo.dom.getNextSiblingElement
取得指定节点的下一个满足指定 Tag 条件的子节点
Usage Example:
dojo.dom.nextElement(node, 'SPAN');
dojo.dom.prevElement
dojo.dom.getPreviousSiblingElement
function(/* Node */node, /* string? */tagName)
returns the previous sibling element matching tagName
dojo.dom.prevElement = dojo.dom.getPreviousSiblingElement
取得指定节点的前一个满足指定 Tag 条件的子节点
dojo.dom.prevElement(node, 'SPAN');
dojo.dom.moveChildren
function(/*Element*/srcNode, /*Element*/destNode, /*boolean?*/trim)
summary:
//
//
Moves children from srcNode to destNode and returns the count of
children moved; will trim off text nodes if trim == true
把指定节点下的所有子节点移动到目标节点下,并返回移动的节点数
Usage Example:
dojo.dom.moveChildren(srcNode, destNode, true); //仅移动子节点,srcNode 中的文字将被丢弃
dojo.dom.moveChildren(srcNode, destNode, false);//包括文字和子节点都将被移动到目标节点下
dojo.dom.copyChildren
function(/*Element*/srcNode, /*Element*/destNode, /*boolean?*/trim)
summary:
//
//
Copies children from srcNde to destNode and returns the count of
children copied; will trim off text nodes if trim == true
把指定节点下的所有子节点复制到目标节点下,并返回复制的节点数
dojo.dom.copyChildren(srcNode, destNode, true); //仅复制子节点,srcNode 中的文字将被忽略
dojo.dom.copyChildren(srcNode, destNode, false);//包括文字和子节点都将被复制到目标节点下
dojo.dom.replaceChildren
function(/*Element*/node, /*Node*/newChild)
summary:
//
//
Removes all children of node and appends newChild. All the existing
children will be destroyed.
// FIXME: what if newChild is an array‐like object?
用指定的新节点替换父节点下的所有子节点
Usage Example:
dojo.dom.replaceChildren(node, newChild); //目前还不支持 newChild 为数组形式
dojo.dom.removeChildren
function(/*Element*/node)
removes all children from node and returns the count of children removed.
//
//
The children nodes are not destroyed. Be sure to call destroyNode on them
after they are not used anymore.
删除指定节点下的所有子节点,并返回删除的节点数
Usage Example:
dojo.dom.removeChildren(node);
dojo.dom.replaceNode
function(/*Element*/node, /*Element*/newNode)
// summary:
//
//
//
replaces node with newNode and returns a reference to the removed node.
To prevent IE memory leak, call destroyNode on the returned node when
it is no longer needed.
dojo.dom.destroyNode
function(/*Node*/node)
summary:
//
//
//
destroy a node (it can not be used any more). For IE, this is the
right function to call to prevent memory leaks. While for other
browsers, this is identical to dojo.dom.removeNode
用指定的新节点替换父节点下的所有子节点
Usage Example:
dojo.dom.replaceChildren(node, newChild); //目前还不支持 newChild 为数组形式
dojo.dom.removeNode
function(/*Node*/node)
summary:
//
//
//
//
if node has a parent, removes node from parent and returns a
reference to the removed child.
To prevent IE memory leak, call destroyNode on the returned node when
it is no longer needed.
// node:
//
the node to remove from its parent.
删除指定的节点
Usage Example:
dojo.dom.removeNode(node);
dojo.dom.getAncestors
function(/*Node*/node, /*function?*/filterFunction, /*boolean?*/returnFirstHit)
返回指定节点的父节点集合
Usage Example:
dojo.dom.getAncestors(node, null, false); //返回所有的父节点集合(包括指定的节点 node)
dojo.dom.getAncestors(node, null, true); //返回最近的一个父节点
dojo.dom.getAncestors(node, function(el){/* 此处增加过滤条件 */return true}, false); //返回所有满足条件的父节点集
合
dojo.dom.getAncestorsByTag
function(/*Node*/node, /*String*/tag, /*boolean?*/returnFirstHit)
返回所有符合指定 Tag 的指定节点的父节点集合
Usage Example:
dojo.dom.getAncestorsByTag(node, 'span', false); //返回所有的类型为 SPAN 的父节点集合
dojo.dom.getAncestorsByTag(node, 'span', true); //返回最近的一个类型为 SPAN 的父节点
dojo.dom.getFirstAncestorByTag
function(/*Node*/node, /*string*/tag)
返回最近的一个符合指定 Tag 的指定节点的父节点
Usage Example:
dojo.dom.getFirstAncestorByTag(node, 'span'); //返回最近的一个类型为 SPAN 的父节点
dojo.dom.isDescendantOf
function(/* Node */node, /* Node */ancestor, /* boolean? */guaranteeDescendant)
判断指定的节点是否为另一个节点的子孙
Usage Example:
dojo.dom.isDescendantOf(node, ancestor, true); //判断 node 是否为 ancestor 的子孙
dojo.dom.isDescendantOf(node, node, false); //will return true
dojo.dom.isDescendantOf(node, node, true); //will return false
dojo.dom.innerXML
function(/*Node*/node)
返回指定节点的 XML
Usage Example:
dojo.dom.innerXML(node);
dojo.dom.createDocument
function()
创建一个空的文档对象
Usage Example:
dojo.dom.createDocument();
dojo.dom.createDocumentFromText
function(/*string*/str, /*string?*/mimetype)
根据文字创建一个文档对象
Usage Example:
dojo.dom.createDocumentFromText('<?xml version="1.0" encoding="gb2312" ?><a>1</a>','text/xml');
dojo.dom.prependChild
function(/*Element*/node, /*Element*/parent)
将指定的节点插入到父节点的最前面
Usage Example:
dojo.dom.prependChild(node, parent);
dojo.dom.insertBefore
function(/*Node*/node, /*Node*/ref, /*boolean?*/force)
将指定的节点插入到参考节点的前面
Usage Example:
dojo.dom.insertBefore(node, ref, false); //如果满足要求的话就直接退出
dojo.dom.insertBefore(node, ref, true);
dojo.dom.insertAfter
function(/*Node*/node, /*Node*/ref, /*boolean?*/force)
将指定的节点插入到参考节点的后面
Usage Example:
dojo.dom.insertAfter(node, ref, false); //如果满足要求的话就直接退出
dojo.dom.insertAfter(node, ref, true);
dojo.dom.insertAtPosition
function(/*Node*/node, /*Node*/ref, /*string*/position)
将指定的节点插入到参考节点的指定位置
Usage Example:
dojo.dom.insertAtPosition(node, ref, "before");//参考节点之前
dojo.dom.insertAtPosition(node, ref, "after"); //参考节点之后
dojo.dom.insertAtPosition(node, ref, "first"); //参考节点的第一个子节点
dojo.dom.insertAtPosition(node, ref, "last"); //参考节点的最后一个子节点
dojo.dom.insertAtPosition(node, ref); //默认位置为"last"
dojo.dom.insertAtIndex
function(/*Node*/node, /*Element*/containingNode, /*number*/insertionIndex)
将指定的节点插入到参考节点的子节点中的指定索引的位置
Usage Example:
dojo.dom.insertAtIndex(node, containingNode, 3); //把 node 插入到 containingNode 的子节点中,使其成为第 3 个子
节点
dojo.dom.textContent
function(/*Node*/node, /*string*/text)
设置或获取指定节点的文本
Usage Example:
dojo.dom.textContent(node, 'text'); //设置 node 的文本为'text'
dojo.dom.textContent(node); //返回 node 的文本
dojo.dom.hasParent
function(/*Node*/node)
判断指定节点是否有父节点
Usage Example:
dojo.dom.hasParent(node);
dojo.dom.isTag
function(/* Node */node /* ... */)
判断节点是否具有指定的 tag
Usage Example:
var el = document.createElement("SPAN");
dojo.dom.isTag(el, "SPAN"); //will return "SPAN"
dojo.dom.isTag(el, "span"); //will return ""
dojo.dom.isTag(el, "INPUT", "SPAN", "IMG"); //will return "SPAN"
dojo.dom.setAttributeNS
function( /*Element*/elem, /*string*/namespaceURI,
/*string*/attrName, /*string*/attrValue)
summary:
//
implementation of DOM2 setAttributeNS that works cross browser.
模块:dojo.event.topic
dojo.event.topic
Topic 机制与 Advice 机制都能够实现事件的绑定,但是显然,Topic 更适合处理多重绑定。
发布主题,然后由用户订阅的机制就是一个典型的观察者模式
function()
dojo.event.topic.registerPublisher
function(/*String*/topic, /*Object*/obj, /*String*/funcName)
summary:
//
//
//
//
// topic:
//
// obj:
//
registers a function as a publisher on a topic. Subsequent
calls to the function will cause a publish event on the topic
with the arguments passed to the function passed to registered
listeners.
a unique, opaque string that names the topic
the scope to locate the function in
// funcName:
//
注册主题发布器
Usage Example:
the name of the function to register
dojo.event.topic.registerPublisher("myTopic", obj, "doOnClick2");
dojo.event.topic.subscribe
function(/*String*/topic, /*Object*/obj, /*String*/funcName)
summary:
//
//
//
// topic:
//
// obj:
//
susbscribes the function to the topic. Subsequent events
dispached to the topic will create a function call for the
obj.funcName() function.
a unique, opaque string that names the topic
the scope to locate the function in
// funcName:
//
the name of the function to being registered as a listener
订阅主题
Usage Example:
dojo.event.topic.subscribe("myTopic", "test"); //执行 obj.doOnClick2()以后会自动执行 test()
dojo.event.topic.unsubscribe
function(/*String*/topic, /*Object*/obj, /*String*/funcName)
summary:
//
// topic:
//
// obj:
//
unsubscribes the obj.funcName() from the topic
a unique, opaque string that names the topic
the scope to locate the function in
// funcName:
//
取消订阅主题
Usage Example:
the name of the function to being unregistered as a listener
dojo.event.topic.unsubscribe("myTopic", "test");
dojo.event.topic.destroy
function(/*String*/topic)
summary:
//
// topic:
//
destroys the topic and unregisters all listeners
a unique, opaque string that names the topic
删除主题,此主题所有的订阅都将失效
Usage Example:
dojo.event.topic.destroy("myTopic");
dojo.event.topic.publishApply
function(/*String*/topic, /*Array*/args)
summary:
//
//
//
// topic:
//
// args:
//
dispatches an event to the topic using the args array as the
source for the call arguments to each listener. This is similar
to JavaScript's built‐in Function.apply()
a unique, opaque string that names the topic
the arguments to be passed into listeners of the topic
dojo.event.topic.publish
function(/*String*/topic, /*Object*/message)
summary:
//
// topic:
//
manually "publish" to the passed topic
a unique, opaque string that names the topic
// message:
//
//
//
can be an array of parameters (similar to publishApply), or
will be treated as one of many arguments to be passed along in
a "flat" unrolling
模块:dojo.graphics.color
下面是 dojo 里定义的颜色名称
dojo.graphics.color.named.white //白色
dojo.graphics.color.named.black //黑色
dojo.graphics.color.named.red //红色
dojo.graphics.color.named.green //绿色
dojo.graphics.color.named.blue //蓝色
dojo.graphics.color.named.navy //海军蓝
dojo.graphics.color.named.gray //灰色
dojo.graphics.color.named.silver//银色
dojo.graphics.color.Color
颜色类
Usage Example:
var color = new dojo.graphics.color.Color(dojo.graphics.color.named.black); //定义一个黑色的颜色对象
var color = new dojo.graphics.color.Color(0,0,0); //定义一个黑色的颜色对象
var color = new dojo.graphics.color.Color(0,0,0,1.0); //定义一个黑色的颜色对象
var color = new dojo.graphics.color.Color([0,0,0,1.0]); //定义一个黑色的颜色对象
var color = new dojo.graphics.color.Color('rgb(0,0,0)'); //定义一个黑色的颜色对象
var color = new dojo.graphics.color.Color('#000000'); //定义一个黑色的颜色对象
dojo.graphics.color.Color.toRgb
Usage Example:
color.toRgb(); //返回一个[0,0,0]的数组
color.toRgb(true); //返回一个[0,0,0,1.0]的数组
dojo.graphics.color.Color.toRgba
Usage Example:
color.toRgba(); //返回一个[0,0,0,1.0]的数组
dojo.graphics.color.Color.toHex
dojo.graphics.color.Color.toString
Usage Example:
color.toHex(); //返回"#000000"
color.toString(); //返回"#000000"
dojo.graphics.color.Color.toCss
Usage Example:
color.toCss(); //返回"rgb(0,0,0)"
dojo.graphics.color.Color.blend
混合另一个颜色得到一个新颜色
Usage Example:
color.blend('#ffffff', 1); //返回[255,255,255]
color.blend('#ffffff', -1); //返回[0,0,0]
color.blend('#ffffff', 0); //按 1 比 1 混合黑色和白色,返回[127,127,127]
颜色参数可以为颜色的任意形式,比如数组,字符串等
or
dojo.graphics.color.blend([0,0,0], [255,255,255], 0); //will return [127,127,127]
dojo.graphics.color.blend("#000000", "#ffffff", 0); //will return "#7f7f7f"
若第一个参数为字符串,则返回值也会返回字符串
dojo.graphics.color.Color.blendHex
Usage Example:
dojo.graphics.color.blendHex("#000000", "#ffffff", 0); //will return "#7f7f7f"
dojo.graphics.color.extractRGB
将输入转换为 RGB 数组
dojo.graphics.color.hex2rgb
将输入的字符串转换为 RGB 数组
dojo.graphics.color.rgb2hex
将输入的 RGB 数组转换为字符串
dojo.graphics.color.Color.fromArra
y
Usage Example:
var color = dojo.graphics.color.Color.fromArray([0,0,0,1.0]);
模块:dojo.uri.Uri
dojo.uri.Uri
专门用来处理 URI(统一资源标识符)的类
Usage Example:
uri = (new dojo.uri.Uri("http://myserver/dojo/", "guide.html")).toString(); //uri will be "http://myserver/dojo/guide.html
"
uri = (new dojo.uri.Uri("http://myserver/dojo/", "../guide.html")).toString(); //uri will be "http://myserver/guide.html"
RFC 规定的 URI 语法:[scheme:][//authority][path][?query][#fragment]
authority 语法:[user-info@]host[:port]
比如我们定义一个 uri
var uri = new dojo.uri.Uri("http://user:password@myserver:80/dojo/", "guide.html?page=1#top");
则 uri 的属性如下:
authority: 服务器名 "user:password@myserver:80"
fragment: 片断名 "top"
host: 主机名 "myserver"
password: 密码 "password"
path: 路径 "/dojo/guide.html"
port: 端口 80
query: 参数 "page=1"
scheme: 模式 "http"
uri: 完整的地址 "http://user:password@myserver:80/dojo/guide.html?page=1"
user: 用户名 "user:" 似乎有点问题,多了一个冒号
模块:dojo.undo.browser
动态网页程序(dynamic web application)避免了频繁的刷新页面,不过通常也带来后退和前进按钮
会失去作用。更多的,有的时候,用户可能很难把网页加入收藏夹。
Dojo 提供了一个解决办法,让网页程序处理浏览器的后退和前进,并且提供给浏览器一个唯一的地址。这
个解决办法就是使用 dojo.undo.browser。
使用 dojo.undo.browser
在 dojo 0.2.2 版本中,并没有 dojo.undo.browser,这是在 0.3 以后的版本中才加入的。
首先,需要使用 dojo.undo.browser.setInitialStae(state)设定当浏览器第一次载入网页的状态。
理论
动态网页程序会调用 XMLHTTPRequest 和 DOM 来更新网页内容而避免了刷新,更新浏览历史,并且也
不会改变浏览器的地址栏。这就意味着当用户点击 了后退按钮,整个网页程序丢失了当前运行的状态(s
tate)。而且即使用户想把当前的网页内容加入收藏夹,也是不可能的,因为收藏夹不会记录网页程序运
行的状态,而只会简单的记录下网页程序的地址(URL)。
开发者可以使用 dojo.undo.browser 包得到用户点击后退和前进的事件(event),然后根据这些事件
来更新页面内容。 dojo.undo.browser 通过使用一个隐藏的表单(hidden IFRAME)或者一个唯一的
标签(fragment identifier)传递浏览的历史记录。(译者注:可以想像成一个 cookie 或者一个 sessi
on,但是这个 session 信息是存储在 hidden IFRAME 或者标签中) 例如:
http://some.domain/my/path/to/page.html#fragmentIdentifier
(译者注:#fragmentIdentifier 就是标签记录)
因为当改变标签的时候并不会使网页刷新,所以非常适合记录当前网页程序的状态。当然开发者可以自定
义一个更容易读懂的标签,并且使用户可以把它加入收藏夹。
dojo.undo.browser 允许开发者创建一个相对于运行状态的对象(state object),这个对象会得到回
叫(callback)当用户点击后退或者前进按钮。
开发
下面是使用 dojo.undo.browser 之前必须作的一些事情:
1:在 djConfig 中设置 preventBackButtonFix: false。这样保证了隐藏的表单(hidden IFRAME)
将会添加到页面当中,如果不加入这段,dojo.undo.browser 不会正常工作。
译者注:设置方法就是在 header 中加入如下代码:
<script language="JavaScript" type="text/javascript">
djConfig = { isDebug: true, preventBackButtonFix: false };
</script>
2: 加入 dojo.require("dojo.undo.browser");
设定网页程序的初始状态:
dojo.undo.browser.setInitialState(
state);
当用户每次点击前进或者后退,state 对象都会被调用。
然后我们需要给 state 对象创建几个方法(function)
• 得到后退提示:back(),backButtion()或者 handle(type),type 可
以是“back”或者是“forward”。
• 得到前进提示:forward(),forwardButton()或者 handle(type),ty
pe 如上。
下面是个简单的例子:
var state = {
back: function() { alert("Back was clicked!"); },
forward: function() { alert("Forward was clicked!"); }
};
注册一个 state 对象使用下面的方法:
dojo.undo.browser.addToHistory(sta
te);
如 果向改变浏览器的地址(URL),引用 state 对象的 changeUrl 属性。如果 changeUrl 是 true,doj
o.undo.browser 就将产生一个唯一的标签,如果 changeUrl 被定义为任何其他的值(不包括 undefin
ed,null,0 和空 string),那么这个值就会被使 用为标签。这样用户就可以把当前页加入收藏夹了。
提示
• 如果你要使用 changeUrl,即使你不设定自己的标签,也至少定义为 true。
• 如果你要在本机测试,不要使用 IE。因为当 IE 访问本地文件时不会创建历史列表 ifram_histor
y.html。请把网页上传到服务器上测试。
• Safari2.0.3+:只有后退按钮可以正常工作,并且只有当 changeUrl 没用使用的时候。
• Opera 8.5.3:不会正常运行。
这里有一个网上的例子:
http://archive.dojotoolkit/nightly/tests/undo/test_browser.html
模块:dojo.connect
模块:dojo.widget
dojox.widget.FisheyeList
dojo.widget.FisheyeList
<body>
<%--
dojoType="dojox.widget.FisheyeList" dojoType 设置
itemWidth/itemHeight:普通模式的宽和高
itemMaxWidth/itemMaxHeight:最大模式的宽和高
orientation:是否水平,默认为垂直方式
effectUnits:有效相关变化的单元数
itemPadding:调整每项的大小
attachEdge:icon 跟随的方向 分为 bottom,、center、top 三种
labelEdge:标签的显示位置:bottom,和 top
conservativeTrigger:进入图标才展现鱼眼效果
--%>
//主层
<div dojoType="dojox.widget.FisheyeList"
itemWidth="50"
itemHeight="50"
itemMaxWidth="200"
itemMaxHeight="200"
orientation="horizontal"
effectUnits="2"
itemPadding="10"
attachEdge="top"
labelEdge="bottom"
conservativeTrigger="false">
//下面为包含在主层中的子层
<%--
dojoType="dojox.widget.FisheyeListItem" 设置为子项
--%>
<div dojoType="dojox.widget.FisheyeListItem"
iconsrc="image1.jpg" label="维远泰克">
</div>
<div dojoType="dojox.widget.FisheyeListItem"
iconsrc="image2.jpg" label="网易">
</div>
<div dojoType="dojox.widget.FisheyeListItem"
iconsrc="image3.jpg" label="夏新博客">
</div>
</div>
</body>
dijit.layout.TabContainer
让页面更有条理:dijit.layout.TabContainer
当一个页面内容比较多,比较复杂的时候,可以用标签页,将功能类似的一些表格或者信息放在同一个标签页内,用户可以方
便的在不同的标签页之间切换,关闭某个标签页,或者删除某个标签页。
一个最简单的例子:
<html>
<head>
<title>Button Widget Dojo Tests</title>
<style type="text/css">
@import "../js/dojo/resources/dojo.css";
@import "../js/dijit/themes/tundra/tundra.css";
</style>
<script type="text/javascript"
djConfig="parseOnLoad: true, isDebug: true"
src="../js/dojo/dojo.js"></script>
<script type="text/javascript">
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout.TabContainer");
</script>
</head>
<body class="tundra">
<div id="mainTabContainer" dojoType="dijit.layout.TabContainer" style="width: 100%; height: 20em;" selectedChild="tab1">
<div id="tab1" dojoType="dijit.layout.ContentPane" title="Tab 1" closable="true">hi</div>
<div id="tab2" dojoType="dijit.layout.ContentPane" title="Tab 2">hi2</div>
</div>
</body>
</html>
如果不同的标签也是单独不通的文件,我们可以在 dijit.layout.ContentPane 组件上设置 href 属性,指定到一个外部文件。需要
注意的是,那个页面必须是 utf-8 的字符集,否则的话中文会出现乱码。例如:<div id="tab2" dojoType="dijit.layout.ContentPane"
href="tab2.html" refreshOnShow="true" title="Tab 2"></div>
如果要动态添加一个标签页的话可以尝试下面的例子:
<script>
function fff(){
var rrr=document.createElement("DIV");
var tmp = new dijit.layout.ContentPane({title:"tab3",closable:true},rrr);
tmp.setContent(" <iframe style='width:100%;height:100%;border:1px' border=1 src='http://www.baidu/'></iframe>");
dijit.byId("mainTabContainer").addChild(tmp);
dijit.byId("mainTabContainer").selectChild(tmp);
//dijit.byId("mainTabContainer").removeChild(dijit.byId("tab2"));
}
</script>
这个例子中使用了 iframe,主要原因:如果多个页面的话,很有可能有多个 form,form 之间如果有嵌套就会比较乱,所以分成
了独立的 iframe,当然完全可以在新建一个 ContentPane 的时候设置一下 href 属性,直接加载一个页面。
dijit.form.ValidationTextbox
功能强大的文本框:dijit.form.ValidationTextbox
这个文本输入框的功能比较强大,关键是它能够提供一些常用的验证和大小写转换。下面介绍一个例子和一些常用的属性:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>validationTextbox</title>
<style type="text/css">
@import "../js/dojo/resources/dojo.css";
@import "../js/dijit/themes/tundra/tundra.css";
.dijitInputFieldFocused{
border:solid 2px #FFDF00;
}
</style>
<script type="text/javascript"
djConfig="parseOnLoad: true, isDebug: true"
src="../js/dojo/dojo.js"></script>
<script>
dojo.require("dijit.form.ValidationTextbox");
dojo.require("dijit.form.NumberTextbox");
</script>
</head>
<body class="tundra">
<form name="form1">
<input type="text" id="vt" dojoType="dijit.form.ValidationTextbox"
promptMessage="请输入信息"
invalidMessage="输入的信息有误"
required="true"
trim="true"
propercase="true"
><br />
一些属性:<br />
required="true" //必须填写<br />
trim="true" //将前后的空格自动删除<br />
propercase="true" //单词首字母大写<br />
uppercase="true" //大写字母形式<br />
lowercase="true" //小写字母形式<br />
<hr />
验证文本组件可以支持正则表达式验证,比如:<br />
不包含空格验证:<input id="vt1" type="text" name="phone" value="someTestString"
dojoType="dijit.form.ValidationTextbox"
regExp="[\w]+"
required="true"
trim="true"
invalidMessage="输入中不允许包含空格"><br />
email 地址验证:<input id="vt2" type="text" name="phone" value="/amushen2005@hotmail"
dojoType="dijit.form.ValidationTextbox"
regExp="(\w+@\w+\.\w+)(\.{0,1}\w*)(\.{0,1}\w*)"
required="true"
trim="true"
invalidMessage="输入合法的 email 地址"><br />
只允许输入数字:
<input id="vt1" type="text" name="phone" value="/123.34"
dojoType="dijit.form.NumberTextbox"
required="true"
trim="true"
invalidMessage="只允许输入数字"><br />
</form>
</body>
</html>
ValidationTextbox 的一些常用方法:
setValue(); //不要使用.value 或者.innerHTML 来设置值,你可能设置不成功或者失去校验
getValue();
validate(); 手工校验
isEmpty(); 是否为空
isValid(); 是否符合校验规则
关于校验的正则表达式法比较灵活,功能也非常强大,可以到微软或者 sun 的官方网站查看一些权威的资料。或者直接上网上
搜索一些常用的正则表达式。
下面给出一些常用正则表达式:
1、 非负整数:”^d+$”
2、 正整数:”^[0-9]*[1-9][0-9]*$”
3、 非正整数:”^((-d+)|(0+))$”
4、 负整数:”^-[0-9]*[1-9][0-9]*$”
5、 整数:”^-?d+$”
6、 非负浮点数:”^d+(.d+)?$”
7、 正浮点数:”^((0-9)+.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*.[0-9]+)|([0-9]*[1-9][0-9]*))$”
8、 非正浮点数:”^((-d+.d+)?)|(0+(.0+)?))$”
9、 负浮点数:”^(-((正浮点数正则式)))$”
10、英文字符串:”^[A-Za-z]+$”
11、英文大写串:”^[A-Z]+$”
12、英文小写串:”^[a-z]+$”
13、英文字符数字串:”^[A-Za-z0-9]+$”
14、英数字加下划线串:”^w+$”
15、E-mail 地址:”^[w-]+(.[w-]+)*@[w-]+(.[w-]+)+$”
16、URL:”^[a-zA-Z]+://(w+(-w+)*)(.(w+(-w+)*))*(?s*)?$”
17、匹配中文字符的正则表达式: [\u4e00-\u9fa5]
18、匹配双字节字符(包括汉字在内):[^\x00-\xff]
19、匹配 HTML 标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/
20、匹配国内电话号码:\d{3}-\d{8}|\d{4}-\d{7}
21、匹配中国邮政编码:[1-9]\d{5}(?!\d)
22、匹配身份证:\d{15}|\d{18}
dijit.Dialog
带背景遮罩的对话框:dijit.Dialog
这个对话框通用性非常好。而且显示效果比较友好,能给使用者很好的体验。而且无论是正常方式,还是编程方式,实现起来
都比较简单。
对话框包括两种,一种是普通的对话框,一种是提示窗口的对话框,用起来都很方便。
下面是一个普通的对话框:
<html>
<head>
<title>Dialog</title>
<style type="text/css">
@import "../js/dojo/resources/dojo.css";
@import "../js/dijit/themes/tundra/tundra.css";
</style>
<script type="text/javascript"
djConfig="parseOnLoad: true, isDebug: true"
src="../js/dojo/dojo.js"></script>
<script type="text/javascript">
dojo.require("dijit.Dialog");
function showDia(){
dijit.byId("dialog1").show();
}
</script>
<style>
.dijitDialogUnderlay {
background: #666666;
opacity: 0.5;
}
</style>
</head>
<body class="tundra">
<button id="b1" οnclick="showDia()">显示 dojo 对话框</button> <br>
<div dojoType="dijit.Dialog" id="dialog1" closeNode="hider" title="填写表单">
<form οnsubmit="return false;">
<table>
<tr>
<td><label for="name">姓名: </label></td>
<td><input type="text" id="name"></td>
</tr>
<tr>
<td><label for="loc">性别: </label></td>
<td><input type="text" id="loc"></td>
</tr>
<tr>
<td><label for="desc">年龄: </label></td>
<td><input type="text" id="desc"></td>
</tr>
<tr>
<td><label for="fileloc">电子邮件: </label></td>
<td><input type="file" id="fileloc"></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="button" id="hider" value="填好了"></td>
</tr>
</table>
</form>
</div><br>
<br>
<select><option>看看对话框能不能挡住这个东西</option></select><br>
<br>
遮罩的颜色可以通过设置.dijitDialogUnderlay 来控制
</body>
</html>
通过编程方式的一个对话框:
<html>
<head>
<title>Dialog</title>
<style type="text/css">
@import "../js/dojo/resources/dojo.css";
@import "../js/dijit/themes/tundra/tundra.css";
</style>
<script type="text/javascript"
djConfig="parseOnLoad: true, isDebug: true"
src="../js/dojo/dojo.js"></script>
<script type="text/javascript">
dojo.require("dijit.Dialog");
function showDia(cont){
var pane=dojo.byId("Dpane");
if(!pane){
pane=document.createElement("DIV");
pane.setAttribute("id","Dpane");
pane.style.width = "300px";
document.body.appendChild(pane);
}
pane.innerHTML=cont;
var dia=new dijit.Dialog({title:"dojo 对话框"},pane);
dia.show();
}
var alert=showDia;
</script>
<style>
.dijitDialogUnderlay {
background: #666666;
opacity: 0.5;
}
</style>
</head>
<body class="tundra">
<button id="b1" οnclick="alert('测试编程方式')">显示 dojo 对话框</button> <br>
<br>
<select><option>看看对话框能不能挡住这个东西</option></select><br>
<br>
遮罩的颜色可以通过设置.dijitDialogUnderlay 来控制
</body>
</html>
提示对话框的例子:
<html>
<head>
<title>Dialog</title>
<style type="text/css">
@import "../js/dojo/resources/dojo.css";
@import "../js/dijit/themes/tundra/tundra.css";
</style>
<script type="text/javascript"
djConfig="parseOnLoad: true, isDebug: true"
src="../js/dojo/dojo.js"></script>
<script type="text/javascript">
dojo.require("dijit.Dialog");
dojo.require("dijit.form.Button");
</script>
</head>
<body class="tundra">
<div dojoType="dijit.form.DropDownButton">
<span>显示登录表单</span>
<div dojoType="dijit.TooltipDialog" id="tooltipDlg" title="登录信息" closeNode="hider2">
<form οnsubmit="return false;">
<table>
<tr>
<td><label for="user">用户名:</label></td>
<td><input type="text" id="user"></td>
</tr>
<tr>
<td><label for="pwd">密 码:</label></td>
<td><input type="password" id="pwd"></td>
</tr>
<tr>
<td colspan="2" align="center">
<button id="hider2">登 录</button>
</tr>
</table>
</form>
</div>
</div>
<br>
<select><option>看看对话框能不能挡住这个东西</option></select><br>
<br>
这个弹出式的对话框使用 DropDownButton 来实现比较方便,如果想要通过其他方式实现可能需要一些 dojo 的编程。<br>
其实也可以使用 dijit.MasterTooltip 来实现类似的功能。<br>
</body>
</html>
dijit.Menu
介绍一下使用 dojo 创建右键菜单,有的时候很有用的。右键菜单的核心类是 dijit.Menu,菜单类是 dijit.MenuItem;
如果想要添加二级菜单,需要使用 dijit.PopupMenuItem; 如果只是简单的右键菜单,还需要设置一下 dijit.Menu 属性,设置 contextMenuForWindow="true"
下面这个是最简单的一个例子:
<html>
<head>
<title>测试菜单</title>
<style type="text/css">
@import "../js/dojo/resources/dojo.css";
@import "../js/dijit/themes/tundra/tundra.css";
</style>
<script type="text/javascript"
djConfig="parseOnLoad: true, isDebug: false"
src="../js/dojo/dojo.js"></script>
<script type="text/javascript">
dojo.require("dijit.Menu");
</script>
</head>
<body class="tundra">
<div dojoType="dijit.Menu" id="submenu1" contextMenuForWindow="true" style="display: none;">
<div dojoType="dijit.MenuItem" onClick="alert('复制');">复制</div>
<div dojoType="dijit.MenuItem" onClick="alert('粘贴');">粘贴</div>
<div dojoType="dijit.MenuSeparator"></div>
<div dojoType="dijit.MenuItem" onClick="alert('添加新用户');">添加新用户</div>
<div dojoType="dijit.PopupMenuItem">
<span>搜索</span>
<div dojoType="dijit.Menu" id="submenu2">
<div dojoType="dijit.MenuItem" onClick="alert('正常搜索')">正常搜索 </div>
<div dojoType="dijit.MenuItem" onClick="alert('模糊搜索')">模糊搜索 </div>
</div>
</div>
</div>
点右键测试菜单
</body>
</html>
如果想为菜单添加图标,使用 iconClass="dijitEditorIconCut" 在 MenuItem 上面。
dijit.TitlePane
带有标题的容器:dijit.TitlePane
TitlePane 的用处十分广泛,它可以是一个页面看上去很整齐,而且,它独特的隐藏显示内容的功能,可以节省页面很多的空间。
如果和 dnd 连在一起使用,还可以实现拖动,也就是让用户自定义自己的页面布局。下面一个简单的例子:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>titlepane</title>
<style type="text/css">
@import "../js/dojo/resources/dojo.css";
@import "../js/dijit/themes/tundra/tundra.css";
</style>
<script type="text/javascript"
djConfig="parseOnLoad: true, isDebug: true"
src="../js/dojo/dojo.js"></script>
<script>
dojo.require("dijit.TitlePane");
</script>
</head>
<body class="tundra">
<div dojoType="dijit.TitlePane" title="<b>简单测试一下</b>" style="width: 300px;">
这是一个 TitlePan 的最简单例子
</div>
</body>
</html>
Dijit.TitlePane 也同样可以设置 href 属性,来链接到另外一个页面,都是通过 xhrGet 的方式从另一个页面返回数据的,所以要
注意汉字字符集问题。
可以调用方法:setTitle(str)来设置 Title 上面的汉字。
dijit.Tooltip
在大多数业务系统中,有很多表单的填写都很复杂,有些文本框的含义比较难理解。为了给使用者一个提示,html 默认有一个
title 属性,比如<div title=’haha’>test</div>,如果设置了这个属性,浏览器会在你鼠标停留在这个元素上的时候,给出你一个提
示。
后来微软为了解决<select>控件的一个 bug,又提供了 window.createPopup()方法,这个方法可以定制一个 popup 窗口。也可
以很好的显示提示信息。
现在 dojo 为我们提供了一个更美观,更实用,更方便的控件。Dijit.Tooltip 控件的外观可以方便的定制,而且使用起来非常方便。
当然它也有它的不足之处,比如,当一个页面有两个控件想共用一个 tooltip 的话,就会失效。下面给出一个最简单的例子:
<html>
<head>
<title>Dojo Tooltip Widget Test</title>
<script type="text/javascript" src="testBidi.js"></script>
<script type="text/javascript" src="../js/dojo/dojo.js"
djConfig="parseOnLoad: true, isDebug: true"></script>
<script type="text/javascript">
dojo.require("dijit.Tooltip");
dojo.require("dojo.parser"); // find widgets
</script>
<style type="text/css">
@import "../js/dojo/resources/dojo.css";
@import "../js/dijit/themes/tundra/tundra.css";
@import "css/dijitTests.css";
</style>
</head>
<body class="tundra">
<form>
<input type="input" name="id1" value="#1"><br>
<input type="input" name="id2" value="#2"><br>
</form>
<span dojoType="dijit.Tooltip" connectId="id1">tooltip for id1 这个怎么样</span>
<div title="haha">tesdfdfdfdfdft</div>
</body>
</html>
dijit/tooltip.js 还提供了另一个有用的工具 dijit.MasterTooltip 这个工具使用起来非常方便,只要 dojo.require(“dijit.Tooltip”)就可
以使用了,不需要用 html 标签定义,是编程来显示和隐藏的。主要就两个方法:第一:show;第二 hide。
例子:
<html>
<head>
<title>tooltip</title>
<style type="text/css">
@import "../js/dojo/resources/dojo.css";
@import "../js/dijit/themes/tundra/tundra.css";
</style>
<script type="text/javascript"
djConfig="parseOnLoad: true, isDebug: true"
src="../js/dojo/dojo.js"></script>
<script type="text/javascript">
dojo.require("dijit.Tooltip");
function showMessage(){
dijit.MasterTooltip.show("显示提示信息", dojo.byId("select1"));
}
function hideMessage(){
dijit.MasterTooltip.hide();
}
</script>
</head>
<body class="tundra"><br>
<select id="select1"><option>测试使用</option><option>2</option></select><br><br>
<br>
<button οnclick="showMessage()">show</button>
<button οnclick="hideMessage()">hide</button>
</body>
</html>
dijit.Tree
使用恐怖的 dijit.Tree
可以说 dojo0.9bate的 dijit.Tree 太灵活了,功能太强大了。所以使用的时候定制和编程就要很多了。Dijit.Tree数据源必须是Store,
常用的是 dojo.data.JsonItemStore ,不能够使用 inline 方式。
下面给出两个例子,一个例子是最基础的,一个例子是动态生成的:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>TREE</title>
<style type="text/css">
@import "../js/dojo/resources/dojo.css";
@import "../js/dijit/themes/tundra/tundra.css";
</style>
<script type="text/javascript"
djConfig="parseOnLoad: true, isDebug: true"
src="../js/dojo/dojo.js"></script>
<script>
dojo.require("dojo.data.JsonItemStore");
dojo.require("dijit.Tree");
dojo.addOnLoad(function(){
dojo.subscribe("tree", null, function(message){
console.log("sn:"+message.event);
console.log("sn:"+message.node.item.name);
});
});
</script>
</head>
<body class="tundra">
<div dojoType="dojo.data.JsonItemStore" jsId="continentStore"
url="../js/dijit/tests/countries.json"></div>
<div dojoType="dijit.Tree" id=tree store="continentStore" query="{type:'continent'}"
labelAttr="name" typeAttr="type"></div>
</body>
</html>
动态添加树节点:
function addNode(){
//add one treeNode
var _tree=dijit.byId("tree");
var tdata={label:"FR",tree:_tree,item:{name:"FR",type:"one"}};
var child=new dijit._TreeNode(tdata);
_tree.addChild(child,1);
child._updateLayout();
_tree.getChildren()[2]._updateLayout();
child.setChildren({});
child._setExpando();
// console.debug();
}
function addSecondNode(){
// add a treenode for FR
var _tree=dijit.byId("tree");
var fr=_tree.getChildren()[1];
var tdata=[{label:"Paris",item:{type:"city",name:"Paris"}}];
fr.setChildren(tdata);
fr.getChildren()[0].setChildren({});
fr.isFolder=true;
fr.isExpanded=false;
fr._updateLayout();
fr._setExpando();
}
function addThirdNode(){
var _tree=dijit.byId("tree");
var fr=_tree.getChildren()[1];
var tdata={label:"pp",tree:_tree,item:{name:"pp",type:"city"}};
var child=new dijit._TreeNode(tdata);
child.setChildren({});
fr.addChild(child);
child._updateLayout();
fr.getChildren()[0]._updateLayout();
}
如果要懒加载一个树,就需要继承 JsonItemStore,可以参考/dojox/data/demos/里面的例子。如果想从其他数据源得到树,可
以参考 dojox.data 里面的其他 store.总之,tree 的数据源必须是 Store。
最新版本的 dojo 取消了 jsonitemstore,使用了 IterFileReadStore。(子节点的定义不一样了,多了个下划线。)
所以如果想要动态创建一个树,必须修改一下程序。
例子如下:
<html>
<head>
<title>test tree , dynamic add treenode</title>
<style type="text/css">
@import "../js/dojo/resources/dojo.css";
@import "../js/dijit/themes/tundra/tundra.css";
</style>
<script type="text/javascript"
djConfig="parseOnLoad: true, isDebug: false"
src="/"";../js/dojo/dojo.js"></script>
<script type="text/javascript">
dojo.require("dijit.Tree");
dojo.require("dojo.data.ItemFileReadStore");
function init(){
var treeData={
items: [
{ name:'China', type:'one',
children:[{_reference:'beijing'}] },
{ name:'beijing', type:'city'},
{ name:'USA' , type:'one'},
{ name:'UK' , type:'one'}
],
identifier: 'name',
label: 'name'
};
var store1=new dojo.data.ItemFileReadStore({data:treeData});
var _tree=new dijit.Tree({
id:'tree',
store:store1,
query:{type:'one'},
labelAttr:"name",
typeAttr:"type"},dojo.byId("tree"));
console.log(store1._getItemsArray()[0].name);
}
dojo.addOnLoad(init);
function openNode(message){
var node=message.node;
if(message.event!="toggleOpen")return;
console.log('click');
}
dojo.subscribe("tree",null,"openNode");
</script>
</head>
<body class="tundra">
<div id="tree"></div>
</body>
</html>
版权声明:本文标题:DOJO API 中文参考手册 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/jishu/1726379523h948712.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论