MYJS
出自Manyou开发者指南
MYJS是标准JavaScript的扩展。在MYOP上,由于涉及到页面安全及用户隐私,因此标准JavaScript存在很多安全性问题。MYJS帮助开发者实现几乎全功能的特性,且同时又可以避免恶意JavaScript对网页安全和用户隐私造成的潜在破坏。
目录 |
实现方式
大多数允许第三方应用在同域下使用JavaScript的平台提供商,通常都限定这些JS必须在iframe中执行,以避免安全问题。MYOP通过MYJS的方式来解决此类问题。应用服务器产生的JavaScript脚本,都将被MYOP解析和过滤,其中的标识符(包括函数、变量、元素ID),都会被自动转换成包含应用ID的名字。例如如下的JavaScript代码:
| function foo(bar) { var obj = {property: bar}; return obj.property; } |
将被自动转换成:
| function a12345_foo(a12345_bar) { var a12345_obj = {property: a12345_bar}; return a12345_obj.property; } |
这使得每一个应用的JavaScript都如同运行在一个“虚拟空间”一样,互不影响。在这种虚拟空间中,应用自身的元素会被重新命名,进而完全实现被JavaScript所控制。对于已经熟悉直接使用JavaScript的开发者而言,可能需要稍加熟悉MYJS的原理和结构,以便更好的在应用中实现各种效果。
基本原理
MYJS与您所了解的标准JavaScript语法是基本相同的。除了在改变DOM对象方面存在细微不同以外,其余方面都像JavaScript一样,您可以以任何您熟悉的方式来使用MYJS,包括但不限于创建对象,使用匿名函数,设置超时机制等等。
以如下MYML代码举例:
| <a href="#" onclick="hello_world(this); return false;">Hello World!</a> <script> <!-- function random_int(lo, hi) { return Math.floor((Math.random() * (hi - lo)) + lo); } function hello_world(obj) { var r = random_int(0, 255), b = random_int(0, 255), g = random_int(0, 255); var color = r+', '+g+', '+b; obj.setStyle('color', 'rgb('+color+')'); } //--> </script> |
从上述范例中可以看到,创建MYJS与JavaScript是十分相似的。
然而,如下的范例就有轻微的不同了,它不会返回和JavaScript一致的结果:
| <a href="#" id="hello">Hello World!</a> <script> <!-- function random_int(lo, hi) { return Math.floor((Math.random() * (hi - lo)) + lo); } function hello_world(obj) { var r = random_int(0, 255), b = random_int(0, 255), g = random_int(0, 255); var color = r+', '+g+', '+b; obj.setStyle('color', 'rgb('+color+')'); } hello_world(document.getElementById('hello')); //--> </script> |
MYJS DOM 对象
您可以使用 document.getElementById 或 document.createElement 来获取一个 MYJS DOM 对象。另外,DOM 事件中的 "this" 关键字指向事件本身。
对象操作
MYJS DOM 对象的方法,大部分都和 JavaScript 对象方法一样,包括:appendChild、insertBefore、 removeChild 和 cloneNode。但是例如 parentNode、 nextSibling、 src、 href 这样的属性,被重新定义为包括“获取器(get)” 和 “设置器(set)”的成对形式。
例如,obj.parentNode 可以使用 obj.getParentNode() 来替代,等等。大部分的属性名您都可以直接根据这样的规律得出。但是,我们仍然给出一个 JavaScript 和 MYJS 的对应列表:
| JavaScript | MYJS 获取器(get) | MYJS 设置器(set) | 描述 |
|---|---|---|---|
| parentNode | getParentNode | ||
| nextSibling | getNextSibling | ||
| previousSibling | getPreviousSibling | ||
| firstChild | getFirstChild | ||
| lastChild | getLastChild | ||
| childNodes | getChildNodes | 返回一个 childNodes 的克隆数组 | |
| innerHTML | n/a | setInnerMYML | 仅可以用在 AJAX 请求中,用来将 AJAX 返回的 MYML 代码设置到某个元素中(例如div)。AJAX 请求的返回数据格式必须指定为 'Ajax.MYML' |
| innerHTML | n/a | setInnerXHTML | 允许您将 XHTML 内容传递给 innerHTML 元素。但 XHTML 将会根据 MYML 的规则被做相应处理。 |
| innerText/textContent | n/a | setTextValue | 仅允许使用纯文本(不允许使用任何的 HTML 标签),并且会自动删除所有的子节点。 |
| form | getForm | 请使用 document.getElementById('formid') 来替代 | |
| action | getAction | setAction | |
| value | getValue | setValue | 获取或设置文本框(包括 text类型的input、textarea)的值 |
| href | getHref | setHref | |
| target | getTarget | setTarget | |
| src | getSrc | setSrc | |
| className | getClassName | setClassName | |
| tagName | getTagName | ||
| id | getId | setId | |
| dir | getDir | setDir | |
| checked | getChecked | setChecked | 使用 setChecked(true)。 |
| clientWidth | getClientWidth | ||
| clientHeight | getClientHeight | ||
| offsetWidth | getOffsetWidth | ||
| offsetHeight | getOffsetHeight | ||
| n\a | getAbsoluteTop | 返回相对与页面顶部的元素的绝对位置。 | |
| n\a | getAbsoluteLeft | 返回相对与页面最左边的元素的绝对位置。 | |
| scrollTop | getScrollTop | setScrollTop | |
| scrollLeft | getScrollLeft | setScrollLeft | |
| scrollHeight | getScrollHeight | ||
| scrollWidth | getScrollWidth | ||
| tabIndex | getTabIndex | setTabIndex | |
| title | getTitle | setTitle | |
| name | getName | setName | |
| cols | getCols | setCols | |
| rows | getRows | setRows | |
| accessKey | getAccessKey | setAccessKey | |
| disabled | getDisabled | setDisabled | |
| readOnly | getReadOnly | setReadOnly | |
| type | getType | setType | |
| selectedIndex | getSelectedIndex | setSelectedIndex | |
| selected | getSelected | setSelected | |
| location | n/a | setLocation | |
| style | getStyle | setStyle | |
| n/a | getRootElement | 使用方法:document.getRootElement,返回值为画布页面最高一层的元素。 |
样式操作
请使用 setStyle 方法来设定样式,用 getStyle 方法来获取样式。 setStyle 可以一次设定多条样式,语法如下:
| obj.setStyle({color: 'black', background: 'white'}); |
也可以一次只设定一条样式:
| obj.setStyle('color', 'black'); |
但是注意,您需要转换一下样式的名字(将样式名中的下划线去掉,并将下划线后的第一个字母转换为大写),像这样:
| obj.setStyle('textDecoration', 'underline') |
这样的样式名字是错误的:
| obj.setStyle('text-decoration', 'underline') |
当指定高宽位置等等时,别忘了加上单位 'px'
正确的:
| obj.setStyle('width', '340px') |
错误的:
| obj.setStyle('width', '340') |
请记住,这些将是非常重要的,尤其是当您在计算相关的值的时候。您不能像这样仅仅使用计算出来的数字:setStyle('left', x), 而应该这样: setStyle('left', x+'px')。
在 MYJS DOM 中允许您操作 CSS 样式,相关方法如下:
- addClassName(className)
-
className没有设定样式名时,为className添加一个样式名。 - removeClassName(className)
-
className设定了样式名时,此方法将删除这个名字。 - toggleClassName(className)
- 样式名存在时删除该样式名,不存在时创建该样式名。
- hasClassName(className)
- 如果样式名已存在,返回 true,否则返回 false。
设置内容
由于安全原因,我们不允许您使用 innerHTML。但是我们提供三种替代方案:
- obj.setTextValue(newText) 可以用来设置纯文本内容,但不允许使用 HTML 和 MYML 标签。
- obj.setInnerMYML(myMymlString) 可以用来将 HTML 或 MYML 内容放入 DOM 对象中。
- obj.setInnerXHTML(string) 允许您直接将 XHTML 内容放入页面中,但是我们会使用 JavaScript 对其做一些处理。
使用文本框
文本框的相关方法为 getSelection 和 setSelection。 getSelection 方法返回一下带有 start 和 end 属性的对象,它们是符合 W3C 标准的 selectionStart 和 selectionEnd。setSelection 带有两个参数,分别为 start 和 end(可选),因为 Internet Explorer 浏览器不支持 selectionStart 和 selectionEnd,所以我们加入了这个概念(在 IE 浏览器中,get 和 set 方法被整合成了一个)。 本方法在所有的浏览器中都是一样的,这样可以帮助开发者少做一些工作。
创建 MYML 元素
您可以使用 createElement 创建一个 MYML 元素,但请注意,目前我们只允许您使用此方法创建 my:swf 这个 MYML 元素。元素一旦被创建,它就会像其他元素一样开始工作。但是,当它被附加到 DOM 对象后,您将不能移动它,同时,obj.getElementsByTagName() 方法也将不能工作。说明:本方法同样可以用来创建普通的 HTML 元素。
| var newName = document.createElement('my:swf'); var newName = document.createElement('div'); |
事件
您可以遵循 W3C 规范 addEventListener 方法 给 MYJS DOM 中加入事件。 但是目前还不支持 useCapture(第三个参数) 和 removeEventListener。 除了 W3C 规定的方法外,我们还添加了 listEventListeners 和 purgeEventListeners 两个方法。
- listEventListeners(eventName)
- 以数组形式返回一个已添加的所有事件的列表。其中,用 on<event> 给 MYML 中添加的事件也会被返回。
- purgeEventListeners(eventName)
- 删除一个指定的事件。同时,此方法也会删除以属性形式添加给 MYML 的事件。
您需要以事件的对象作为参数来调用方法,当事件被作为属性附加时,通过 event 变量,您就可以存取此对象(和 JavaScript 相同)。事件有如下属性:target、 type、 pageX、 pageY、 ctrlKey、 keyCode、 metaKey 和 shiftKey。它有两个方法:
- stopPropagation
- 不再派发事件。该方法将停止事件的传播,阻止它被分派到其他 Document 节点。
- preventDefault
- 使用 preventDefault 方法可防止浏览器的默认事件操作发生。例如,如果防止 input 元素的 keydown 事件发生,则用户键入的字符不会自动追加到 input 元素的值中。
- getId 方法:
当您在一个事件对象上使用 getId() 方法时,要重获对象 ID 并激活事件,您可以这样做:
| <div id="firedByDescription"></div> <div id="foo"></div> <div id="bar"></div> <script> //注意:本例仅用于展示此方法的功能,并不用于实际用途。 function myEventHandler(evt) { // 我们将把内容放在这个 DIV 中 firedByDescription = document.getElementById('firedByDescription'); if (evt.type == 'mouseout') { //如果鼠标指针移出,清空 DIV 中的内容,并取消事件的监听 firedByDescription.setTextValue(''); return true; } //开始主要流程 eventFiredBy_ObjectId = evt.target.getId(); //如果得到 ID 的话,将它传递给 firedByDescription DIV。 firedByDescription.setTextValue(eventFiredBy_ObjectId); // 判断 if (eventFiredBy_ObjectId == 'foo') { //如果事件被 'foo' 激活,那么 ... } else { //如果事件被 'bar' 激活,那么 ... } } // 为 'foo' div 添加事件(mouseover 和 mouseout) document.getElementById('foo').addEventListener('mouseover',myEventHandler); document.getElementById('foo').addEventListener('mouseout',myEventHandler); // 为 'bar' div 添加同样的事件 (mouseover 和 mouseout) document.getElementById('bar').addEventListener('mouseover',myEventHandler); document.getElementById('bar').addEventListener('mouseout',myEventHandler); </script> |
在您要将同一事件附加到相同类型的多个对象上时,此方法非常有用。举一个购物车的例子:当用户将鼠标移动到购物车中的某件商品上的时候,根据该商品的 ID ,您可以在另一个 DIV 中显示出该商品的相关信息,这样可以极大的增强用户体验。所以,正如您所看到的,在您需要显示一些额外信息的时候,事件是非常有用的。
AJAX
MYJS 为开发者提供了一个非常强大的 AJAX 对象。Manyou 代理了所有的 AJAX 请求,并且对返回的数据做后期处理,例如解析成 JSON 或 MYML。想使用它的话,您仅仅需要实例化一个 AJAX 对象就可以。它支持以下特性:
- ondone(data)
- 当 AJAX 请求成功返回时,此事件将会被激活。
- onerror
- 当 AJAX 调用发生错误时,此事件将会被激活。
- responseType
- 可以为 Ajax.RAW、Ajax.JSON 或 Ajax.MYML。
- useLocalProxy
- 如果这个值为 true 表示您正在使用 RAW 或 JSON。
- Ajax.RAW
- 服务器返回的数据以原始形式发送到您的 callback url。
- Ajax.JSON
- 服务器返回的数据先被 Manyou 转换为 JSON 对象,然后再返回到您的 callback url。JSON 每个字段的名称将被加上前缀 "myml_",然后返回 MYML 代码。您可以通过使用 setInnerMYML 方法来将这些 MYML 设置到您指定的 DOM 对象上。每个变量名和变量值的长度都不得超过 5000 个字符。注意: 请确保您使用的是 JSON 格式,否则您可能会得到一些奇怪的返回结果。JSON 在 PHP5 中默认就被安装了,如果您使用的不是 PHP 语言,您也可以在 json.org 上找到您使用的语言的 JSON 实现。
- Ajax.MYML
- 服务器返回的结果将被转换为 MYML 返回, 您可以使用 setInnerMYML 方法将返回的 MYML 设置在指定的 DOM 对象中。
两个方法:
- post(url, query)
- 发起一个 AJAX POST 请求。
url必须为一个远程 URL,query可以为一个字符串也可以为一个对象,但如果是对象,它将会被自动转换为字符串。 - abort()
- 终止一个 AJAX POST 请求。
对话框
您可以使用我们为您准备的对话框对象与我们的基本对话框结构挂接,使用它,您可以为您的应用程序创建出丰富多样的对话框。
- Dialog(type)
- (构造函数) 它的类型可以为 Dialog.DIALOG_POP 或 Dialog.DIALOG_CONTEXTUAL。
- Dialog.DIALOG_POP
- 一种对话框类型。
- Dialog.DIALOG_CONTEXTUAL
- 一种对话框类型。
- onconfirm
- 当用户点击“确定”按钮时激活此事件,当此事件不返回 flase 时,对话框将被隐藏。
- oncancel
- 当用户点击“取消”按钮时激活此事件,当此事件不返回 flase 时,对话框将被隐藏。
- setStyle
- 指定对话框父节点的样式。
- showMessage(title, content, '确定')
- 显示带有一个确定按钮的对话框,
title和content只可以为普通字符串。 - showChoice(title, content, '确定', '取消')
- 显示一个带有确定按钮和取消按钮的对话框,
title和content只可以为普通字符串。 - setContext
- (仅适用于 DIALOG_CONTEXTUAL 类型的对话框)。设置一个对象,对话框将显示在这个对象下面。
- hide
- 设置是否隐藏对话框。
动画
Manyou 为开发者提供了一个非常强大的动画效果实现库,详情请查看 用MYJS实现动画效果 一节。
