•  
开发中心

FBJS

出自YiqiWiki

跳转到: 导航, 搜索

FBJS是开发者在自己的fb应用中使用的js的方案。FBJS是为了让开发者使用他们需要的js功能并且保护我们平台中的用户的隐私。

目录

  • 1 FBJS是怎样工作的
  • 2 基础知识
  • 3 FBJS DOM 对象
    • 3.1 Retrieving 对象
    • 3.2 Manipulating 对象
    • 3.3 操作样式
    • 3.4 设置内容
    • 3.5 文本框的使用
  • 4 Events(事件)
  • 5 AJAX
  • 6 对话框
  • 7 FBML Blocks
  • 8 动画
  • 9 示例
  • 10 技巧

FBJS是怎样工作的

大多数允许嵌入js代码的提供商要求开发者使用iframe的方式来保护他们的代码。 Facebook采用了不同的解决方案。 开发者提供的js会被分析,并且所有标识符(函数和变量名)会加上一个应用id的前缀。 例如,下面的代码片断:

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;
}

这样就为每个f8应用创建了一个虚拟生命周期。我们还提供了一系列js对象,用来修改你的f8应用的内容。这些对象尽可能地模仿原来js中对应对象的功能,但是对于那些已经熟悉了js的人也需要花点时间才能掌握。

基础知识

FBJS跟你已经熟悉的js语法完全一样.你可以创建对象,使用匿名函数, 创建timeout 等其他你想做的事情. 但是,修改dom树的方法稍微有点不同。

例如:下面的FBML代码:

<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>

正如你看到的,创建FBJS代码与标准的js非常相似。 但是,这段代码并不像你期望的那样工作:

<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>

在profile页中, 内联script会被用户第一次操作触发。操作包括 onfocus, onclick, onmousedown等等。 基本上所有用户的点击都是操作。但是canvas页中,上述代码也可以正常工作。

请注意,在script标签中要像上面例子那样使用html注释语法, 否则 ‘<’会被删除,从而编写正确代码变得困难。将来,我们计划修改我们的FBML解析器,以支持不需要上述注释方式的js代码,但是现在还不可以。

FBJS DOM 对象

Retrieving 对象

一个FBJS DOM对象可以通过 document.getElementById或者 document.createElement来调用。除此之外,DOM中的this指针也可以。

Manipulating 对象

FBJS DOM 对象实现了许多跟常用的js对象一样的接口方法,包括: appendChild, insertBefore, removeChild, and cloneNode。许多parentNode, nextSibling, src, href 等等这样的属性已经被重新定义为一对get和set方法.

例如应该象这样调用 obj.getParentNode(),而不是原来的obj.parentNode。 下面是js的属性转化成 FBJS的详细列表:

JavaScript FBJS getter FBJS setter Description
parentNode getParentNode
nextSibling getNextSibling
previousSibling getPreviousSibling
firstChild getFirstChild
lastChild getLastChild
childNodes getChildNodes 返回子节点数组。
innerHTML n/a setInnerFBML 注意:如果你直接传入一个字符串,会抛出异常。应该使用 [Fb:js-string] 来创建一个字符串,然后再传入。
innerHTML n/a setInnerXHTML Beta feature. 允许你传入一个XHTML字符串来设置一个元素的innerHTML。这个XHTML按照FBML的规则清洗了一次,然后放进document中。
innerText/textContent n/a setTextValue 不完全象 setInnerFBML 的话,只允许为TEXT (而不是 HTML)! 被调用的节点的所有的子结点将被删除。
form getForm 不工作, 用 document.getElementById('formid') 代替
action getAction setAction
value getValue setValue
href getHref setHref
target getTarget setTarget
src getSrc setSrc
className getClassName setClassName
tagName getTagName
id getId setId
dir getDir setDir
checked getChecked setChecked
clientWidth getClientWidth
clientHeight getClientHeight
offsetWidth getOffsetWidth
offsetHeight getOffsetHeight
n\a getAbsoluteTop 返回相对于页顶的相对位置。 因为缺乏 offsetParent 支持而变得非常有用.
n\a getAbsoluteLeft 与getAbsoluteTop一样,但是是横向的。
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 这样使用- 返回你的profile 页或者canvas 页的顶层元素。

操作样式

Styles are set with the setStyle method and queried with the getStyle method. 调用setStyle方法来设置styles,调用getStyle来请求styles。setStyle 能够按照下面的语法设置多个style:

obj.setStyle({color: 'black', background: 'white'});

或者同时使用一个style:

obj.setStyle('color', 'black');

注意,你需要style名称来设置属性时, 象下面这样:

obj.setStyle('textDecoration', 'underline')

但是,下面这样就不会起作用:

obj.setStyle('text-decoration', 'underline')

当你指定位置或者高度/宽度等等时,必须记住使用‘px’符号。

下面能正常工作:

obj.setStyle('width', '340px')

但是下面的不能:

obj.setStyle('width', '340')

当你用算法来计算他们的值时,这是非常重要的。你不能象下面这样计算x的值:

setStyle('left', x)

但是这样可以:

|setStyle('left', x+'px')

除此之外,操作css的方法也加在了FBJS DOM节点类的方法中。

addClassName(className) 
增加一个类名到classname字符串,如果这个字符串不是已经存在的。
removeClassName(className) 
从className字符串中删除一个类名,如果这个字符串不是已经存在的。
toggleClassName(className) 
如果这个类名存在,则删除,否则,就增加.
hasClassName(className) 
如果类名存在返回true,否则为false。

设置内容

innerHTML 没有实现是出于安全的考虑。 有两种替代方法。

  1. obj.setTextValue(newText) 用于设置你的DOM对象里的一个text的值(不支持html或者fbml)。
  2. obj.setInnerFBML(fbJsStringVar) 用于把html或者fbml放进你的DOM对象中。你需要首先创建一个Fb:js-string对象然后传入,如果你直接传送字符串,会出错。

文本框的使用

文本框选项用getSelection 和 setSelection实现。 getSelection 返回一个对象,该对象包含start 和 end 属性,对应W3C风格的属性selectionstart和selectionend。 setSelection 有两个参数, start 和 end(可选)。 增加这两个抽象是因为ie浏览器不支持selectionStart 和 selectionEnd。因为在ie中同时查询俩个值是非常快的, 所以在getter和setter中俩个属性同时出现。 这个函数在所有的浏览器中运行方式都一样,对于你来说没有任何额外的工作。


Events(事件)

“事件”可以添加到采用W3C-style(样式) addEventListener method的FBJS DOM 对象中去,仍支持removeEventListener,但不支持第三个参数—useCapture。除了W3C“事件”方法(W3C event method)之外,我们还增加了listEventListeners和purgeEventListeners2种方法:

listEventListeners(eventName) 
对任何事件,均可返回一组该事件的处理结果。其中也包括采用on<event>属性的FBML中添加的事件。
purgeEventListeners(eventName) 
可一个特定事件移除所有listeners,还可以移除那些作为属性添加到FBML里的事件。

人们通常把Event handlers(事件处理器)与一个参数联系在一起,该参数是个带有事件信息的对象。如果事件处理器被作为属性添加,该对象则可通过“事件”变量(如同它在常规JavaScript中一样)来获得。 事件将拥有下列属性:target, type, pageX, pageY, ctrlKey, keyCode, metaKey, 和 shiftKey。并且还可以使用下面2种方法:

stopPropagation
防止该事件扩散到DOM中任何更多的元素里面。
preventDefault
取消该事件的缺省动作而无需停止扩散。例如,在onfocus 事件中用preventDefault 就可以阻止(事件的)该元素获得焦点。
getId on event object of a listener function

当在事件对象的Listener函数中使用getID方法时,下列语法将被用来获取(激活该事件的)对象的ID:

<div id="firedByDescription"></div>
<div id="foo"></div>
<div id="bar"></div>

<script>
//disclaimer: sample code block meant only to demonstrate functionality

function myEventHandler(evt) {
  //we'll use this div later to drop stuff into it
  firedByDescription = document.getElementById('firedByDescription');
  if (evt.type == 'mouseout') { 
    //if the event is a mouseout, empty out the description div, and exit the event listener
    firedByDescription.setTextValue('');
    return true;
  }

  //otherwise... do some processing:

  //*VERY IMPORTANT*: note that the object, which fired the event is located two nodes up in the DOM tree
  //See note below
  //eventFiredBy_ObjectId = evt.target.getParentNode().getParentNode().getId();

  //On newer versions, it seems that there is no need to go up two levels int he DOM tree, hence
  eventFiredBy_ObjectId = evt.target.getId();
  //works, whereas the first does not!

  //**NOTE** My testing of this suggests that when you call addEventListener() it adds it to the element, AND all it's descendants
  // This can then cause the event to be fired multiple times, as it is fired for the element and it's descendant elements.
  // When fired by a descendant element, you will probably have to do some kind of getParent()-ing
  // I'm raising this as a bug, as it does make things a little unworkable!

  //once you have the ID, you may, for example, drop its id into the firedByDescription div:
  firedByDescription.setTextValue(eventFiredBy_ObjectId);

  //... or do some conditional processing:
  if (eventFiredBy_ObjectId == 'foo') {
    //do something if the event was fired by 'foo'
  } else {
    //do something if the event was fired by 'bar'
  }
}

//add event listener to 'foo' div (mouseover & mouseout)
document.getElementById('foo').addEventListener('mouseover',myEventHandler);
document.getElementById('foo').addEventListener('mouseout',myEventHandler);

//add *the same* event listener to 'bar' div (mouseover & mouseout)
document.getElementById('bar').addEventListener('mouseover',myEventHandler);
document.getElementById('bar').addEventListener('mouseout',myEventHandler);
</script>

当你拥有一个同类型多对象的事件处理器时,该功能将非常有用。比如购物车,或任意类型的对象浏览器。当一个用户移动鼠标至购物车中的某件商品时,你会习惯性地通过它的ID展示该商品的相关信息,你也许还会为该商品添加一个描述文本,并把它展示给其他用户。正如你所看到的,基于在Facebook应用中移动鼠标的位置,采用事件listeners将是非常有效的方式来向用户展示更多有用信息。祝你们编码愉快,创作愉快!

AJAX

FBJS 为开发者支持一个非常强大的AJAX对象。Facebook代理所有的AJAX请求,并选择运行有用的返回数据后处理程序,比如 JSON或FBML句法。为了便于使用,我们举个新AJAX类别的例子。它支持下列属性:

ondone(data)
AJAX请求返回时激活的一个事件处理器,依赖于.responseType ,数据会是一个对象,一个原始字符串,或一个FBML串。
onerror 
当一个AJAX请求发生错误时激活的一个事件处理器。
requireLogin 
如果你认为AJAX请求确实会在通过之前,要求移植用户到你的应用中去的话,那么该AJAX请求将会被赋予常规的fb_sig 参数,用来包含用户身份。如果用户不愿登录,该AJAX请求将失败。
responseType 
这可以是一个Ajax.RAW, Ajax.JSON,或 Ajax.FBML.
useLocalProxy 
Beta版。如果你确实正在使用RAW或JSON type, Ajax对象将趋于使用[fb:local-proxy] 来向你的APP服务器发出一个直接请求。看[FBJS_LocalProxy] 获取更多细节。
Ajax.RAW 
来自服务器的请求源码被返回到你的回应系统。
Ajax.JSON 
来自服务器的请求被解析成一个JSON对象,并被以对象形式返回到回应系统。字头带有“FBML”的JSON对象的属性被解析成独立的FBML串,并被作为FBML blocks返回。这些blocks可通过setInnerFBML方法,被用于DOM对象。请求中的每个变量和变量值都限于总共5000个字符长度。 Note: 确认使用json_encode,否则你会看到带大量数据集的奇怪结果。看Bugzilla #363 可获得更多信息。大多数PHP5设备都可获得缺省的json_encode,其他语言的可执行版本可在json.org获得。
Ajax.FBML 
来自服务器的请求被解析成FBML,并被作为FBML blocks返回。这些blocks可通过setInnerFBML方法,被用于DOM对象。

另2个方法:

post(url, query) 
启动一个AJAX post。url 必须是个远程地址,query 可以是一个字符串或者一个自动转换成字符串的对象。
abort(放弃) 
放弃一个AJAX post。


这儿有个例子可以显示AJAX的大多数功能: [FBJS/Examples/Ajax |Ajax Example]

对话框

Dialog是一个基于我们对话框的类,它能让你在应用中创建丰满的动态对话框。

Dialog(type) 
(构造) type 可以是 Dialog.DIALOG_POP 或者 Dialog.DIALOG_CONTEXTUAL.
Dialog.DIALOG_POP 
这种类型是当你删除a wall post的时候显示的对话框。
Dialog.DIALOG_CONTEXTUAL 
这种类型是当你在删除minifeed story的时候显示的对话框。
onconfirm 
是一个句柄,当用户选择标示为"确认"的按钮时调用,如果这个事件不返回false,这个对话框将被隐藏。
oncancel 
是一个句柄,当用户选择标示为"取消"的按钮时调用,如果这个事件不返回false,这个对话框将被隐藏。
setStyle 
设置父对话框节点的样式。
showMessage(title, content, button_confirm = 'Okay') 
展示一个只有“确认”按钮的对话框。title 和content 可以使字符串或者 预先提供的 FBML blocks。
showChoice(title, content, button_confirm = 'Okay', button_cancel = 'Cancel') 
展示一个带着“确认”和“取消”按钮的对话框。title和content可以使字符串或者 预先提供的 FBML blocks。
setContext 
(仅仅适用于 DIALOG_CONTEXTUAL). 设置对话框的内容, 这个对话框显示鼠标正在指向的元素的说明。
hide 
隐藏可见的对话框

FBML Blocks

之前提供的FBML Blocks能够输出到你的页加载的JavaScript中。为此,简单地总结FBML Blocks代替为一段<fb:js-string var="variable_name"> 标签 (详细请看 Fb:js-string)。不是渲染FBML Blocks在网页上,而是放进FBML Blocks变量,然后,您可以在setinnerfbml使用您的JavaScript。这是非常有用的,因为象<fb:swf> 的标签获得所提供的不带waitforclick 的限制。FBML块也可以被Ajax提出请求,如上文所述。

动画

Facebook 提供了一个强大的动画库。 详细请看 Animation。

示例

  • Hello World!
  • Typeahead widget
  • Ajax Typeahead widget
  • Dialogs
  • Dynamic Dialogs using Ajax
  • Ajax
  • Dynamic Tables
  • Slider Widget
  • Tabs

技巧

  • 不要创建 依赖于敏感的dom结构的JavaScript。象代码
    this.getElementByTagName('div')[1].getFirstChild().getLastChild().setStyle('color', 'white')
    ,如果我们改变某些要素的方式被提供了,这些代码是很脆弱并可能被攻破。


  • 大部分 FBJS DOM 方法是连续的,例如,而不是:
var obj = document.createElement('div');
obj.addEventListener('click', click);
obj.addEventListener('mousemove', mousemove);
obj.setStyle('color', 'black');

你可以这样做:

document.createElement('div').addEventListener('click', on_click).addEventListener('mousemove', mousemove).setStyle('color', 'black');
  • 你不能像函数或阵列那样继承对象,不过,我们对函数的原型提供了一个典型的“bind”实现。
  • FBJS 对象不包含任何他们实际的DOM对象的句柄,但是如果你用firebug,控制台可以告诉你句柄指向的实际对象。试试 console.dir 在 FBJS DOM 对象上。在您的控制台你会看见一段实际的DOM节点代表您的fbjs DOM的处理的属性PRIV_obj 。 这能帮助你清楚FBJS实际上在做什么。这个技巧对例如AJAX和FBML blocks等FBJS 对象都适用。
  • 如果您想要使用 timed fading/unfading 的元素, 创建下拉阴影“panes”或一般拖拽, check out the small FBJS effects library Backface, at http://supercodex.com/backface/backface.zip, with a demo at http://apps.facebook.com/backface.
  • 用 [Firebug]去排查和诊断任何那些不在你的FBJS上工作的事情 。
  • 考虑使用[Include files]支持,以节省处理/加载时间和带宽。
取自"http://f8.yiqi.com/wiki/index.php/FBJS"
1个分类: FBJS
查看
  • 页面
  • 讨论
  • 源码
  • 历史
个人工具
  • 10.0.5.33
  • 该IP的对话页
  • 登录
导航
  • 首页
  • API
  • FBML
  • FQL
  • FBJS
  • 快速入门
 
工具箱
  • 链入页面
  • 链出更改
  • 上传文件
  • 特殊页面
  • 可打印版
  • 永久链接
Powered by MediaWiki
  • 这页的最后修订在 2008年9月8日 (星期一) 15:11。
  • 本页面已经被浏览21,826次。
  • 隐私政策
  • 关于YiqiWiki
  • 免责声明