<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>随网之舞YUI</title>
	<atom:link href="http://dancewithnet.com/tag/yui/feed/" rel="self" type="application/rss+xml" />
	<link>http://dancewithnet.com</link>
	<description>WEB Design{HTML:CSS:Javascript:DOM:AJAX:PHP:Usability}/Viewpoint/Photo/Food/Mood</description>
	<lastBuildDate>Mon, 18 Jul 2011 02:45:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>在服务端合并和压缩JavaScript和CSS文件</title>
		<link>http://dancewithnet.com/2010/06/08/minify-js-and-css-files-in-server/</link>
		<comments>http://dancewithnet.com/2010/06/08/minify-js-and-css-files-in-server/#comments</comments>
		<pubDate>Mon, 07 Jun 2010 17:50:57 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Apache &  MySQL &  PHP]]></category>
		<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[Combo Handler]]></category>
		<category><![CDATA[Minify]]></category>
		<category><![CDATA[YUI]]></category>
		<category><![CDATA[性能]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/?p=1507</guid>
		<description><![CDATA[Web性能优化最佳实践中最重要的一条是减少HTTP请求，它也是YSlow中比重最大的一条规则。减少HTTP请求的方案主要有合并JavaScript和CSS文件、CSS Sprites、图像映射（Image Map）和使用Data URI来编码图... ]]></description>
			<content:encoded><![CDATA[<p>Web性能优化最佳实践中最重要的一条是<a href="http://developer.yahoo.com/performance/rules.html#num_http">减少HTTP请求</a>，它也是<a href="http://developer.yahoo.com/yslow/">YSlow</a>中比重最大的一条规则。减少HTTP请求的方案主要有合并JavaScript和CSS文件、<a href="http://alistapart.com/articles/sprites">CSS Sprites</a>、<a href="http://www.w3.org/TR/html401/struct/objects.html#h-13.6">图像映射（Image Map）</a>和<a href="http://dancewithnet.com/2009/08/15/data-uri-mhtml/">使用Data URI来编码图片</a>。CSS Sprites和图像映射现在已经随处可见了，但由于IE6和IE7不支持Data URI以及性能问题，这项技术尚未大量使用。目前大部分网页中的JavaScript和CSS文件数量和开发时一致，少量的网页会根据实际情况采取本地合并，这些合并中相当多的是有选择地手动完成，每次新的合并都需要重新在本地完成并上传到服务器，比较的随意和繁琐，同样文件的压缩也有类似的情况。而利用服务端的合并和压缩，我们就可以按照开发的逻辑尽可能让文件的颗粒度变小，利用网页中URL的规则来自动实现文件的合并和压缩，这会相当的灵活和高效。</p>
<p><span id="more-1507"></span></p>
<h3>YUI Combo Handler</h3>
<p><a href="http://www.yuiblog.com/blog/2008/07/16/combohandler/">2008年7月YUI Team宣布在YAHOO! CDN上对YUI JavaScript组件提供Combo Handler服务</a>。Combo Handler是Yahoo!开发的一个Apache模块，它实现了开发人员简单方便地通过URL来合并JavaScript和CSS文件，从而大大减少文件请求数。比如在页面上使用<a href="http://developer.yahoo.com/yui/editor/">YUI2的Rich Text Editor组件</a>需要引入多个JavaScript文件，常用方式如下：</p>
<pre><code>&lt;script src="http://yui.yahooapis.com/2.8.0r4/build/yahoo-dom-event/
yahoo-dom-event.js"&gt;&lt;/script&gt;
&lt;script src="http://yui.yahooapis.com/2.8.0r4/build/container/
container_core-min.js"&gt;&lt;/script&gt;
&lt;script src="http://yui.yahooapis.com/2.8.0r4/build/menu/menu-min.js"&gt;&lt;/script&gt;
&lt;script src="http://yui.yahooapis.com/2.8.0r4/build/element/element-min.js"&gt;&lt;/script&gt;
&lt;script src="http://yui.yahooapis.com/2.8.0r4/build/button/button-min.js"&gt;&lt;/script&gt;
&lt;script src="http://yui.yahooapis.com/2.8.0r4/build/editor/editor-min.js"&gt;&lt;/script&gt;
</code></pre>
<p>而使用Combo Handler服务之后，则上述的代码可以写为：</p>
<pre><code>&lt;script src="http://yui.yahooapis.com/combo?
2.8.0r4/build/yahoo-dom-event/yahoo-dom-event.js&#038;
2.8.0r4/build/container/container_core-min.js&#038;
2.8.0r4/build/menu/menu-min.js&#038;
2.8.0r4/build/element/element-min.js&#038;
2.8.0r4/build/button/button-min.js&#038;
2.8.0r4/build/editor/editor-min.js"&gt;&lt;/script&gt;</code></pre>
<p>除了代码的可读性稍稍有一点点降低外，使用Combo Handler服务大大的降低了HTTP请求数，同时也减少了URL代码量，这对于Web性能优化来讲至关重要。所以，随后<a href="http://yuiblog.com/blog/2008/10/17/loading-yui/">YUI从2.6.0开始，其核心组件YUI Loader内置了Combo Handling功能</a>，即使用YUI Loader时，通过配置<code>combine</code>属性就可以把要加载的多个JavaScript或CSS文件按照使用Combo Handler服务的形式合并起来，这时只要静态文件的服务器支持Combo Handler就行了。在YUI中当<code>combine</code>配置为<code>true</code>时，CDN默认是使用Yahoo! CDN（http://yui.yahooapis.com），所以没有任何问题。这正是YUI最迷人的地方之一。</p>
<p>遗憾的是http://yui.yahooapis.com在中国的速度并不佳，本来中国雅虎提供了http://cn.yui.yahooapis.com/ ，但尚未提供Combo Handler服务，同时因种种原因，其更新在<a href="http://cn.yui.yahooapis.com/2.7.0/build/yahoo-event-dom/yahoo-event-dom.js">YUI 2.7.0</a>之后就停滞了。更糟糕的是Yahoo!开发的支持Combo Handler的Apache模块虽然据传有计划开源，但至少现在依旧是私有技术，要使用就需要自己实现类似功能，所以国内类似技术的应用并不太多。</p>
<h3>Minify</h3>
<p>在Google Code上有一个PHP的开源项目叫<a href="http://code.google.com/p/minify/">Minify</a>，它可以合并、精简、Gzip压缩和缓存JavaScript和CSS文件。其文件合并功能就非常类似Combo Handler，只不过URL的语法稍微有点不同。如果Yahoo! CDN安装了Minify，那么上面Rich Text Editor的代码用Minify的默认格式来写就是：</p>
<pre><code>&lt;script src="http://yui.yahooapis.com/min/f=
2.8.0r4/build/yahoo-dom-event/yahoo-dom-event.js,
2.8.0r4/build/container/container_core-min.js,
2.8.0r4/build/menu/menu-min.js,
2.8.0r4/build/element/element-min.js,
2.8.0r4/build/button/button-min.js,
2.8.0r4/build/editor/editor-min.js"&gt;&lt;/script&gt;</code></pre>
<p>本地使用Minify很简单，只需要Apache + PHP环境就OK了：</p>
<ol>
<li>安装好Apache + PHP (<a href="http://dancewithnet.com/2005/09/16/install-apache-and-php-in-windows/">Windows</a>、<a href="http://dancewithnet.com/2010/05/09/run-apache-php-mysql-in-mac-os-x/">Mac</a>)。</li>
<li>下载<a href="http://code.google.com/p/minify/downloads/list">Minify源码</a>，解压，然后把min文件夹复制到指定的根目录下，比如localhost。这时URL的写法大概是<code>http://localhost/min/f=...</code></li>
<li><a href="http://dancewithnet.com/2010/05/29/making-mod-rewrite-and-htaccess-work-on-mac-os-x/">启用Apache的Mod Rewrite模块</a>，然后在min文件夹下<a href="http://www.zendstudio.net/archives/create-htaccess-file-in-windows/">新建.htaccess文件</a>，并添加如下<a href="http://code.google.com/p/minify/source/browse/branches/2.1.4/min/.htaccess">Rewrite规则</a>：
<pre><code>&lt;IfModule mod_rewrite.c&gt;
RewriteEngine on

# You may need RewriteBase on some servers
<span># 如果做了所有的开启Mod Rewrite的设置依旧无效，请城市尝试启用下面这句</span>
#RewriteBase /min

# rewrite URLs like "/min/f=..." to "/min/?f=..."
RewriteRule ^([bfg]=.*)  index.php?$1 [L,NE]
&lt;/IfModule&gt;</code></pre>
<p>如果不启用Mod Rewrite功能，则Minify的URL会类似http://localhost/min/index.php?f=&#8230;，这<a href="http://www.stevesouders.com/blog/2008/08/23/revving-filenames-dont-use-querystring/">对客户端和中间服务器的缓存不利</a>，而启用了Mod Rewrite之后的URL类似http://localhost/min/f=&#8230;，不仅解决前面问题且更短。</p>
</li>
<li>配置Minify，即编辑min/config.php文件
<pre><code>$min_enableBuilder = true;
<span>//本地使用时可以通过http://dwn/min/builder/来进行配置，外部使用时请设置为false</span>

//$min_cachePath = 'c:\\WINDOWS\\Temp';
//$min_cachePath = '/tmp';
//$min_cachePath = preg_replace('/^\\d+;/', '', session_save_path());
<span>//选择其一，去掉注释设置临时缓存目录，这样可以减少程序运算提高性能</span>

$min_serveOptions['maxAge'] = 1800;
<span>//设置浏览器缓存的时间，为了提升性能建议这个时间设置尽可能的长，比如315360000
//如果需要在不改变URL的情况下更新静态文件，可以采用类似时间戳的方式，
//如http://localhost/min/f=example/example.css&#038;20100601.css
//建议静态文件采用版本号管理，每次修改都需要升级版本号，这样就无需时间戳了，
//如http://localhost/min/f=example/example_1_0_1.css
</span>
$min_serveOptions['minApp']['maxFiles'] = 10;
<span>//参数f获取参数的个数，即合并的文件个数，这个数量完全可以增大，比如50，
//当然可能会遇到URL最大值问题，后会有解释</span>

$min_documentRoot = '';
//$min_documentRoot = substr(__FILE__, 0, strlen(__FILE__) - 15);
//$min_documentRoot = $_SERVER['SUBDOMAIN_DOCUMENT_ROOT'];
<span>//当$min_documentRoot为空时，其值就是$_SERVER['DOCUMENT_ROOT']，
//但合并的文件不在$_SERVER['DOCUMENT_ROOT']下，会导致<a href="http://code.google.com/p/minify/wiki/CommonProblems#Builder_Fails_/_400_Errors">400错误</a>，
//这个时候可以启用第2行或第3行</span>
<span></span>
</code></pre>
</li>
<li>使用Minify
<p>比如，有两个JavaScript文件，<code>http://localhost/example/a.js,http://localhost/example/b.js</code>，那么使用Minify合并的URL是<code>http://localhost/min/f=/example/a.js,/example/b.js</code>，直接把这个URL放到页面中就可以使用了。</p>
</li>
</ol>
<p>实际上Minify不仅仅实现了合并功能，同时默认在合并的同时还会对文件进行精简压缩，如果你在本地本身就对文件进行压缩了，比如使用<a href="http://yuilibrary.com/projects/yuicompressor/">YUI Compressor</a>，那么可以在config.php中进行如下设置取消Minify的压缩以提升性能：</p>
<pre><code>$min_serveOptions['minifiers']['application/x-javascript'] = '';
$min_serveOptions['minifiers']['text/css'] = '';
</code></pre>
<p>如果服务端支持Java，那么也可以<a href="http://code.google.com/p/minify/wiki/CookBook#YUICompressor">对Minify进行简单配置而实现利用YUI Compressor压缩JavaScript和CSS文件</a>。</p>
<p>直接在服务端进行合并和压缩，这非常的灵活，也极大的减轻了前端开发成果的部署过程，真使事半功倍。更多配置请看<a href="http://code.google.com/p/minify/wiki/CookBook">Minify CookBook</a>和<a href="http://code.google.com/p/minify/w/list">Wiki</a></p>
<p>小提示：Minify使用的<a href="http://www.opensource.org/licenses/bsd-license.php">New BSD License</a>，这就意味着使用者可以几乎自由的使用该代码。BSD协议鼓励代码共享，但需要尊重代码作者的著作权。BSD由于允许使用者修改和重新发布代码，也允许使用或在BSD代码上开发商业软件发布和销售，因此是对商业集成很友好的协议。而很多的公司企业在选用开源产品的时候都首选BSD协议，因为可以完全控制这些第三方的代码，在必要的时候可以修改或者二次开发。更多中文信息请看<a href="http://baike.baidu.com/view/1178915.html">《BSD协议》</a>。</p>
<h3>在YUI3中使用Minify</h3>
<p>在YUI2中，合并机制只支持库本身的文件，自定义的文件会单独一一加载。从YUI3开始，模块变得更小，这样就导致使用合并时URL会变长，但<a href="http://support.microsoft.com/kb/208427">在IE下URL的最大值是2083</a>，Apache默认的URL最大值是8192，所以当URL在对应浏览器下超出最大值时，YUI3会自动根据浏览器判断进行拆分成多个合并的URL，并且还提供了<a href="http://developer.yahoo.com/yui/3/api/Loader.html#property_maxURLLength"><code>maxURLLength</code></a>来设置最大值。而从YUI3.1.0开始，不仅仅支持自定义文件的合并，还支持可以使用多个提供合并服务的CDN，即可以对YUI组件使用http://yui.yahooapis.com这个CDN，其余文件使用其他支持合并的CDN，这样非常的实用、方便和灵活。示例<a href="http://dancewithnet.com/lab/2010/yui3-loader-and-minify/">在YUI3中使用Minify</a>就说明了这点。</p>
<p>由于YUI默认URL的合并形式和Minify的不相同，所以在YUI实例化时需要利用正则替换来实现YUI3支持Minify的URL合并形式，但这种方式既不灵活，且有风险，不友好又效率低。比较简单的方式是直接修改YUI 3的源码，如示例<a href="http://dancewithnet.com/lab/2010/yui3-loader-and-minify/fixed.html">在修改后的YUI3中使用Minify</a>。同时，YUI 3.1.*的版本有一个bug，即同时合并JavaScript和CSS时，较短的那个URL结尾处多一个&#038;符号，如<a href="http://dancewithnet.com/lab/2010/yui3-loader-and-minify/">示例在YUI3中使用Minify</a>中：</p>
<pre><code>http://yui.yahooapis.com/combo?3.1.1/build/widget/assets/skins/sam/widget.css&#038;
3.1.1/build/console/assets/skins/sam/console.css&#038;

http://dancewithnet.com/min/b=yui&#038;f=3.1.1/tabview/assets/skins/sam/tabview.css&#038;</code></pre>
<p>这两种都可以使用，虽然<a href="http://dancewithnet.com/2009/11/05/a-little-practice-about-js-lazy-load/#comment-219359">在早期的IE浏览器版本（如IE6）中会有无法解析的风险</a>，且影响某些特定情况下的缓存，但当使用修改后的YUI时，合并的URL变成类似<code>/min/b=yui&#038;f=3.1.1/tabview/assets/skins/sam/tabview.css,</code>的样子，就会出现bug了。对于YUI的Combo Handler来说这是一个小bug，所以<a href="http://yuilibrary.com/projects/yui3/ticket/2528680">YUI3把这个bug设置为P5</a>。但当我们改造YUI3来更好的支持Minify时，还要解决这个问题，具体方案请看示例<a href="http://dancewithnet.com/lab/2010/yui3-loader-and-minify/fixed.html">在修改后的YUI3中使用Minify</a>。</p>
<h3>在CDN上使用Minify</h3>
<p>CDN的全称是Content Delivery Network，即内容分发网络。其最常应用就是通过位于不同地理位置的服务器把静态资源部署到用户最近的边缘，这样能有效解决Web服务中大量静态资源的速度和性能问题。由于实施成本比较高，所以在实际的应用中，大型公司一般会组建自己的CDN，而小型公司只能租借第三方的CDN，但不管怎样这两种方式都不会影响在服务端实施合并和压缩程序。一般情况下，静态资源也并不是直接上传到CDN，而是先传到一台后台服务器，然后各地CDN的前端Cache服务器按需索取。YUI CDN的Combo Handler就是部署在其后台服务器上的，Minify也应如此。简单图示如下：<br /><img src="http://dancewithnet.com/wp-content/uploads/2010/06/cdn-and-minify.png" alt="" title="cdn-and-minify" width="678" height="201" class="alignnone size-full wp-image-1519" /></p>
<p>当一个资源请求到CDN时，CDN会先检查本地是否存在这个资源，如果有则会直接返回该资源，如果没有则会请求其后台服务器，后台服务器会依据资源URL的信息进行相应的处理，然后返回给CDN，CDN就会存储这个资源，再次出现这个资源请求时就无需请求后台服务器了。所以，虽然合并特别是压缩JavaScript和CSS文件是消耗时间的，但是由于只需要第一次，并且第一次基本上由我们自己访问掉（我们可以创建程序自动进行一次访问来保证，实际上图片优化也可以采用这种方式），所以基本上很安全。这正是目前在<a href="http://koubei.com">口碑网</a>实施的JavaScript和CSS合并方案，在<a href="http://www.slideshare.net/kavenyan/ss-2755539">第4届D2的《前端性能优化和自动化》</a>中也介绍了它。</p>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2010/06/08/minify-js-and-css-files-in-server/feed/</wfw:commentRss>
		<slash:comments>44</slash:comments>
		</item>
		<item>
		<title>动态加载JavaScript的小实践</title>
		<link>http://dancewithnet.com/2009/11/05/a-little-practice-about-js-lazy-load/</link>
		<comments>http://dancewithnet.com/2009/11/05/a-little-practice-about-js-lazy-load/#comments</comments>
		<pubDate>Wed, 04 Nov 2009 16:56:30 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Loader]]></category>
		<category><![CDATA[YUI]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/?p=1488</guid>
		<description><![CDATA[动态加载JavaScript文件和CSS资源为Web前端开发提供了巨大的灵活性，同时也实现了lazy load和按需加载，相比XMLHttpRequest而言其没有跨域的限制使其广泛应用。其基本原理是：在页面DOMReady后，利用... ]]></description>
			<content:encoded><![CDATA[<p>动态加载JavaScript文件和CSS资源为Web前端开发提供了巨大的灵活性，同时也实现了lazy load和按需加载，相比XMLHttpRequest而言其没有跨域的限制使其广泛应用。其基本原理是：在页面DOMReady后，利用JavaScript把指定文件路径的script和link元素插入到页面中，然后判断其加载状态再进行继续操作。</p>
<p><span id="more-1488"></span></p>
<p><a href="http://developer.yahoo.com/yui/3/get/">YUI的Get</a>就专门提供了一套动态加载的机制，是YUI最基础的功能之一。在YUI中利用Get加载JavaScript和CSS资源会在HTML的head节点中插入如下代码：</p>
<pre><code>&lt;script id="..." type="text/javascript" src="some.js"&gt;&lt;/script&gt;
&lt;link id="..." type="text/css" rel="stylesheet" href="some.css"&gt;
</code></pre>
<p>当页面编码和JavaScript或CSS资源编码不一致时，常见的方法是通过charset属性声明其编码，比如页面是gb2312，而资源文件为utf-8，则设置编码后其插入的代码是</p>
<pre><code><span>//YUI3.0.0 和 YUI 2.8.0中</span>
&lt;script id="..." type="text/javascript" src="some.js" charset="utf-8"&gt;&lt;/script&gt;
&lt;link id="..." type="text/css" rel="stylesheet" href="some.css" charset="utf-8"&gt;
</code></pre>
<p>然而，<a href="http://dancewithnet.com/lab/2009/yui-loader-bug-in-ie/in-gb2312.html">在IE的一些特殊情况下加载JavaScript时，当你刷新页面时会看到状态栏上有如下的错误提示</a>：<br /><img src="http://dancewithnet.com/wp-content/uploads/2009/11/yui-loader-bug-in-ie.png" alt="YUI3.0.0动态加载JavaScript的bug" title="YUI3.0.0动态加载JavaScript的bug" width="593" height="460" class="alignnone size-full wp-image-1489" /></p>
<p>当你<a href="http://dancewithnet.com/lab/2009/yui-loader-bug-in-ie/random-in-gb2312.html">通过随机参数让JavaScript文件不缓存</a>时，或者<a href="http://dancewithnet.com/lab/2009/yui-loader-bug-in-ie/fixed-in-gb2312.html">让script元素中的charset属性位于src属性之前（比如利用YUI2.8.0之前版本加载）</a>就不会有这个错误提示。所以，这个问题可能是IE的缓存解码机制的bug，也可以看着是<a href="http://yuilibrary.com/projects/yui3/ticket/2528363">YUI的bug（已经提交给YUI开发团队，将在3.1.0中解决）</a>。</p>
<p>因此，动态添加script或CSS资源时，把charset放在资源路径前面是最佳实践。<a href="http://dancewithnet.com/lab/2009/yui-loader-bug-in-ie/fixed-in-gb2312.html">对于YUI，暂时可以这样修改源码来修复</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2009/11/05/a-little-practice-about-js-lazy-load/feed/</wfw:commentRss>
		<slash:comments>26</slash:comments>
		</item>
		<item>
		<title>CSS实现HTML元素透明的那些事</title>
		<link>http://dancewithnet.com/2009/09/06/css-opacity/</link>
		<comments>http://dancewithnet.com/2009/09/06/css-opacity/#comments</comments>
		<pubDate>Sun, 06 Sep 2009 15:44:00 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[HTML & CSS]]></category>
		<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[-ms-filter]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[hasLayout]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[Mootools]]></category>
		<category><![CDATA[opacity]]></category>
		<category><![CDATA[YUI]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/?p=1469</guid>
		<description><![CDATA[CSS3草案中定义了{opacity:&#60;length&#62; &#124; inherit;}来声明元素的透明度，这已经得到了大多数现代浏览器的支持，而IE则很早通过特定的私有属性filter来实现的，所以HTML元素的透明效果已经无处... ]]></description>
			<content:encoded><![CDATA[<p>CSS3草案中定义了<a href="http://www.w3.org/TR/css3-color/#transparency"><code>{opacity:&lt;length&gt; | inherit;}</code></a>来声明元素的透明度，这已经得到了大多数现代浏览器的支持，而IE则很早通过特定的私有属性<a href="http://msdn.microsoft.com/en-us/library/ms532967%28VS.85%29.aspx"><code>filter</code></a>来实现的，所以HTML元素的透明效果已经无处不在了。首先看看<a href="http://developer.yahoo.com/yui/articles/gbs/">A级浏览器</a>所支持的用<a href="https://developer.mozilla.org/en/CSS/opacity">CSS实现元素透明的方案</a>：</p>
<p><span id="more-1469"></span></p>
<table>
<tr>
<th>浏览器</th>
<th>最低<br />版本</th>
<th>方案</th>
</tr>
<tr>
<th rowspan="3">Internet Explorer</th>
<td>4.0</td>
<td><code>filter: alpha(opacity=xx);</code></td>
</tr>
<tr>
<td>5.5</td>
<td><code>filter: progid:DXImageTransform.Microsoft.Alpha(opacity=xx);</code>
</td>
</tr>
<tr>
<td>8.0</td>
<td><code>filter: "alpha(opacity=xx)";<br />
filter: "progid:DXImageTransform.Microsoft.Alpha(opacity=xx)";<br />
-ms-filter: "alpha(opacity=xx)";<br />
-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(opacity=30)";</code>
</td>
</tr>
<tr>
<th>Firefox (Gecko)</th>
<td>0.9 (1.7)</td>
<td><code>opacity</code></td>
</tr>
<tr>
<th>Opera</th>
<td>9.0</td>
<td><code>opacity</code></td>
</tr>
<tr>
<th>Safari (WebKit)</th>
<td>1.2 (125)</td>
<td><code>opacity</code></td>
</tr>
</table>
<p>实际上在IE8中，-ms-filter是filter的别名，两者区别是<a href="http://msdn.microsoft.com/en-us/library/ms530752%28VS.85%29.aspx">-ms-filter的属相值必须被单引号或双引号包围</a>，而filter中则不是必须，而在IE8之前的版本中，filter的属性值必须不被单引号或双引号包围。</p>
<p id="hasLayout">IE中的HTML元素要实现透明，则其必须具备layout，这样的元素有仅可读的属性<a href="http://msdn.microsoft.com/en-us/library/ms530764%28VS.85%29.aspx">hasLayout</a>，且其值为true。具体情况如下：</p>
<ol>
<li><code>body</code>、<code>img</code>、<code>table</code>、<code>tr</code>、<code>th</code>、<code>td</code>等元素的<code>hasLayout</code>一直为<code>true</code>。</li>
<li><code>type</code>为<code>text</code>、<code>button</code>、<code>file</code>或<code>select</code>的<code>input</code>的<code>hasLayout</code>一直为<code>true</code>。</li>
<li>设置<code>{position:absolute}</code>的元素的<code>hasLayout</code>为<code>true</code></li>
<li>设置<code>{float:left|right}</code>的元素的<code>hasLayout</code>为<code>true</code></li>
<li>设置<code>{display:inline-block}</code>的元素的<code>hasLayout</code>为<code>true</code></li>
<li>设置<code>{height:xx}</code>或<code>{width:xx}</code>的元素必须具体以下两个条件之一，其<code>hasLayout</code>才能为<code>true</code>：
<ol>
<li>IE8兼容模式和IE8以前的浏览器中，在标准(strict)模式下其<code>display</code>的值是<code>block</code>，如<a href="http://dancewithnet.com/lab/2009/css-opacity/#demo3">demo3</a>就不行。</li>
<li>元素在怪癖模式（compat mode）下。</li>
</ol>
</li>
<li>设置了<code>{zoom:xx}</code>的元素在IE8的兼容模式或IE8之前的浏览器中其<code>hasLayout</code>为<code>true</code>，但在IE8的标准模式下则不会触发<code>hasLayout</code>。</li>
<li>设置了<code>{writing-mode:tb-rl}</code>的元素的<code>hasLayout</code>为<code>true</code>。</li>
<li>元素的<a href="http://msdn.microsoft.com/en-us/library/ms537837%28VS.85%29.aspx"><code>contentEditable</code></a>的属性值为<code>true</code>。</li>
<li>在IE8标准模式下设置了<code>{display:block}</code>的元素的<code>hasLayout</code>一直为<code>true</code>，如<a href="http://dancewithnet.com/lab/2009/css-opacity/#demo8">demo8</a>。</li>
</ol>
<p>关于hasLayout的更多详情可以看<a href="http://msdn.microsoft.com/en-us/library/bb250481%28VS.85%29.aspx">Exploring Internet Explorer &#8220;HasLayout&#8221; Overview</a>和<a href="http://www.satzansatz.de/cssd/onhavinglayout.html">On having layout</a></p>
<p>从上面就可以看出IE实现HTML元素的透明如此混乱，为了向下兼容和自己的私有属性让IE上实现元素透明有多种方式，比如<a href="http://dancewithnet.com/lab/2009/css-opacity/" class="link-btn">CSS Opacity实例中的demo1到demo8</a>，虽然<a href="http://blogs.msdn.com/ie/archive/2008/09/08/microsoft-css-vendor-extensions.aspx">IE团队推荐实现透明的方式</a>是：</p>
<pre><code>{
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";
  filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50);
  opacity: .5;
}</code></pre>
<p>而目前简单最好用的实现方式是<a href="http://dancewithnet.com/lab/2009/css-opacity/" class="link-btn">如CSS Opacity中demo4这样</a>：</p>
<pre><code>{
    filter:alpha(opacity=30);
    opacity:.3;
}</code></pre>
<p>实际上目前最流行的JavaScript框架的设置样式方法都是应用这种方式，并且针对IE设置了<code>{zoom:1}</code>来让元素的<code>hasLayout</code>为<code>true</code>，但在IE8的标准模式下<code>zoom</code>并不能触发<code>hasLayout</code>，所以利用它们设置<code>hasLayout</code>为<code>false</code>的元素的透明度时在IE8的标准模式下是失败的，这个bug在<a href="http://developer.yahoo.com/yui/">YUI</a><ins datetime="2009-09-09T09:38:41+08:00">（我已经给YUI团队提交了这个bug，他们会在<a href="http://yuilibrary.com/projects/yui2/ticket/2528440">下个版本修复</a>，最新的2.8.0中依旧存在，期待2.9.0吧）</ins>、<a href="http://prototypejs.org">Prototype</a>、<a href="http://jquery.com">jQuery</a>和<a href="http://mootools.net">Mootools</a>的最新版本中都存在，具体请在IE8标准模式下看<a href="http://dancewithnet.com/lab/2009/css-opacity/#demo9">demo9到demo11</a>。同样由于在IE8中设置透明度的方式多种多样，所以利用JavaScript获取HTML元素的透明度值需要考虑多种情况，YUI完美解决了这个问题，Prototype比jQuery稍微周全一点，而Mootools直接是<a href="https://mootools.lighthouseapp.com/projects/2706/tickets/707-getstyleopacity-always-returns-1">bug</a>，具体可以<a href="http://dancewithnet.com/lab/2009/css-opacity/" class="link-btn">在IE下看demo1到demo8</a>的演示。从这个角度给4个框架来个排名的话，YUI第一、Prototype第二、jQuery第三、Mootools垫底。</p>
<p>我简单的实现了设置和获取Opacity的函数，可以避开上面框架存在的bug，请<a href="http://dancewithnet.com/lab/2009/css-opacity/#demo12" class="link-btn">在IE8标准模式下看demo12</a>：</p>
<pre><code><span>//设置CSS opacity 属性的函数，解决IE8的问题</span>
var setOpacity = function(el,i){
  if(window.getComputedStyle){<span>// for non-IE</span>
    el.style.opacity = i;
  }else if(document.documentElement.currentStyle){ <span>// for IE</span>
    if(!el.currentStyle.hasLayout){
      el.style.zoom = 1;
    }
    if(!el.currentStyle.hasLayout){ <span>//在IE8中zoom不生效，所以再次设置inline-block</span>
      el.style.display = 'inline-block';
    }
    try{
      <span>//测试是否已有filter
      //http://msdn.microsoft.com/en-us/library/ms532847%28VS.85%29.aspx</span>
      if(el.filters){
        if(el.filters('alpha')){
	  el.filters('alpha').opacity = i * 100;
	}else{
	  el.style.filter += 'alpha(opacity='+ i * 100 +')';
	 }
       }
    }catch(e){
      el.style.filter = 'alpha(opacity='+ i * 100 +')';
    }
  }
}

<span>//获取CSS opacity 属性值的函数</span>
<span>//借鉴自http://developer.yahoel.com/yui/docs/YAHOO.util.Dom.html#method_getStyle</span>
var getOpacity = function(el){
  var value;
  if(window.getComputedStyle){
    value = el.style.opacity;
    if(!value){
      value = el.ownerDocument.defaultView.getComputedStyle(el,null)['opacity'];
    }
    return value;
  }else if(document.documentElement.currentStyle){
    value = 100;
    try { // will error if no DXImageTransform
        value = el.filters['DXImageTransform.Microsoft.Alpha'].opacity;
    } catch(e) {
        try { // make sure its in the document
            value = el.filters('alpha').opacity;
        } catch(err) {
        }
    }
    return value / 100;
  }
}
</code></pre>
<p>不得不说，这些事都是IE整出来的……</p>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2009/09/06/css-opacity/feed/</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>如何开始使用YUI Doc工具？</title>
		<link>http://dancewithnet.com/2008/12/30/why-start-yui-doc/</link>
		<comments>http://dancewithnet.com/2008/12/30/why-start-yui-doc/#comments</comments>
		<pubDate>Mon, 29 Dec 2008 16:42:59 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[YUI]]></category>
		<category><![CDATA[yuidoc]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/?p=1418</guid>
		<description><![CDATA[YUI Team实践出了一个高效易协作的前端代码开发流程：代码首先由Ant来组织管理和版本化、接着由JsLint来验证，然后由YUI Doc文档化、最后由YUI Compressor进行压缩发布。上个月初，YUI Team公布了这... ]]></description>
			<content:encoded><![CDATA[<p>YUI Team实践出了一个高效易协作的前端代码开发流程：代码首先由Ant来组织管理和版本化、接着由<a href="http://www.jslint.com/">JsLint</a>来验证，然后由<a href="http://developer.yahoo.com/yui/yuidoc/">YUI Doc</a>文档化、最后由<a href="http://developer.yahoo.com/yui/compressor/">YUI Compressor</a>进行压缩发布。上个月初，YUI Team公布了这个新的JavaScript API文档生成工具<a href="http://developer.yahoo.com/yui/yuidoc/">YUI Doc</a>，它本来专门为<a href="http://developer.yahoo.com/yui/">YUI</a>提供<a href="http://developer.yahoo.com/yui/docs/">API级别的文档</a>的，现在它开源为人民服务了。</p>
<p>YUI Doc和JavaDoc、JSDoc和<a href="http://code.google.com/p/jsdoc-toolkit/">JsDoc Toolkit</a>相似。YUI Doc是由注解驱动（comment-driven ）的系统，它通过解析代码中描述结构的注解来生成文档。由于它纯粹的依赖于注解，所以并不像一些模拟系统一样需要有惯用语和代码模式。更详细的介绍可以看<a href="http://developer.yahoo.com/yui/yuidoc/">YUI Doc的官方文档</a>和YUI blog上的《YUI Doc: A New Tool for Generating JavaScript API Documentation》（由于YUI blog咱们无法访问，比较好的解决方案就是在Google Reader中订阅它的Feed，直接输入 http://yuiblog.com即可。）</p>
<p>YUI Doc是基于Python开发，且依赖几个扩展库，加之其<a href="http://developer.yahoo.com/yui/yuidoc/#start">Getting Started</a>写的也比较含糊，所以如何使用这个工具反而成为第一道门槛，尤其对于那些对Python不熟悉的同学来说。所以，下面的重点是介绍如何在Windows上使用YUI Doc：<span id="more-1418"></span></p>
<ol>
<li>下载<a href="http://www.python.org/ftp/python/2.5.2/python-2.5.2.msi">Python2.5.2</a>安装之。<br />
虽然Python3.0和Python2.6都已经出来很久了，但之所以依旧选择Python2.5.2，是因为后面要用到的安装Python扩展库的工具<a href="http://pypi.python.org/pypi/setuptools#credits">setuptools</a>在Windows下的最新版本对应的是Python2.5。我不知道它是否支持2.5以上，有兴趣的可以试试。
</li>
<li>下载<a href="http://pypi.python.org/packages/2.5/s/setuptools/setuptools-0.6c9.win32-py2.5.exe#md5=602d06054ec1165e995ae54ac30884d7">setuptools-0.6c9.win32-py2.5.exe</a>并安装之，setuptools会自动安装到Python所在安装目录的Scripts目录下。<br />
<a href="http://peak.telecommunity.com/DevCenter/setuptools">setuptools</a>为Python提供了简单的包管理和发行功能。后面的扩展库的安装就是利用它的easy_install，非常方便。有兴趣的可以看看<a href="http://www.ibm.com/developerworks/cn/linux/l-cppeak3.html">《可爱的 Python: 使用 setuptools 孵化 Python egg》</a>。</li>
<li>为了使用方便需要配置一下“环境变量”，即在“我的电脑 》右键 》属性 》高级 》环境变量 》系统变量 》 选中Path 》 编辑”，在弹出框中加入：
<pre><code>;D:\Program Files\python;D:\Program Files\python\Scripts</code></pre>
<p>然后应用即可。前面的两个路径分别是我的Python和setuptools的安装路径，你需要修改成你自己的。
</li>
<li>开始 》运行 》(Win + R)输入“cmd”，输入：
<pre><code>python -c "import pkg_resources"</code></pre>
<p>没有任何输出，即表示setuptools安装成功。接着依次输入运行：</p>
<pre><code>easy_install Pygments
easy_install simplejson
easy_install Cheetah
</code></pre>
<p>setuptools会自动寻找并下载<a href="http://pygments.org/">Pygments</a>、<a href="http://svn.red-bean.com/bob/simplejson/tags/simplejson-1.3/docs/index.html">SimpleJSON</a>和<a href="http://www.cheetahtemplate.org/">Cheetah</a>这三个扩展库，并安装它。
</li>
<li>下载最新版本<a href="http://github.com/yui/yuidoc/downloads">YUI Doc</a>，并解压在某个目录下。复制其bin目录下的example.bat文件，重命名为test.bat，然后用记事本或其他编辑器打开并配置它:
<pre><code>SET yuidoc_home="D:\yui\yuidoc"
<span>REM YUI Doc的路径</span>
SET parser_in="D:\yui\src"
<span>REM 要生成文档的JS文件路径，比如为了测试就我临时建一个，里面就放着YUI 的 dom.js</span>
SET parser_out="D:\yui\src\parser"
<span>REM YUI Doc会把解析的JS文件提取出来所要存放的位置</span>
SET generator_out="D:\yui\src\generator"
<span>REM 生成文档存放的位置</span>
</code></pre>
<p>保存并运行test.bat后，就会发现D:\yui\src中多了parser和generator两个目录，而generator中正是你要的文档。
</li>
</ol>
<h3>支持中文注释的解决方案</h3>
<ol>
<li>下载最新版本<a href="http://github.com/yui/yuidoc/downloads">YUI Doc</a>，解决方案在<a href="http://github.com/yui/yuidoc/zipball/yuidoc-27">yuidoc-27</a>中验证通过</li>
<li>把所有.js文件都转成不带BOM的UTF-8编码</li>
<li>修改文件/bin/yuidoc_highlight.py：
<pre><code>from pygments.formatters import HtmlFormatter
<span>#新增下行</span>
import codecs
<span>...</span>
<span>#f=open(os.path.join(path, file))</span>
</span>#fileStr=StringIO(f.read()).getvalue()</span>
</span>#f.close()</span>
fileStr = codecs.open( os.path.join(path, file), "r", "utf-8" ).read()
log.info("highlighting " + file)

<span>#highlighted = highlightString(fileStr)</span>
highlighted = highlightString(unicode(fileStr))
</code></pre>
</li>
<li>在Python的\Lib\site-packages\下增加一个名为sitecustomize.py的文件，其内容为：
<pre><code>import sys
sys.setdefaultencoding('utf-8')
</code></pre>
</li>
</ol>
<p>谢谢小马提供中文注释的解决方案</p>
<p>学会使用工具仅仅是开始了一小步，仔细看看<a href="http://developer.yahoo.com/yui/yuidoc/#overview">YUI Doc的官方文档</a>吧，利用其来促使我们写出更高效优雅的前端代码并惠及更多的人才是一大步。</p>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2008/12/30/why-start-yui-doc/feed/</wfw:commentRss>
		<slash:comments>22</slash:comments>
		</item>
		<item>
		<title>第二届D2见闻和随想</title>
		<link>http://dancewithnet.com/2008/04/28/info-and-thoughts-about-2th-d2/</link>
		<comments>http://dancewithnet.com/2008/04/28/info-and-thoughts-about-2th-d2/#comments</comments>
		<pubDate>Sun, 27 Apr 2008 18:09:34 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[web2.0 & so on]]></category>
		<category><![CDATA[D2]]></category>
		<category><![CDATA[yahoo]]></category>
		<category><![CDATA[YUI]]></category>
		<category><![CDATA[前端]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/?p=1283</guid>
		<description><![CDATA[这个周末回京参加了期待已久的第二届D2前端技术论坛，见到众多的前端同行，更聆听了几场高质量的讲演，收获良多。讲演的资料整理后会在第二届D2前端技术论坛的官网上提供下载，同时也... ]]></description>
			<content:encoded><![CDATA[<p>这个周末回京参加了期待已久的<a href="http://d2forum.cn/">第二届D2前端技术论坛</a>，见到众多的前端同行，更聆听了几场高质量的讲演，收获良多。讲演的资料整理后会在<a href="http://d2forum.cn/">第二届D2前端技术论坛的官网</a>上提供下载，同时也会提供会议视频，强烈推荐前端工程师关注。</p>
<ol>
<li><a href="http://blog.csdn.net/aimingoo/">周爱民</a>的讲演“前端设计与开发的基本模式”，看起来很丰富，很多模式或理念听起来也蛮有争议，避免不了空和虚，但我不能不承认他提供了很多我有兴趣但尚未涉及东西，这些给了我新的视角。</li>
<li>黄继佳的讲演“Silverlight应用”，虽然很高兴他能来参加和支持D2，幻灯片也很cool，但我强烈的感觉这是一个很纯正的Silverlight的产品推广，我不是太喜欢。</li>
<li><a href="http://blog.hedgerwow.com/">Hedger Wang</a>的讲演“Enterprise Ajax in PHP”，是这次D2的精华。他提出管理Ajax在企业级应用的设计模式，很多正是我日常开发中遇到，比如他讲到的映射，我也曾经做过类似的解决方案，比如他讲到的对多次同一请求的管理，我也曾思考过，但那往往是一个个独立的小点，这次讲演终于让我有了从点到线到面的感觉。他的讲演也准备的相当好，既有总结，又有代码，同时利用生活中的例子来说明原理，想听不明白都不行。我不需要如何得称赞hedger的讲演，如果你的开发涉及到Ajax，那么你就应该去看看他的讲演。ps，祝他杭州玩的开心。</li>
<li><a href="http://nate.koechley.com/blog">Nate Koechly</a>的讲演“Enhanceing Web Sites With The YUI Library&#8221;(English)”，作为YUI开发的核心成员，这次讲演虽然有点推广<a href="http://developer.yahoo.com/yui/">YUI</a>的意味（在此有近一年应用<a href="http://developer.yahoo.com/yui/">YUI</a>经验的我也强烈推荐<a href="http://developer.yahoo.com/yui/">YUI</a>），但是仅仅从他幻灯片上就可以看出他事先的准备和用心，甚至他表达出了要学习汉语的意愿。但很遗憾的是，由于语言的原因，这次没有能充分的从Nate身上获取更多的更深的东西，虽然有hedger义务做翻译，虽然对nate的提问是最多的。</li>
<li><a href="http://agentzh.org/misc/blog/#main">章亦春</a>的讲演“Nifty web apps on an OpenResty”，讲的很有激情，也给出了一个新的Web OS，作为一个视角是一个很棒的东西，但是作为我个人来讲我并不赞同这个思路，我一直认为让一门语言处于它最适当的位置才是王道，就像语义化设计一样，应该用合适的标签来组织合适的数据。虽然章亦春提到了不应该对Javascript滥用，但是很遗憾的是我感觉这就是一种滥用。</li>
<li>案例分享阶段，<a href="http://realazy.org/blog/">贤安</a>的“如何写一个富文本编辑器”，小马的“前端开发工具介绍”，一位仁兄（不好意思，记不起来名字）的“用Adobe Air开发IM”，都很有意思，这些很务实的小分享越多越好，因为每个人的心得体会小窍门汇聚在一起就有了越来越顺畅的前端开发。</li>
</ol>
<p><span id="more-1283"></span></p>
<p>第二届D2已经结束，第三届目前还没有明确的主办方（有兴趣请看<a href="http://club.cn.yahoo.com/bbs/threadview/1600133944_25__pn1.html">如何申办D2</a>），我的一些想法和建议如下：</p>
<ol>
<li>主办D2是需要费用的，所以建议下一次D2可以有正式的赞助商和门票，这将能保证D2更好的运作。</li>
<li>不少人对我说互动不够，但是由于演讲本身就是一对多的，所以注定了互动是有限度的。建议通过在午餐和晚餐时话题分桌，一边吃，一边彼此认识，一边圆桌会议。</li>
<li>这次D2已经很务实了，下一次希望更务实。可以提前征集大家期望的讲演内容，可以参考大家主题邀请演讲嘉宾。同样也可以提前搜集分享案例，更好的更深入的组织分享。我期望下一次D2能遇到的内容：
<ol>
<li>语义化的HTML。这是一个最基础的东西，也将是一个巨大的挑战。</li>
<li>Firebug实战。虽然大家开发基本上离不开它，但是我总感觉并没有充分的利用它，每一个小技巧都可以让我们进步。</li>
<li>整站的CSS管理。这肯定是一个百花齐放的问题。</li>
<li>高性能的WEB页面。<a href="http://developer.yahoo.com/performance/">Yahoo的preformance</a>列了34条，但是我们的实战呢？</li>
<li>前端工程师如何推动整个项目的设计和开发流程？这就是需要实践+经验+效果。</li>
</ol>
</li>
</ol>
<p>中国雅虎主办第二届D2前端开发论坛<br /><img src="http://dancewithnet.com/wp-content/uploads/2008/04/2th-d2-1.jpg" alt="" title="D2前端开发者论坛" width="640" height="480" class="alignnone size-full wp-image-1284" /></p>
<p>坐着听讲演的开发者。由于2008的原因，北京的会议室不是特别好找，这次的会议室过于细长，hedger首先坐在了地上，并且号召大家都这么做，很多年没有坐在地上了，感觉不错。<br /><img src="http://dancewithnet.com/wp-content/uploads/2008/04/2th-d2-2.jpg" alt="" title="D2开发者论坛，坐着听开发" width="640" height="480" class="alignnone size-full wp-image-1285" /></p>
<p>Nate正在开讲，首先拿出相机拍一下听讲者。他的幻灯片开始部分用了中文，是他临时学的，拿到他名片的朋友也会发现，有一面是简体中文的。<br /><img src="http://dancewithnet.com/wp-content/uploads/2008/04/2th-d2-4.jpg" alt="" title="D2前端开发者论坛" width="640" height="480" class="alignnone size-full wp-image-1284" /></p>
<p>Nate讲演时发现的一个提示站点是否使用YUI的小工具。在他的演讲过程中，列出了当前哪些站点使用了YUI，估计都是用这个小工具挖掘的。<br /><img src="http://dancewithnet.com/wp-content/uploads/2008/04/2th-d2-3.jpg" alt="" title="D2前端开发者论坛" width="640" height="480" class="alignnone size-full wp-image-1284" /></p>
<p>hedger演讲中&#8230;<br /><img src="http://dancewithnet.com/wp-content/uploads/2008/04/2th-d2-5.jpg" alt="" title="D2前端开发者论坛" width="640" height="480" class="alignnone size-full wp-image-1284" /></p>
<p>部分现场的工作人员，我的同事们<br /><img src="http://dancewithnet.com/wp-content/uploads/2008/04/2th-d2-6.jpg" alt="" title="D2前端开发者论坛" width="640" height="480" class="alignnone size-full wp-image-1284" /></p>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2008/04/28/info-and-thoughts-about-2th-d2/feed/</wfw:commentRss>
		<slash:comments>32</slash:comments>
		</item>
		<item>
		<title>Firefox的默认样式表</title>
		<link>http://dancewithnet.com/2008/04/17/firefox-default-stylesheet/</link>
		<comments>http://dancewithnet.com/2008/04/17/firefox-default-stylesheet/#comments</comments>
		<pubDate>Wed, 16 Apr 2008 16:31:10 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[HTML & CSS]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[Firefox]]></category>
		<category><![CDATA[YUI]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/?p=1280</guid>
		<description><![CDATA[每个浏览器都有自己的默认样式，这是一段预定义的CSS，用以简单地呈现网页。在Firefox中的地址栏中输入resource://gre/res/html.css即可以看到该浏览器的默认样式。在Firebug 1.2 Alphas的styles中就可以... ]]></description>
			<content:encoded><![CDATA[<p>每个浏览器都有自己的默认样式，这是一段预定义的CSS，用以简单地呈现网页。在Firefox中的地址栏中输入<a href="resource://gre/res/html.css">resource://gre/res/html.css</a>即可以看到该浏览器的默认样式。在<a href="http://www.getfirebug.com/releases/">Firebug 1.2 Alphas</a>的styles中就可以看到默认样式对页面定义样式的影响。毫无疑问，理解和学习浏览器的默认样式能更好的理解浏览器对解析样式和呈现页面。Firefox3和Firefox2相比，默认样式仅有8处不同，但这些改变也可以让我们感觉到Firefox3在样式上的改进：<span id="more-1280"></span></p>
<pre><code>@namespace url(http://www.w3.org/1999/xhtml); <span>/* set default namespace to HTML */</span>

<span>/* bidi */</span>

[dir="rtl"] {
  direction: rtl;
  unicode-bidi: embed;
}
[dir="ltr"] {
  direction: ltr;
  unicode-bidi: embed;
}
bdo[dir] {
  unicode-bidi: bidi-override;
}

<span>/* blocks */</span>

html, div, map, dt, isindex, form {
  display: block;
}

body {
  display: block;
  margin: 8px;
}

p, dl, multicol {
  display: block;
  margin: 1em 0;
}

dd {
  display: block;
  -moz-margin-start: 40px;
}

blockquote {
  display: block;
  margin: 1em 40px;
}

address {
  display: block;
  font-style: italic;
}

center {
  display: block;
  text-align: -moz-center;
}

blockquote[type=cite] {
  display: block;
  margin: 1em 0px;
  <span>/*** start:Firefox2 ***/</span>
  padding-left: 1em;
  border-left: solid;
  <span>/*** end:Firefox2 ***/</span>
  <span>/*** start:Firefox3 ***/</span>
  -moz-padding-start: 1em;
  -moz-border-start: solid;
  <span>/*** end:Firefox3 ***/</span>
  border-color: blue;
  border-width: thin;
}

span[_moz_quote=true] {
  color: blue;
}

pre[_moz_quote=true] {
  color: blue;
}

h1 {
  display: block;
  font-size: 2em;
  font-weight: bold;
  margin: .67em 0;
}

h2 {
  display: block;
  font-size: 1.5em;
  font-weight: bold;
  margin: .83em 0;
}

h3 {
  display: block;
  font-size: 1.17em;
  font-weight: bold;
  margin: 1em 0;
}

h4 {
  display: block;
  font-weight: bold;
  margin: 1.33em 0;
}

h5 {
  display: block;
  font-size: 0.83em;
  font-weight: bold;
  margin: 1.67em 0;
}

h6 {
  display: block;
  font-size: 0.67em;
  font-weight: bold;
  margin: 2.33em 0;
}

listing {
  display: block;
  font-family: -moz-fixed;
  font-size: medium;
  white-space: pre;
  margin: 1em 0;
}

xmp, pre, plaintext {
  display: block;
  font-family: -moz-fixed;
  white-space: pre;
  margin: 1em 0;
}

<span>/* tables */</span>

table {
  display: table;
  border-spacing: 2px;
  border-collapse: separate;
  margin-top: 0;
  margin-bottom: 0;
  <span>/* XXXldb do we want this if we're border-collapse:collapse ? */</span>
  -moz-box-sizing: border-box;
  text-indent: 0;
}

table[align="left"] {
  float: left;
}

table[align="right"] {
  float: right;
  text-align: start;
}

table[rules]:not([rules="none"]) {
  border-collapse: collapse;
}

<span>/* caption inherits from table not table-outer */</span>
caption {
  display: table-caption;
  text-align: center;
  -moz-box-sizing: border-box;
}

table[align="center"] >gt; caption {
  margin-left: auto;
  margin-right: auto;
}

table[align="center"] >gt; caption[align="left"] {
  margin-right: 0;
}

table[align="center"] >gt; caption[align="right"] {
  margin-left: 0;
}

tr {
  display: table-row;
  vertical-align: inherit;
}

col {
  display: table-column;
}

colgroup {
  display: table-column-group;
}

tbody {
  display: table-row-group;
  vertical-align: middle;
}

thead {
  display: table-header-group;
  vertical-align: middle;
}

tfoot {
  display: table-footer-group;
  vertical-align: middle;
}

<span>/* for XHTML tables without tbody */</span>
table >gt; tr {
  vertical-align: middle;
}

td {
  display: table-cell;
  vertical-align: inherit;
  text-align: inherit;
  padding: 1px;
}

th {
  display: table-cell;
  vertical-align: inherit;
  font-weight: bold;
  padding: 1px;
}

tr >gt; form:-moz-is-html, tbody >gt; form:-moz-is-html,
thead >gt; form:-moz-is-html, tfoot >gt; form:-moz-is-html,
table >gt; form:-moz-is-html {
  <span>/* Important: don't show these forms in HTML */</span>
  display: none !important;
}

<span>/* inlines */</span>

q:before {
  content: open-quote;
}

q:after {
  content: close-quote;
}

b, strong {
  font-weight: bolder;
}

i, cite, em, var, dfn {
  font-style: italic;
}

tt, code, kbd, samp {
  font-family: -moz-fixed;
}

u, ins {
  text-decoration: underline;
}

s, strike, del {
  text-decoration: line-through;
}

blink {
  text-decoration: blink;
}

big {
  font-size: larger;
}

small {
  font-size: smaller;
}

sub {
  vertical-align: sub;
  font-size: smaller;
  line-height: normal;
}

sup {
  vertical-align: super;
  font-size: smaller;
  line-height: normal;
}

nobr {
  white-space: nowrap;
}

<span>/* titles */</span>
abbr[title], acronym[title] {
  border-bottom: dotted 1px;
}

<span>/* lists */</span>

ul, menu, dir {
  display: block;
  list-style-type: disc;
  margin: 1em 0;
  -moz-padding-start: 40px;
}

ol {
  display: block;
  list-style-type: decimal;
  margin: 1em 0;
  -moz-padding-start: 40px;
}

li {
  display: list-item;
  <span>/** start:Firefox2 **/</span>
  -moz-float-edge: margin-box;
  <span>/** end:Firefox2 **/</span>
}

<span>/* nested lists have no top/bottom margins */</span>
ul ul,   ul ol,   ul dir,   ul menu,   ul dl,
ol ul,   ol ol,   ol dir,   ol menu,   ol dl,
dir ul,  dir ol,  dir dir,  dir menu,  dir dl,
menu ul, menu ol, menu dir, menu menu, menu dl,
dl ul,   dl ol,   dl dir,   dl menu,   dl dl {
  margin-top: 0;
  margin-bottom: 0;
}

<span>/* 2 deep unordered lists use a circle */</span>
ol ul,   ul ul,   menu ul,   dir ul,
ol menu, ul menu, menu menu, dir menu,
ol dir,  ul dir,  menu dir,  dir dir {
  list-style-type: circle;
}

<span>/* 3 deep (or more) unordered lists use a square */</span>
ol ol ul,     ol ul ul,     ol menu ul,     ol dir ul,
ol ol menu,   ol ul menu,   ol menu menu,   ol dir menu,
ol ol dir,    ol ul dir,    ol menu dir,    ol dir dir,
ul ol ul,     ul ul ul,     ul menu ul,     ul dir ul,
ul ol menu,   ul ul menu,   ul menu menu,   ul dir menu,
ul ol dir,    ul ul dir,    ul menu dir,    ul dir dir,
menu ol ul,   menu ul ul,   menu menu ul,   menu dir ul,
menu ol menu, menu ul menu, menu menu menu, menu dir menu,
menu ol dir,  menu ul dir,  menu menu dir,  menu dir dir,
dir ol ul,    dir ul ul,    dir menu ul,    dir dir ul,
dir ol menu,  dir ul menu,  dir menu menu,  dir dir menu,
dir ol dir,   dir ul dir,   dir menu dir,   dir dir dir {
  list-style-type: square;
}

<span>/* leafs */</span>

<span>/* <lt;hr>gt; noshade and color attributes are handled completely by
 * the nsHTMLHRElement attribute mapping code
 */</span>
hr {
  display: block;
  height: 2px;
  <span>/** start:Firefox2 **/</span>
  border: 1px -moz-bg-inset;
  <span>/** end:Firefox2 **/</span>
  <span>/** start:Firefox3 **/</span>
  border: 1px inset;
  <span>/** end:Firefox3 **/</span>
  margin: 0.5em auto 0.5em auto;
  <span>/** start:Firefox3 **/</span>
  color: gray;
  <span>/** end:Firefox3 **/</span>
  -moz-float-edge: margin-box;
  -moz-box-sizing: border-box;
}

hr[size="1"] {
  <span>/** start:Firefox2 **/</span>
  border-style: -moz-bg-solid none none none;
  <span>/** end:Firefox2 **/</span>
  <span>/** start:Firefox3 **/</span>
  border-style: solid none none none;
  <span>/** end:Firefox3 **/</span>
}

*|*:-moz-any-link img, img[usemap], object[usemap] {
  border: 2px solid;
}

<span>/** start:Firefox3 **/</span>
img:-moz-broken::before, input:-moz-broken::before,
img:-moz-user-disabled::before, input:-moz-user-disabled::before,
img:-moz-loading::before, input:-moz-loading::before,
applet:-moz-empty-except-children-with-localname(param):-moz-broken::before,
applet:-moz-empty-except-children-with-localname(param):-moz-user-disabled::before {
  content: -moz-alt-content !important;
  unicode-bidi: embed;
}

object:-moz-broken >gt; *|*, applet:-moz-broken >gt; *|*
object:-moz-user-disabled >gt; *|*, applet:-moz-user-disabled >gt; *|* {
  <span>/*
    Inherit in the object's alignment so that if we aren't aligned explicitly
    we'll end up in the right place vertically.  See bug 36997.  Note that this
    is not !important because we _might_ be aligned explicitly.
  */</span>
  vertical-align: inherit;
}

img:-moz-suppressed, input:-moz-suppressed, object:-moz-suppressed,
embed:-moz-suppressed, applet:-moz-suppressed {
  <span>/*
    Set visibility too in case the page changes display.  Note that we _may_
    want to just set visibility and not display, in general, if we find that
    display:none breaks too many layouts.  And if we decide we really do want
    people to be able to right-click blocked images, etc, we need to set
    neither one, and hack the painting code.... : (
   */</span>
  display: none !important;
  visibility: hidden !important;
}
<span>/** end:Firefox3 **/</span>  

img[usemap], object[usemap] {
  color: blue;
}

frameset {
  display: block ! important;
  overflow: -moz-hidden-unscrollable;
  position: static ! important;
  float: none ! important;
  border: none ! important;
}

frame {
  border: none ! important;
}

iframe {
  border: 2px inset;
}

noframes {
  display: none;
}

spacer {
  position: static ! important;
  float: none ! important;
}

canvas {
  -moz-user-select: none;
}

<span>/* focusable content: anything w/ tabindex >gt;=0 is focusable */</span>
abbr:focus, acronym:focus, address:focus, applet:focus, b:focus,
base:focus, big:focus, blockquote:focus, br:focus, canvas:focus, caption:focus,
center:focus, cite:focus, code:focus, col:focus, colgroup:focus, dd:focus,
del:focus, dfn:focus, dir:focus, div:focus, dl:focus, dt:focus, em:focus,
fieldset:focus, font:focus, form:focus, h1:focus, h2:focus, h3:focus, h4:focus,
h5:focus, h6:focus, hr:focus, i:focus, img:focus, ins:focus,
kbd:focus, label:focus, legend:focus, li:focus, link:focus, menu:focus,
object:focus, ol:focus, p:focus, pre:focus, q:focus, s:focus, samp:focus,
small:focus, span:focus, strike:focus, strong:focus, sub:focus, sup:focus,
table:focus, tbody:focus, td:focus, tfoot:focus, th:focus, thead:focus,
tr:focus, tt:focus, u:focus, ul:focus, var:focus {
  <span>/** start:Firefox2 **/</span>
   outline: 1px dotted invert;
  <span>/** end:Firefox2 **/</span>
  <span>/** start:Firefox3 **/</span>
  <span>/* Don't specify the outline-color, we should always use initial value. */</span>
   outline: 1px dotted;
  <span>/** end:Firefox3 **/</span>
}

<span>/* hidden elements */</span>
area, base, basefont, head, meta, script, style, title,
noembed, param {
   display: none;
}

<span>/* emulation of non-standard HTML <lt;marquee>gt; tag */</span>
marquee {
  <span>/** start:Firefox2 **/</span>
  display: block;
  <span>/** end:Firefox2 **/</span>
  <span>/** start:Firefox3 **/</span>
  width: -moz-available;
  display: inline-block;
  vertical-align: text-bottom;
  text-align: start;
  <span>/** end:Firefox3 **/</span>
  -moz-binding: url('chrome://xbl-marquee/content/xbl-marquee.xml#marquee-horizontal');
}

marquee[direction="up"], marquee[direction="down"] {
  -moz-binding: url('chrome://xbl-marquee/content/xbl-marquee.xml#marquee-vertical');
  height: 200px;
}

<span>/* PRINT ONLY rules follow */</span>
@media print {

  marquee { -moz-binding: none; }

  <span>/* XXX this should not be necessary, we should be stopping blinking
     of any kind in print preview, not just the <lt;blink>gt; element */</span>
  blink {
    text-decoration: none;
  }

}</code></pre>
<p>虽然CSS2.1的附录里给了<a href="http://www.w3.org/TR/CSS21/sample.html">HTML4默认样式的建议(Appendix D. Default style sheet for HTML 4)</a>，这本身就不是一个很完美的解决方案，加上各个浏览器附加上一点自己私有的属性，Firefox默认样式表中清楚的说明了这点，导致了各个浏览器的默认样式表不尽相同，比如对比这份参考CSS2.1的对HTML4默认样式的建议通过实践总结出来的<a href="http://gabrieleromanato.altervista.org/css-test/internet-explorer-6-default-style-sheet/index.html">IE6的默认样式表(INTERNET EXPLORER 6 DEFAULT STYLE SHEET)</a>。解决这个问题的常见方法就是通过一个通用的CSS文件来重置HTML标签的样式，使其在各个浏览器中表现的一样，比如<a href="http://developer.yahoo.com/yui/reset/">YUI Reset CSS</a>和Eric Meyer的<a href="http://meyerweb.com/eric/tools/css/reset/">CSS Tools: Reset CSS</a>就是很好的解决方案。</p>
<p>扩展阅读：<a href="http://meyerweb.com/eric/thoughts/2004/09/15/emreallyem-undoing-htmlcss/">Really Undoing html.css</a> &#8211; Eric Meyer</p>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2008/04/17/firefox-default-stylesheet/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>扩展YUI Loader</title>
		<link>http://dancewithnet.com/2008/03/26/extend-yuiloader/</link>
		<comments>http://dancewithnet.com/2008/03/26/extend-yuiloader/#comments</comments>
		<pubDate>Wed, 26 Mar 2008 15:45:24 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[yahoo]]></category>
		<category><![CDATA[YAHOO_config]]></category>
		<category><![CDATA[YUI]]></category>
		<category><![CDATA[YUILoader]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/2008/03/26/extend-yuiloader/</guid>
		<description><![CDATA[YUI Loader是YUI的动态载入外部Javascript和CSS文件的整体解决方案。它的可靠、安全、高效，优化了页面的呈现速度，实现了外部Js和CSS的按需加载。
在YUI 2.4.0到2.5.1版本中，YUI Loader通过其addModule()... ]]></description>
			<content:encoded><![CDATA[<p><a href="http://developer.yahoo.com/yui/yuiloader/">YUI Loader</a>是YUI的动态载入外部Javascript和CSS文件的整体解决方案。它的可靠、安全、高效，优化了页面的呈现速度，实现了外部Js和CSS的按需加载。</p>
<p>在YUI 2.4.0到2.5.1版本中，<a href="http://developer.yahoo.com/yui/yuiloader/">YUI Loader</a>通过其<a href="http://developer.yahoo.com/yui/yuiloader/#addmodule"><code>addModule()</code></a>方法只能配置一个YUI Loader实例的加载模块信息，无法配置全局的加载模块信息。实际中，能够全局的配置加载文件的模块信息对于统一维护非常的重要，特别是在静态文件服务器设置了上传文件不可以修改和删除情况下。下面是解决这个问题的两个方法：<span id="more-1273"></span></p>
<h3>方法1：修改YUI Loader源文件，引入YAHOO_config.load来配置全局信息</h3>
<p>在YUI两个全局变量之一的<a href="http://developer.yahoo.com/yui/docs/YAHOO_config.html">    <code>YAHOO_config</code></a>中,有一个<code>load</code>属性是用来配置YUI Loader的全局信息的，但是遗憾的是仅仅是2.4.0之前的版本支持。</p>
<h4>1、修改YUI Loader源文件</h4>
<pre><code>var Y=YAHOO, util=Y.util, lang=Y.lang, env=Y.env;
<span>/*
 *在上面一行代码的位置下面加上下面的代码：
 *判断当YAHOO_config存在且有load属性时，把YAHOO_config.load赋值给变量Y_load
 */</span>
if('undefined'!== typeof YAHOO_config){
	if(lang.hasOwnProperty(YAHOO_config,'load')){
		var Y_load = YAHOO_config.load;
	}
}
<span>...</span>
this.base = YUI.info.base;
<span>/*把上面一行修改为下面一行，这样可以用过YAHOO_config.load.base来指定YUI组件的路径*/</span>
this.base  = (lang.hasOwnProperty(Y_load,'base'))?Y_load.base:YUI.info.base;
<span>...</span>
this.moduleInfo = lang.merge(YUI.info.moduleInfo);
<span>/*把上面一行修改为下面一行，这样可以用过YAHOO_config.load.moduleInfo来指定YUI组件的路径*/</span>
this.moduleInfo = (lang.hasOwnProperty(Y_load,'moduleInfo'))?
lang.merge(YUI.info.moduleInfo,Y_load.moduleInfo):lang.merge(YUI.info.moduleInfo);
</code></pre>
<h4>2、在YUI Loader文件前写下如下配置文件：</h4>
<pre><code>YAHOO_config = {
load : {
 base : 'http://cn.yui.yahooapis.com/2.5.1/build/',
 <span>/*
 *  通用的非YUI组件和不自动加载皮肤的YUI组件
 *  @name   string
 *  @type   string
 *  @fullpath   string
 *  @requires   array
 *  @optinal    array
 *  @skinnable  boolean
 */</span>
 moduleInfo : {
<span>/*
 *YUI的组件中，有皮肤的组件使用时都会自动加载皮肤
 *比如require(['container'])时，会加载container.js，也会加载container.css
 *但是实际应用中，往往不会直接使用YUI的默认皮肤
 *<a href="http://developer.yahoo.com/yui/yuiloader/#usingskins">利用YUI Loader本身的skins属性设置</a>，只能在具体的YUI实例中使用，且需要满足YUI的文件结构
 *利用insert({},'js')方法虽然只能加载Js，但如何require()方法中的CSS也会被过滤掉
 *所以最好的方法是全局性的把其skinnable属性值修改为false
 */</span>
  'container': {
   'type': 'js',
   'path': 'container/container-min.js',
   'requires': ['dom', 'event'],
   'optional': ['dragdrop', 'animation', 'connection'],
   'supersedes': ['containercore'],
   'skinnable': false
  },
  'dwncontainercss' : {
   'type' : 'css',
   'fullpath' : '/lab/2008/extend-yuiloader/container.css'
  },
  'dwncarouselcss':{
   'name' : 'dwncarouselcss',
   'type' : 'css',
   'fullpath' : '/lab/2008/extend-yuiloader/carousel.css'
  },
  'dwncarousel':{
   'type' : 'js',
   'fullpath' : '/lab/2008/extend-yuiloader/carousel-min.js',
   'requires':['dwncarouselcss','yahoo','event','dom',
                'containercore','animation']
  }
 }
}
}</code></pre>
<p>请看<a href="/lab/2008/extend-yuiloader/" class="link-btn">演示实例1</a></p>
<h3>方法2：利用YAHOO.lang.extend方法封装一个新的Loader</h3>
<pre><code>YAHOO.namespace('CN.util');
<span>/* start:YAHOO.CN.util.YUILoader */</span>
YAHOO.CN.util.YUILoader = function(o){
 YAHOO.CN.util.YUILoader.superclass.constructor.call(this,o);
  this.base = 'http://cn.yui.yahooapis.com/2.5.1/build/';
  this.addModule({
   'name': 'container',
   'type': 'js',
   'path': 'container/container-min.js',
   'requires': ['dom', 'event'],
   'optional': ['dragdrop', 'animation', 'connection'],
   'supersedes': ['containercore'],
   'skinnable': false
  });
  this.addModule({
   'name' : 'dwncontainercss',
   'type' : 'css',
   'fullpath' : '/lab/2008/extend-yuiloader/container.css'
  });
  this.addModule({
   'name' : 'dwncarouselcss',
   'type' : 'css',
   'fullpath' : '/lab/2008/extend-yuiloader/carousel.css'
  });
  this.addModule({
   'name' : 'dwncarousel',
   'type' : 'js',
   'fullpath' : '/lab/2008/extend-yuiloader/carousel-min.js',
   'requires':['dwncarouselcss','yahoo','event','dom',
                'containercore','animation']
  });
}
YAHOO.lang.extend(YAHOO.CN.util.YUILoader,YAHOO.util.YUILoader);
<span>/* end: YAHOO.CN.util.YUILoader */</span></code></pre>
<p>YAHOO.CN.util.YUILoader的使用和<a href="http://developer.yahoo.com/yui/yuiloader/#using">YAHOO.util.YUILoader的使用</a>没有任何区别。请看<a href="/lab/2008/extend-yuiloader/index1.html" class="link-btn">演示实例2</a></p>
<h3><ins datetime="2008-03-28T09:46:41+08:00">两种方法的优劣比较</ins></h3>
<p>方法1的缺点是需要修改YUI Loader的源文件，而方法二2只是外层增加一个壳，比较友好和保险，但方法1直接修改配置文件的方法比方法2每次实例化都需要通过特定方法修改配置文件要高效，特别是当添加或者修改的配置模块间也有依赖关系的时候，方法2很可能会因为过度运算而死掉。例如把实例中的模块<code>container</code>依赖于<!--more-->dwncontainercss的时候，方法1没有问题（请看<a href="/lab/2008/extend-yuiloader/index2.html" class="link-btn">演示实例3</a>），但方法2下浏览器会提示脚本忙（请看<a href="/lab/2008/extend-yuiloader/index3.html" class="link-btn">演示实例4</a>）。</p>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2008/03/26/extend-yuiloader/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Javascript的一种模块模式</title>
		<link>http://dancewithnet.com/2007/12/04/a-javascript-module-pattern/</link>
		<comments>http://dancewithnet.com/2007/12/04/a-javascript-module-pattern/#comments</comments>
		<pubDate>Mon, 03 Dec 2007 16:49:07 +0000</pubDate>
		<dc:creator>秦歌</dc:creator>
				<category><![CDATA[Javascript & DOM & AJAX]]></category>
		<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[yahoo]]></category>
		<category><![CDATA[YUI]]></category>
		<category><![CDATA[命名空间]]></category>

		<guid isPermaLink="false">http://dancewithnet.com/2007/12/04/a-javascript-module-pattern/</guid>
		<description><![CDATA[全局变量是魔鬼。在YUI中，我们仅用两个全局变量：YAHOO和YAHOO_config。YUI的一切都是使用YAHOO对象级的成员或这个成员作用域内的变量。我们建议在你的应用程序也使用类似的规则。
Douglas Crockfo... ]]></description>
			<content:encoded><![CDATA[<p><a href="http://yuiblog.com/blog/2006/06/01/global-domination/">全局变量是魔鬼。</a>在YUI中，我们仅用两个全局变量：YAHOO和YAHOO_config。YUI的一切都是使用YAHOO对象级的成员或这个成员作用域内的变量。我们建议在你的应用程序也使用类似的规则。</p>
<p>Douglas Crockford已经传授了一个有用的单例模式（singleton pattern）实现此规则，我认为他的模式有益于你基于YUI的那些应用。Douglas叫它模块模式（module pattern）。它是如下工作的：<span id="more-1222"></span></p>
<ol>
<li>创建一个命名空间对象：如果你使用YUI，可以用YAHOO.namespace()方法：<code>    YAHOO.namespace("myProject");</code>这分配了一个空的myProject对象，是YAHOO的一个成员（如    果myProject已存在的话，则不会被覆盖）。现在我们可以开始添加YAHOO.myProject的成员。
</li>
<li>对你的命名空间对象分配一个匿名函数返回值：
<pre><code>YAHOO.myProject.myModule = function () {
return  {
  myPublicProperty: "我作为YAHOO.myProject.myModule.myPublicProperty被访问。";
  myPublicMethod: function () {
    YAHOO.log("我作为YAHOO.myProject.myModule.myPublicMethod被访问。");
  }
};
}();<span> // 这个括号导致匿名函数被执行且返回</span>
</code></pre>
<p>注意有闭合大括号和紧接着的括号()的最后一行&#8212;这种符号导致了匿名函数的立即执行，返回包含myPublicProperty和myPublicMethod的对象。只要这个匿名函数一返回，返回对象就作为YAHOO.myProject.myModule被访问。</li>
<li>在匿名函数中，在返回语句前加入“私有”方法和变量。到目前为止，我们只是将myPublicProperty和myPublicMethod直接分配到YAHOO.myProject.myModule中。此外，当我们在返回语句之前放置一些代码时，这个模式还支持被增加的效用。
<pre><code>YAHOO.myProject.myModule = function () {
<span>//“私有”变量：</span>
var myPrivateVar = "我仅能在YAHOO.myProject.myModule内被访问。";
<span>//私有方法：</span>
var myPrivateMethod = function () {
    YAHOO.log("我仅能在YAHOO.myProject.myModule内被访问。");
}

return  {
    myPublicProperty: "我作为YAHOO.myProject.myModule.myPublicProperty能被访问。"
    myPublicMethod: function () {
    YAHOO.log("我作为YAHOO.myProject.myModule.myPublicMethod能被访问。");
    <span>//在myProject,我能访问私有的变量和方法</span>
    YAHOO.log(myPrivateVar);
    YAHOO.log(myPrivateMethod());
    <span>//myPublicMethod的原生作用域是myProject，我们可以用“this”来访问公共成员。</span>
    YAHOO.log(this.myPublicProperty);
    }
};
}();</code></pre>
<p>在上面的代码中，我们从一个匿名函数返回有两个成员的一个对象。在YAHOO.myProject.myModule内部，可以分别用this.myPublicProperty和this.myPublicMethod来访问。在YAHOO.myProject.myModule外部，公共成员可以用YAHOO.myProject.myModule.myPublicProperty和YAHOO.myProject.myModule.myPublicMethod来访问。<br />私有变量myPrivateProperty和myPrivateMethod只能被匿名函数本身或返回对象的成员访问。尽管匿名函数会立即执行和终止，但它们依然是保留着，凭借闭包（closure）的力量——通过一个函数的局部变量在这个函数返回后是保留的规则。只要 YAHOO.myProject.myModule需要它们，我们的两个私有变量就不会被销毁。</li>
<li>实践这个模式。让我们来看看这个模式的一个常见应用案例。假设你有一个列表，列表上的一些项可以被拖拽。应用拖拽的项上有拖拽的CSS类。
<pre><code>&lt;!--这个脚本文件包含所有的YUI实用程序--&gt;
  &lt;script type=&quot;text/javascript&quot;
src=&quot;http://yui.yahooapis.com/2.2.2/build/utilities/utilities.js&quot;&gt;&lt;/script&gt;
&lt;ul id=&quot;myList&quot;&gt;
   &lt;li class=&quot;draggable&quot;&gt;一项&lt;/li&gt;
   &lt;li&gt;二项&lt;/li&gt; &lt;!--二项将不能被拖拽--&gt;
   &lt;li class=&quot;draggable&quot;&gt;三项&lt;/li&gt;
   &lt;/ul&gt;
&lt;script&gt;
  YAHOO.namespace(&quot;myProject&quot;);
  YAHOO.myProject.myModule = function () {
 <span>//YUI实用程序的私有简写引用：</span>
  var yue = YAHOO.util.Event,
  yud = YAHOO.util.Dom;
 <span>//私有方法</span>
  var getListItems = function () {
 <span>// 注意这个地方使用其他的私有变量，包括&quot;yud&quot;YAHOO.util.Dom的简写：</span>
  var elList = yud.get(&quot;myList&quot;);
  var aListItems = yud.getElementsByClassName(
  &quot;draggable&quot;, <span>//得到仅有CSS类&quot;draggable&quot;的项</span>
  &quot;li&quot;, <span>//仅返回列表项</span>
  elList <span>//限定搜索改元素的子</span>
  );
  return aListItems;
  };
 <span>//这个放回的对象将变成YAHOO.myProject.myModule:</span>
  return  {
 aDragObjects: [], <span>//可对外访问的，存储DD对象</span>
 init: function () {
  <span>//直到DOM完全加载好，才实现列表项可拖拽：</span>
  yue.onDOMReady(this.makeLIsDraggable, this, true);
  },
 makeLIsDraggable: function () {
  var aListItems = getListItems(); <span>//我们可以拖拽的那些元素</span>
  for (var i=0, j=aListItems.length; i&lt;j; i++) {
  this.aDragObjects.push(new YAHOO.util.DD(aListItems[i]));
  }
  }
 };
  }();
<span>//上面的代码已经执行，所以我们能立即访问init方法：</span>
  YAHOO.myProject.myModule.init();
  &lt;/script&gt;</code></pre>
<p>这是一个简单的例子，特意写的详细一些——如果按照这种方式做，我们无疑能把它写的更紧凑。当项目变得更加复杂和它的API增加，这个模式缩放的很好。通过这种方式，它避免了全局命名空间，提供了对外的可以访问的API方法，支持受保护或“私有”的数据和方法。</li>
</ol>
<ul class="refer">
<li>[1]原文：<a href="http://yuiblog.com/blog/2007/06/12/module-pattern/">《a javascript module pattern》</a>。这是在YUI blog上的，有的地方可能打不开，可以搜一下英文的转载或者利用搜索引擎的缓存也能看。
<li>
<li>[2]<a href="http://www.javaeye.com/topic/93650">《A JavaScript Module Pattern &#8211; JavaScript的一种模组模式》</a>这是别人的翻译，参考了不少，不过感觉挺不方便看的，这是我翻译的这篇文章的一个原因，当然最主要的原因是这篇文章算是学习YUI的最基础的文章了，整个YUI的模块模式都基于此。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://dancewithnet.com/2007/12/04/a-javascript-module-pattern/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
	</channel>
</rss>

