解决 Finder 中挂载 Samba 出现“输入的文本似乎不是可识别的 URL 格式”错误

在公司里为了让笔记本和台式机共享文档,决定用内部的 Samba 做中转,但是在 Finder 中直接使用“连接到服务器”时,会出现“输入的文本似乎不是可识别的 URL 格式”错误,但是我输入的地址明明是 smb:// 开头的。

用这个错误信息在网上找了找,没有找到任何解决文案,遂放弃。

今天决定再尝试一下,换了个关键字,直接用“iDeneb samba”作为关键字来搜索,慢慢发掘之后还真找到了有用的信息:http://www.hackint0sh.org/f179/81233.htm

按照文中说明,到 /System/Library/Filesystems 目录下,把 afpfs.fs 删除,并重新创建到 /System/Library/Filesystems/AppleShare/afpfs.kext 的软链接,但是操作完之后还是会提示“输入的文本似乎不是可识别的 URL 格式”。

再找了找,找到了这篇:http://www.insanelymac.com/forum/i … opic=92989&st=580,似乎说是系统安装完成时 afpfs.fs 到 /System/Library/Filesystems/AppleShare/afpfs.kext 的软链接少了开头的斜杠,也就是说它的软链接地址是 System/Library/Filesystems/AppleShare/afpfs.kext

好吧,我在之前操作的时候为了省事,直接进入 Filesystems 目录用相对路径来创建软链接的,看了文章之后,老老实实的用全路径再次创建软链接,Command+K,双击,成功连上 Samba 服务器:)

完整的操作步骤也只有两步:

sudo rm /System/Library/Filesystems/afpfs.fs

sudo ln -s /System/Library/Filesystems/AppleShare/afpfs.kext /System/Library/Filesystems/afpfs.fs

注意:一定不能省略了路径最开始的斜杠(/)或者使用相对路径。

所以,如果你也是用黑苹果的,也碰到了这个问题,不妨试试这个解决方法吧。

1000E 升级到 2G 内存时安装 OSX 需要用到的 dsdt.aml

上周去把 EPC 的内存升级到了 2G,直接发现开机进不了 OSX 了。

在两天没有电脑用之后,下定决心重装系统。重装之后,能进系统,但是重新启动之后键盘和触摸板就不能用了,电池状态指示挂了,郁闷。

在网上找了找,发现可能是 dsdt 的问题。由于内存大小变了,dsdt 中的信息不正确,继而导致 ACPI 失效,然后就整个玩完了。

一个老外找到了解决方法,通过修改 dsdt.aml 文件中的内存大小信息,就可以正确进入系统了。直接下载他提供的压缩包中的 dsdt.aml,开机直接四国了……

好吧,这个老外蛮厚道的,给出了手动处理的方法:

For the 1GB:

Name (SMBS, 0×0400)
OperationRegion (BIOS, SystemMemory, 0×3F7AE064, 0xFF)
Field (BIOS, ByteAcc, NoLock, Preserve)
{

For the 2GB:

Name (SMBS, 0×0400)
OperationRegion (BIOS, SystemMemory, 0×7F7AE064, 0xFF)
Field (BIOS, ByteAcc, NoLock, Preserve)
{

手动修改步骤

1. 首先要下载一个 dsdt.aml 反编译的工具:ACPICA - Windows Binary Tools

2. 解压后有一个 iasl.exe,把它拷贝到 dsdt.aml 所在的目录或者把 dsdt.aml 拷贝到 iasl 的目录都行,然后在命令行中运行:iasl -d dsdt.aml

3. 按照上面的说明,使用文本编辑器打开 dsdt.aml.dsl,根据你的内存大小修改 SystemMemory 后面的数值,1G 就用 0×3F7AE064,2G 就用 0×7F7AE064。

4. 再到命令行中,运行 iasl dsdt.aml.dsl,它会生成一个 dsdt.aml.aml,把它拷贝到 OSX 所在分区的根目录,覆盖原来的 dsdt.aml 即可。或者也可以把原来的文件备份一下,方便出错的还原。

参考资料

  1. eee 1000H(E) – DSDT files and the memory problem

Coda 前端开发插件 F2E Tools

在 EeePC 上装了个 Mac OS X,相应的开发工具也选择了 Coda。在 Windows 下,EditPlus 可以通过添加自定义 工具的方式来给 EditPlus 的添加前端工具,但是在 Coda 上,就没有这么方便的自定义方式了。之前师兄清羽用 Python 实现 了 Coda 的 YUI Compressor 和 JS Lint 两个插件,后来在群里讨论要不要把 JS Beautify 也集成。

想 法有了,上周末回家就开写,Coda 的插件有两种形式的,一种是用脚本来写,另外一种是用 Cocoa 来写。使用脚本很简单,Python、 Ruby 等等都可以,只要系统上有解释器。相对而言还是 Python 熟一点,就选用 Python 来编写这几个插件了。

图片附件

下载:http://dl.getdropbox.com/u/1451589/Blog/CodaF2ETools.zip

安 装方法:解压后,双击 F2E Tools.codeplugin 即可完成安装。

该插件集成了以下 5 个前端开发工 具:

1. YUI Compressor

压缩工具,可以压缩 JS 和 CSS 代码, 去掉注释、空白字符,缩短变量名等。

2. JS Lint

JavaScript 语法检 查工具,可以让你的代码更健壮。

3. JS Beautify

如果碰到了压缩过的代码, 那么可以用这个工具来把代码格式化一下,可以看起来很清楚,它也可以格式化 HTML。

4. HTML Tidy

格 式化并检查 HTML 代码,并检查是否符合相应的规范,例如 XHTML 或 HTML 等。

5. CSS Tidy

格 式化 CSS 代码。

更详细的介绍大家可以去网上找一找。

说明: YUI Compressor 压 缩时是使用的 GB18030 编码,如果你常用的编码不是 GB18030,而是 UTF-8 或者其他,那么你需要修 改 YUI Compressor 插件的脚本,步骤如下:

1. 定位到 用户主目录/Library /Application Support/Coda/Plug-ins

2. 找到 F2E Tools.codeplugin,鼠标右 击,选择“显示包内容”

3. 定位到 Content/Resources/yuicompressor

4. 使用文本编辑 器打开 yuicompressor.py

5. 定位到文件底部,找到 GB18030,有两处,修改为 UTF-8 或你要使用的编码

6. 保 存并退出,重新启动 Coda 即可生效。

HTML5 Canvas 起步(3) – 颜色与渐变

上一篇介绍了 HTML5 中 Canvas 的路径,这篇将要介绍一下 Canvas 中的颜色及渐变。

Canvas 中的基本颜色系统

在 Canvas 中,颜色主要用途就是在绘制路径时,用来指定填充颜色和边框颜色。

Canvas 中的颜色参数值有两种格式:

1. 如果透明度为 1.0,也就是不透明,颜色值的格式就与一般使用一样,为:#AABBCC,其中 AA、BB、CC 分别为 Red、Green、Blue 分量。

2. 如果透明度不为 1.0,也就是带透明,颜色值格式可以使用 rgba(r, g, b, a),其中 r、g、b、a 分别为 Red、Green、Blue 分量和透明度。透明度的值为 0 至 1.0 之间的一个数值。

3. 颜色值还可以为已知的颜色名称,例如 red、blue、green 等。

总的说来,Canvas 中颜色值的格式与 CSS 中一致,因此颜色值没有特别需要注意的地方。

图片附件

<div id="_mcePaste">&lt;canvas id="canvas" width="600" height="500"&gt;&lt;/canvas&gt;
&lt;script type="text/javascript"&gt;
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    // fill a rectangle whit sepecified fill style
    function fillRect(color) {
        ctx.fillStyle = color;
        ctx.fillRect(0, 0, 150, 100);
        ctx.font = "10pt Arial";
        ctx.fillStyle = "white";
        ctx.fillText(color, 6, 20);
        ctx.translate(160, 0);
    }
    ctx.translate(0, 50);
    // fill rect with color name
    fillRect("green");
    // fill rect with 0xAABBCC
    fillRect("#AABBCC");
    // fill rect with rgba(50, 100, 150, 0.5)
    ctx.translate(0, -25);
    fillRect("rgba(50,100,150,0.5)");
 
    // fill another rect with rgba(150, 100, 50, 0.5)
    ctx.translate(-110, 50);
    fillRect("rgba(150, 100, 50, 0.5)");
&lt;/script&gt;</div>

注意,以上代码需要使用 Firefox 3.5 来查看,在 Firefox 3.0.x 中,Canvas 的 Context 对象不支持 fillText 方法,而我安装的 Chrome 2.0.174.0 对 translate 方法的实现有误。

2. Canvas 中的渐变

WHATWG 的 Canvas 规范中规划了两种渐变模式,一种是线性渐变,另一种是径向渐变。如果需要在 Canvas 中使用渐变,首先要根据你所要创建的渐变模式来调用 Context 的相应方法来创建一个渐变对象,这个对象就是用来控制渐变的效果。

More >

HTML5 Canvas 起步(2) – 路径

上一篇介绍了 HTML5 中 Canvas 的基本概念,这篇将要介绍一下 Canvas 中的基本图形。

图形的基础 - 路径

在 Canvas 中,所有基本图形都是以路径为基础的,也就是说,我们在调用 2dContext 的 lineTo、rect 等方法时,其实就是往已经的 context 路径集合中再添加一些路径点,在最后使用 fill 或 stroke 方法进行绘制时,都是依据这些路径点来进行填充或画线。

在每次开始绘制路径前,都应该使用 context.beginPath() 方法来告诉 Context 对象开始绘制一个新的路径,否则接下来绘制的路径会与之前绘制的路径叠加,在填充或画边框时就会出现问题。在绘制完成路径后,可以直接使用 context.closePath() 方法来关闭路径,或者手动关闭路径。另外,如果在填充时路径没有关闭,那么 Context 会自动调用 closePath 方法将路径关闭。

基本路径方法

1. beginPath, closePath

这两个方法在前面已经介绍过,分别用来通知 Context 开始一个新的路径和关闭当前的路径。

在 Canvas 中使用路径时,应该要保持一个良好的习惯,每次开始绘制路径前都要调用一次 beginPath 方法,否则画出来的效果难看不说,还会严重影响性能。

在下面这张图中,左边的图形在每次绘制矩形前都调用了一次 beginPath 来清除之前的路径并重新开始绘制新的路径,而后面的图形则就只在绘制所有图形前调用了一次 beginPath 来清除路径,因此,虽然这里是使用的边框色是 #666,但是右边的图形颜色比左边的深一些,因为每次使用 stroke 绘制边框时,会把之前的路径再次绘制一遍,叠加起来颜色就比原来深一些。

图片附件

<div id="_mcePaste">&lt;canvas id="canvas" width="500" height="500"&gt;&lt;/canvas&gt;
&lt;script type="text/javascript"&gt;
    var canvas = document.getElementById("canvas");
    var ctx = canvas.getContext("2d");
    ctx.strokeStyle = "#666";
    function useBeginPath() {
        for (var i = 0; i &lt; 5; ++i) {
            ctx.beginPath();
            ctx.rect(10 + i*20, 10 + i*20, 210 - i*40, 210 - i*40);
            ctx.stroke();
        }
    }
    function notUseBeginPath() {
        ctx.beginPath();
        for (var i = 0; i &lt; 5; ++i) {
            ctx.rect(240 + i*20, 10 + i*20, 210 - i*40, 210 - i*40);
            ctx.stroke();
        }
    }
    useBeginPath();
    notUseBeginPath();
&lt;/script&gt;</div>

在 Context 中路径数较少时,如果不考虑显示效果,性能上还可以接受,但是如果 Context 中的路径数很多时,在开始绘制新路径前不使用 beginPath 的话,因为每次绘制都要将之前的路径重新绘制一遍,这时性能会以指数下降。

因此,除非有特殊需要,每次开始绘制路径前都要调用 beginPath 来开始新路径。 More >

Bespin 0.2.1 “Cheeky Cirrus” Released

Mozilla Labs 昨天发布了 Bespin 0.2.1 ”Cheeky Cirrus”。就在前天的时候,Mozilla Labs 发布了 Bespin 0.2.0 ”Sassy Cirrus”,不得不说开源项目的更新速度是相当快,现在 Bespin 项目的开发成员好像越来越多,估计要进入快速发展期了,非常期待 Bespin 的优异表现。

昨天发布的 Bespin 0.2.1 ”Cheeky Cirrus” 中更新了以下内容:

1. Jetpack 支持:按文档来看,应该是用于扩展程序功能的,可以在以后 Bespin 支持插件时,给插件提供调试、永久存储以及用户界面上面的支持。

2. 增加了 ”hg init” 命令来给将一个项目初始化为一个 Mercurial 版本库。

3. 增加了 ”vcs status” 查看当前工作副本的状态。

4. 增加了对子命令自动完成的支持。

Bespin 从 0.2.0 Sassy Cirrus” 开始就开始支持 Mercurial 了,这也就意味着,可以使用 Bespin 来进行协作开发,通过 Mercurial 来同步工作。另外,Google Code 也在前些天宣布 Google Code 将要支持 Mercurial,已经在征集测试者。等到 Google Code 正式支持 Mercurial,那个时候就可以直接使用 Bespin 进行编辑,使用 Google Code 来进行代码的版本管理了。这对于托管在 Google Code 上的开源项目的开发者来说,以后就可以过上一个浏览器走天下的日子了,在换到新的环境时,不需要再重新配置开发环境等。

现在 Bespin 的 vcs 命令并不完整,目前只能 push 到 clone 时指定的版本库,也不支持 pull 命令。不过如果就单人开发来说,现在的 vcs 命令已经足够。

如果需要尝试 Bespin 的 vcs 功能,可以在 http://bitbucket.org/ 注册一个帐号,并在 Bespin 使用 SSH 方式连接版本库。详细使用方法可以参考 Kevin Dangoor 录制的一段视频

在 Bespin 0.2.0 ”Sassy Cirrus” 中,主要是增加了对版本控制命令的支持,以及其他界面和功能上的细微更新。

Bespin 并不仅仅支持 HTML、JavaScript 和 CSS 语法高亮,目前还支持的有 Python,以后也会有更多语言的语法高亮支持,这也就是说 Bespin 可以用来做为任何语言的编辑器。而且目前 Bespin 已经支持了 JavaScript 的 outline,相信以后会有更强大的功能出现。

Bespin 所有的 Release Notes 可以在 这里 看到。

HTML5 Canvas 起步(1) – 基本概念

什么是Canvas

<canvas> 是一个新的 HTML 元素,这个元素在 HTML5 中被定义。这个元素通常可以被用来在 HTML 页面中通过 JavaScript 进行绘制图形、合成图像等等操作,也可以用来做一些动画。当然,目前 HTML5 规范还在草稿阶段,正式发布也许要等到2010年,不过现在已经有不少浏览器已经支持了部分 HTML5 规范。目前支持 canvas 元素的浏览器有 Firefox 3+、Safari 4、Chrome 2.0+ 等,因此,在运行本页中的例子时,请确保你使用的是上述浏览器之一。

尽管在 Mozilla 已经有不少关于 Canvas 的教程,我还是决定把自己的学习过程记录下来。如果觉得我写的不够明白,那么你可以在参考资料中找到 Mozilla 网站上 Canvas 教程的链接。

另外,可以在这里找到一些有趣的 Canvas 示例。

开始使用 Canvas

使用 Canvas 很简单,与使用其他 HTML 元素一样,只需要在页面中添加一个 <canvas> 标签即可:

<canvas id="screen" width="400" height="400"></canvas>

当然,这样只是简单的创建了一个 Canvas 对象而已,并没有对它进行任何操作,这个时候的 canvas 元素看上去与 div 元素是没什么区别的,在页面上什么都看不出来:)

另外,canvas 元素的大小可以通过 width 与 height 属性来指定,这与 img 元素有点相似。

Canvas 的核心:Context

前面说到可以通过 JavaScript 来操作 Canvas 对象来进行绘制图形、合成图像等操作,这些操作并不是通过 Canvas 对象本身来进行的,而是通过 Canvas 对象的一个方法 getContext 获取 Canvas 操作上下文来进行。也就是说,在后面我们使用 Canvas 对象的过程中,都是与 Canvas 对象的 Context 打交道,而 Canvas 对象本身可以用来获取 Canvas 对象的大小等信息。

要获取 Canvas 对象的 Context 很简单,直接调用 canvas 元素的 getContext 方法即可,在调用的时候需要传递一个 Context 类型参数,目前可以用的并且是唯一可以用的类型值就是 2d:

<script type="text/javascript"><!--mce:0--></script>

Firefox 3.0.x 的尴尬

Firefox 3.0.x 虽然支持了 canvas 元素,但是并没有完全按照规范来实现,规范中的 fillText、measureText 两个方法在 Firefox 3.0.x 中被几个 Firefox 特有的方法代替,因此在 Firefox 3.0.x 中使用 Canvas 时需要先 fix 这个几个方法在不同浏览器中的差别。

More >

“云端的编辑器”,10 步安装 Bespin Development Server(Python版)

Mozilla Labs 在今年情人节那天发布了一个叫 Bespin 的编辑器,这是一个基于网络的可扩展文本编辑器,按照现在流行的说法,就是“云编辑”了。并且,这个编辑器是开源的。

图片附件

Bespin 是基于 Canvas 的,因此目前它只支持少数浏览器,其中包括 Firefox 3+、Safari 4 以及 Chrome 2 开发版,因此,如果要使用 Bespin 的话,你必须使用这几款浏览器中的一种。

要体验 Bespin,可以直接在 bespin.mozilla.com 注册一个帐号并且登录,不过目前 bespin.mozilla.com 所用的代码并不是最新版本的,线上使用的代码有许多不完善之处。因此,除了使用 Mozilla Labs 官方的 Bespin 站点,我们也可以从 Mozilla Labs 下载 Bespin 源代码,并在本地搭建 Bespin 服务,从而可以体验 Mozilla Labs 最新的开发成果。

注意,这篇文章并不介绍怎么去使用 Bespin,而是介绍怎么样去配置一个可以在本地运行的 Bespin 服务器,因此,如果你需要了解怎么去使用这个编辑器,可以参阅 Mozilla Labs 上的文档,或者等我再写一篇使用 Bespin 的文章:)

准备工作

首先需要说明的是,这里介绍的配置 Bespin 本地服务器的环境是 Windows Vista(or WinXP) + Python。另外,如果是在 Vista 中安装 Bespin Server,你使用管理员权限来运行 cmd。

第 1 步:在这里把 Bespin 的源代码下载下来,然后解压到任意目录,我这里解压到的是“D:\Source\Bespin\bespin-8b89188c5066”。

第 2 步:这篇文章介绍的是 Python 版 Bespin 服务器的配置,因此还需要安装 Python 解释器,可以在这里下载到 Python 2.5.4,使用默认设置安装即可。

第 3 步:在 bespin 源代码目录中新建一个目录 Scripts,这个目录与 backend 和 frontend 两个目录是平级的。然后到 Python 的安装目录下,将安装目录下的 msvcr71.dll、python.exe、python25.dll、pythonw.exe 四个文件拷贝到前面建立的 Script 目录中。

第 4 步:将 Python 安装目录中的 libs 目录拷贝到 bespin 源代码目录中。

第 5 步:Bespin Python 服务器所用的有些组件是使用 C 写的,在 Windows 上要编译与 Python 兼容的 C 扩展,需要使用 MinGW,下载以下这些压缩包,解压到 D:\Tools\MinGW,这里解压的位置可以自己选,但是后面要用到,所以请记住你解压的路径:

http://nchc.dl.sourceforge.net/sourceforge/mingw/binutils-2.19.1-mingw32-bin.tar.gz

http://nchc.dl.sourceforge.net/sourceforge/mingw/gcc-g++-3.4.5-20060117-3.tar.gz

http://nchc.dl.sourceforge.net/sourceforge/mingw/gcc-core-3.4.5-20060117-3.tar.gz

http://nchc.dl.sourceforge.net/sourceforge/mingw/w32api-3.13-mingw32-dev.tar.gz

http://nchc.dl.sourceforge.net/sourceforge/mingw/mingwrt-3.15.2-mingw32-dev.tar.gz

More >

YUI学习笔记(4)

YUI学习笔记(4)

by xujiwei (http://www.xujiwei.com/)

YAHOO.util.Subscriber 与 YAHOO.util.CustomEvent。

1. YAHOO.util.Subscriber (event.js)

这 应该算是设计模式中的观察者模式了,Subscriber 订阅一个事件,在 Publisher 触发那个事件后,会逐个通知 Subscriber。

对 于一般开发者来说,并不需要去关心 Subscriber 的实现,因为 Subscriber 主要是 CustomEvent 用来分发动作以及删 除 Subscriber 的。

Subscriber 类只定义了 3 个属性:fn、obj 以及 override,3 个方 法:getScope、contains、toString,其中 fn 为订阅者的回调函数,obj 为要传递给回调函数的一个额外参 数,override 如果是布尔型的 true 值,那么表示使用 obj 属性为回调函数执行时的上下文,或者直接使用一个对象来作为回调函数执行的 上下文。

Subscriber 的 3 个方法中比较有用的是 getScope 和 contains,toString 只是简单的 将 Subscriber 对象转换成一个字符串。getScope 会根据 Subscriber 对象的 override 属性来获取回调函数执行 的上下文,contains 用来判断 Subscriber 对象与指定的回调函数和 obj 是否一致。

2. YAHOO.util.CustomEvent (event.js)

CustomEvent 的 作用相当在观察者模式中发布者的身份,可以通过它来实现一个自己的事件发布者。

CustomEvent 构造函数的定义如下:

CustomEvent = function(type, oScope, silent, signature)

在 创建 CustomEvent 对象时,几个参数的用途如下:

type 是自定义事件的名称,在使用回调函数的参数格式 为 YAHOO.util.Event.LIST 时,回调函数的第一个参数就是 CustomEvent 对象的名称;

oScope 是 执行回调函数时的上下文对象,也就是在回调函数中可以用 this 来引用这个对象;

silent 参数是用指示是否 在 YUI 为 debug 版本时禁用调试信息;

signature 用来指示回调函数参数的格式,可以为 YAHOO.util.Event.FLAT 或 YAHOO.util.Event.LIST, 默认是 YAHOO.util.Event.LIST。

在使用 CustomEvent 之前,先要了解一下 CustomEvent 中 回调函数参数的格式,CustomEvent 的回调函数可以有两种格式,一种为 YAHOO.util.Event.LIST,这种格式的回调函数具有 三个参数,分别是事件名称、参数数组和附加对象参数;另外一种回调函数参数格式为 YAHOO.util.Event.FLAT,这个时候回调函数只有两 个参数,一个为 CustomEvent 对象调用 fire 方法时的第一个参数,另外一个是订阅时的额外对象参数。

在创 建 CustomEvent 对象时,CustomEvent 构造函数还会首先创建一个内部的自定义事件,用来处理该自定义事件被订阅的事件,这 在 EventProvider 中用到,这里暂且不提。

CustomEvent 对象使用一个名为 subscribers 的数组来保 存所有订阅者的列表,并且通过维护这个列表来维护该自定义事件的订阅者。

CustomEvent 对象提供了 subscribe、 unsubscribe、unsubscribeAll、fire 这几个方法来处理自定义事件的订阅、退订以及触发等动作,而这几个就是观察者模式中的 主要动作了。

subscribe 的签名为 subscribe: function(fn, obj, override), 三个参数分别对应了 Subscriber 类构造函数的三个参数,分别对应了回调函数、额外对象参数以及是否使用额外对象参数作为执行上下文。 subscribe 只是简单的判断参数 fn 是否有定义,然后会触发自定义事件订阅事件,最后使用这三个参数创建一个 Subscriber 对象添 加到 CustomEvent 对象的 subscribers 属性中。

unsubscribe 方法用来取消事件的订阅,它的函数签名 为 unsubscribe: function(fn, obj),两个参数分别是回调函数和额外对象参数,如果使用无参数调 用 unsubscribe 方法,那么会直接调用 unsubscribeAll 来删除所有订阅者,否则会逐一判断 subscribers 中的每 个对象,通过使用 Subscriber 对象的 contains 方法来判断给定的 fn 和 obj 与其是否一致,如果一致,就使用一个私有方 法 _delete 来删除这个 Subscriber。

unsubscribeAll 方法没有参数,它只是简单的直接删除自定义事件的 所有订阅者,最后直接给 subscribers 赋值一个空数组来避免有可能出现漏删订阅者的情况。

内部方法 _delete 的参数 是 Subscriber 对象在 subscribers 数组中的索引,它会先删除 Subscriber 对象的 fn 和 obj 属性,最后使 用 splice 方法将 Subscriber 对象从数组中删除。

var s = this.subscribers[index];
if (s) {
delete s.fn;
delete s.obj;
}
this.subscribers.splice(index, 1);

使用 delete 删除 Subscriber 对象的 fn 和 obj 属性是为了去除 回调函数及额外对象参数的引用,以免引起不必要的内 存泄露。

CustomEvent 对象最重要的方法就是 fire 了,就是通过这个方法来通知所有了订阅者这个自定义事件被触发了。 fire 方法先使用 Array 的 slice 方法将调用 fire 方法时的参数转化成数组,这样就可以在调用 Subscriber 的回调函 数时可以传递参数给它们。

在遍历 subscribers 中的 Subscriber 前,fire 方法先使用 了 subscribers 的 slice 方法来创建一个 subscribers 的副本,这样避免在执行 fire 的过程中 有 Subscirber 取消订阅了这个自定义事件会导致错误。

在执行 Subscriber 的回调函数前,先使 用 Subscriber 对象的 getScope 方法来获取执行回调函数时的上下文对象,再根据 CustomEvent 对象 的 signature 属性来决定怎么去调用 Subscriber 的回调函数。

如 果 signature 为 YAHOO.util.CustomEvent.FLAT,那么就把调用 fire 方法时的第一个参数做为回调函数的第一 个参数,再把 Subscriber 对象的 obj 属性做为第二个参数:

s.fn.call(scope, param, s.obj)

如 果 signature 为 YAHOO.util.CustomEvent.LIST,那么就除了把整个 fire 方法的参数列表传递给回调函数外, 还要传递当前 CustomEvent 的名称给回调函数:

s.fn.call(scope, this.type, args, s.obj)

Subscriber 的 回调函数如果在执行过程中出现了错误,那么 CustomEvent 的 lastError 属性就是指向错误对象的引用,另外,如 果 YAOO.util.Event.throwErrors 为 true,那么会把这个错误再次抛出。

另外,Subscriber 对 象也可以控制事件通知是否继续,如果 Subscriber 对象的回调函数执行后的返回一个 false,那么在 fire 方法中就会停止通知剩下 的 Subscriber 对象,通常情况下,先订阅自定义事件的 Subscriber 可以阻止后订阅的 Subscriber 接收到通知。

使 用 YUI 的自定义事件(CustomEvent)可以很方便地实现观察者模式,更好地组织 JavaScript 程序的结构。

YUI学习笔记(3)

YUI学习笔记(3)

by xujiwei (http://www.xujiwei.com/)

YAHOO.lang.later,YAHOO.lang.trim,YAHOO.lang.isXXX 以及 YAHOO.lang.hasOwnProperty。

1. YAHOO.lang.later(yahoo/yahoo.js)

later 方法用来延迟执行方法,是对 setInterval 和 setTimeout 的封装,并且可以传递参数到延迟执行的函数或者使用参数数组批量执行指定的函数。

later 方法的签名为:

later: function(when, o, fn, data, periodic)

when 是用来指定在多长时间后执行指定的函数,以毫秒计算;

o 是上下文对象,即在要执行的函数里使用 this 是会引用这个 o 对象;

fn 就是要延迟执行的函数了,可以传递一个函数引用,也可以传递一个字符串,later 方法会在 o 对象中查找对应名称的属性来做为要执行的方法;

data 就是传递给延迟执行的函数的参数了,可以为一个参数,或者是一个参数数组,那么如果我们要传递的参数本身就是一个数组的话,就要自己先把这个参数数组包装成一个数组;

peridoic 参数是一个布尔值,用来表示延迟执行的函数是否需要周期执行而不是只执行一次。

later 方法执行后会返回一个对象,包含了一个名 interval 的属性用来表示函数是以 setInterval 来执行的还是以 setTimeout 来执行的,以及一个方法 cancel 用来取消执行被延迟执行的函数。嗯,不过只有在 peridoic 为 true 时这个 cancel 方法比较有用,毕竟如果 peridoic 为 false 时函数执行一次就不会再执行了,cancel 也没有什么意义。

{
interval: periodic,
cancel: function() {
if (this.interval) {
clearInterval(r);
} else {
clearTimeout(r);
}
}
};

    2. YAHOO.lang.trim (yahoo/yahoo.js)

    trim 方法用来去除字符串两边的空白字符,其实也就用了一个正则来匹配字符串两端的空白字符并替换成空白字符串。

    不过在 YAHOO.lang.trim 中,它使用了一个 try … catch 来在调用的参数不为字符串时直接返回原来的对象。

    3. 对象类型判断 YAHOO.lang.isXXX (yahoo/yahoo.js)

    YAHOO.lang 中包含了一堆用于判断对象是否为某个类型的方法,例如 isObject、isString、isNumber 等。

    YAHOO.lang.isArray 用来判断一个对象是否为数组,YUI 中并不是使用的 obj instanceof Array 或者 obj.constructor == Array,而是判断指定的对象是否有两个数组应该具有的经典属性和方法 length 和 splice,这是因为如果要判断的对象是属于另外一个 frame 中时,除非你能获得另外一个 frame 中 Array 定义的费用,否则 instanceof 和 constructor == Array 都是返回 false 的,我们可以使用以下代码来测试一下:

    test.html

    <iframe id=”frame” src=”iframe.html”></iframe>
    <script type=”text/javascript”>
    <!–
    var f = document.getElementById(‘frame’);
    setTimeout(function() {
    alert(f.contentWindow.arr.constructor == Array);
    }, 1000);
    //–>
    </script>

      iframe.html

      <script type=”text/javascript”>
      <!–
      var arr = [1, 2, 3];
      //–>
      </script>

        而如果把 Array 换成 arr 所在 frame 中 Array 的引用,结果就是为 true 了:

        test.html

        <iframe id=”frame” src=”iframe.html”></iframe>
        <script type=”text/javascript”>
        <!–
        var f = document.getElementById(‘frame’);
        setTimeout(function() {
        // 这里将 Array 换成 f.contentWindow.Array
        alert(f.contentWindow.arr.constructor == f.contentWindow.Array);
        }, 1000);
        //–>
        </script>

          但是因为 isArray 是一个通用的方法,在使用时不可能要求调用者同时也传递一个目标 frame 的引用过来,所以只好通过判断两个经典的属性来代替了。

          YUI 的注释中提到是 Safari 不支持跨框架通过 instanceof 的检测,但是我测试的结果是几个主流浏览器都不支持跨框架的 instanceof 检测。

          YAHOO.lang.isBooleanYAHOO.lang.isFunctionYAHOO.lang.isStringYAHOO.lang.isUndefined 这 4 个方法是直接通过使用 typeof 来判断对象类型是否为 boolean、function、string 或 undefined 的。

          YAHOO.lang.isNumber 也是通过 typeof 来判断的,不过附加了一个检测条件,使用 isFinite 来检测数字是否为有限的,即不是 NaN、负无穷或正无穷。

          YAHOO.lang.isObject 通过 typeof 来判断对象类型是否 object 以及使用 isFunction 方法来检测对象是否为一个 Function,在 YAHOO.lang.isObject 方法的眼中,Object 与 Function 都是 Object。

          YAHOO.lang.isNull 直接将判断对象与 null 进行严格相等比较。

          YAHOO.lang.isValue 用来判断传递给它的参数是否为一个有值的对象,它是将 isObject、isString、isNumber 以及 isBoolean 四个方法对参数进行判断的结果进行或操作来作为结果的,对 null/undefined/NaN 这三个值进行 isValue 判断时就会返回 false,因为 0、false、’ 这三个值在分别在 isNumber、isBoolean、isString 时判断为 true,所有 isValue 的结果也为 true。

          4. YAHOO.lang.hasOwnProperty (yahoo/yahoo.js)

          嗯,这个方法也是对 Object.prototype.hasOwnProperty 的封装,前提是当前上下文的 Object.prototype 有 hasOwnProperty 方法,如果 Object.prototype.hasOwnProperty 不存在,那么 YAHOO.lang.hasOwnProperty 就实现了自己的 hasOwnProperty 方法,它是通过判断对象的属性与对象 prototype 的同名属性是否为同一个对象的判断的。如果对象的属性不是从原型继承过来的,那么两个属性值就有可能不一致:

          o.constructor.prototype[prop] !== o[prop]

          不过这里也有个问题,在 YAHOO.lang.hasOwnProperty 的注释中也提到了,就是 YUI 自己实现的 hasOwnProperty 是无法分辨在属性值一样时,这个属性是从原型继承过来的还是对象自身的:

          var YAHOO = {
          lang : {
          isUndefined : function(o) {
          return typeof o === ”undefined”;
          },
          hasOwnProperty : function(o, prop) {
          return !this.isUndefined(o[prop]) &&
          o.constructor.prototype[prop] !== o[prop];
          }
          }
          }
          var A = function() {};
          A.prototype.foo = ’foo’;
          var a = new A();
          a.foo = ’foo’;
          alert(a.hasOwnProperty(‘foo’)); // true
          alert(YAHOO.lang.hasOwnProperty(a, ’foo’)); // 这里返回 false,事实上应该是 true

            但是现在 Object.prototype 中没有 hasOwnProperty 的浏览器应该基本没有了,所以这个问题也不是很大。

            5. YAHOO.lang.augmentProto 以及 YAHOO.lang.extend 的别名 (yahoo/yahoo.js)

            在 yahoo.js 中,将 YAHOO.lang.augment 以及 YAHOO.augment 指向了 YAHOO.lang.augmentProto,YAHOO.extend 指向了 YAHOO.lang.extend,可以一定程度上减少代码的编写。