<?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>ZHOUQICF.COM</title>
	<atom:link href="http://www.zhouqicf.com/feed" rel="self" type="application/rss+xml" />
	<link>http://www.zhouqicf.com</link>
	<description>Time,not enough.</description>
	<lastBuildDate>Tue, 31 Jan 2012 06:50:24 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>监测移动设备的HTTP请求</title>
		<link>http://www.zhouqicf.com/others/mobile-network-requests-monitor</link>
		<comments>http://www.zhouqicf.com/others/mobile-network-requests-monitor#comments</comments>
		<pubDate>Wed, 11 Jan 2012 08:08:33 +0000</pubDate>
		<dc:creator>Zhou Qi</dc:creator>
				<category><![CDATA[others]]></category>
		<category><![CDATA[charles]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[wireshark]]></category>
		<category><![CDATA[代理]]></category>
		<category><![CDATA[抓包]]></category>
		<category><![CDATA[瀑布图]]></category>
		<guid isPermaLink="false">http://www.zhouqicf.com/?p=555</guid>
		<description><![CDATA[在PC上监测web页面的HTTP请求是一件非常简单的事，我们有大量的软件可以来做，甚至浏览器就自带了有这样功能的开发插件。但是在移动设备上就没那么简单了，没有软件，权限控制……介绍2种监测移动设备HTTP请求的方式。]]></description>
			<content:encoded><![CDATA[<div class="desc">
<p>在PC上监测web页面的HTTP请求是一件非常简单的事，我们有大量的软件可以来做，甚至浏览器就自带了有这样功能的开发插件。但是在移动设备上就没那么简单了，没有软件，权限控制……下面将介绍2种监测移动设备HTTP请求的方式。</p>
</div>
<h2>一、使用Charles</h2>
<div class="desc">
<p>在连上WIFI的前提下，android和ios设备都可以通过Charles来监测HTTP请求，原理是通过Charles在PC上架设一个代理，手机访问这个代理，Charles记录网络请求。ios设备，在“设置”-“无线局域网络”里可以直接设置代理，而android没有设置代理的功能，需要取得root权限后安装第三方软件来实现。</p>
<h3>操作步骤：</h3>
<ol>
<li>下载Charles（http://www.charlesproxy.com/download/），安装完成后打开软件</li>
<li>通过菜单上的“Proxy”-“Proxy Settings&#8230;”，进入代理设置见面</li>
<li>“Port”填默认的“8888”即可，勾选“Enable transparent HTTP proxying”，点“OK”确认</li>
<li>设置手机的代理，端口（Port）写Charles中的端口设置，即“8888”，IP填你PC的IP地址</li>
<li>用手机发起任意HTTP请求，Charles会弹出一个提示框，点“Allow”，好了HTTP请求都出现在Charles里了</li>
</ol>
<p>全选所有请求，并选择右侧的“Chart”选项卡就能看到整个HTTP请求瀑布图了：</p>
<p><img src="http://www.zhouqicf.com/wp-uploads/2012/01/charles.jpg" /></p>
<h3>Android手机设置代理的方式：</h3>
<ol>
<li>安装“z4root”软件，进入软件后选择第二项，等待一段时间后，自动重启，取得root权限完成</li>
<li>安装“Transparent Proxy”，进入“Proxy Host”设置PC的IP地址，进入“Proxy Port”设置端口号，即“8888”，勾选“Proxy”，设置完成</li>
</ol>
</div>
<h2>二、使用TCPDUMP和Wireshark</h2>
<div class="desc">
<p>Android手机，可以使用TCPDUMP输出网络请求的LOG文件，然后用Wireshark打开该文件，进行统计分析。</p>
<h3>操作步骤：</h3>
<ol>
<li>下载TCPDUMP（http://www.strazzere.com/android/tcpdump），放到D根目录盘下</li>
<li>下载安装Wireshark（http://www.wireshark.org/）</li>
<li>root手机，方法如上所述</li>
<li>用usb连上手机</li>
<li>打开命令行工具CMD，依次输入如下命令：</li>
<li><code>adb push d:\tcpdump /data/local/tcpdump</code></li>
<li><code>adb shell chmod 6755 /data/local/tcpdump</code></li>
<li><code>adb shell tcpdump -p -vv -s 0 -w /sdcard/capture.pcap -Z root</code></li>
<li>停止抓包：按<kbd>Ctrl+c</kbd></li>
<li>导出抓包得到的文件到d盘根目录：<code>adb pull /sdcard/capture.pcap d:/</code></li>
<li>双击capture.pcap文件，wireshark启动</li>
</ol>
<p><img src="http://www.zhouqicf.com/wp-uploads/2012/01/wireshark.jpg"/></p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhouqicf.com/others/mobile-network-requests-monitor/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>CodeCola Patterns</title>
		<link>http://www.zhouqicf.com/others/codecola-patterns</link>
		<comments>http://www.zhouqicf.com/others/codecola-patterns#comments</comments>
		<pubDate>Thu, 03 Nov 2011 12:53:23 +0000</pubDate>
		<dc:creator>Zhou Qi</dc:creator>
				<category><![CDATA[others]]></category>
		<guid isPermaLink="false">http://www.zhouqicf.com/?p=526</guid>
		<description><![CDATA[CodeCola Patterns is designed to collect and share css code.
CodeCola Patterns是一个用来收集和分享css代码的网站。]]></description>
			<content:encoded><![CDATA[<p><a href="http://codecolapatterns.com"><img src="http://zhouqicf.com/img/2011/codecolapatterns.png" rel="CodeCola Patterns" width="720"/></a></p>
<p><a href="http://codecolapatterns.com">CodeCola Patterns</a> is designed to collect and share css code. It&#8217;s so free that you can use all patterns for free, and modify all patterns with out register or login. Quality of the shared environment need you and I worked together to protect. With <a href="http://www.zhouqicf.com/code-cola">Code Cola</a>, you can share your css code easy, the only thing you have to do is click the share button<img src="http://codecolapatterns.com/img/share.png" alt="share" with="16" height="16" style="padding:0;border:none;background:none;">. <a href="http://codecolapatterns.com">CodeCola Patterns</a> borrow ideas from <a href="http://subtlepatterns.com/">Subtle Patterns</a> which is a amazing site to collection Photoshop patterns.</p>
<p><a href="http://codecolapatterns.com">CodeCola Patterns</a>是一个用来收集和分享css代码的网站。它非常的自由，你可以免费地使用网站上所有的设计，向全世界分享你的代码，对别的的代码进行改进，而这一切你都无需注册和登录，网站资源的质量需要你我共同维护。通过<a href="http://www.zhouqicf.com/code-cola">Code Cola</a>，可以方便地分享你的代码，你唯一需要做的仅仅是按下分享按钮：<img src="http://codecolapatterns.com/img/share.png" alt="share" with="16" height="16" style="padding:0;border:none;background:none;">。<a href="http://codecolapatterns.com">CodeCola Patterns</a>的创意来自<a href="http://subtlepatterns.com/">Subtle Patterns</a>，它是一个用来分享Photoshop设计的网站。</p>
<h5>为什么用英文？</h5>
<p><a href="http://www.zhouqicf.com/code-cola">Code Cola</a>85%的用户来至国外，等有时间了再对多语言进行支持。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zhouqicf.com/others/codecola-patterns/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>淘宝招聘前端开发工程师</title>
		<link>http://www.zhouqicf.com/others/taobao-need-f2e</link>
		<comments>http://www.zhouqicf.com/others/taobao-need-f2e#comments</comments>
		<pubDate>Fri, 26 Aug 2011 04:31:14 +0000</pubDate>
		<dc:creator>Zhou Qi</dc:creator>
				<category><![CDATA[others]]></category>
		<category><![CDATA[招聘]]></category>
		<guid isPermaLink="false">http://www.zhouqicf.com/?p=512</guid>
		<description><![CDATA[淘宝招聘前端开发工程师，有意向的同学请发简历至<a href="mailto:zhanyan@taobao.com">zhanyan@taobao.com</a>。]]></description>
			<content:encoded><![CDATA[<p>淘宝招聘前端开发工程师，要求如下：</p>
<ol>
<li>已把前端作为自己的职业发展的方向；</li>
<li>精通各种Web前端技术，包括XHTML/XML/CSS/Javascript/ActionScript等（JS和AS之一即可）；</li>
<li>有基于Ajax或Flash的RIA应用开发经验；</li>
<li>理解 Web 标准，对可用性、可访问性等相关知识有实际的了解和实践经验；</li>
<li>至少精通一门非Web前端脚本的语言（如Java/PHP/C++），并有项目经验；</li>
<li>个性乐观开朗，逻辑性强，对前端有自己的想法，善于和各种背景的人合作；</li>
</ol>
<p>有意向的同学请发简历至<a href="mailto:zhanyan@taobao.com">zhanyan@taobao.com</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.zhouqicf.com/others/taobao-need-f2e/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Firebug查看元素</title>
		<link>http://www.zhouqicf.com/javascript/firebug-inspect-element</link>
		<comments>http://www.zhouqicf.com/javascript/firebug-inspect-element#comments</comments>
		<pubDate>Fri, 11 Feb 2011 17:24:34 +0000</pubDate>
		<dc:creator>Zhou Qi</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[event capture]]></category>
		<category><![CDATA[firebug]]></category>
		<category><![CDATA[pointer-events]]></category>
		<guid isPermaLink="false">http://www.zhouqicf.com/?p=455</guid>
		<description><![CDATA[firebug选择元素最困难的地方就是当用户点击某个元素的时候，阻止绑定在这个元素上的点击事件，或者当这个元素是一个链接时，阻止链接的释放，提供3种实现类似firebug的元素选择功能的方法。
Tell you how to inspect elements like firebug.]]></description>
			<content:encoded><![CDATA[<div class="desc">
<p>firebug查看元素功能最困难的地方就是当用户点击某个元素的时候，阻止绑定在这个元素上的点击事件，或者当这个元素是一个链接时，阻止链接的释放。也许你首先想到的是鼠标移入的时候，在鼠标底下浮动一个元素，该元素带有1像素的蓝色边框。但这样一来，鼠标事件的<code>e.target</code>就成了底下浮动的元素了。</p>
</div>
<h2>方法一</h2>
<div class="desc">
<p>比较笨的一个方式是在鼠标的四周各浮动一个元素，分别表示当前元素的四条边，四条边的中间也就是鼠标底下是空的。为了阻止事件、链接的促发，当<code>mousedown</code>的时候，在鼠标底下浮动一个看不见的元素，从而阻断<code>click</code>事件，当<code>mouseup</code>后，又将这个浮动的元素移开，从而让<code>mouseover</code>的<code>e.target</code>恢复成鼠标底下的元素。</p>
<p><a href="http://www.zhouqicf.com/demo/js/2011/firebug_inspect_element.html" rel="demo">Demo</a></p>
</div>
<div class="code">
<pre class="brush:js"><code>
var getXY = function(node){
		return {"x": node.getBoundingClientRect().left + Math.max(document.body.scrollLeft, document.documentElement.scrollLeft), "y": node.getBoundingClientRect().top + Math.max(document.body.scrollTop, document.documentElement.scrollTop)};
}
$(document).mouseover(function(e) {
	var target = e.target,
	     width = target.offsetWidth,
	     height = target.offsetHeight,
	     p = getXY(target),
	     x = p.x,
	     y = p.y;
	$('#abs-1').css({"left":x+"px","top":y+"px","width":width+"px","height":0,"border-top":"1px solid blue"});
	$('#abs-2').css({"left":x+width+"px","top":y+"px","width":0,"height":height+"px","border-left":"1px solid blue"});
	$('#abs-3').css({"left":x+"px","top":y+height+"px","width":width+"px","height":0,"border-top":"1px solid blue"});
	$('#abs-4').css({"left":x+"px","top":y+"px","width":0,"height":height+"px","border-left":"1px solid blue"});
});
$(document).mousedown(function(e) {
	$('#abs-mask').css({"left":0,"top":0,"right":0,"bottom":0});
});
$(document).mouseup(function(e) {
	$('#abs-mask').css({"left":0,"top":0,"right":"auto","bottom":"auto"});
});
</code></pre>
</div>
<h2>方法二</h2>
<div class="desc">
<p>第二个方法就比较优雅了，CSS有一个让事件穿透某个元素的属性——<code><a href="https://developer.mozilla.org/en/CSS/pointer-events" rel="external">pointer-events</a></code>，有了它我们只需要改变这个属性的值就可以了。当<code>mouseover</code>的时候，属性值为<code>auto</code>，事件可以穿透元素，鼠标的底下浮动的元素就像不存在了一样，<code>e.target</code>始终是我们想要的元素；而当<code>mousedown</code>的时候，将属性值修改为<code>none</code>，让事件不能穿透元素，这样鼠标底下的浮动的元素就阻止了目标元素的<code>click</code>事件；当<code>mouseup</code>后，又将属性值修改为<code>auto</code>。</p>
<p><a href="http://www.zhouqicf.com/demo/js/2011/firebug_inspect_element_pointer_events.html" rel="demo">Demo</a></p>
</div>
<div class="code">
<pre class="brush:js"><code>
var getXY = function(node){
		return {"x":node.getBoundingClientRect().left+Math.max(document.body.scrollLeft,document.documentElement.scrollLeft),"y":node.getBoundingClientRect().top+Math.max(document.body.scrollTop,document.documentElement.scrollTop)};
}
$(document).mouseover(function(e) {
	var target = e.target,
	     width = target.offsetWidth,
	     height = target.offsetHeight,
	     p = getXY(target),
	     x = p.x,
	     y = p.y;
	$('#abs-mask').css({"left":x+"px","top":y+"px","width":width+"px","height":height+"px","pointer-events":"none"});
});
$(document).mouseup(function(e) {
	$('#abs-mask').css({"pointer-events":"none"});
});
$(document).mousedown(function(e) {
	$('#abs-mask').css({"pointer-events":"auto"});
});
</code></pre>
</div>
<h2>方法三</h2>
<div class="desc">
<p>第二个方法虽然比第一种幽雅一些，但是当你快速点击的时候，偶尔会失效，不知道是不是事件来不及执行导致的。这里要介绍第三种更加规范、稳定的方法：<b>事件捕获</b>。不了解的朋友可以google一下“事件流”。简单的说，事件有2种传播的方式，一种是我们常用的“事件冒泡”，即当我们点击一个按钮时，这个点击事件，会根据dom结构，一级一级往上传播，直到<code>document</code>对象（chrome、safari、opera、firefox浏览器都将冒泡至<code>window</code>对象）；另一种就是“事件捕获”，与前者相反，在事件捕获中，<code>document对象</code>（chrome、safari、opera、firefox都是从<code>window</code>对象开始捕获）首先接受到事件，然后沿着DOM树，依次往下传播，一直到目标按钮，当需要在事件到达目标之前截获时就需要它了，这正是我们需要的。</p>
<p><a href="http://www.zhouqicf.com/demo/js/2011/firebug_inspect_element_event_capture.html" rel="demo">Demo</a></p>
</div>
<div class="code">
<pre class="brush:js"><code>
var getXY = function(node){
		return {"x":node.getBoundingClientRect().left+Math.max(document.body.scrollLeft,document.documentElement.scrollLeft),"y":node.getBoundingClientRect().top+Math.max(document.body.scrollTop,document.documentElement.scrollTop)};
};
document.documentElement.addEventListener('mouseover', function(e) {
	e.preventDefault();
	var target = e.target,
		width = target.offsetWidth,
		height = target.offsetHeight,
		p = getXY(target),
		x = p.x,
		y = p.y;
	document.getElementById('abs-mask').style.cssText = 'left:'+x+'px;top:'+y+'px;width:'+width+'px;height:'+height+'px;';
}, false);
document.body.addEventListener('click', function(e){
	e.preventDefault();
	e.stopPropagation();
	//console.log(e.target);
}, true);
</code></pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhouqicf.com/javascript/firebug-inspect-element/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>HTTPS页面包含HTTP资源</title>
		<link>http://www.zhouqicf.com/browser/https-pages-contains-http-resource</link>
		<comments>http://www.zhouqicf.com/browser/https-pages-contains-http-resource#comments</comments>
		<pubDate>Mon, 17 Jan 2011 09:08:58 +0000</pubDate>
		<dc:creator>Zhou Qi</dc:creator>
				<category><![CDATA[browser]]></category>
		<category><![CDATA[fiddler]]></category>
		<category><![CDATA[https]]></category>
		<category><![CDATA[minify]]></category>
		<guid isPermaLink="false">http://www.zhouqicf.com/?p=440</guid>
		<description><![CDATA[<p>在各个浏览器的安全策略中，<em>HTTPS</em>协议页面，不能包含<em>HTTP</em>的资源请求，否则会进行不安全的提示，这篇文章将介绍Https页面包含Http资源相关的一些问题。</p>
<p>In each browser's security strategy, <em>HTTPS</em> pages can not contains <em>HTTP</em> resource, or browsers would tips unsafe, this article will introduce the Https page contains Http resource related problems.</p>]]></description>
			<content:encoded><![CDATA[<div class="desc">
<p>在各个浏览器的安全策略中，<em>HTTPS</em>协议页面，不能包含<em>HTTP</em>的资源请求，否则会进行不安全的提示，这篇文章将介绍Https页面包含Http资源相关的一些问题。</p>
</div>
<h2>各个浏览器的表现</h2>
<div class="desc">
<h3>IE6、IE7、IE8</h3>
<p><img src="http://www.zhouqicf.com/img/2011/https_contains_http_ie.jpg" width="600" height="298" alt="https contains http resource in ie"></p>
<h3>Firefox</h3>
<p><img src="http://www.zhouqicf.com/img/2011/https_contains_http_firefox.jpg" width="600" height="459" alt="https contains http resource in firefox"></p>
<h3>Safari</h3>
<p><img src="http://www.zhouqicf.com/img/2011/https_contains_http_safari.jpg" width="600" height="174" alt="https contains http resource in safari"></p>
<h3>chrome</h3>
<p><img src="http://www.zhouqicf.com/img/2011/https_contains_http_chrome.jpg" width="600" height="333" alt="https contains http resource in chrome"></p>
<h3>Opera</h3>
<p>有点诡异，再研究下。</p>
</div>
<h2>激活Fiddler的HTTPS通信解密</h2>
<div class="desc">
<p>因为HTTPS证书的问题（假证书无法通过浏览器的安全验证），很多前端问题我们必须在线上真实环境进行测试，这时候Fiddler的AutoResponder功能就可以大展拳脚了，但Fiddler默认是关闭对于HTTPS资源请求的监测的，需要手动开启。开启步骤：<em>tools > fiddler > https > decrypt https traffic</em>。更详细的请看官方的<a href="http://www.fiddlertool.com/fiddler/help/httpsdecryption.asp" rel="external">帮助文档</a>。</p>
<p><img src="http://www.zhouqicf.com/img/2011/enable_fiddler_https.jpg" width="600" height="369" alt="enable fiddler's https"></p>
</div>
<h2>将所有HTTP资源转化为HTTPS</h2>
<div class="desc">
<p>因为https页面不能包含http资源，所有我们要做的就是将所有http的资源改成https。包括以下内容：</p>
<ul>
<li>图片 image</li>
<li>样式表 stylesheet</li>
<li>脚本文件 Js</li>
<li>Iframe</li>
<li>&#8230;</li>
</ul>
</div>
<h2>修改Minify的路径</h2>
<div class="desc">
<p>很多大型网站会使用Minify或者类似的方案来合并资源请求，那么我们就需要修改这个Minify之后的资源的路径。以<a href="http://www.koubei.com" rel="external">口碑网</a>为例，Minify路径定义在某个CMS文件中，需要对它进行改写：</p>
</div>
<div class="code">
<pre><code>
//原来的
String result="&lt;link  href=\"http://k.kbcdn.com";
</code></pre>
</div>
<div class="code">
<pre><code>
//修改后的
//这里的https的路径仅仅做了一个跳转的功能，实际访问的仍然是"http://k.kbcdn.com"上的资源
String result="&lt;link  href=\"https://login.koubei.com/kbcdn";
</code></pre>
</div>
<h2>CSS背景图片</h2>
<div class="desc">
<p>除了样式表的资源要改成HTTPS，它里面的css背景也需要改成HTTPS的，那么难道我们要把所有的背景修改成<code>background:url(https://login.koubei.com/xxx);</code>吗？当然不是，因为我们已经把css文件修改成了HTTPS的路径，那么我们只要确保我们的<code>background</code>规则中的图片路径是一个<em>相对路径</em>就可以了，浏览器会将它们解析成一个HTTPS的资源请求。</p>
<p>这里需要说明的是Minfy会自动将相对路径改成相对于根目录的绝对路径，比如<code>../img/login.png</code>经过转化后可能是<code>/product/login/v2/img/login.png</code>，浏览器经过解析，得到<code>https://login.koubei.com/product/login/v2/img/login.png</code>，然后再进行一次跳转到<code>http://k.kbcdn.com/product/login/v2/img/login.png</code>。当然这种2层跳转的做法实在是太恶心了。</p>
</div>
<div class="code">
<pre><code>
Selector{
    background:url(../img/login.png) no-repeat 0 0;
}
</code></pre>
</div>
<h2>修改JS Loader的config</h2>
<div class="desc">
<p>以YUI Combo为例，当我们使用<code>use</code>方法异步加载各种资源文件的时候，YUI会根据<code>YUI_config</code>中的资源路径，来生成一个Combo后的资源路径。一般网站都会有一个整站的配置，例如口碑的配置放在<code>seed.js</code>中，为此我们需要在自己的项目中重新配置一个<code>YUI_config</code>来覆盖整站的配置，方法如下：</p>
</div>
<div class="code">
<pre><code>
YUI_config.base = "https://login.koubei.com/kbcdn/yui/3.2.0/";
YUI_config.comboBase = "https://login.koubei.com/kbcdn/min/f=";
//口碑k2框架的资源路径
YUI_config.groups.K2.base = "https://login.koubei.com/kbcdn/k2/";
</code></pre>
</div>
<h2 class="title">Data URI</h2>
<div class="desc">
<p>Data URI是一个减少http请求，降低前端工作量的好东西，口碑早已通过自动化的方式在整站使用。但是很可惜，<em>在HTTPS的环境下，IE6、IE7无法使用Data URI</em>。不光<code>mhtml</code>的资源会导致IE6/7报安全提示（即使你已经把它转化成了HTTPS的路径）&#8211; <q>This page contains both secure and nonsecure items. Do you want to display the nonsecure items?</q>，甚至用于其它浏览器的<code>base64</code>编码也将导致IE6/7报安全提示。</p>
</div>
<div class="code">
<pre><code>
/*两者都将导致IE6、7报安全提示*/
Selector{
    background:url(data:image/png;base64,iVBORw0…) no-repeat 0 0;
   *background:url(mhtml:https://login.koubei.com/kbcdn/product/login/v2/css/login-1-0-0-mhtml.css!tab.png) no-repeat 0 0;
}
</code></pre>
</div>
<div class="code">
<pre><code>
/*改成图片就ok了*/
Selector{
    background:url(../img/login.png) no-repeat 0 0;
}
</code></pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhouqicf.com/browser/https-pages-contains-http-resource/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Visual Firebug V1.0发布</title>
		<link>http://www.zhouqicf.com/visual-tools/visual-firebug-v10</link>
		<comments>http://www.zhouqicf.com/visual-tools/visual-firebug-v10#comments</comments>
		<pubDate>Tue, 14 Dec 2010 08:12:38 +0000</pubDate>
		<dc:creator>Zhou Qi</dc:creator>
				<category><![CDATA[Visual Tools]]></category>
		<category><![CDATA[tool]]></category>
		<category><![CDATA[visual]]></category>
		<guid isPermaLink="false">http://www.zhouqicf.com/?p=384</guid>
		<description><![CDATA[Visual Firebug是一个编辑在线页面样式的chrome插件。它的产生是为了让一些不会使用firebug的视觉、交互、运营等同学能够快速、方便地修改在线页面。]]></description>
			<content:encoded><![CDATA[<p>Visual Firebug是一个编辑在线页面样式的chrome插件。它的产生是为了让一些不会使用firebug的视觉、交互、运营等同学能够快速、方便地修改在线页面。</p>
<p>当前版本：1.0</p>
<p>下载：<a href="https://chrome.google.com/extensions/detail/lomkpheldlbkkfiifcbfifipaofnmnkn?hl=zh-CN" rel="external">https://chrome.google.com/extensions/detail/lomkpheldlbkkfiifcbfifipaofnmnkn?hl=zh-CN</a></p>
<h3 id="section0">内容索引</h3>
<ol>
<li><a href="#section1">使用方法</a>
<ol>
<li><a href="#section1-p1">开启插件</a></li>
<li><a href="#section1-p2">选择节点</a></li>
<li><a href="#section1-p3">编辑节点样式</a></li>
<li><a href="#section1-p4">获取节点样式</a></li>
<li><a href="#section1-p5">保存整页的修改结果</a></li>
</ol>
</li>
<li><a href="#section2">所有功能介绍</a></li>
<li><a href="#section3">现有控件</a>
<ol>
<li><a href="#section3-p1">列表项符号</a></li>
<li><a href="#section3-p2">字号</a></li>
<li><a href="#section3-p3">行高</a></li>
<li><a href="#section3-p4">字体</a></li>
<li><a href="#section3-p5">字形，包括加粗、斜体、下划线</a></li>
<li><a href="#section3-p6">字色</a></li>
<li><a href="#section3-p7">对齐方式</a></li>
<li><a href="#section3-p8">文字阴影</a></li>
<li><a href="#section3-p9">背景色</a></li>
<li><a href="#section3-p10">盒阴影</a></li>
<li><a href="#section3-p11">边框，包括边框及圆角</a></li>
<li><a href="#section3-p12">布局，包括内边距及外边距</a></li>
<li><a href="#section3-p13">宽高，包括宽度及高度</a></li>
</ol>
</li>
</ol>
<h3 id="section1">一、使用方法</h3>
<h4 id="section1-p1">1、开启插件</h4>
<p><img src="http://www.zhouqicf.com/img/vf/turn-on.jpg" alt="开启插件"/></p>
<p>点击chrome工具条上的图标即可，待插件加载完毕后，会在当前Tab的页面内插入面板，并默认自动开启元素选择功能。</p>
<h4 id="section1-p2">2、选择节点</h4>
<p><img src="http://www.zhouqicf.com/img/vf/selector.jpg" alt="选择节点"/></p>
<p>当鼠标移入某个节点时，该节点周围会出现蓝色边框，直接点击该点击，则选中该节点作为待编辑节点。</p>
<p>在节点上右键鼠标则会唤出与该节点相关的其它节点列表，鼠标移出这些列表项后，页面上同样将以蓝色边框的方式显示该列表项所对应的节点，如果该节点没有相关的其他节点列表，则会显示”no-selector”，并且该提示会在2秒钟后消失。相关节点列表包括”Tag选择”及”Class选择”两种方式，”Tag选择”将选中与该节点类型相同的节点，即如果当前节点为一个表格单元格（<code>td</code>），则会选中该单元格所在表格内的所有单元格；而”Class选择”将选中整个页面中拥有该class的所有节点。</p>
<p>选择完节点后，在面板的左上方将出现当前待编辑节点的类型及数量。</p>
<h4 id="section1-p3">3、编辑节点样式</h4>
<p><img src="http://www.zhouqicf.com/img/vf/editor.jpg" alt="编辑节点"/></p>
<p>通过面板上的控件编辑节点样式。</p>
<h4 id="section1-p4">4、获取节点样式</h4>
<p><img src="http://www.zhouqicf.com/img/vf/get-style.jpg" alt="获取样式"/></p>
<p>点击面板右上角”查看样式”按钮，下方将展开一个文本域，显示当前编辑节点的样式，在修改样式的过程中，该区域的样式将即时更新。并且该区域中的样式都进行了缩写处理，运营同学拿到后即可在cms中写入节点的style的属性。</p>
<h4 id="section1-p5">5、保存整页的修改结果</h4>
<p><img src="http://www.zhouqicf.com/img/vf/get-html.jpg" alt="保存整页的修改结果"/></p>
<p>点击面板右上角”获取修改结果”按钮，页面的左上方将出现一个浮层，显示”loadding”，待加载完之后，该浮层将变大撑满整个屏幕，浮层内的内容正是修改后的html代码，复制代码到一个文本文件，并另存为”xxx.html”即可。视觉、交互同学对某些网页进行微调时，不必再打开Photoshop、Axure等工具，直接打开本工具编辑即可，保存后即可丢给前端，前端看到效果后即可查看代码，在工具生成的代码的基础上code。</p>
<h3 id="section2">二、所有功能介绍</h3>
<p><img src="http://www.zhouqicf.com/img/vf/function.jpg" alt="具体功能介绍"/></p>
<h3 id="section3">三、现有控件</h3>
<ol>
<li id="section3-p1">
<p>列表项符号</p>
<p><img src="http://www.zhouqicf.com/img/vf/c-list.jpg" alt="列表项符号"/></p>
</li>
<li id="section3-p2">
<p>字号</p>
<p><img src="http://www.zhouqicf.com/img/vf/c-font-size.jpg" alt="字号"/></p>
</li>
<li id="section3-p3">
<p>行高</p>
<p><img src="http://www.zhouqicf.com/img/vf/c-line-height.jpg" alt="行高"/></p>
</li>
<li id="section3-p4">
<p>字体</p>
<p><img src="http://www.zhouqicf.com/img/vf/c-font-family.jpg" alt="字体"/></p>
</li>
<li id="section3-p5">
<p>字形，包括加粗、斜体、下划线</p>
<p><img src="http://www.zhouqicf.com/img/vf/c-font-style.jpg" alt="字形，包括加粗、斜体、下划线"/></p>
</li>
<li id="section3-p6">
<p>字色</p>
<p><img src="http://www.zhouqicf.com/img/vf/c-color.jpg" alt="字色"/></p>
</li>
<li id="section3-p7">
<p>对齐方式</p>
<p><img src="http://www.zhouqicf.com/img/vf/c-text-align.jpg" alt="对齐方式"/></p>
</li>
<li id="section3-p8">
<p>文字阴影</p>
<p><img src="http://www.zhouqicf.com/img/vf/c-text-shadow.jpg" alt="文字阴影"/></p>
</li>
<li id="section3-p9">
<p>背景色</p>
<p><img src="http://www.zhouqicf.com/img/vf/c-background-color.jpg" alt="背景色"/></p>
</li>
<li id="section3-p10">
<p>盒阴影</p>
<p><img src="http://www.zhouqicf.com/img/vf/c-box-shadow.jpg" alt="盒阴影"/></p>
</li>
<li id="section3-p11">
<p>边框，包括边框及圆角</p>
<p><img src="http://www.zhouqicf.com/img/vf/c-border.jpg" alt="边框，包括边框及圆角"/></p>
</li>
<li id="section3-p12">
<p>布局，包括内边距及外边距</p>
<p><img src="http://www.zhouqicf.com/img/vf/c-layout.jpg" alt="布局，包括内边距及外边距"/></p>
</li>
<li id="section3-p13">
<p>宽高，包括宽度及高度</p>
<p><img src="http://www.zhouqicf.com/img/vf/c-size.jpg" alt="宽高，包括宽度及高度"/></p>
</li>
</ol>
]]></content:encoded>
			<wfw:commentRss>http://www.zhouqicf.com/visual-tools/visual-firebug-v10/feed</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>模块化</title>
		<link>http://www.zhouqicf.com/html-css/modularity</link>
		<comments>http://www.zhouqicf.com/html-css/modularity#comments</comments>
		<pubDate>Mon, 25 Oct 2010 15:10:13 +0000</pubDate>
		<dc:creator>Zhou Qi</dc:creator>
				<category><![CDATA[HTML & CSS]]></category>
		<category><![CDATA[modularity]]></category>
		<category><![CDATA[模块化]]></category>
		<guid isPermaLink="false">http://www.zhouqicf.com/?p=320</guid>
		<description><![CDATA[<em>全局</em>、<em>项目</em>、<em>页面</em>三种样式作用域下的模块化。]]></description>
			<content:encoded><![CDATA[<div class="desc">
<p>ghostzhang在<a href="http://www.cssforest.org" rel="external">CSS森林</a>上发表了6篇关于<dfn>模块化</dfn>的文章，详细介绍了<dfn>基类</dfn>和<dfn>扩展类</dfn>的概念和用法。下面我要说的内容是对这一系列文章的补充和完善，简单地浏览一下那6篇文章能帮助你更好地理解，以下代码很好地总结了这些文章的主要内容：</p>
</p></div>
<div class="code">
<pre><code>
/**
  * @name: mode_name
  * @author: ghostzhang
  * @version: 1.0
  * @type: 基类
  * @explain: Demo
  */
.mode_name{...}
.mode_name h2{...}
.mode_name .cont{...}
/* @end **/
/**
  * @name: mode_name_b
  * @author: ghostzhang
  * @version: 1.0
  * @type: 扩展类
  * @explain: Demo
  * @dependent: mode_name
  */
.mode_name_b{...}
.mode_name_b h2{...}
.mode_name_b .cont{...}
/* @end **/
/* 针对单个模块的个性化定义 */
.mode_xxxx{...}
.mode_xxxx h2{...}
.mode_xxxx .cont{...}
</code></pre>
</div>
<div class="desc">
<p>相信各位参与项目开发的同学遇到相似语义或者相似样式的模块时，都会在代码中体现出<dfn>基类</dfn>和<dfn>扩展类</dfn>的概念，以上代码似乎只是一种实践方式的概念提炼。并且<a href="http://oocss.org/">OOCSS</a>所提出的面向对象的概念，也将所谓的<em>类</em>从功能模块细化为了页面元素，比如所有的标题都继承<code>.title</code>类，所有的注释都继承<code>.note</code>类，然后在模块级基类中去覆盖这些元素级基类，如<code>.mode_name .title{...}</code>。而这样的细化将带来以下问题：</p>
<p><em>全局</em>、<em>项目</em>、<em>页面</em>三种样式作用域的混乱。因为缺少了模块基类后<span class="note">(如以上代码中的<code>.mode-news</code>、<code>.mode-links</code>&#8230;)</span>，各种对象基类<span class="note">(如<code>.title</code>、<code>.tag</code>&#8230;)</span>就会暴露在外，而全局会有全局的通用元素，项目会有项目级的通用模块，项目中的各个页面同样也会有一些通用模块，这样就很容易产生作用域间的混乱。你不知道<code>.title</code>类的作用域是全局的还是项目的还是页面的；你不知道它们在哪个页面被用过；过了一段时间后你甚至不知道有没有定义过<code>.title</code>这个类，遇到一个标题元素的时候不知道是不是用现成的类可以用……为此我们需要一些显示的声明来处理类的<em>作用域</em>及<em>被调用关系</em>等问题。</p>
</p></div>
<div class="code">
<pre><code>
/*全局：*/
.K2-note{…}
.K2-title{…}
/*项目：*/
.project-note{…}
.project-title{…}
/*页面：*/
#modify-account .note{…}
#modify-account .title{…}
</code></pre>
</div>
<div class="desc">
<p>最简单直接的方式就是通过类名前缀来区分不同的作用域，比如<a href="http://www.koubei.com">口碑网</a>的全局类都以<code>k2</code>为前缀；项目的前缀可以用<code>project</code>，甚至以具体的项目id来区分，比如团购项目的标题元素用<code>.tuan-title</code>；对于页面级的类，建议使用php等服务端语言来搭建本地开发环境，在做demo时，为每个页面配置一个唯一的id，该id既是该页面的文件名也是该页面<code>body</code>元素的id名，然后通过该id去定义元素样式，而不像ghostzhang一样通过一个唯一的类名来区分。</p>
<p>以上方式运用于模块，与<dfn>基类</dfn>、<dfn>扩展类</dfn>结合后<span class="note">(以项目级为例)</span>：</p>
</p></div>
<div class="code">
<pre><code>
/**
  * @name: project_mode_prompt
  * @author: zhouqi
  * @version: 1.0
  * @type: 基类
  * @explain: 操作提示模块
  * @caller:add_pic\modify_pic
  */
.project_mode_prompt{...}
.project_mode_prompt h2{...}
.project_mode_prompt .cont{...}
/* @end **/
/**
  * @name: project_mode_prompt_b
  * @author: zhouqi
  * @version: 1.0
  * @type: 扩展类
  * @explain: 操作提示模块
  * @dependent: project_prompt_name
  * @caller:del_pic
  */
.project_mode_prompt_b{...}
.project_mode_prompt_b h2{...}
.project_mode_prompt_b .cont{...}
/* @end **/
/* 针对modify-account页面的个性化定义 */
#modify-account project_mode_prompt{...}
#modify-account project_mode_prompt h2{...}
#modify-account project_mode_prompt .cont{...}
</code></pre>
</div>
<div class="desc">
<p>这里有2个改进，一是为模块增加了显式的作用域声明即类名前缀，开发者及维护者一看到该类名就知道它是一个什么作用域的类；二是在类注释中声明了<em>caller</em>属性，即表明该类被哪些页面调用，这样当修改了该基类后就知道要去哪些页面检查样式是不是乱了。</p>
</p></div>
<h2 class="title">相关资源</h2>
<div class="desc">
<ol>
<li><a href="http://www.slideshare.net/stubbornella/object-oriented-css" rel="external">object oriented css</a></li>
<li><a href="http://www.cssforest.org/blog/index.php?id=168" rel="external">页面重构中的模块化设计</a></li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhouqicf.com/html-css/modularity/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>css3 button maker</title>
		<link>http://www.zhouqicf.com/visual-tools/css3-button-maker</link>
		<comments>http://www.zhouqicf.com/visual-tools/css3-button-maker#comments</comments>
		<pubDate>Wed, 04 Aug 2010 10:08:20 +0000</pubDate>
		<dc:creator>Zhou Qi</dc:creator>
				<category><![CDATA[Visual Tools]]></category>
		<category><![CDATA[button]]></category>
		<category><![CDATA[css3]]></category>
		<guid isPermaLink="false">http://www.zhouqicf.com/?p=250</guid>
		<description><![CDATA[一个可视化的css3按钮制作工具，让视觉同学用我们提供的工具进行设计，设计完成后，前端的代码也完成了。]]></description>
			<content:encoded><![CDATA[<h2>Demo：</h2>
<div class="desc">
<p><a href="http://www.zhouqicf.com/demo/css/2010/button_maker/button_maker.html">css3 button maker</a></p>
<p><img src="http://www.zhouqicf.com/img/2010/css3_button maker.png" alt="css3 button maker" width="553" height="467"></p>
</p></div>
<h2>站在别人的肩上</h2>
<div class="desc">
<p>基于<a href="http://css-tricks.com/examples/ButtonMaker/">button maker</a>。</p>
</p></div>
<h2>改进：</h2>
<div class="desc">
<ul>
<li>增加text-shadow、box-shadow、border等css属性</li>
<li>增加:active伪类支持</li>
<li>增加IE hack，实现IE优雅降级</li>
<li>生成样式时，剔除不需要的代码，如:hover时样式和正常状态一样、:active时和:hover时样式一样，这些情况下样式的重复定义都是没有意义的，剔除之。</li>
<li>通过fixed定位，代替js位置计算</li>
<li>增加中文字体集</li>
<li>0px转化为0</li>
</ul></div>
<h2>需要改进的：</h2>
<div class="desc">
<ul>
<li>目前只支持两种色值的渐变，3种较为理想，并且不支持自定义渐变的方向</li>
<li>IE最好有更少的降级</li>
<li>拖动条最好用html5的range控件来实现</li>
<li>脚本可以再完善</li>
</ul></div>
<h2>价值：</h2>
<div class="desc">
<p>接手“前端和视觉之间的故事”这个团队内部的项目已经有一段时间了，一直没有找到一个让视觉同学了解<em>前端可以做什么</em>、<em>前端有什么新技术</em>的好方法，一旦这个做不好，让视觉协助我们前端做一些<em>渐进增强</em>的东西就很困难。</p>
<p>无意中我看到了Chris Coyier的button maker，我想这是一个有效解决问题的好方法，视觉用我们提供的工具进行设计，设计完成后，前端的代码也完成了，太棒了。为此我在征得Chris Coyier的同意后，借鉴了他的代码，进行了如上提到的改进，给视觉看后，似乎很认可，希望能真的运用到设计中去。</p>
</p></div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhouqicf.com/visual-tools/css3-button-maker/feed</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>用:visited窥探用户访问历史</title>
		<link>http://www.zhouqicf.com/html-css/%e7%94%a8visited%e7%aa%a5%e6%8e%a2%e7%94%a8%e6%88%b7%e8%ae%bf%e9%97%ae%e5%8e%86%e5%8f%b2</link>
		<comments>http://www.zhouqicf.com/html-css/%e7%94%a8visited%e7%aa%a5%e6%8e%a2%e7%94%a8%e6%88%b7%e8%ae%bf%e9%97%ae%e5%8e%86%e5%8f%b2#comments</comments>
		<pubDate>Fri, 09 Jul 2010 07:05:06 +0000</pubDate>
		<dc:creator>Zhou Qi</dc:creator>
				<category><![CDATA[HTML & CSS]]></category>
		<category><![CDATA[:visited]]></category>
		<category><![CDATA[firefox]]></category>
		<category><![CDATA[mozilla]]></category>
		<guid isPermaLink="false">http://www.zhouqicf.com/?p=217</guid>
		<description><![CDATA[因为通过js可以访问链接的<code>:visited</code>样式，从而获知用户的访问历史，firefox4开始限制可用于<code>:visited</code>伪类的css属性。这里提供一个简单的用<code>:visited</code>窥探用户访问历史的方法。]]></description>
			<content:encoded><![CDATA[<h2>更新</h2>
<div class="desc">
<ol>
<li id="post-217-note1"><code>window.getComputedStyle(node,pseudo)[property]</code>不能取<code>:visited</code>的值，这里的“pseudo”应该是”Pseudo-Element(伪元素)”而不是“伪类”。</li>
</ol>
</div>
<h2>起因</h2>
<div class="desc">
<p>mozilla发布了<a href="http://www.mozilla.com/en-US/firefox/beta/">firefox4 beta 1</a>，更新了一些CSS属性，不知道你有没有注意到其中有一条关于<code>:visited</code>伪类的更新，为了保护用户的隐私，限制绝了绝大多数的css样式应用到<code>:visited</code>元素上，这其中就包含了一些我们常用于访问过链接的CSS属性，比如<code>background</code>、<code>border-color</code>、<code>font</code>。比如我的博客，对访问过的链接，就会用<code>content</code>属性生成一个勾，提示读者这个链接他已经访问过了。我尝试了几个常用的CSS属性，只有<code>color</code>依然有效。</p>
<p>既然color仍然有效，不知道mozilla这样做有什么意义？在这个越来越注重可用性的时代，不考虑<code>:visited</code>样式绝不是一个好的做法，说句题外话，各位设计师们应该在设计中考虑更多的css伪类样式，而不局限于<code>:hover</code>，按下一个按钮、表单获得焦点这些动作没有反馈是一件令人沮丧的事。言归正传，限制那么多的CSS属性运用于<code>:visited</code>将大大降低设计师的创作空间。访问后变色本身又是一个不受大多数人喜欢的标识方法，<code>a,a:visited{color:XXX;}</code>是绝大多数网站的做法。只能用两个字形容我的现在的心情：“我操”。</p>
</div>
<h2>如何窥探</h2>
<div class="desc">
<p>我没有去查这个隐私问题到底是怎么发生的，我的猜测就是用脚本去遍历链接，判断它的<code>:visited</code>样式有没有生效，生效了就说明访问过了。这里原理类似我的这篇文章：<a href="http://www.zhouqicf.com/javascript/browser-detector-with-css">Browser Detector With CSS</a>。<del>真想问问mozilla为什么不从js下刀呢，为什么不去限制<code>window.getComputedStyle(node,pseudo)[property]</code>取<code>:visited</code>的值？IE知道这事笑了，“哈哈，我不支持用js取伪类样式！”。</del><sup class="note-sign"><a href="#post-217-note1">[1]</a></sup>基本代码如下，请忽视转换色值的函数：</p>
<p><a href="http://demo.zhouqicf.com/css/2010/firefox4_visited.html" rel="demo">[Demo]用firefox4看看是不是只有颜色生效了？</a> <a href="http://demo.zhouqicf.com/css/2010/visited_history.html" rel="demo">[Demo]看看你访问过哪里？</a></p>
</div>
<div class="code css">
<pre><code>
a:visited{color:#f00;}
</code></pre>
</div>
<div class="code js">
<pre><code>
var Color = {
    "toHex" : function(rgb){
        var a = rgb.replace(/rgb\(|\)/g,"").split(","),
              hex = "";
        for (var i = 0;i < 3;i++){
            var b = parseInt(a[i]).toString(16);
            hex += (b.length === 1)?"0"+b:b;
        }
        return "#" + hex;
    },
    "toComplate" : function(hex){
        if (hex.length === 4){
            var hex = hex.toLowerCase(),
                  newHex = "";
            for (var i = 0;i < 3;i++){
                var a = hex.substring(i+1,i+2);
                newHex += a + a;
            }
            return "#" + newHex;
        }else{
            return hex;
        }
    }
};
function getColor(node,property){
    if(node.currentStyle){
        return Color.toComplate(node.currentStyle[property]);
    }
    if(window.getComputedStyle){
        return Color.toHex(window.getComputedStyle(node,null)[property]);
    }
}
var links = document.getElementsByTagName("a");
for(var i = 0,j = links.length;i&lt;j;i++){
    var color = getColor(links[i],"color");
    if(color === "#ff0000"){
        alert("你访问过："+links[i].firstChild.nodeValue);
    }
}
</code></pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhouqicf.com/html-css/%e7%94%a8visited%e7%aa%a5%e6%8e%a2%e7%94%a8%e6%88%b7%e8%ae%bf%e9%97%ae%e5%8e%86%e5%8f%b2/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>iframe自适应高度</title>
		<link>http://www.zhouqicf.com/javascript/iframe-auto-height</link>
		<comments>http://www.zhouqicf.com/javascript/iframe-auto-height#comments</comments>
		<pubDate>Wed, 07 Jul 2010 04:00:45 +0000</pubDate>
		<dc:creator>Zhou Qi</dc:creator>
				<category><![CDATA[Javascript]]></category>
		<category><![CDATA[iframe]]></category>
		<category><![CDATA[跨域]]></category>
		<guid isPermaLink="false">http://www.zhouqicf.com/?p=203</guid>
		<description><![CDATA[解决跨域、同域、高度不断变化等情况下iframe高度自适应的问题。]]></description>
			<content:encoded><![CDATA[<h2 class="title">同域、子页面高度不会动态增加</h2>
<div class="desc">
<p>这种情况最简单，直接通过脚本获取字页面实际高度，修改<code>iframe</code>元素高度即可。但有二点必须注意：</p>
<ol>
<li>如果页面内有<em>绝对定位</em>或者<em>没有清浮动</em>的元素，情况有些复杂，不同浏览器处理结果不同，甚至包括<em>Webkit</em>内核的浏览器，具体请看这个<a href="http://www.zhouqicf.com/demo/js/2010/iframe_height/different_broswer_height.html">Demo</a>。所以你要么进行浏览器检测，要么用<code>Math.max</code>计算一个最大值，要么你想别的方法。</li>
<li><code>iframe</code>所包含页面可能非常大，需要很长的加载时间，为此直接计算高度的时候，很可能页面还没下载完，高度计算就会有问题。所以最好在<code>iframe</code>的<code>onload</code>事件中计算高度。这里还要注意的是，IE下必须使用微软事件模型<code>obj.attachEvent</code>来绑定<code>onload</code>事件。而别的浏览器直接<code>obj.onload = function(){}</code>也可以。</li>
</ol></div>
<div class="code js">
<pre><code>
(function(){
    var frame = document.getElementById("frame_content_parent"),
        setIframeHeight = function(){
            var frameContent = frame.contentWindow.document,
                frameHeight = Math.max(frameContent.body.scrollHeight,frameContent.documentElement.scrollHeight);
            frame.height = frameHeight;
        };
    if(frame.addEventListener){
        frame.addEventListener("load",setIframeHeight,false);
    }else{
        frame.attachEvent("onload",setIframeHeight);
    }
})();
</code></pre>
</div>
<h2 class="title">同域、子页面高度会动态增加</h2>
<div class="desc">
<p>原理与第一种情况一样，多一个计时器，一直检测字页面高度，当子页面高度和<code>iframe</code>的高度不一致时，重新设置<code>iframe</code>的高度。这边也可以加一个<code>try</code>在js出错时，加一个足够的高度。</p>
</p></div>
<div class="code">
<pre><code>
(function(){
    var _reSetIframe = function(){
        var frame = document.getElementById("frame_content_parent")
        try {
            var frameContent = frame.contentWindow.document,
                bodyHeight = Math.max(frameContent.body.scrollHeight,frameContent.documentElement.scrollHeight);
            if (bodyHeight != frame.height){
                frame.height = bodyHeight;
            }
        }
        catch(ex) {
            frame.height = 1800;
        }
    }
    if(frame.addEventListener){
        frame.addEventListener("load",function(){setInterval(_reSetIframe,200);},false);
    }else{
        frame.attachEvent("onload",function(){setInterval(_reSetIframe,200);});
    }
})();
</code></pre>
</div>
<h2 class="title">同域、子页面高度会动态增加、脚本可能完全失效</h2>
<div class="desc">
<p>第二个例子中，考虑到了脚本出错的情况，但是万一脚本根本不执行了呢，那<code>iframe</code>中的内容就会因为<code>iframe</code>的高度不够而显示不了。为此我们通常事先设置一个足够的高度，为了前端控制方便，我觉得写在CSS文件中比较合适，需要修改时只改CSS就行了。这里我设置了<code>selector{ height:1800px; }</code>。需要注意的是，写在样式表里的样式，不能直接用<code>node.style[property]</code>来取，对于微软模型，要用<code>node.currentStyle[property]</code>（题外话：悲剧的IE模型不支持CSS伪类），对于W3C模型，要用<code>window.getComputedStyle(node,null)[property]</code>来取。我这里图方便直接用了YUI。</p>
<p>这里又有一个问题，设置<code>iframe</code>的高度大于其包含页面的高度时，各个浏览器的处理不一样。例如在Firefox下，必须计算<code>body</code>元素的高度，而<code>html</code>元素的高度等于<code>iframe</code>的高度，然而当恰巧这个页面又有<em>绝对定位</em>、<em>未清浮动</em>元素时，又不能通过<code>body</code>元素来取，显然第一种方法缺点更小一些。具体请看这个<a href="http://demo.zhouqicf.com/js/2010/iframe_height/iframe_higher.html">Demo</a>。</p>
<p>从上面这个Demo可以看到，除IE浏览器外，别的浏览器计算出来的都是<code>iframe</code>的高度，即CSS里设置的<code>#frame_content_parent{ height:1800px; }</code>。而IE计算出来的是<code>iframe</code>所引用页面的实际高度。</p>
</p></div>
<div class="code">
<pre><code>
#frame_content_parent{ height:1800px; }
</code></pre>
</div>
<div class="code">
<pre><code>
(function(){
    var $ = YAHOO.util.Dom,
        frame = $.get("frame_content_parent");
    function reSetIframe(){
        var frameContent = frame.contentWindow.document,
            bodyHeight = Math.max(frameContent.documentElement.scrollHeight,frameContent.body.scrollHeight);
        if (bodyHeight != $.getStyle(frame, "height")){
            $.setStyle(frame, "height", bodyHeight + "px");
        }
    }
    if(frame){
        $.setStyle(frame,"height","auto");
        setInterval(reSetIframe,300);
    }
})();
</code></pre>
</div>
<h2 class="title">跨域</h2>
<div class="desc">
<p>这里提供一个Iframe代理的方法，简单地说一下原理。假设有3个页面，分别是主页面A.html，字页面B.html，代理页面C.html。其中A与B是跨域的，而A和C是同域的。它们的关系：A包含B，B包含C。很显然A和B，以及B和C，因为跨域不能相互通信，而A和C同域，可以相互通信。为此我们就想到让C页面告诉A页面，B页面到底有多少高。因为B和C也是跨域的不能相互通信，所以想在C页面中，直接<code>window.parent.document.body.scrollHeight</code>这样是行不通的，所以我们只能让B页面自己计算自身的高度，然后通过某种方法告诉C页面，再由C页面告诉A页面。这里的一个方法就是在B页面生成一个<code>Iframe</code>节点，然后设置它的<code>src</code>属性，在这个地址上附加一个参数，即B页面计算出来的高度，然后C页面就可以通过<code>window.location</code>获取这个地址栏中的地址，提取出高度值，通过<code>window.top</code>找到A页面，设置A页面的Iframe的高度。基本的原理就是这样，看代码吧：</p>
<p><a href="http://demo.zhouqicf.com/js/2010/iframe_height/iframe_height_different_area_once.html">DEMO</a></p>
</p></div>
<div class="code">
<pre><code>
//B页面脚本
//任务：计算其实际高度，然后生成一个iframe节点，将高度作为代理页面C的地址的一部分赋值给Src属性
(function(){
    var agent_iframe = document.createElement("iframe"),
        b_height = Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);
    agent_iframe.src = "http://demo.zhouqicf.com/js/2010/iframe_height/agent_iframe_once.html#" + b_height;
    document.body.appendChild(agent_iframe);
    agent_iframe.style.display = "none";
})();
</code></pre>
</div>
<div class="code">
<pre><code>
//C页面脚本
//任务：获取请求地址中的高度值，将其赋值给A页面的Iframe的高度
window.top.document.getElementById("frame_content_parent").height = parseInt(window.location.hash.substring(1),10);
</code></pre>
</div>
<h2 class="title">跨域、字页面高度动态变化</h2>
<div class="desc">
<p>这里结合了第2、第4两种方法，我的想法是在B页面通过一个计时器，不停计算B页面的高度，一但变化，马上修改<code>iframe</code>标签的<code>src</code>属性，而C页面也有计时器不断监听<code>src</code>的变化，改变A<code>iframe</code>标签的高度。需要注意的是仅仅修改<code>src</code>属性后面的锚点值（如“#1234”），页面并不会刷新，不会重新请求，这也是在C页面增加计时器的原因。</p>
<p><a href="http://demo.zhouqicf.com/js/2010/iframe_height/iframe_height_different_area.html">DEMO</a></p>
</p></div>
<div class="code">
<pre><code>
//B页面脚本
(function(){
    var getHeight = function(){
        return Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);
    };
    var preHeight = getHeight(),
        agent_iframe;
    var createIframe = function(height){
        agent_iframe = document.createElement("iframe");
        agent_iframe.style.height = "0";
        agent_iframe.style.width = "0";
        agent_iframe.style.border = "none";
        agent_iframe.src = "http://demo.zhouqicf.com/js/2010/iframe_height/agent_iframe.html#" + height;
        document.body.appendChild(agent_iframe);
    }
    createIframe(preHeight);
    var checkHeight = function(){
        var currentHeight = getHeight();
        if(currentHeight != preHeight){
            agent_iframe.src = "http://demo.zhouqicf.com/js/2010/iframe_height/agent_iframe.html#" + currentHeight;
            preHeight = currentHeight;
        }
        setTimeout(checkHeight,500);
    }
    setTimeout(checkHeight,500);
})();
</code></pre>
</div>
<div class="code">
<pre><code>
//C页面脚本
(function(){
    var preHeight = parseInt(window.location.hash.substring(1),10),
        ifrmae = window.top.document.getElementById("frame_content_parent");
    ifrmae.height = preHeight;
    setInterval(function(){
        var newHeight = parseInt(window.location.hash.substring(1),10);
        if (newHeight !== preHeight){
            ifrmae.height = newHeight;
            preHeight = newHeight;
        }
    },500);
})();
</code></pre>
</div>
<div class="desc">
<p>这里还有另一种方案，就是让<code>iframe</code>每一次都重新请求，这样C页面就不需要计时器了，但是如果2次计算高度重复的话，就会导致<code>src</code>属性的值相同，这样浏览器就很可能不重新请求该页面了，那么C页面中的脚本也就不运行了。要修复这个问题很简单，只要在每次计算出来的<code>src</code>属性上增加一个随机数的参数就行了。比如<code>http://demo.zhouqicf.com/js/2010/iframe_height/agent_iframe.html?temp=123123423712937#1563</code></p>
</p></div>
<div class="code">
<pre><code>
//B页面关键脚本
agent_iframe.src = "http://demo.zhouqicf.com/js/2010/iframe_height/agent_iframe.html?a=" + Math.random() + "#" + currentHeight;
</code></pre>
</div>
<div class="code">
<pre><code>
//C页面脚本
window.top.document.getElementById("frame_content_parent").height = parseInt(window.location.hash.substring(1),10);
</code></pre>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.zhouqicf.com/javascript/iframe-auto-height/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
	</channel>
</rss>

