<?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>影の域 &#187; Web</title>
	<atom:link href="http://www.zfkun.com/blog/index.php/archives/category/code/web/feed" rel="self" type="application/rss+xml" />
	<link>http://www.zfkun.com/blog</link>
	<description>时光真的如水...</description>
	<lastBuildDate>Thu, 29 Apr 2010 06:43:15 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>IE6+和FF的CSS Hack</title>
		<link>http://www.zfkun.com/blog/index.php/archives/142</link>
		<comments>http://www.zfkun.com/blog/index.php/archives/142#comments</comments>
		<pubDate>Thu, 22 Apr 2010 16:59:21 +0000</pubDate>
		<dc:creator>影之迷惑</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[ff]]></category>
		<category><![CDATA[hack]]></category>
		<category><![CDATA[ie]]></category>

		<guid isPermaLink="false">http://www.zfkun.com/blog/?p=142</guid>
		<description><![CDATA[一、CSS HACK
以下两种方法几乎能解决现今所有HACK.
1, !important
随着IE7对!important的支持, !important 方法现在只针对IE6的HACK.(注意写法.记得该声明位置需要提前.)
&#60;style&#62;
#wrapper
{
width: 100px!important; /* IE7+FF */
width: 80px; /* IE6 */
}
&#60;/style&#62;
2, IE6/IE77对FireFox
*+html 与 *html 是IE特有的标签, firefox 暂不支持.而*+html 又为 IE7特有标签.
&#60;style&#62;
#wrapper
{
#wrapper { width: 120px; } /* FireFox */
*html #wrapper { width: 80px;} /* ie6 fixed */
*+html #wrapper { width: 60px;} /* ie7 fixed, 注意顺序 */
}
&#60;/style&#62;
注意:
*+html 对IE7的HACK 必须保证HTML顶部有如下声明：
&#60;!DOCTYPE HTML PUBLIC &#8220;-//W3C//DTD HTML 4.01 Transitional//EN&#8221;　&#8221;http://www.w3.org/TR/html4/loose.dtd&#8221;&#62;
二、万能 float 闭合(非常重要!)
关于 [...]]]></description>
			<content:encoded><![CDATA[<p>一、CSS HACK<br />
以下两种方法几乎能解决现今所有HACK.</p>
<p>1, !important</p>
<p>随着IE7对!important的支持, !important 方法现在只针对IE6的HACK.(注意写法.记得该声明位置需要提前.)<br />
&lt;style&gt;<br />
#wrapper<br />
{<br />
width: 100px!important; /* IE7+FF */<br />
width: 80px; /* IE6 */<br />
}<br />
&lt;/style&gt;</p>
<p>2, IE6/IE77对FireFox</p>
<p>*+html 与 *html 是IE特有的标签, firefox 暂不支持.而*+html 又为 IE7特有标签.<br />
&lt;style&gt;<br />
#wrapper<br />
{<br />
#wrapper { width: 120px; } /* FireFox */<br />
*html #wrapper { width: 80px;} /* ie6 fixed */<br />
*+html #wrapper { width: 60px;} /* ie7 fixed, 注意顺序 */<br />
}<br />
&lt;/style&gt;</p>
<p>注意:<br />
*+html 对IE7的HACK 必须保证HTML顶部有如下声明：<br />
&lt;!DOCTYPE HTML PUBLIC &#8220;-//W3C//DTD HTML 4.01 Transitional//EN&#8221;　&#8221;http://www.w3.org/TR/html4/loose.dtd&#8221;&gt;</p>
<p>二、万能 float 闭合(非常重要!)</p>
<p>关于 clear float 的原理可参见 [How To Clear Floats Without Structural Markup]<br />
将以下代码加入Global CSS 中,给需要闭合的div加上 即可,屡试不爽.<br />
&lt;style&gt;<br />
/* Clear Fix */</p>
<p>.clearfix:after<br />
{<br />
content:&#8221;.&#8221;;<br />
display:block;<br />
height:0;<br />
clear:both;<br />
visibility:hidden;<br />
}<br />
.clearfix<br />
{<br />
display:inline-block;<br />
}<br />
/* Hide from IE Mac */<br />
.clearfix {display:block;}<br />
/* End hide from IE Mac */<br />
/* end of clearfix */<br />
&lt;/style&gt;</p>
<p>三、其他兼容技巧(再次啰嗦)</p>
<p>1, FF下给 div 设置 padding 后会导致 width 和 height 增加, 但IE不会.(可用!important解决)<br />
2, 居中问题.<br />
1).垂直居中.将 line-height 设置为 当前 div 相同的高度, 再通过 vertical-align: middle.( 注意内容不要换行.)<br />
2).水平居中. margin: 0 auto;(当然不是万能)<br />
3, 若需给 a 标签内内容加上 样式, 需要设置 display: block;(常见于导航标签)<br />
4, FF 和 IE 对 BOX 理解的差异导致相差 2px 的还有设为 float的div在ie下 margin加倍等问题.<br />
5, ul 标签在 FF 下面默认有 list-style 和 padding . 最好事先声明, 以避免不必要的麻烦. (常见于导航标签和内容列表)<br />
6, 作为外部 wrapper 的 div 不要定死高度, 最好还加上 overflow: hidden.以达到高度自适应.<br />
7, 关于手形光标. cursor: pointer. 而hand 只适用于 IE.</p>
<p>1 针对firefox ie6 ie7的css样式<br />
现在大部分都是用!important来hack，对于ie6和firefox测试可以正常显示，<br />
但是ie7对!important可以正确解释，会导致页面没按要求显示！找到一个针<br />
对IE7不错的hack方式就是使用“*+html”，现在用IE7浏览一下，应该没有问题了。<br />
现在写一个CSS可以这样：</p>
<p>#1 { color: #333; } /* Moz */<br />
* html #1 { color: #666; } /* IE6 */<br />
*+html #1 { color: #999; } /* IE7 */<br />
那么在firefox下字体颜色显示为#333，IE6下字体颜色显示为#666，IE7下字体颜色显示为#999。</p>
<p>2 css布局中的居中问题<br />
主要的样式定义如下：</p>
<p>body {TEXT-ALIGN: center;}<br />
#center { MARGIN-RIGHT: auto; MARGIN-LEFT: auto; }<br />
说明：<br />
首先在父级元素定义TEXT-ALIGN: center;这个的意思就是在父级元素内的内容居中；对于IE这样设定就已经可以了。<br />
但在mozilla中不能居中。解决办法就是在子元素定义时候设定时再加上“MARGIN-RIGHT: auto;MARGIN-LEFT: auto; ”<br />
需要说明的是，如果你想用这个方法使整个页面要居中，建议不要套在一个DIV里，你可以依次拆出多个div，<br />
只要在每个拆出的div里定义MARGIN-RIGHT: auto;MARGIN-LEFT: auto; 就可以了。</p>
<p>3 盒模型不同解释.</p>
<p>#box{ width:600px; //for ie6.0- w\idth:500px; //for ff+ie6.0}<br />
#box{ width:600px!important //for ff width:600px; //for ff+ie6.0 width /**/:500px; //for ie6.0-}</p>
<p>4 浮动ie产生的双倍距离</p>
<p>#box{ float:left; width:100px; margin:0 0 0 100px; //这种情况之下IE会产生200px的距离 display:inline; //使浮动忽略}<br />
这里细说一下block,inline两个元素,Block元素的特点是:总是在新行上开始,高度,宽度,行高,边距都可以控制(块元素);Inline元素的特点是:和其他元素在同一行上,&#8230;不可控制(内嵌元素);</p>
<p>#box{ display:block; //可以为内嵌元素模拟为块元素 display:inline; //实现同一行排列的的效果 diplay:table;</p>
<p>5 IE与宽度和高度的问题</p>
<p>IE不认得min-这个定义，但实际上它把正常的width和height当作有min的情况来使。这样问题就大了，如果只用宽度和高度，<br />
正常的浏览器里这两个值就不会变，如果只用min-width和min-height的话，IE下面根本等于没有设置宽度和高度。<br />
比如要设置背景图片，这个宽度是比较重要的。要解决这个问题，可以这样：<br />
#box{ width: 80px; height: 35px;}html&gt;body #box{ width: auto; height: auto; min-width: 80px; min-height: 35px;}</p>
<p>6 页面的最小宽度</p>
<p>min-width是个非常方便的CSS命令，它可以指定元素最小也不能小于某个宽度，这样就能保证排版一直正确。但IE不认得这个，<br />
而它实际上把width当做最小宽度来使。为了让这一命令在IE上也能用，可以把一个&lt;div&gt; 放到 &lt;body&gt; 标签下，然后为div指定一个类：<br />
然后CSS这样设计：<br />
#container{ min-width: 600px; width:expression(document.body.clientWidth &lt; 600? &#8220;600px&#8221;: &#8220;auto&#8221; );}<br />
第一个min-width是正常的；但第2行的width使用了Javascript，这只有IE才认得，这也会让你的HTML文档不太正规。它实际上通过Javascript的判断来实现最小宽度。</p>
<p>7 清除浮动</p>
<p>.hackbox{ display:table; //将对象作为块元素级的表格显示}或者.hackbox{ clear:both;}<br />
或者加入:after（伪对象）,设置在对象后发生的内容，通常和content配合使用，IE不支持此伪对象，非Ie 浏览器支持，<br />
所以并不影响到IE/WIN浏览器。这种的最麻烦的&#8230;&#8230;#box:after{ content: &#8220;.&#8221;; display: block; height: 0; clear: both; visibility: hidden;}</p>
<p>8 DIV浮动IE文本产生3象素的bug</p>
<p>左边对象浮动，右边采用外补丁的左边距来定位，右边对象内的文本会离左边有3px的间距.</p>
<p>#box{ float:left; width:800px;}#left{ float:left; width:50%;}#right{ width:50%;}*html #left{ margin-right:-3px; //这句是关键}<br />
HTML代码&lt;div&gt; &lt;div&gt;&lt;/div&gt; &lt;div&gt;&lt;/div&gt;&lt;/div&gt;</p>
<p>9 属性选择器(这个不能算是兼容,是隐藏css的一个bug)</p>
<p>p[id]{}div[id]{}<br />
这个对于IE6.0和IE6.0以下的版本都隐藏,FF和OPera作用<br />
属性选择器和子选择器还是有区别的,子选择器的范围从形式来说缩小了,属性选择器的范围比较大,如p[id]中,所有p标签中有id的都是同样式的.</p>
<p>10 IE捉迷藏的问题</p>
<p>当div应用复杂的时候每个栏中又有一些链接，DIV等这个时候容易发生捉迷藏的问题。<br />
有些内容显示不出来，当鼠标选择这个区域是发现内容确实在页面。<br />
解决办法：对#layout使用line-height属性 或者给#layout使用固定高和宽。页面结构尽量简单。</p>
<p>11 高度不适应</p>
<p>高度不适应是当内层对象的高度发生变化时外层高度不能自动进行调节，特别是当内层对象使用<br />
margin 或paddign 时。<br />
例：<br />
&lt;div&gt;<br />
&lt;p&gt;p对象中的内容&lt;/p&gt;<br />
&lt;/div&gt;<br />
CSS：#box {background-color:#eee; }<br />
#box p {margin-top: 20px;margin-bottom: 20px; text-align:center; }<br />
解决方法：在P对象上下各加2个空的div对象CSS代码：.1{height:0px;overflow:hidden;}或者为DIV加上border属性。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zfkun.com/blog/index.php/archives/142/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Data URI 和 MHTML</title>
		<link>http://www.zfkun.com/blog/index.php/archives/138</link>
		<comments>http://www.zfkun.com/blog/index.php/archives/138#comments</comments>
		<pubDate>Sat, 10 Apr 2010 03:32:45 +0000</pubDate>
		<dc:creator>影之迷惑</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[base64]]></category>
		<category><![CDATA[datauri]]></category>
		<category><![CDATA[mhtml]]></category>

		<guid isPermaLink="false">http://www.zfkun.com/blog/?p=138</guid>
		<description><![CDATA[Data URI是由RFC 2397定义的一种把小文件直接嵌入文档的方案。通过如下语法就可以把小文件变成指定编码直接嵌入到页面中。
MHTML是MIME HTML (Multipurpose Internet Mail Extension HTML)的缩写，是由RFC 2557定义的把一个多媒体的页面所有内容都保存到同一个文档解决方案。这个方案是由微软提出从IE5.0开始支持，另外Opera9.0也开始支持，Safari可以把文件保存为.mht（MHTML文件的后缀）格式，但不支持显示它。]]></description>
			<content:encoded><![CDATA[<h3>Data URI</h3>
<p><a href="http://en.wikipedia.org/wiki/Data_URI_scheme">Data URI</a>是由<a href="http://tools.ietf.org/html/rfc2397">RFC 2397</a>定义的一种把小文件直接嵌入文档的方案。通过如下语法就可以把小文件变成指定编码直接嵌入到页面中：</p>
<pre><code>data:[&lt;MIME-type&gt;][;base64],&lt;data&gt;
</code></pre>
<ol>
<li>MIME-type：指定嵌入数据的<a href="http://zh.wikipedia.org/wiki/MIME">MIME</a>。其形式是<code>[type]/[subtype]; parameter</code>，比如png图片对应的MIME是image/png。parameter可以用來指定附加的信息，更多情況下是用于指定text/plain和text/htm等的文字编码方式的charset参数。默认是text/plain;charset=US-ASCII。</li>
<li>base64：声明后面的数据的编码是<a href="http://zh.wikipedia.org/wiki/Base64">base64</a>的，否则数据必须要用百分号编码（即对内容进行urlencode）。</li>
</ol>
<p> </p>
<p>在上个世纪<a href="http://www.w3.org/TR/1999/REC-html401-19991224/struct/objects.html#h-13.3.1">HTML4.01引入了Data URI方案</a>，到今天为止<a href="http://en.wikipedia.org/wiki/Data_URI_scheme#Web_browser_support">除了IE6和IE7之外，所有主流浏览器都支持</a>，但<a href="http://msdn.microsoft.com/en-us/library/cc848897%28VS.85%29.aspx">IE8对Data URI的支持还是有限制的</a>，只支持object（仅是图片时）、img、input type=image、link和CSS中的URL，且数据量不能大于32K。</p>
<h4>优点：</h4>
<ol>
<li><a href="http://developer.yahoo.com/performance/rules.html#num_http">减少HTTP请求数</a>，没有了TCP连接消耗和同一域名下浏览器的并发数限制。</li>
<li>对于小文件会降低带宽。虽然编码后数据量会增加，但是却减少了http头，当http头的数据量大于文件编码的增量，那么就会降低带宽。</li>
<li>对于HTTPS站点，HTTPS和HTTP混用会有安全提示，而HTTPS相对于HTTP来讲开销要大更多，所以Data URI在这方面的优势更明显。</li>
<li>可以把整个多媒体页面保存为一个文件。</li>
</ol>
<h4>缺点：</h4>
<ol>
<li>无法被重复利用，同一个文档应用多次同一个内容，则需要重复多次，数据量大量增加，增加了下载时间。</li>
<li>无法被独自缓存，所以其包含文档重新加载时，它也要重新加载。</li>
<li>客户端需要重新解码和显示，增加了点消耗。</li>
<li>不支持数据压缩，base64编码会增加1/3大小，而urlencode后数据量会增加更多。</li>
<li>不利于安全软件的过滤，同时也存在一定的安全隐患。</li>
</ol>
<h3>MHTML</h3>
<p>MHTML是<a href="http://en.wikipedia.org/wiki/MHTML">MIME HTML (Multipurpose Internet Mail Extension HTML)</a>的缩写，是由<a href="http://tools.ietf.org/html/rfc2557">RFC 2557</a>定义的把一个多媒体的页面所有内容都保存到同一个文档解决方案。这个方案是由微软提出从IE5.0开始支持，另外Opera9.0也开始支持，Safari可以把文件保存为.mht（MHTML文件的后缀）格式，但不支持显示它。</p>
<p>MHTML和Data URI还比较类似，有更强大的功能和更复杂的语法，并且没有Data URI中“无法被重复利用”的缺点，但MHTML使用起来不够灵活方便，比如对资源引用的URL在mht文件中可以是相对地址，否则必须是绝对地址。hedger在<a href="http://www.hedgerwow.com/360/dhtml/base64-image/demo.php">《Cross Browser Base64 Encoded Images Embedded in HTML》</a>针对IE的解决方案使用的是相对路径就是因为声明了<code>Content-type:message/rfc822</code>使IE按照MHTML来解析，如果不修改<code>Content-type</code>则需要使用MHTML协议，这个时候必须使用绝对路径，如<a href="http://www.phpied.com/mhtml-when-you-need-data-uris-in-ie7-and-under/">《MHTML – when you need data: URIs in IE7 and under》</a>。</p>
<h3>应用</h3>
<p>Data URI和MHTML两者的配合可以完整的解决所有的主流浏览器，它们由于无法被缓存和重复利用的缺陷，所以并不适合直接在页面中使用，但在CSS和JavaScript文件中对图片适当地使用有非常大的优越性：</p>
<ol>
<li>大大减少请求数，现在大型网站的CSS引用了大量的图片资源。</li>
<li>CSS和JavaScript都可以被缓存，间接的实现了数据的缓存。</li>
<li>利用CSS可以解决Data URI的重复利用问题</li>
<li>告别<a href="http://www.alistapart.com/articles/sprites">CSS Sprites</a>，CSS Sprites的出现是为了减少请求数，但它除了<a href="http://blog.vlad1.com/2009/06/22/to-sprite-or-not-to-sprite/">带来在不确定情况下的异常</a>外，CSS Sprites还需要人为的图片合并，即使有合并工具也依旧必须人为地在如何有效的拼图上耗费大量的时间，并带来维护的困难。当你遵循一定的设计原则后，你就可以完全抛弃CSS Sprites来编写CSS，最后使用工具在上传到服务器环节把图片转换成Data URI和MHTML，如<a href="http://bluehua.org/tag/data-uri">《利用data-uri合并样式表和图片》</a>中用python实现的工具，这可以节约大量的时间。</li>
<li>base64编码把图片文件增加了1/3，Data URI和MHTML同时使用相当于增加了2/3，但CSS和JavaScript可以使用<a href="http://developer.yahoo.com/performance/rules.html#gzip">gzip压缩</a>，其可以节省2/3的数据量，所以使用gzip压缩后的最终数据量是<code>(1 + 1/3) * 2 * (1/3) = 8/9</code>，所以最终流量是减少的。</li>
</ol>
<p>为了方便在CSS中实现Data URI和MHTML，我写了一个Data URI &amp; MHTML 生成器，你可以看利用其生成<a href="http://dancewithnet.com/lab/2009/data-uri-mhtml/create/1250345288.php">Data URI &amp; MHTML应用实例</a>。</p>
<p>其他DEMO：   <a href="http://phpied.com/files/mhtml/mhtml.html" target="_blank">demo1</a>      <a href="http://labs.aoao.org.cn/yep/test.html" target="_blank">demo2</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zfkun.com/blog/index.php/archives/138/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>5 个简单实用的 CSS 属性</title>
		<link>http://www.zfkun.com/blog/index.php/archives/131</link>
		<comments>http://www.zfkun.com/blog/index.php/archives/131#comments</comments>
		<pubDate>Tue, 09 Mar 2010 01:57:06 +0000</pubDate>
		<dc:creator>影之迷惑</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[clip]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[cursor]]></category>
		<category><![CDATA[display]]></category>
		<category><![CDATA[min-height]]></category>
		<category><![CDATA[white-space]]></category>

		<guid isPermaLink="false">http://www.zfkun.com/blog/?p=131</guid>
		<description><![CDATA[这篇文章介绍了 5 个实用的 CSS 属性。你应该很熟悉，但很可能很少会使用到。我并不是在谈论展望全新的 CSS3 属性，我指的是旧的 CSS2 中的属性，如：clip，min-height，white-space，curosr 和 display 等一些被所有浏览器广泛支持的属性。]]></description>
			<content:encoded><![CDATA[<p>这篇文章介绍了 5 个实用的 <strong>CSS</strong> 属性。你应该很熟悉，但很可能很少会使用到。我并不是在谈论展望全新的 CSS3 属性，我指的是旧的 CSS2 中的属性，如：clip，min-height，white-space，curosr 和 display 等一些被所有浏览器广泛支持的属性。因此，千万不要错过这篇文章，因为你可能发现它们竟有如此之大的用途。</p>
<p><strong>1、CSS Clip</strong></p>
<p>剪辑 (clip) 属性就像一个面具。它允许你使用矩形掩盖页面元素的内容。要剪辑一个元素：你必须指定其 position 属性为 absolute，然后指定相对于元素的 top，right，bottom，left 值。</p>
<p><img src="http://www.blueidea.com/articleimg/2010/03/7410/01.gif" border="0" alt="" width="470" height="349" /></p>
<p><strong>图片剪辑实例（<a href="http://www.webdesignerwall.com/wp-content/uploads/2009/11/css-clip.html" target="_blank">演示</a>）</strong></p>
<p>以下示例演示了如何使用 clip 属性掩盖一张图片。首先，指定 &lt;div&gt; 元素为 position:relative，然后指定 &lt;img&gt; 元素为 position:absolute，并且根据实际需要设定 rect 值。</p>
<p><img src="http://www.blueidea.com/articleimg/2010/03/7410/02.gif" border="0" alt="" width="470" height="219" /></p>
<pre name="code" class="css">
.clip {
  position: relative;
  height: 130px;
  width: 200px;
  border: solid 1px #ccc;
}
.clip img {
  position: absolute;
  clip: rect(30px 165px 100px 30px);
}
</pre>
<pre><strong>图像调整尺寸和剪辑（<a href="http://www.webdesignerwall.com/wp-content/uploads/2009/11/css-clip.html" target="_blank">演示</a>）</strong></pre>
<p>在这个示例中，我将展示如何调整图像尺寸和剪辑图片。素材图片是矩形的，我想将其削减至 50％ 的尺寸，用来创建一个正方形格式的缩略图。因此，我用宽度和高度属性来调整图像，并使用 clip 剪辑属性予以掩盖。然后用 left 属性将图片移开左侧 15px 的距离。</p>
<p><img src="http://www.blueidea.com/articleimg/2010/03/7410/03.gif" border="0" alt="" width="470" height="422" /></p>
<pre name="code" class="css">
.gallery li {
  float: left;
  margin: 0 10px 0 0;
  position: relative;
  width: 70px;
  height: 70px;
  border: solid 1px #000;
}
.gallery img {
  width: 100px;
  height: 70px;
  position: absolute;
  clip: rect(0 85px 70px 15px);
  left: -15px;
}
</pre>
<pre><strong>2、Min-height （<a href="http://www.webdesignerwall.com/wp-content/uploads/2009/11/min-height.html" target="_blank">演示</a>）</strong></pre>
<p>min-height 属性允许你指定元素的最小高度，适用于需要平衡布局的情况。我将它用于 <a href="http://jobs.webdesignerwall.com/" target="_blank">Job 面板</a>上，以确保内容区域高于侧边栏。</p>
<p><img src="http://www.blueidea.com/articleimg/2010/03/7410/04.gif" border="0" alt="" width="470" height="270" /></p>
<pre name="code" class="css">
.with_minheight {
  min-height: 550px;
}
</pre>
<p><strong>IE6 的 Min-height hack</strong></p>
<p>注：神奇的 IE6 原生不支持 min-height 属性，不过幸好有一个 <a href="http://www.dustindiaz.com/min-height-fast-hack/">min-height hack</a>。</p>
<pre name="code" class="css">
.with_minheight {
  min-height:550px;
  height:auto !important;
  height:550px;
}
</pre>
<pre><strong>3、White-space（<a href="http://www.webdesignerwall.com/wp-content/uploads/2009/11/white-space.html" target="_blank">演示</a>）</strong></pre>
<p>white-space 属性指定了元素中空白的处理方式。比如，指定 white-space:nowrap 会阻止文本自动换行。</p>
<p><img src="http://www.blueidea.com/articleimg/2010/03/7410/05.gif" border="0" alt="" width="470" height="258" /></p>
<pre name="code" class="css">
em {
  white-space: nowrap;
}
</pre>
<p><strong>4、Cursor（<a href="http://www.webdesignerwall.com/wp-content/uploads/2009/11/cursor.html" target="_blank">演示</a>）</strong></p>
<p>如果你改变了按钮的行为，其指针也应该随之改变。比如，当一个按钮不可用时，指针应该改变为默认的箭头，来表明它不可点击。因此，cursor 属性在开发 Web 应用程序时相当有用。</p>
<p><img src="http://www.blueidea.com/articleimg/2010/03/7410/06.gif" border="0" alt="" width="470" height="200" /></p>
<pre name="code" class="css">
.disabled {
  cursor: default;
}

.busy {
  cursor: wait;
}

.clickable:hover {
  cursor: pointer;
}
</pre>
<pre><strong>5、Display inline / block（<a href="http://www.webdesignerwall.com/wp-content/uploads/2009/11/display.html" target="_blank">演示</a>）</strong></pre>
<p>如果你不知道：块级元素是作为独立的一行来渲染的，而行内元素是在同一行被渲染的。&lt;div&gt;，&lt;h1&gt; 和 &lt;p&gt; 标签都是块级元素，&lt;em&gt;，&lt;span&gt;，&lt;strong&gt; 都是行内元素。通过 display:inline 或 block 的方式，你可以重设这些元素的 display 样式。</p>
<p><img src="http://www.blueidea.com/articleimg/2010/03/7410/07.gif" border="0" alt="" width="470" height="206" /></p>
<pre name="code" class="css">
.block em {
  display: block;
}

.inline h4, .inline p {
  display: inline;
}
</pre>
<pre>英文原稿：<a href="http://www.webdesignerwall.com/tutorials/5-simple-but-useful-css-properties" target="_blank">5 Simple, But Useful CSS Properties | WebDesignWall</a>
翻译整理：<a href="http://www.mangguo.org/5-simple-but-useful-css-properties" target="_blank">5 个简单实用的 CSS 属性 | 芒果</a></pre>
<p>本文链接：<a href="http://www.blueidea.com/tech/web/2010/7410.asp" target="_blank">http://www.blueidea.com/tech/web/2010/7410.asp</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zfkun.com/blog/index.php/archives/131/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Comet—“服务器推”技术</title>
		<link>http://www.zfkun.com/blog/index.php/archives/115</link>
		<comments>http://www.zfkun.com/blog/index.php/archives/115#comments</comments>
		<pubDate>Wed, 03 Mar 2010 06:02:46 +0000</pubDate>
		<dc:creator>影之迷惑</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[comet]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[push]]></category>

		<guid isPermaLink="false">http://www.zfkun.com/blog/?p=115</guid>
		<description><![CDATA[Comet指的是一种Web应用程序架构。可以直接说，它不是一种技术，而是一种思想，只是这种思想采用了已有的技术去实现。在这种思想里，客户端（Client）不需要显式地向服务器端（Server）发出请求，Server会在其数据发生变化的时候主动将数据异步发送给Client，从而使Client能够及时更新数据并呈现给用户。它不同于传统的Web，也不同于当前流行的Ajax，这种思想非常架构思想非常适合event-driven(事件驱动)式的Web应用和对交互性及实时性要求很强的应用，比如股票交易，聊天室，Web IM，网游等。]]></description>
			<content:encoded><![CDATA[<h2>一、名称解释：</h2>
<p>Comet最早是由Alex Russell（Dojo Toolkit 项目主管和Dojo Foundation主席）在自己的博客中提出的术语，他是这样说的：”New services like Jot Live and Meebo are built with a style of data transmission that is neither traditional nor Ajax. Their brand of low-latency data transfer to the browser is unique, and it is becoming ever-more common. Lacking a better term, I’ve taken to calling this style of event-driven, server-push data streaming “Comet”.” “They all use long-lived HTTP connections to reduce the latency with which messages are passed to the server. In essence, they do not poll the server occasionally. Instead the server has an open line of communication with which it can push data to the client.”</p>
<p>Comet指的是一种Web应用程序架构。可以直接说，它不是一种技术，而是一种思想，只是这种思想采用了已有的技术去实现。在这种思想里，客户端（Client）不需要显式地向服务器端（Server）发出请求，Server会在其数据发生变化的时候主动将数据异步发送给Client，从而使Client能够及时更新数据并呈现给用户。它不同于传统的Web，也不同于当前流行的Ajax，这种思想非常架构思想非常适合event-driven(事件驱动)式的Web应用和对交互性及实时性要求很强的应用，比如股票交易，聊天室，Web IM，网游等。</p>
<h2>二、成功案例：</h2>
<ul>
<li><a href="http://mail.google.com/mail/help/chat.html" target="_blank">GMail’s GTalk integration</a></li>
<li><a href="http://jotlive.com/" target="_blank">Jot Live</a></li>
<li><a href="http://renkoo.com/" target="_blank">Renkoo</a></li>
<li><a href="http://meebo.com/" target="_blank">Meebo</a></li>
</ul>
<h2>三、实现方式：</h2>
<p>Comet使用Client和Server之前的HTTP长链接最为数据传输的通道。</p>
<p>实现Comet，最常见的有下面两种方式：</p>
<ol>
<li>Ajax的长轮询（long-polling）：Javascript在处理完服务器返回的信息后再次发出请求，重新建立连接。不同于一般的Ajax，Javascript请求Server，无数据时Server不中断请求，still loading，在一定时间内，获取到数据后，返回请求，又Javascript获取数据后再次发出请求，由此轮询。需要注意的是请求的间隔时间以及每次请求的最长Loading时间。<br />
优点：异步请求；无需浏览器任何插件支持；采用Ajax技术，兼容性强；<br />
缺点：会产生大量的通信量，只能通过增加轮询的时间间隔来减轻Server的压力；</li>
<li>Iframe结合Htmlfile流（streaming）：通过在页面上嵌入一个隐藏的Iframe，设置其src属性为一个长连接的请求，Server采用flush方式将数据作为前端Javascript函数的参数传递；<br />
优点：不会有很大的通信量，而且数据接收非常及时，并且无中断；<br />
缺点：会产生进度条的Loading状态并一直穿着，用户使用体验很不好，在Google Talk中，通过Htmlfile Active解决了IE下的进度条显示问题；保持长期链接也非常耗服务器资源；</li>
</ol>
<h2>四、临时采用方案：</h2>
<p>目前，白社会(bai.sohu.com)采用了第一种方式来实现实时消息的推送，这种方式还存在一个问题就是，在多个tab页下，如何保证没有相同域的长连接请求（IE在同域下只能同时支持两个长链接），于是采用了子域形式来区分多个域，以保证每个tab页下访问的地址都不在一个域名下，此时问题又出来了，出现了Ajax跨域名请求，不过这个问题比较常见，解决方案也很多，我们采用的是Iframe形式；由此，为了实现Comet，我们走了很长一条路，虽然路的确走完了，但是走得很长很艰难，这也是为什么称它为“临时解决方案”，因为它并不是一个完美的方案，但我也相信，以后会更加完美。</p>
<h2>五、现有可参考框架</h2>
<ol>
<li>Cometd：官方地址：<a href="http://www.cometd.org" target="_blank">www.cometd.org<br />
</a>可以参考<a href="http://www.blogjava.net/xmatthew/archive/2008/11/20/208911.html" target="_blank">http://www.blogjava.net/xmatthew/archive/2008/11/20/208911.html</a></li>
<li>Pushlet：官方地址：<a href="http://www.pushlets.com" target="_blank">www.pushlets.com</a><br />
pushlet 提供了基于 AJAX 的 JavaScript 库文件用于实现长轮询方式的”服务器推”；还提供了基于 iframe 的 JavaScript 库文件用于实现流方式的”服务器推”。<br />
可以参考<a href="http://http://www.javaeye.com/topic/89158" target="_blank">http://www.javaeye.com/topic/89158</a></li>
</ol>
<h2>六、文章参考</h2>
<ol>
<li><a href="http://www.ibm.com/developerworks/cn/web/wa-lo-comet/" target="_blank">Comet：基于 HTTP 长连接的”服务器推”技术</a></li>
<li><a href="http://www.ibm.com/developerworks/cn/web/wa-lo-w2fpak-comet/index.html" target="_blank">实战 Comet 应用程序开发</a></li>
<li><a href="http://en.wikipedia.org/wiki/Comet_(programming)" target="_blank">Comet on wikipedia</a></li>
</ol>
<p>最后，本人对Comet也未进行深入的研究，只是希望通过此文能给大家起一个抛砖引玉的作用，希望大家能够在客户端实时技术上能够起点帮助作用，能够越来越丰富我们前端技术。</p>
<p>原文地址： <a href="http://ued.sohu.com/article/118">http://ued.sohu.com/article/118</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zfkun.com/blog/index.php/archives/115/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Understanding and Solving Internet Explorer Leak Patterns</title>
		<link>http://www.zfkun.com/blog/index.php/archives/109</link>
		<comments>http://www.zfkun.com/blog/index.php/archives/109#comments</comments>
		<pubDate>Sun, 28 Feb 2010 06:01:57 +0000</pubDate>
		<dc:creator>影之迷惑</dc:creator>
				<category><![CDATA[JavaScript]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[closure]]></category>
		<category><![CDATA[dom]]></category>
		<category><![CDATA[gc]]></category>
		<category><![CDATA[ie]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[leak]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[reference]]></category>

		<guid isPermaLink="false">http://www.zfkun.com/blog/?p=109</guid>
		<description><![CDATA[In the past, memory leaks haven't posed huge problems for Web developers. Pages were kept relatively simple and navigation between different locations within a site was a great way to clean up any loose memory. If there was a leak, it was most likely small enough to go unnoticed.

New Web applications live up to higher standards. A page might run for hours without being navigated and retrieve updated information dynamically through Web services. Language features are pushed to the breaking point by combining complex event schemes, object-oriented JScript, and closures to produce entire applications. With these and other changes, certain memory leak patterns are becoming more prominent, especially those previously hidden by navigation.

The good news is that memory leak patterns can be easily spotted if you know what to look for. Most of the troublesome patterns you might face have known workarounds requiring only a small amount of extra work on your behalf. While some pages might still fall prey to small memory leaks, the most noticeable ones can be easily removed.]]></description>
			<content:encoded><![CDATA[<h2><strong>Understanding and Solving Internet Explorer Leak Patterns</strong></h2>
<p><!--Content type: PSDK_3. Transform: webcollection2mtps.xslt.--><a id="ie_leakpattern"><!----></a></p>
<p>Justin Rogers<br />
Microsoft Corporation</p>
<p>June 2005</p>
<h2>The Evolution of the Web Developer</h2>
<p>In the past, memory leaks haven&#8217;t posed huge problems for Web developers. Pages were kept relatively simple and navigation between different locations within a site was a great way to clean up any loose memory. If there was a leak, it was most likely small enough to go unnoticed.</p>
<p>New Web applications live up to higher standards. A page might run for hours without being navigated and retrieve updated information dynamically through Web services. Language features are pushed to the breaking point by combining complex event schemes, object-oriented JScript, and closures to produce entire applications. With these and other changes, certain memory leak patterns are becoming more prominent, especially those previously hidden by navigation.</p>
<p>The good news is that memory leak patterns can be easily spotted if you know what to look for. Most of the troublesome patterns you might face have known workarounds requiring only a small amount of extra work on your behalf. While some pages might still fall prey to small memory leaks, the most noticeable ones can be easily removed.</p>
<h2>Leak Patterns</h2>
<p>The following sections will discuss patterns of memory leaks and point out some common examples of each pattern. One great example of a pattern is the closure feature of JScript, while another example is the use of closures in hooking events. If you&#8217;re familiar with the event hooking example, you might be able to find and fix many of your memory leaks, but other closure-related issues might go unnoticed.</p>
<p>Now, let&#8217;s look at the following patterns:</p>
<ol>
<li>Circular References—When mutual references are counted between Internet Explorer&#8217;s COM infrastructure and any scripting engine, objects can leak memory. This is the broadest pattern.</li>
<li>Closures—Closures are a specific form of circular reference that pose the largest pattern to existing Web application architectures. Closures are easy to spot because they rely on a specific language keyword and can be searched for generically.</li>
<li>Cross-Page Leaks—Cross-page leaks are often very small leaks of internal book-keeping objects as you move from site to site. We&#8217;ll examine the DOM Insertion Order issue, along with a workaround that shows how small changes to your code can prevent the creation of these book-keeping objects.</li>
<li>Pseudo-Leaks—These aren&#8217;t really leaks, but can be extremely annoying if you don&#8217;t understand where your memory is going. We&#8217;ll examine the script element rewriting and how it appears to leak quite a bit of memory, when it is really performing as required.</li>
</ol>
<h2>Circular References</h2>
<p>Circular references are the root of nearly every leak. Normally, script engines handle circular references through their garbage collectors, but certain unknowns can prevent their heuristics from working properly. The unknown in the case of IE would be the status of any DOM elements that a portion of script has access to. The basic principle would be as follows:</p>
<p><!--src=[ie_leak_patterns_fig01.gif]--><img src="http://i.msdn.microsoft.com/Bb250448.ie_leak_patterns_fig01(en-us,VS.85).gif" alt="Figure 1 Basic Circular Reference Pattern" /></p>
<p><strong>Figure 1. Basic Circular Reference Pattern</strong></p>
<p>The cause of the leak in this pattern is based on COM reference counting. The script engine objects will hold a reference to the DOM element and will be waiting for any outstanding references to be removed before cleaning up and releasing the DOM element pointer. In our case we have two references on the script engine object: the script engine scope, and the DOM element expando property. While terminating the script engine will release the first reference, the DOM element reference will never be released because it is waiting on the script engine object to release it! You might think it would be easy to detect this scenario and fix the problem, but in practice the basic case presented is only the tip of the iceberg. You could have circular references at the end of a 30 object chain and those would be much harder to detect.</p>
<p>If you are wondering what this pattern looks like in HTML, you can cause a leak by using a global script engine variable and a DOM element as shown.</p>
<pre><code>&lt;html&gt;
    &lt;head&gt;
        &lt;script language="JScript"&gt;

        var myGlobalObject;

        function SetupLeak()
        {
            // First set up the script scope to element reference
            myGlobalObject =
                document.getElementById("LeakedDiv");

            // Next set up the element to script scope reference
            document.getElementById("LeakedDiv").expandoProperty =
                myGlobalObject;
        }

        function BreakLeak()
        {
            document.getElementById("LeakedDiv").expandoProperty =
                null;
        }
        &lt;/script&gt;
    &lt;/head&gt;

    &lt;body onload="SetupLeak()" onunload="BreakLeak()"&gt;
        &lt;div id="LeakedDiv"&gt;&lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>To break the leak pattern you can make use of explicit null assignments. By assigning null before the document unloads you are telling the script engine there is no longer an association between the element and the object inside the engine. It can now properly clean up references and will release the DOM element. In this case, you as the Web developer know more about the relationships between your objects than the script engine does.</p>
<p>While that is the basic pattern, it can be difficult to spot more complex scenarios. A common usage of object-oriented JScript is to extend DOM elements by encapsulating them inside of a JScript object. During the construction process, you generally pass in the DOM element you want to attach to and then store a reference to the DOM element on the newly constructed object while at the same time storing an instance of the newly constructed object on the DOM element. That way your application model always has access to everything it needs. The problem is this is a very explicit circular reference, but because it uses different language aspects it might go unnoticed. Breaking up this kind of pattern can become more complex, and you can use the same simple methods discussed earlier.</p>
<pre><code>&lt;html&gt;
    &lt;head&gt;
        &lt;script language="JScript"&gt;

        function Encapsulator(element)
        {
            // Set up our element
            this.elementReference = element;

            // Make our circular reference
            element.expandoProperty = this;
        }

        function SetupLeak()
        {
            // The leak happens all at once
            new Encapsulator(document.getElementById("LeakedDiv"));
        }

        function BreakLeak()
        {
            document.getElementById("LeakedDiv").expandoProperty =
                null;
        }
        &lt;/script&gt;
    &lt;/head&gt;

    &lt;body onload="SetupLeak()" onunload="BreakLeak()"&gt;
        &lt;div id="LeakedDiv"&gt;&lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;
</code></pre>
<p>More complex solutions to this problem involve registration schemes to note which elements/properties need to be unhooked, having the peer element hook events so that it can clean up before the document unloads, but often you can run into additional leak patterns without actually fixing the problem.</p>
<h2>Closures</h2>
<p>Closures are very often responsible for leaks because they create circular references without the programmer being fully aware. It isn&#8217;t immediately obvious that parent function parameters and local variables will be frozen in time, referenced, and held until the closure itself is released. In fact this has become such a common programming tactic, and users have run into issues so often, there are quite a few resources already available. Because they detail some of the history behind closures as well as some of the specific instances of closure leaks we&#8217;ll check those out after applying the closure model to our circular reference diagram and figuring out where these extra references are coming from.</p>
<p><!--src=[ie_leak_patterns_fig02.gif]--><img src="http://i.msdn.microsoft.com/Bb250448.ie_leak_patterns_fig02(en-us,VS.85).gif" alt="Figure 2 Circular References with Closures" /></p>
<p><strong>Figure 2. Circular References with Closures</strong></p>
<p>With normal circular references there were two solid objects holding references to each other, but closures are different. Rather than make the references directly, they are made instead by importing information from their parent function&#8217;s scope. Normally, a function&#8217;s local variables and the parameters used when calling a function only exist for the lifetime of the function itself. With closures, these variables and parameters continue to have an outstanding reference as long as the closure is alive, and since closures can live beyond the lifetime of their parent function so can any of the locals and parameters in that function. In the example, Parameter 1 would normally be released as soon as the function call was over. Because we&#8217;ve added a closure, a second reference is made, and that second reference won&#8217;t be released until the closure is also released. If you happened to attach the closure to an event, then you would have to detach it from that event. If you happened to attach the closure to an expando then you would need to null that expando.</p>
<p>Closures are also created per call, so calling this function twice will create two individual closures, each holding references to the parameters passed in each time. Because of this transparent nature it is really easy to leak closures. The following example provides the most basic of leaks using closures:</p>
<pre><code>&lt;html&gt;
    &lt;head&gt;
        &lt;script language="JScript"&gt;

        function AttachEvents(element)
        {
            // This structure causes element to ref ClickEventHandler
            element.attachEvent("onclick", ClickEventHandler);

            function ClickEventHandler()
            {
                // This closure refs element
            }
        }

        function SetupLeak()
        {
            // The leak happens all at once
            AttachEvents(document.getElementById("LeakedDiv"));
        }

        function BreakLeak()
        {
        }
        &lt;/script&gt;
    &lt;/head\&gt;

    &lt;body onload="SetupLeak()" onunload="BreakLeak()"&gt;
        &lt;div id="LeakedDiv"&gt;&lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>If you are wondering how to break this leak, it won&#8217;t be as easy as a normal circular reference. The &#8220;closure&#8221; can be viewed as a temporary object that exists in the function scope. Once the function exits, you lose reference to the closure itself, so what would you end up calling <strong>detachEvent</strong> with? One of the most interesting approaches to this problem was demonstrated on <a id="ctl00_MTCS_main_ctl03" onclick="javascript:Track('ctl00_MTCS_main_ctl00|ctl00_MTCS_main_ctl03',this);" href="http://spaces.msn.com/members/siteexperts/Blog/cns!1pNcL8JwTfkkjv4gg6LkVCpw!338.entry">MSN spaces thanks to Scott Isaacs</a>. The approach uses a second closure to additionally hook the window&#8217;s <strong>onUnload</strong> event, and because this closure has the same &#8220;scoped&#8221; objects it is able to detach the event, detach itself, and finish the clean up process. To make everything easily fit with our model we can also store the closure on an expando, detach it, and then null the expando, as in the following example.</p>
<pre><code>&lt;html&gt;
    &lt;head&gt;
        &lt;script language="JScript"&gt;

        function AttachEvents(element)
        {
            // In order to remove this we need to put
            // it somewhere. Creates another ref
            element.expandoClick = ClickEventHandler;

            // This structure causes element to ref ClickEventHandler
            element.attachEvent("onclick", element.expandoClick);

            function ClickEventHandler()
            {
                // This closure refs element
            }
        }

        function SetupLeak()
        {
            // The leak happens all at once
            AttachEvents(document.getElementById("LeakedDiv"));
        }

        function BreakLeak()
        {
            document.getElementById("LeakedDiv").detachEvent("onclick",
                document.getElementById("LeakedDiv").expandoClick);
            document.getElementById("LeakedDiv").expandoClick = null;
        }
        &lt;/script&gt;
    &lt;/head&gt;

    &lt;body onload="SetupLeak()" onunload="BreakLeak()"&gt;
        &lt;div id="LeakedDiv"&gt;&lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>In a <a id="ctl00_MTCS_main_ctl04" onclick="javascript:Track('ctl00_MTCS_main_ctl00|ctl00_MTCS_main_ctl04',this);" href="http://support.microsoft.com/default.aspx?scid=KB;EN-US;830555">Knowledge Base article</a>, we actually recommend that you try not to use closures unless they are necessary. In the example, I&#8217;ve given we don&#8217;t need to use a closure as the event handler, instead we can move the closure to a global scope. When the closure becomes a function, it no longer inherits the parameters or local variables from its parent function so we don&#8217;t have to worry about closure-based circular references at all. Most code can be fixed by creating an architecture that doesn&#8217;t rely on closures where they aren&#8217;t necessary.</p>
<p>Finally, Eric Lippert, one of the developers of the scripting engines, has a <a id="ctl00_MTCS_main_ctl05" onclick="javascript:Track('ctl00_MTCS_main_ctl00|ctl00_MTCS_main_ctl05',this);" href="http://blogs.msdn.com/ericlippert/archive/2003/09/17/53028.aspx">great post on closures in general</a>. His final recommendations are also along the lines of only using closures when truly necessary. While his article doesn&#8217;t mention any of the workarounds for the closure pattern, hopefully we&#8217;ve covered enough examples here to get you started.</p>
<h2>Cross-Page Leaks</h2>
<p>Leaks that are based on order of insertion are almost always caused by the creation of intermediate objects that don&#8217;t get cleaned up properly. That is exactly the case when creating dynamic elements and then attaching them to the DOM. The basic pattern is attaching two dynamically created objects together temporarily which creates a scope from the child to the parent element. Later, when you attach this two-element tree to the primary tree, they both inherit the scope of the document and a temporary object is leaked. The following diagram shows two methods for attaching dynamically created elements to the tree. In the first model, attach each child element to its parent, and finally attach the entire subtree to the primary tree. This method can cause leaks through temporary objects if other conditions are met. In the second model, we attach elements into the primary tree working our way from top-level dynamically created element down through all of the children. Because each attachment inherits the scope of the primary document we never generate temporary scopes. This method is much better at avoiding potential memory leaks.</p>
<p><!--src=[ie_leak_patterns_fig03.gif]--><img src="http://i.msdn.microsoft.com/Bb250448.ie_leak_patterns_fig03(en-us,VS.85).gif" alt="Figure 3 DOM Insertion Order Leak Model" /></p>
<p><strong>Figure 3. DOM Insertion Order Leak Model</strong></p>
<p>Next, we are going to cover an example of a leak that is transparent to most leak-detection algorithms. Because we don&#8217;t leak any publicly visible elements and the objects we leak are very small you might never notice this problem. For our example to work, the dynamically created elements will have to contain a script pointer in the form of an inline function. This will allow us to leak an internal script object that is created temporarily as we attach elements together. Because the leak is small, we&#8217;ll have to run thousands of samples. In fact, the objects leaked are only a few bytes. By running the sample and navigating to an empty page, you can see the difference in memory consumption between the two versions. When we use the first DOM model of attaching child to parent, then parent to the primary tree, our memory usage goes up a bit. This is a cross-navigation leak and the memory isn&#8217;t reclaimed until you restart the IE process. If you run the sample a few more times, using the second DOM model of attaching the parent to the primary tree and then the child to the parent, your memory won&#8217;t continue to climb and you&#8217;ll find that you&#8217;ve fixed the cross-page navigation leak.</p>
<pre><code>&lt;html&gt;
    &lt;head&gt;
        &lt;script language="JScript"&gt;

        function LeakMemory()
        {
            var hostElement = document.getElementById("hostElement");

            // Do it a lot, look at Task Manager for memory response

            for(i = 0; i &lt; 5000; i++)
            {
                var parentDiv =
                    document.createElement("&lt;div onClick='foo()'&gt;");
                var childDiv =
                    document.createElement("&lt;div onClick='foo()'&gt;");

                // This will leak a temporary object
                parentDiv.appendChild(childDiv);
                hostElement.appendChild(parentDiv);
                hostElement.removeChild(parentDiv);
                parentDiv.removeChild(childDiv);
                parentDiv = null;
                childDiv = null;
            }
            hostElement = null;
        }

        function CleanMemory()
        {
            var hostElement = document.getElementById("hostElement");

            // Do it a lot, look at Task Manager for memory response

            for(i = 0; i &lt; 5000; i++)
            {
                var parentDiv =
                    document.createElement("&lt;div onClick='foo()'&gt;");
                var childDiv =
                    document.createElement("&lt;div onClick='foo()'&gt;");

                // Changing the order is important, this won't leak
                hostElement.appendChild(parentDiv);
                parentDiv.appendChild(childDiv);
                hostElement.removeChild(parentDiv);
                parentDiv.removeChild(childDiv);
                parentDiv = null;
                childDiv = null;
            }
            hostElement = null;
        }
        &lt;/script&gt;
    &lt;/head&gt;

    &lt;body&gt;
        &lt;button onclick="LeakMemory()"&gt;Memory Leaking Insert&lt;/button&gt;
        &lt;button onclick="CleanMemory()"&gt;Clean Insert&lt;/button&gt;
        &lt;div id="hostElement"&gt;&lt;/div&gt;
    &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>This leak deserves clarification, because our workaround goes against some best practices in IE. The key points to understand about the leak are that DOM elements are being created with scripts already attached. This is actually crucial to the leak, because if we create DOM elements that don&#8217;t contain any script and attach them together in the same manner we don&#8217;t have a leak problem. This gives rise to a second workaround that might be even better for larger subtrees (in the example we only have two elements, so building the tree off the primary DOM isn&#8217;t a performance hit). The second workaround would be to create your elements with no scripts attached initially so that you can safely build your subtree. After you&#8217;ve attached your subtree to the primary DOM, go back and wire up any script events at that point. Remember to follow the principles for circular references and closures so you don&#8217;t cause a different leak in your code as you hook up your events.</p>
<p>I really wanted to point out this issue because it shows that not all memory leaks are easy to find. It could take thousands of iterations of a smaller pattern to become visible, and it might be something slight, like the order of insertion of DOM elements that causes the problem to arise. If you tend to program using only best practices, then you think you are safe, but this leak shows that even best practices can exhibit leaks. Our solution here was to improve upon the best practice or even introduce a new best practice in order to remove the leaking condition.</p>
<h2>Pseudo-Leaks</h2>
<p>Often times the actual behavior and expected behavior of some APIs can lead you to misdiagnose memory leaks. Pseudo-leaks almost always appear on the same page during dynamic scripting operations and should rarely be visible after navigation away from the page to a blank page. That is how you can eliminate the issue as a cross-page leak and then start to work on whether the memory consumption is expected. We&#8217;ll use script text rewriting as our example of a pseudo-leak.</p>
<p>Like the DOM Insertion Order issue, this issue also relies on the creation of temporary objects in order to &#8220;leak&#8221; memory. By rewriting the script text inside of a script element over and over again, slowly you&#8217;ll begin to leak various script engine objects that were attached to the previous contents. In particular, objects related to debugging script are left behind as are fully formed code elements.</p>
<pre><code>&lt;html&gt;
    &lt;head&gt;
        &lt;script language="JScript"&gt;

        function LeakMemory()
        {
            // Do it a lot, look at Task Manager for memory response

            for(i = 0; i &lt; 5000; i++)
            {
                hostElement.text = "function foo() { }";
            }
        }
        &lt;/script&gt;
    &lt;/head&gt;

    &lt;body&gt;
        &lt;button onclick="LeakMemory()"&gt;Memory Leaking Insert&lt;/button&gt;
        &lt;script id="hostElement"&gt;function foo() { }&lt;/script&gt;
    &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>If you run the above code and use the Task Manager trick again, while navigating between the &#8220;leaking&#8221; page and a blank page, you won&#8217;t notice a script leak. This script leak is entirely within a page and when you navigate away then you get your memory back. The reason this one is bad is due to expected behavior. You expect that after rewriting some script that the original script won&#8217;t stay around. But it really has to, because it might have been used already for event attachments and there might be outstanding reference counts. As you can see, this is a pseudo-leak. On the surface the amount of memory consumption looks really bad, but there is a completely valid reason.</p>
<h2>Conclusion</h2>
<p>Every Web developer builds a personal list of code examples that they know leak and learns to work around those leaks when they see them in code. This is extremely handy and is the reason the Web is relatively leak-free today. Thinking about the leaks in terms of patterns instead of individual code examples, you can start to develop even better strategies for dealing with them. The idea is to take them into account during the design phase and make sure you have plans for any potential leaks. Use defensive coding practices and assume that you&#8217;ll need to clean up all your own memory. While this is an overstatement of the problem, you very rarely need to clean up your own memory; it becomes obvious which variables and expando properties have the potential for leaking.</p>
<p>In the interest of patterns and design I highly recommend <a id="ctl00_MTCS_main_ctl07" onclick="javascript:Track('ctl00_MTCS_main_ctl00|ctl00_MTCS_main_ctl07',this);" href="http://spaces.msn.com/members/siteexperts/Blog/cns!1pNcL8JwTfkkjv4gg6LkVCpw!338.entry">Scott&#8217;s short blog entry</a> because it demonstrates a general purpose example of removing all closure-based leaks. It does require a bit more code, but the practice is sound and the improved pattern is easy to spot in code and to debug. Similar registration schemes can be used for expando-based circular references as long as care is taken that the registration method itself isn&#8217;t riddled with leaks (especially where closures are used)!</p>
<p><!----></p>
<p><!----></p>
<p><strong>About the author</strong></p>
<p><strong>Justin Rogers</strong> recently joined the Internet Explorer team as an Object Model developer working on extensibility and previously worked on such notable projects as the .NET QuickStart Tutorials, .NET Terrarium, and SQL Reporting Services Management Studio in SQL Server 2005.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zfkun.com/blog/index.php/archives/109/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CSS圆角—透明圆角化背景图片</title>
		<link>http://www.zfkun.com/blog/index.php/archives/91</link>
		<comments>http://www.zfkun.com/blog/index.php/archives/91#comments</comments>
		<pubDate>Thu, 21 Jan 2010 03:11:53 +0000</pubDate>
		<dc:creator>影之迷惑</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[sprites]]></category>
		<category><![CDATA[圆角]]></category>
		<category><![CDATA[弹性]]></category>

		<guid isPermaLink="false">http://www.zfkun.com/blog/?p=91</guid>
		<description><![CDATA[序言：第一章中我介绍了最基本的纯CSS圆角框的实现原理，并给出Demo，在本章中会对上一个模型作一些新的创新，实现将背景图片透明圆角化。并给出一些漂亮的通用演示效果。
在上面的案例中，我只给出最为原始的圆角框模型，它还是存在一些不足之处。比如不能将图片应用到圆角框内。而在本例中，我会在上面的基础上作出一些创新。就是将背景图片也圆角化。]]></description>
			<content:encoded><![CDATA[<p>作者：<a href="http://www.blueidea.com/common/contact.asp?type=作者&amp;username=by0001" target="_blank">by0001</a>　来自：<a href="http://www.blueidea.com/">蓝色理想</a><br />
原文：<a href="http://www.blueidea.com/tech/web/2010/7353.asp">http://www.blueidea.com/tech/web/2010/7353.asp</a></p>
<p>序言：第一章中我介绍了最基本的纯CSS圆角框的实现原理，并给出Demo，在本章中会对上一个模型作一些新的创新，实现将背景图片透明圆角化。并给出一些漂亮的通用演示效果。</p>
<p>在上面的案例中，我只给出最为原始的圆角框模型，它还是存在一些不足之处。比如不能将图片应用到圆角框内。而在本例中，我会在上面的基础上作出一些创新。就是将背景图片也圆角化，好像目前在网络上还没有这样的功能应用，我只见过用js方式来实现的，可以参看我的《<a href="http://www.blueidea.com/tech/web/2009/6488.asp" target="_blank">超圆滑圆角框的半完美解决方案</a>》一文中后面几种JS方案。但是纯CSS方式的实现可是我独家所创，如有雷同，只能说英雄所见略同。呵呵！</p>
<p>还是先看看最终的效果图，让大家有一个大概的印象。</p>
<p style="text-align: center;"><img class="aligncenter" src="http://www.blueidea.com/articleimg/2010/01/7353/01.jpg" border="0" alt="" width="510" height="533" /></p>
<p style="text-align: center;">图一</p>
<p>像这种小面积布局在网页设计中应用得很普遍，但目前网络流行的作法都是采用图片的方式来实现的，将图片按上中下切成三块内容，然后使用三个同级的DIV或SPAN容器各自填充一张图，但是这种方法有一个最大的毛病：不能自动适应宽度的变化，一般做法都是采用固定宽度的方式，这是由于图片的宽度决定的。</p>
<p>当然对于一些比较有经验的人员来说，可以采用九宫格布局（可参看我的另一篇文章《<a href="http://www.blueidea.com/tech/web/2009/6800.asp" target="_blank">九宫格基本布局</a>》）方式或者滑动门方式来做到自适应宽度的变化，九宫格一般都需要用到八张图片，而滑动门虽然只用一张图片，但为了适应宽度的变化，这张图片一般都做得很大。<br />
而我现在独创的这种方法可以完全做到适应不同宽度的需要，并且全部兼容所有的浏览器，而所需要的仅仅是一张很小的水平平辅的背景图片而已。</p>
<p><strong>基本原理</strong>：</p>
<p style="text-align: center;">我们都知道图片是方方正正的，不可能做出圆角效果，那么我们如何来做外圆透明的图片呢？其实道理说明了也就是一件很简单的事情，你看过下面的放大示意图后可能就会“哦”地一声，原来不过如此……<br />
<img class="aligncenter" src="http://www.blueidea.com/articleimg/2010/01/7353/02.jpg" border="0" alt="" width="464" height="388" /></p>
<p style="text-align: center;">图二</p>
<p>是的，看到这个效果图你会一目了然，可是要想到这个方法，我却浪费了不少脑细胞。呵呵！</p>
<p>实现这种方法原理很简单：<strong>在每个b标签中各加载一次同样的图片，并结合背景定位background-position方式来达到效果。</strong>我们知道，同一张图片加载多少次对于性能的影响并不大，因为这张图片已经被电脑缓存到本地，和用css sprites合并图片一样的道理。</p>
<p>但是需要注意的是：每个B标签加载图片的定位是不一样的。</p>
<p><strong>背景图片定位原理</strong>：　　</p>
<p>b1标签位于第一位，它主要用来描绘上边框线，所以它不需要加载背景图片。</p>
<p>b2标签位于第二位，它是第一个需要加载背景图片的，但是不需要图片负偏移，所以直接居左居顶定位就可以了。</p>
<pre name="code" class="css">
.b2{background-position:left top;}
</pre>
<p>b3标签位于第三位，它需要加载背景图片，让它的背景图片向上负偏移b2的高度值就可以，也就是1px。</p>
<pre name="code" class="css">
.b3{background-position:left -1px;}
</pre>
<p>b4位于第四位，所以它向上负偏移b2+b3高度值的和，为2px.。</p>
<pre name="code" class="css">
.b4{background-position:left -2px;}
</pre>
<p>H3标签位于第五位，所以它的背景图片需要向上负偏移b2+b3+b4高度值的各，也就是4px；</p>
<pre name="code" class="css">
h3{background-position:left -4px;}
</pre>
<p>这样，b2、b3、b4、h3的图片叠加起来和原始图片上下渐变的效果完全重合，如同一张图片，这样就达到模拟圆角图片的效果。<br />
怎么样，原理够简单明了吧！</p>
<p>原理清楚后，要实现起来也就是一件水到渠成的事！</p>
<p><strong>HTML结构层</strong>：</p>
<p>如同我们在第一章中模型所见，保持结构不变。</p>
<p><strong>CSS样式层：（只写关键代码）</strong></p>
<p>将上面的几句代码进行合并，如下所示：</p>
<pre name="code" class="css">
.sharp b.b2{background-position:left top;}
.sharp b.b3{background-position:left -1px;}
.sharp b.b4{background-position:left -2px;}
.sharp .content h3{background-position:left -4px;}
</pre>
<p>和第一章中同样的道理，我们肯定要在各个不同的块框中有不同的背景图片的变化，也就是说，我们也要实现不同的换肤方案，当一个页面要多次调用同一个圆角框时，也可以让它们有些丰富的变化。实现不同的风格。OK，没问题，你只需要简单的将下面的样式中的背景图片的路径改变一下就可以了。</p>
<pre name="code" class="css">
.color1 .b2,.color1 .b3,.color1 .b4,.color1 h3{background:url(images/bg1.gif) repeat-x;}
</pre>
<p>你可以实现不同的颜色方案，就看你的设计师给你多少张不同图片了。</p>
<p>一种风格的定制也是一件简单的事情：</p>
<pre name="code" class="css">
*颜色方案一,绿色风格----------------------------------------*/
/*边框色*/
.color1 .b2,.color1 .b3,.color1 .b4,.color1 .b5,.color1 .b6,
.color1 .b7,.color1 .content{border-color:#A0C044;}
.color1 .b1,.color1 .b8{background:#A0C044;}
.color1 h3{border-bottom:1px #679800 solid;}
/*图片路径*/
.color1 .b2,.color1 .b3,.color1 .b4,.color1 h3{background:url(images/bg1.gif) repeat-x;}
/*文字内容背景色*/
.color1 .b5,.color1 .b6,.color1 .b7{background:#FFF;}
</pre>
<p>你只需要复制上面的代码，简单修改一下边框色，背景色，图片路径就变成你想要的风格了，是不是很简单呢？然后在你想应用样式的容器上定义这个color1类名即可。</p>
<p>在我的演示模型中，我定义了9种风格的变化，看看有没有适合你需要，直接复制就可以使用了，祝您用得开心！</p>
<p><strong>为了演示效果，本模型的宽度值全部采用百分比实现的，你可以随意伸缩宽度，看看它能否适应弹性的变化。</strong></p>
<p><strong>本模型在以下浏览器中完美通过：<br />
IE5.5、IE6、IE7、IE8、FF3、TT、Maxthon2.1.5、Opera9.6、Safari4.0、Chrome2.0。</strong></p>
<p><a class="aligncenter" href="http://www.zfkun.com/soft/CSS_RoundAngle_2.rar" target="_blank">压缩包下载</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zfkun.com/blog/index.php/archives/91/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CSS圆角—基本圆角框</title>
		<link>http://www.zfkun.com/blog/index.php/archives/87</link>
		<comments>http://www.zfkun.com/blog/index.php/archives/87#comments</comments>
		<pubDate>Thu, 21 Jan 2010 02:50:03 +0000</pubDate>
		<dc:creator>影之迷惑</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[sprites]]></category>
		<category><![CDATA[圆角]]></category>
		<category><![CDATA[弹性]]></category>

		<guid isPermaLink="false">http://www.zfkun.com/blog/?p=87</guid>
		<description><![CDATA[纯CSS实现圆角框是一件大家都说烂了的事件，我也写过两篇总结文章，为什么还会有这篇文章呢，事情是这样的。在我们的以前的项目中，实现圆角框往往是用背景图片来实现的，但是，当这些项目发布上线后，在维护过程中，有时需要添加一些新的需求，因为以前的项目中大量采用了圆角图片，并且这些图片全部采用了CSS sprites方式合并的图，为了不增加更多的额外工作，并且也不想用JS来添加更多的http请求，所以需要一些简单的CSS方案来解决这个问题。而我的个人爱好，也喜欢采用无图片的方式来处理这些效果。总觉得CSS能完成的工作，为什么不让它来实现呢？]]></description>
			<content:encoded><![CDATA[<p>作者：<a href="http://www.blueidea.com/common/contact.asp?type=作者&amp;username=by0001" target="_blank">by0001</a>　来自：<a href="http://www.blueidea.com/">蓝色理想</a></p>
<p>原文：<a href="http://www.blueidea.com/tech/web/2010/7347.asp">http://www.blueidea.com/tech/web/2010/7347.asp</a></p>
<p>序言：在我的文章《<a href="http://www.blueidea.com/tech/web/2009/6488.asp" target="_blank">超圆滑圆角框的半完美解决方案</a>》中已经总结了七种不同的圆角框解决方案，基本上总结完了目前网络上比较流行的圆角框实现方案。而在我的另一篇文章《无图片山顶角》中又是一个另类的实现方法。</p>
<p>纯CSS实现圆角框是一件大家都说烂了的事件，我也写过两篇总结文章，为什么还会有这篇文章呢，事情是这样的。在我们的以前的项目中，实现圆角框往往是用背景图片来实现的，但是，当这些项目发布上线后，在维护过程中，有时需要添加一些新的需求，因为以前的项目中大量采用了圆角图片，并且这些图片全部采用了CSS sprites方式合并的图，为了不增加更多的额外工作，并且也不想用JS来添加更多的http请求，所以需要一些简单的CSS方案来解决这个问题。而我的个人爱好，也喜欢采用无图片的方式来处理这些效果。总觉得CSS能完成的工作，为什么不让它来实现呢？</p>
<p><strong>实现原理</strong>：</p>
<p>纯CSS方式实现圆角框的原理在网络上已经有很多人详细解说了，下面这个示意图是我将其中的一个圆角进行放大后的效果。</p>
<p><img src="http://www.blueidea.com/articleimg/2010/01/7347/01.png" border="0" alt="" width="451" height="321" /></p>
<p>图一</p>
<p>从上面效果图中我们可以看到其实这种圆角框是靠一个个容器堆砌而成的，每一个容器的宽度不同，这个宽度是由margin外边距来实现的，如：margin:0 5px;就是左右两侧的外边距5像素，从上到下有5条线，其外边距分别为5px，3px，2px，1px，依次递减。因此根据这个原理我们可以实现简单的html结构和样式。</p>
<p><strong>1、Html结构层：</strong></p>
<pre name="code" class="html">
&lt;div&gt;
       &lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;
       &lt;div&gt;文字内容&lt;/div&gt;
       &lt;/div&gt;
       &lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;  
&lt;/div&gt;
</pre>
<p>b1~b4构成上面的左右两个圆角结构体，而b5~b8则构建了下面左右两个圆角结构体。而content则是内容主体，将这些全部放在一个大的容器中，并给它的一个类名sharp，用来设置通用的样式。再给它叠加了一个color1类名，这个类名用来区别不同的颜色方案，因为可能会有不同颜色的圆角框。</p>
<p><strong>2、CSS样式：</strong></p>
<pre name="code" class="css">
.b1,.b2,.b3,.b4,.b5,.b6,.b7,.b8{height:1px; font-size:1px; overflow:hidden; display:block;}
.b1,.b8{margin:0 5px;}
.b2,.b7{margin:0 3px;border-right:2px solid; border-left:2px solid;}
.b3,.b6{margin:0 2px;border-right:1px solid; border-left:1px solid;}
.b4,.b5{margin:0 1px;border-right:1px solid; border-left:1px solid; height:2px;}
</pre>
<p>将每个b标签都设置为块状结构，并定义其高度为1像素，超出部分溢出隐藏。从上面样式中我们已经看到margin值的设置，是从大到小减少的。而b1和b8的设置是一样，已经将它们合并在一起了，同样的原理，b2和b7、b3和b6、b4和b5都是一样的设置。这是因为上面两个圆和下面的两个圆是一样，只是顺序是相对的，所以将它合并设置在一起。有利于减少CSS样式代码的字符大小。后面三句和第二句有点不同的地方是多设置了左右边框的样式，但是在这儿并没有设置边框的颜色，这是为什么呢，因为这个边框颜色是我们需要适时变化，所以将它们分离出来，在下面的代码中单独定义。</p>
<p>接下我们设置内容区的样式：</p>
<pre name="code" class="css">
.content {border-right:1px solid;border-left:1px solid;overflow:hidden;}
</pre>
<p>也是只设置左右边框线，但是不设置颜色值，它和上面八个b标签一起构成圆角框的外边框轮廓。</p>
<p>往往在一个页面中存在多个圆角框，而每个圆角框有可能其边框颜色各不相同，有没有可能针对不同的设计制作不同的换肤方案呢，答案是有的。在我的这个应用中，可以换不同的皮肤颜色，并且设置颜色方案也并不是一件很难的事情。下面看看我是如何将它们应用到不同的颜色的。</p>
<p>在上面的样式设计中，我已经给颜色方案留下了可以扩展的空间。我将所有的涉及到边框色的类名全部集中在一起，用群选择符给它们设置一个边框的颜色就可以了。如下所示：</p>
<pre name="code" class="css">
.color1 .b2,.color1 .b3,.color1 .b4,.color1 .b5,.color1 .b6,
.color1 .b7,.color1 .content{}{border-color:#96C2F1;}
.color1 .b1,.color1 .b8{background:#96C2F1;}
</pre>
<p>注意：需要将这两句的颜色值设置为一样的，第二句中虽说是设置的background背景色，但它同样是上下边框线的颜色，这一点一定要记住。因为b1和b8并没有设置border，但它的高度值为1px，所以用它的背景色就达到了模拟上下边框的颜色了。<br />
现在已经将一个圆角框描述出来了，但是有一个问题要注意，就是内容区的背景色，因为这儿是存载文字主体的地方。所以还需要加入下面这句话，也是群集选择符来设置圆角内的所有背景色。</p>
<pre name="code" class="css">
.color1 .b2,.color1 .b3,.color1 .b4,.color1 .b5,
.color1 .b6,.color1 .b7,.color1 .content{background:#EFF7FF;}
</pre>
<p>这儿除了b1和b8外，其它的标签都包含进来了，并且包括content容器，将它们的背景色全部设置一个颜色，这样除了线框外的所有地方都成为一种颜色了。在这儿我也用到包含选择符，给它们都加了一个color1，这是颜色方案1的类名，依照这个原理可以设置不同的换肤方案。</p>
<p>好了，我们将上面的所有代码集中起来，就完成一个纯CSS圆角框的实例模型，在源码中，我设置了六套颜色方案，其它的颜色方案就看你的了。</p>
<p>下面是源码演示后的截图：</p>
<p><img src="http://www.blueidea.com/articleimg/2010/01/7347/02.jpg" border="0" alt="" width="510" height="445" /></p>
<p>图二</p>
<p>为了演示效果，本模型的宽度值全部采用百分比实现的，你可以随意伸缩宽度，看看它能否适应弹性的变化。</p>
<p>本模型在以下浏览器中完美通过：<br />
<strong>IE5.5、IE6、IE7、IE8、FF3、TT、Maxthon2.1.5、Opera9.6、Safari4.0、Chrome2.0。</strong></p>
<p><a class="aligncenter" href="http://www.zfkun.com/soft/CSS_RoundAngle_1.rar" target="_blank">压缩包下载</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.zfkun.com/blog/index.php/archives/87/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>腾讯TT、遨游浏览器检测</title>
		<link>http://www.zfkun.com/blog/index.php/archives/59</link>
		<comments>http://www.zfkun.com/blog/index.php/archives/59#comments</comments>
		<pubDate>Sat, 16 Jan 2010 15:39:30 +0000</pubDate>
		<dc:creator>影之迷惑</dc:creator>
				<category><![CDATA[Web]]></category>
		<category><![CDATA[flash]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[maxthon]]></category>
		<category><![CDATA[tencent]]></category>
		<category><![CDATA[tt]]></category>
		<category><![CDATA[wmode]]></category>
		<category><![CDATA[检测]]></category>
		<category><![CDATA[浏览器]]></category>

		<guid isPermaLink="false">http://www.zfkun.com/blog/?p=59</guid>
		<description><![CDATA[最近腾讯TT4.5版发布后，为了兼容一处FLASH的WMODE参数异常的BUG使用到了新版检测方法，特此记录一下，省的以后忘记。
TT4.5 检测方法:   调用 external.getTTVerStr()  返回 浏览器信息，非TT或此版本均会抛出异常。
TT通用版检测方法:  首先检测  navigator.userAgent  是否含有 Tencent 特征串，继而调用 external.ShowBrowserUI(’ku6′)  ，非TT均会抛出异常
顺便提一下 遨游 的检测方法：
也是通过 external 对象来辅助检测，调用  external.tab_count 不抛异常即为 遨游浏览器。
]]></description>
			<content:encoded><![CDATA[<p>最近腾讯TT4.5版发布后，为了兼容一处FLASH的WMODE参数异常的BUG使用到了新版检测方法，特此记录一下，省的以后忘记。</p>
<p>TT4.5 检测方法:   调用 external.getTTVerStr()  返回 浏览器信息，非TT或此版本均会抛出异常。</p>
<p>TT通用版检测方法:  首先检测  navigator.userAgent  是否含有 Tencent 特征串，继而调用 external.ShowBrowserUI(’ku6′)  ，非TT均会抛出异常</p>
<p>顺便提一下 遨游 的检测方法：</p>
<p>也是通过 external 对象来辅助检测，调用  external.tab_count 不抛异常即为 遨游浏览器。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zfkun.com/blog/index.php/archives/59/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
