<?xml version="1.0" encoding="UTF-8"?>
  <feed xmlns="http://www.w3.org/2005/Atom">
  <title type="html"><![CDATA[W3C标准WEB前端DHTML精英俱乐部]]></title>
  <subtitle type="html"><![CDATA[Javascript和CSS权威专家WEB前端开发指南]]></subtitle>
  <id>http://www.v-ec.com/dh20156/</id>
  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/" /> 
  <link rel="self" type="application/atom+xml" href="http://www.v-ec.com/dh20156/atom.asp" /> 
  <generator uri="http://www.pjhome.net/" version="2.8">PJBlog3</generator> 
  <updated>2010-07-28T21:28:46+08:00</updated>

  <entry>
	  <title type="html"><![CDATA[发送自IPad的日志]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-07-28T21:28:46+08:00</updated>
	  <published>2010-07-28T21:28:46+08:00</published>
		  <summary type="html"><![CDATA[Fck Editer只能在源码模式下输入, File Upload灰色禁用状态，木有办法上传文件的IPad下的liu浏览器不是很好用的说。 ]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=303" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=303</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[JQuery字符串转DOM节点BUG]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-06-22T17:37:07+08:00</updated>
	  <published>2010-06-22T17:37:07+08:00</published>
		  <summary type="html"><![CDATA[<p>在修正一个UI的BUG时发现<strong>JQuery将字符串转DOM节点时会将针对IE6的CSS Hack的样式部分进行转义</strong>，测试代码如下：</p>
<p><strong>1、引入JQuery代码</strong></p>
<p>2、运行如下代码测试：</p>
<p><span style="font-size: 14px;">+function(){<br />
var s = '&lt;h1&gt;&lt;em class=&quot;a_b c&quot; style=&quot;min-height:50px;_height:50px;&quot;&gt;x&lt;/em&gt;&lt;/h1&gt;';<br />
var d = $(s);<br />
alert(d.html());<br />
}();</span></p>
<p><strong>FF中的结果为：</strong></p>
<p>&lt;em class=&quot;a_b c&quot; style=&quot;min-height: 50px;&quot;&gt;x&lt;/em&gt;</p>
<p>&quot;_height:50px;&quot; 部分不见了。</p>
<p><strong>IE下的结果为：</strong></p>
<p>&lt;EM class=&quot;a_b c&quot; style=&quot;MIN-HEIGHT: 50px; HEIGHT: 50px&quot;&gt;x&lt;/EM&gt;</p>
<p>&quot;_&quot; 不见了。</p>
<p>&nbsp;</p>
<p>遇到此BUG的同学可以将inline的style改成className的方式来处理一下。</p>
<p><strong>JQuery Bug Report:</strong> <a href="http://forum.jquery.com/topic/transform-bug-in-html-string" target="_blank">http://forum.jquery.com/topic/transform-bug-in-html-string</a></p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=302" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=302</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[苏州太湖之行]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=3" label="My Life" /> 
	  <updated>2010-06-17T23:05:13+08:00</updated>
	  <published>2010-06-17T23:05:13+08:00</published>
		  <summary type="html"><![CDATA[<p>苏州，一路过去，半山半水，鱼米之乡的感叹油然而出，悠然、大气的太湖更是让人无法一窥全貌，朦胧如出浴的妃子。</p>
<p><img alt="苏州太湖" src="http://www.w3cgroup.com/attachments/month_1006/s201061723823.jpg" /></p>
<p>&nbsp;<img alt="苏州太湖" src="http://www.w3cgroup.com/attachments/month_1006/n201061723834.jpg" /></p>
<p>&nbsp;在某开心农场做了本次Off-Site的课外活动，对很久木有外出的大家来说，景致真的不错！</p>
<p><img alt="苏州绿光开心农场" src="http://www.w3cgroup.com/attachments/month_1006/b2010617231012.jpg" /></p>
<p><img alt="农场中的卡丁车赛场" src="http://www.w3cgroup.com/attachments/month_1006/j2010617231325.jpg" /></p>
<p><img alt="农场水渠" src="http://www.w3cgroup.com/attachments/month_1006/y2010617231411.jpg" /></p>
<p><img alt="农场沙滩" src="http://www.w3cgroup.com/attachments/month_1006/o2010617231440.jpg" /></p>
<p><img alt="农场果园" src="http://www.w3cgroup.com/attachments/month_1006/02010617231518.jpg" /></p>
<p><img alt="农场林荫小道" src="http://www.w3cgroup.com/attachments/month_1006/q2010617231546.jpg" /></p>
<p><img alt="农场葡萄架" src="http://www.w3cgroup.com/attachments/month_1006/h2010617231616.jpg" /></p>
<p><img alt="农场中红透的李子" src="http://www.w3cgroup.com/attachments/month_1006/g2010617231648.jpg" /></p>
<p><img alt="结满果实的梨树" src="http://www.w3cgroup.com/attachments/month_1006/l2010617231735.jpg" /></p>
<p><img alt="金黄色的琵琶" src="http://www.w3cgroup.com/attachments/month_1006/k2010617231820.jpg" /></p>
<p>本次Off-Site课外活动的集合点</p>
<p><img alt="Cisco WebEx Off-Site Kick Off" src="http://www.w3cgroup.com/attachments/month_1006/i2010617231858.jpg" /></p>
<p>晚上的篝火晚会灰常热闹，不过火焰太大，好热!</p>
<p><img alt="" src="http://www.w3cgroup.com/attachments/month_1006/3201061723213.jpg" /></p>
<p>苏州真的不错！^_^</p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=301" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=301</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[Freemarker风格的JavaScript模板引擎EasyTemplate]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-06-05T16:32:45+08:00</updated>
	  <published>2010-06-05T16:32:45+08:00</published>
		  <summary type="html"><![CDATA[<h2>在前后端分离的解决方案中，模板起到了重要作用！</h2>
<p>在使用Struts或Spring的后端中，使用Freemarker模板作为载体，能够非常有效的实现前后端的分离。</p>
<p>有人或许会认为使用前端模板一样可以实现此效果，而且实现的会更好。</p>
<p>如果单纯从技术和实现的角度去考虑，确实是使用前端模板效果会更好，前后端分离的会更彻底，但如果真的这样做，任何地方都采用前端模板去渲染，那这样的WEB应用将会失去高可靠性及易用性。</p>
<p>我们的建议是，一般的页面由后端模板渲染，页面中的某些特殊模组，可以由前端模板进行渲染，比如，一个具有诸多交互且内容不断变化的数据列表。</p>
<h3>在使用过Freemarker模板后，感觉它的语法比较朴实，平易近人，容易上手，于是决定按它的语法风格实现一个前端的模板引擎，这就有了下面的EasyTemplate!</h3>
<p>EasyTemplate模板的<strong>函数大小为1.34k</strong>（未压缩），暂时只<strong>实现了list，list index，if elseif&nbsp;else</strong>等功能，应该可以满足大部分的使用需求了。</p>
<p>EasyTemplate模板引擎的解析速度测试，渲染1000行数据，在不同的浏览器中，平均速度大约在<strong>30毫秒以内</strong>（测试机器性能较弱）。</p>
<h3>EasyTemplate可用标签：</h3>
<p><span style="background-color: Yellow;">&lt;#et tname $dataname&gt; //模板开始标签，tname为此模板的名称，$dataname为此模板中用到的数据名称<br />
</span></p>
<p><span style="background-color: Yellow;">&lt;#if (condition)&gt;</span><span style="background-color: Yellow;"><br />
<br />
&lt;#elseif (condition)&gt;<br />
<br />
&lt;#else&gt;<br />
<br />
&lt;/#if&gt;</span></p>
<p><span style="background-color: Yellow;">{$x?a:b} //三元表达式，最后不能加分号&quot;；&quot; 注意：在所有的 {} 中都不能出现分号！<br />
</span></p>
<p><span style="background-color: Yellow;">&lt;#list $List as $list&gt; //遍历一个数组对象<br />
<br />
{$idx} //在此次遍历中的当前索引<br />
<br />
{$list.xxx} //取值<br />
<br />
&lt;/#list&gt; //结束遍历</span></p>
<p><span style="background-color: Yellow;">&lt;/#et&gt; //模板结束标签</span></p>
<p>&nbsp;</p>
<h3>调用方法：</h3>
<p><strong><span style="background-color: Lime;">var x = easyTemplate(sTemplate,oData);</span></strong></p>
<p>&nbsp;</p>
<p>EasyTemplate模板引擎函数下载：<a target="_blank" href="http://www.easyui.org.cn/easyTemplate.js">http://www.easyui.org.cn/easyTemplate.js</a></p>
<p>EasyTemplate模板引擎在线演示：<a target="_blank" href="http://www.easyui.org.cn/easyTemplate.html">http://www.easyui.org.cn/easyTemplate.html</a></p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=300" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=300</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[离线存储解决方案分析实现]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-05-13T16:05:31+08:00</updated>
	  <published>2010-05-13T16:05:31+08:00</published>
		  <summary type="html"><![CDATA[<p>随着HTML5的呼声逐渐增大，是时候将其中的<strong>DOM Storage</strong>纳入考量范围了。</p>
<h2>DOM Storage</h2>
<p>类似http session和cookies的两种全新机制：</p>
<p><strong>Session Storage</strong></p>
<ul>
    <li>会话存储是针对用户执行单个事务的方案而设计的。</li>
    <li>应用于用户在同一时间（同一个会话期）跨多窗口运行同一事务的场景。</li>
    <li>来自MDC的说法:它常用于临时存储那些需要保存的数据以便当浏览器不小心刷新时能够恢复它们。</li>
    <li>它含有一个在页面会话有效期内可用的存储区域。</li>
    <li>只要页面没有关闭，一个页面会话就始终保持着，并且当页面被重新载入或恢复时&ldquo;复活&rdquo;。</li>
    <li>打开一个新的标签页或新窗口都会初始化新的会话。</li>
    <li>Internet Explorer 8:不会在浏览器故障得到恢复后继续使用 sessionStorage。</li>
    <li>Firefox也木有实现介个功能，参见：bug 33945 https://bugzilla.mozilla.org/show_bug.cgi?id=339445</li>
</ul>
<p><br />
Cookies不能很实时的处理这些情形：<br />
<em><br />
如，某个用户在某站点购买机票时打开了两个不同的窗口，如果该站点使用cookies来记录用户的购买信息，那么，该用户在一个窗口中&ldquo;已购买&rdquo;的机票信息可能在另一个窗口中就被&ldquo;漏&rdquo;掉了，这将导致该用户在另一个窗口中得不到实时通知的情况下购买两张相同航班的机票。</em><br />
<br />
sessionStorage接口的定义正是为了解决此情形，一个站点可以将它的数据添加到session storage，然后，该站点在某窗口中打开的任何页面都可以访问到此数据。<br />
<br />
<strong>Local Storage</strong></p>
<ul>
    <li>本地存储机制跨多个窗口，且持续范围可超过当前会话。localStorage属性可为域提供持久存储区域。</li>
    <li>它可使得WEB程序能够存储MB级的用户数据，如，存储整个用户签名档或用户的收件箱。</li>
    <li>它也为客户端性能的优化提供了一种解决方案。</li>
</ul>
<p><br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; Cookies还是不能很好地处理这些情形，因为它每次请求时都会将值传送给服务器，而且数据会过期。<br />
<br />
<strong>每个站点都会有它们各自的存储区域。</strong><br />
<br />
<strong>Storage对象接口定义</strong><br />
<br />
<strong>constructor:</strong><br />
&nbsp;&nbsp;&nbsp; 返回Storage对象的构造器引用（Object）<br />
<br />
<strong>remainningSpace:</strong><br />
&nbsp;&nbsp;&nbsp; 返回Storage对象中剩余的内存数量（Bytes）<br />
<br />
<strong>length:</strong><br />
&nbsp;&nbsp;&nbsp; 返回当前Storage对象中key/value配对列表的长度，只读，数字类型<br />
<br />
<strong>key(n):</strong><br />
&nbsp;&nbsp;&nbsp; 返回当前Storage对象中key/value配对列表的第N个元素的key值，如果N&gt;=length，则返回null<br />
<br />
<strong>getItem(key):</strong><br />
&nbsp;&nbsp;&nbsp; 返回当前Storage对象中给定的key值（复制的）<br />
<br />
<strong>setItem(key, value):</strong><br />
&nbsp;&nbsp;&nbsp; 复制一份给定的value（不支持包含ImageData的对象，报NOT_SUPPORTED_ERR）<br />
&nbsp;&nbsp;&nbsp; 检测在当前Storage对象list中是否存在指定的key：<br />
&nbsp;&nbsp;&nbsp; 如果不存在，则在该list中插入此key/value的配对。<br />
&nbsp;&nbsp;&nbsp; 如果存在，则更新此key的value。<br />
&nbsp;&nbsp;&nbsp; 如果操作失败，则报空间不足（QUOTA_EXCEEDED_ERR）异常。<br />
<br />
<strong>removeItem(key):</strong><br />
&nbsp;&nbsp;&nbsp; 从当前Storage对象中移除指定的key值<br />
<br />
<strong>clear():</strong><br />
&nbsp;&nbsp;&nbsp; 清空当前Storage对象中所有的key/value<br />
<br />
<strong>sessionStorage对象</strong></p>
<ul>
    <li>sessionStorage作为Storage对象的实例，存在于浏览器全局作用域中，同源共用。</li>
    <li>全局对象，可通过sessionStorage或window.sessionStorage访问。</li>
    <li>生存周期为一个窗口或一个TAB的生存期间所加载的所有同源页面。</li>
    <li>session storage存储的内容只在用户请求的数据被删除或者存储空间不足时才会被设置过期。</li>
    <li>当sessionStorage调用setItem,removeItem或clear方法并成功执行时，所有打开的窗口中的sessionStorage都会</li>
    <li>被指向到相同的存储区域，且都会触发Storage对象的相应事件。</li>
</ul>
<p><br />
<strong>localStorage对象</strong></p>
<ul>
    <li>localStorage对象作为Storage对象的实例，存在于浏览器全局作用域中，同源共用。</li>
    <li>每个域和子域都具有自己单独的本地存储区域。 域可以访问子域的存储区域，而子域也可以访问父域的存储区域。</li>
    <li>注意：http://example.com域无法访问https://example.com中的localStorage数据。</li>
    <li>localStorage['example.com']&nbsp; 可由 example.com 及其任何子域访问。</li>
    <li>子域 localStorage['www.example.com']可由 example.com 访问，但不能由其他子域访问，如 mail.example.com。</li>
    <li>全局对象，可通过localStorage或window.localStorage访问。</li>
    <li>local storage存储的内容只有在用户提出请求或出于安全因素处理时才会被设置过期。</li>
</ul>
<p><br />
<strong>安全提示</strong></p>
<ol>
    <li>当请求违反存储限制时，抛出SECURITY_ERR异常（如用户设置不允许存储数据）。</li>
    <li>磁盘配额限制将施加于设置相应值的页面所在的域，而不是施加于在其中设置相应值的域。 这可防止恶意脚本用尽相关域的存储配额。 同时还可阻止此类脚本使用随机子域来存储无限数量的数据。</li>
    <li>如果来自非同源（源由协议、主机名（或 IP 地址）和域的 URL 的端口号确定）的脚本，抛出SECURITY_ERR异常并忽略其他步骤。</li>
    <li>如果文档来源不属于HTML5源时，抛出SECURITY_ERR异常并忽略其他步骤。</li>
    <li>存储在Storage中的数据未经过任何编码和加密，建议在使用的时候不要将敏感的重要的用户数据存储在Storage中。</li>
</ol>
<p>当浏览器切换到private模式时（如果可以的话），localStorage存储的数据在浏览器模式改变后将被丢弃。</p>
<p>当localStorage调用setItem,removeItem或clear方法并成功执行时，所有打开的窗口中的localStorage都会被指向到相同的存储区域，且都会触发Storage对象的相应事件。<br />
<br />
<strong>Storage事件（实现者）</strong><br />
<br />
当一个存储区域发生改变时，Storage事件即被触发，所有窗口中的Storage对象都将被影响。<br />
<br />
<strong>事件定义</strong><br />
<br />
<strong>initStorageEvent():</strong><br />
&nbsp;&nbsp;&nbsp; 使用类似DOM Events接口的方式初始化事件<br />
<br />
<strong>key:</strong><br />
&nbsp;&nbsp;&nbsp; 表示key被改变<br />
<br />
<strong>oldValue:</strong><br />
&nbsp;&nbsp;&nbsp; key被改变之前的值<br />
<br />
<strong>newValue:</strong><br />
&nbsp;&nbsp;&nbsp; key改变之后的值<br />
<br />
<strong>url:</strong><br />
&nbsp;&nbsp;&nbsp; 表示该地址文档对象中的key被改变<br />
<br />
<strong>storageArea:</strong><br />
&nbsp;&nbsp;&nbsp; 影响到的Storage对象<br />
<br />
<strong>DOM Storage Events（IE8+）</strong><br />
<br />
当更新存储区域中的数据时，Internet Explorer 将触发相应事件，以便在浏览器或选项卡的多个实例之间能够保持信息同步。<br />
<br />
<strong>onstorage</strong></p>
<ul>
    <li>当存储区域发生更改时，document&nbsp; 中将触发&nbsp; onstorage 事件。</li>
    <li>所有共享相同会话上下文的文档，以及当前显示来自相同域或子域（即，本地存储将要提交到的域或子域）的页面的文档，都会接收到该事件。</li>
    <li>如果目标文档对象当前未处于活动状态，则 Internet Explorer 不会触发任何事件。</li>
</ul>
<p><br />
<strong>onstoragecommit</strong></p>
<ul>
    <li>Internet Explorer 使用 XML 文件来存储本地存储数据。 将本地存储数据写入到磁盘上时，将触发&nbsp; onstoragecommit 事件。</li>
</ul>
<p>&nbsp;&nbsp;&nbsp; <br />
<strong>磁盘空间</strong></p>
<p>每个域默认可以存储 <strong>5 MB</strong> 的数据，当超过时，需要提醒用户是否增加空间。<br />
IE8+浏览器默认为 10 MB<br />
<br />
<strong>userData Behavior</strong><br />
<br />
IE5+支持，允许对象存储数据在用户端<br />
<br />
使用条件，<strong>为某对象设置behavior样式</strong><br />
<br />
<strong>html:</strong><br />
&nbsp;&nbsp;&nbsp; &lt;ELEMENT&nbsp; STYLE=&quot;behavior:url('#default#userData')&quot; ID=sID&gt;</p>
<p><strong>scripting:</strong><br />
&nbsp;&nbsp;&nbsp; object.style.behavior = &quot;url('#default#userData')&quot;<br />
&nbsp;&nbsp;&nbsp; object.addBehavior(&quot;#default#userData&quot;)<br />
<br />
<strong>userData对象成员表</strong><br />
<br />
<strong>expires:</strong><br />
&nbsp;&nbsp;&nbsp; 设置或返回userData的到期时间<br />
<br />
<strong>XMLDocument:</strong><br />
&nbsp;&nbsp;&nbsp; 返回一个XML引用<br />
<br />
<strong>load(user):</strong><br />
&nbsp;&nbsp;&nbsp; 加载指定user存储在userData中的数据对象<br />
<br />
<strong>getAttribute(attr):</strong><br />
&nbsp;&nbsp;&nbsp; 返回指定attr的值<br />
<br />
<strong>setAttribute(attr):</strong><br />
&nbsp;&nbsp;&nbsp; 设置指定attr的值<br />
<br />
<strong>removeAttribute(attr):</strong><br />
&nbsp;&nbsp;&nbsp; 移除指定的attr值<br />
<br />
<strong>save(user):</strong><br />
&nbsp;&nbsp;&nbsp; 保存指定user的数据对象到userData中<br />
<br />
<strong>磁盘空间</strong><br />
<br />
<strong>本地：</strong><br />
&nbsp;&nbsp;&nbsp; document limit:128KB，domain limit:1024KB<br />
<strong>局域网：</strong><br />
&nbsp;&nbsp;&nbsp; document limit:512KB，domain limit:10240KB<br />
<strong>可信站点：</strong><br />
&nbsp;&nbsp;&nbsp; document limit:128KB，domain limit:1024KB<br />
<strong>互联网：</strong><br />
&nbsp;&nbsp;&nbsp; document limit:128KB，domain limit:1024KB<br />
<strong>受限站点：</strong><br />
&nbsp;&nbsp;&nbsp; document limit:64KB，domain limit:640KB<br />
<br />
<strong>安全提示</strong></p>
<ol>
    <li>为了安全考虑，userData存储的数据只对相同的目录，且使用相同的协议才能访问。</li>
    <li>存储在userData中的数据未经过任何编码和加密，建议在使用的时候不要将敏感的重要的用户数据存储在userData中。</li>
    <li>将userData行为应用在html,head,title,style等对象上时，使用save和load方法时将会发生错误。</li>
</ol>
<p><br />
<br />
<strong>Adobe Flash Player本地存储</strong><br />
存储空间: 100 KB<br />
<br />
<strong>Cookie</strong><br />
存储空间: 4 KB<br />
<br />
<a href="http://www.easyui.org.cn/domStorage.html" target="_blank">简单实现一个兼容新老浏览器的离线存储演示，简单判断是否可用localStorage，否则使用cookie.</a><br />
<br />
在线演示DEMO：<a href="http://www.easyui.org.cn/domStorage.html" target="_blank">http://www.easyui.org.cn/domStorage.html</a></p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=299" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=299</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[客户端环境诊断为解决用户遇到的问题做好准备]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-05-11T11:15:53+08:00</updated>
	  <published>2010-05-11T11:15:53+08:00</published>
		  <summary type="html"><![CDATA[<p>记得以前和<em><strong> <a href="http://www.blogjava.net/emu/" target="_blank">EMU</a></strong></em>  同学聊天的时候，他提到最多的话题就是如何处理用户咨询和投诉，从而较好的解决他们遇到的问题。</p>
<p>当一个产品的用户数量达到一个很大 的数量级时，这种情况确实会经常发生，若不能有效的解决，的确让产品工程师们很困扰。</p>
<p>在<a href="http://www.baiduux.com/" target="_blank"><em><strong>百 度泛用户体验博客</strong></em></a>中，百度有啊的同学分享了他们是怎么来处理这种情况的，那就是，提供一个客户端环境诊断的小工具 （页面），让用户配合工程师一起进行诊断，为处理用户遇到的问题提供较有价值，较全面的资料。</p>
<p>原文如下：</p>
<p><span class="author">作者：<a title="由 Miller
发表" href="http://www.baiduux.com/blog/author/chenminliang/">Miller</a></span></p>
<p><a target="_blank" href="http://co.youa.baidu.com/content/qmrIO0W0Ep43TjA/weddiagnose/index.html">有啊网页诊断工具</a>是一个轻量级的浏览器环境检测工具，基于Javascript以及Flash实现。它的主要 功能包括问题检测以及针对某些问题给予提示性的建议，从而帮助用户自助的解决一些简单的问题。此外还能生成简单的检测报告，通过报告开发人员可是获得更为 详细的环境信息，为解决问题提供有效的支持。</p>
<p>该工具具体的检测项包括以下几个：</p>
<p>1. Javascript版本信息<br />
2. Cookie是否开启<br />
3. 用户的屏幕分辨率<br />
4. Flash版本号以及浏览器是否开启了Flash拦截功能<br />
5. 浏览器字体大小是否正常（某些浏览器缩放后会导致页面布局混乱）<br />
6. 浏览器的Ajax功能是否正常，包括Get方式和Post方式<br />
7. 浏览器的图片浏览功能是否正常<br />
8. 用户的网络速度</p>
<p>通过对以上几个问题的检测，开发人员能够比较全面的了解目标浏览器的整体环境。</p>
<p>&nbsp;</p>
<h3>一、Javascript版本检测</h3>
<p>对于Javascript版本的检测似乎显得不是那么必要，因为通常都可以根据浏览器的版本找到对应关系，不过作为浏览器环境的一部分，还是把该功  能加了进来。具体的实现原理：在页面中嵌入各个版本的script标签，并在每个标签中都给同一个全局变量赋值，最后根据变量的值得到版本号：</p>
<pre><!--mce:0--> &nbsp;&nbsp;&nbsp;&nbsp;
 JS_VERSION=('1.0');&nbsp;&nbsp;&nbsp;&nbsp;

 &nbsp;&nbsp;&nbsp;&nbsp;
 JS_VERSION=('1.1');&nbsp;&nbsp;&nbsp;&nbsp;

 &nbsp;&nbsp;&nbsp;&nbsp;
 JS_VERSION=('1.2');&nbsp;&nbsp;&nbsp;&nbsp;

      ......
      ......
 <!--mce:3-->&nbsp;&nbsp; &nbsp;
 JS_VERSION=('1.3');&nbsp;&nbsp; &nbsp;

 &nbsp;&nbsp; &nbsp;
 window.onload = function(){
 if( typeof JS_VERSION != 'undefined' )
 document.getElementById('test').innerHTML = JS_VERSION;
 }&nbsp;&nbsp; &nbsp;
  <!--mce:4-->
</pre>
<p>根据W3C规范，script的language属性已经被废弃了，不过经测试该属性的兼容性较好，并能得到比较准确的结果。如果使用type=  &ldquo;text/javascriptN&rdquo;则在很多浏览器下得不到正确的版本，因此在此依然使用了language属性。另外，关于javascript各个 版本与浏览器的对应关系可以参考如下表格：</p>
<table border="1">
    <tbody>
        <tr>
            <th>Version</th>
            <th>Release date</th>
            <th>Equivalent to</th>
            <th>Netscape<br />
            Navigator</th>
            <th>Mozilla<br />
            Firefox</th>
            <th>Internet<br />
            Explorer</th>
            <th>Opera</th>
            <th>Safari</th>
            <th>Google<br />
            Chrome</th>
        </tr>
        <tr>
            <td>1.0</td>
            <td>March 1996</td>
            <td>&nbsp;</td>
            <td>2.0</td>
            <td>&nbsp;</td>
            <td>3.0</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.1</td>
            <td>August 1996</td>
            <td>&nbsp;</td>
            <td>3.0</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.2</td>
            <td>June 1997</td>
            <td>&nbsp;</td>
            <td>4.0-4.05</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.3</td>
            <td>October 1998</td>
            <td>ECMA-262 1<sup>st</sup> edition / ECMA-262 2<sup>nd</sup> edition</td>
            <td>4.06-4.7x</td>
            <td>&nbsp;</td>
            <td>4.0</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.4</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>Netscape<br />
            Server</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.5</td>
            <td>November 2000</td>
            <td>ECMA-262 3<sup>rd</sup> edition</td>
            <td>6.0</td>
            <td>1.0</td>
            <td>5.5 (JScript 5.5),<br />
            6 (JScript 5.6),<br />
            7 (JScript 5.7),<br />
            8 (JScript 6)</td>
            <td>6.0,<br />
            7.0,<br />
            8.0,<br />
            9.0,<br />
            10.0</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.6</td>
            <td>November 2005</td>
            <td>1.5 + Array extras + Array and String generics + E4X</td>
            <td>&nbsp;</td>
            <td>1.5</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>3.0, 3.1</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.7</td>
            <td>October 2006</td>
            <td>1.6 + Pythonic generators + Iterators + let</td>
            <td>&nbsp;</td>
            <td>2.0</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>3.2, 4.0</td>
            <td>1.0</td>
        </tr>
        <tr>
            <td>1.8</td>
            <td>June 2008</td>
            <td>1.7 + Generator expressions + Expression closures</td>
            <td>&nbsp;</td>
            <td>3.0</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.8.1</td>
            <td>&nbsp;</td>
            <td>1.8 + Native JSON support + Minor Updates</td>
            <td>&nbsp;</td>
            <td>3.5</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.8.2</td>
            <td>&nbsp;</td>
            <td>1.8.1 + Minor updates</td>
            <td>&nbsp;</td>
            <td>3.6</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
        <tr>
            <td>1.9</td>
            <td>&nbsp;</td>
            <td>1.8.1 + <a href="http://en.wikipedia.org/wiki/ECMAScript" title="ECMAScript"><span style="color: rgb(0, 0, 0);">ECMAScript</span></a> 5 Compliance</td>
            <td>&nbsp;</td>
            <td>4</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
            <td>&nbsp;</td>
        </tr>
    </tbody>
</table>
<p>&nbsp;</p>
<p>相关参考资料：</p>
<p><a href="http://www.w3.org/TR/REC-html40/interact/scripts.html">http://www.w3.org/TR/REC-html40/interact/scripts.html</a>  W3C 关于script标签的描述</p>
<p><a href="http://en.wikipedia.org/wiki/JavaScript">http://en.wikipedia.org/wiki/JavaScript#Versions</a>  维基百科关于JavaScript中的版本描述</p>
<p><a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/JavaScript_Overview">https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/JavaScript_Overview</a>  JavaScript Versions and ECMAScript Editions</p>
<p><a href="http://hi.baidu.com/jiaozhenqing/blog/item/d8f026380392f22cb9998fc7.html">http://hi.baidu.com/jiaozhenqing/blog/item/d8f026380392f22cb9998fc7.html</a>  JavaScript版本一览</p>
<h3>二、检测Cookie是否开启</h3>
<p>先获取window.navigator['cookieEnabled']的值，如果该值非undefined的话则直接使用该值即可判断(经测  试IE7、Firefox3.5、Safari4、Opera10均能支持)。如果为undefined(即不支持该属性）则使用如下的方式：尝试向  Cookie中写入数据（为避免浪费设置1分钟的有效期），写入后检测document.cookie中是否存在刚才写入的数据，如果有则cookie有  效否则cookie无效：</p>
<pre>
 var cookie = document.cookie;
 var cookieEnabled = window.navigator['cookieEnabled'];

 if(typeof cookieEnabled == 'undefined'){
    var expireDate = new Date();
    expireDate.setTime(expireDate.getTime() + 1000);//Expired after 1 second
    var time = expireDate*1;
    var regExp = new RegExp(time + '=' + time);
    document.cookie = time + '=' + time + ';expires=' + expireDate.toGMTString();
    if( regExp.test(document.cookie) )
       cookieEnabled = true;
    else
       cookieEnabled = false;
 }
</pre>
<h3>三、Flash版本以及可用性检测</h3>
<p>Flash检测包含两方面的内容：</p>
<h4>1. Flash是否安装、禁用，Flash版本号</h4>
<p>对于Flash的版本检测可以通过在页面中引入AC_OETags.js（包含在Adobe官方的<a href="http://www.adobe.com/products/flashplayer/download/detection_kit/">Flash   Player Detection Kit</a>中），然后通过调用其中的GetSwfVer方法获得具体的版本号，如果Flash未安装或者被禁用 则  GetSwfVer方法将会返回-1，否则返回正确的版本号。查看GetSwfVer的实现，与浏览器版本检测如出一辙，也是通过navigator信息  得到的，感兴趣的可以直接查看其源码。</p>
<h4>2. 如果Flash已经安装是否被拦截</h4>
<p>做这一步检查的前提是第一步能够获得正确的版本号。具体的检测方法也很简单，在页面中引入一个自定义的swf文件，在该swf文件中只定义  了一个方法checkFlash，并将该方法暴露出来使得JavaScript能够访问到，即  ExternalInterface.addCallback(&ldquo;checkFlash&rdquo;,checkFlash);在swf加载完成后通过 JavaScript访问checkFlash方法，如 果存在该方法则说明Flash访问正常，否则Flash可能被拦截了。</p>
<p>以上两步的代码实现大致如下：</p>
<p>HTML代码</p>
<pre>
&nbsp;</pre>
<p>Javascript代码</p>
<pre>
    //获取Flash版本号，如果version为-1则可能未安装Flash或者Flash被禁用
    var version = GetSwfVer();
    if( version != -1 ){
         var isIE = navigator.appVersion.indexOf(&quot;MSIE&quot;) != -1;
         if( isIE )//IE下取Object元素
            var swfObj = document.getElementById('oCheck');
        else//其他浏览器下取embed元素
            var swfObj = document.getElementById('eCheck');
        if( !swfObj.checkFlash ) {
            //被拦截
        }
        else {
           //未拦截
        }
    }
    else{
        //未安装Flash Player或者Flash Player被禁用
    }</pre>
<div>参考资料</div>
<div><a href="http://www.adobe.com/products/flashplayer/download/detection_kit/">http://www.adobe.com/products/flashplayer/download/detection_kit/</a>  Flash Player Detection Kit</div>
<p>&nbsp;</p>
<h3>四、Ajax功能检测</h3>
<p>该功能的检测比较直接，即分别构造Ajax Get和Ajax  Post请求，在请求过程中详细的记录Ajax的实例类型（ActiveXObject 或  XMLHTTPRequest）、请求的各个阶段的状态以及最终的请求结果。</p>
<h3>五、检测图片是否被禁用</h3>
<p>检测图片是否禁用的原理：新建一个Image对象，并监听其onload事件（IE某些版本中无效，需要监听onreadystatechange  事件）以及onerror事件。</p>
<pre>
 var img = new Image;
 //监听onload事件，由于在ie的某些版本中onload事件并不会被触发，因此增加onreadystatechange监听器
 img.onload = img.onreadystatechange = function(){
 //加载成功说明图片功能是正常的
 }
 //监听onerr事件
 img.onerror = function(){
 //如果触发了onerror事件，则说明图片功能不正常（在img的src正确的情况下）
 }
 img.src = 'xxx';</pre>
<p>以上的实现中，对于加载事件的监听并没有什么问题，不过对于onerror事件还是存在比较大的兼容性问题：经测试发现，在IE下禁用图片后并不会 触发  onerror事件，而在Firefox中禁用图片后则能正常的触发onerror事件，至此的结论是使用onerror来判断图片功能是准确的。取而代  之的是使用超时检测来判断，即假定图片在一定时间内仍未能加载成功则视为失败。</p>
<pre>
 var img = new Image;
 //监听onload事件，由于在ie的某些版本中onload事件并不会被触发，因此增加onreadystatechange监听器
 img.onload = img.onreadystatechange = function(){
 //加载成功说明图片功能是正常的
 }
 //监听onerr事件
 img.onerror = function(){
 //如果触发了onerror事件，则说明图片功能不正常（在img的src正确的情况下）
 }
 img.src = 'xxx';
 var timer = setTimeout(function(){
 //如果执行到这里则认为图片功能异常
 },TIMEOUT);</pre>
<h3>六、检测网络速度</h3>
<p>实现原理：请求一张已知大小的图片N次，并分别记录每次请求所花费的时间，最后根据图片大小计算出平均的网络速度。这里需要注意的是图片的大小问 题，图片如果太小结果会不准确，需要选择一张合适的图片，另外为防止图片被浏览器缓存需要给图片的src添加时间戳。</p>
<pre>
/*
 * @param { Integer } times 请求图片的次数
 * @callback { Function } callback 图片请求完成后调用的函数
 */
 function detectNetSpeedWithImage(times,callback){&nbsp;&nbsp; &nbsp;
 times = times || 1;
 //已完成请求
 var completedImg = 0,
 res = [],
 timer = null,
 done = false;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
 for( var i = 0; i &lt; times; i++){
 (function( index ){
 setTimeout(function(){&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;
 var img = new Image();
 //开关，在某些浏览器（如IE）会响应两次onreadystatechange
 var loaded = false;
 //请求开始时间
 var tStart = new Date();
 img.onload = img.onreadystatechange = function(){
 if( loaded ) return;
 //请求结束时间
 var tEnd = new Date();
 res.push(tEnd - tStart);
 //已完成请求加1
 completedImg++;
 loaded = true;
 //全部请求完成后调用callback
 if( completedImg == times &amp;&amp; callback ){
 callback.call(null,res);
 if( timer ) clearTimeout(timer);
 }
 }
 img.onerror = function(){
 if( done ) return;
 callback([]);
 done = true;
 clearTimeout(timer);
 }
 img.src = Config.NET_SPEED_DETECT_IMAGE_URL + '?t=' + (new Date())*1;
 },index * Config.NET_SPEED_DETECT_IMAGE_REQUEST_INTERVAL);
 })(i);
 }
 //超时操作
 timer = setTimeout(function(){
 if( completedImg != times &amp;&amp; !done ){
 callback([]);
 }
 },Config.NET_SPEED_DETECT_TIMEOUT + times * Config.NET_SPEED_DETECT_IMAGE_REQUEST_INTERVAL);
 }

 detectNetSpeedWithImage(Config.NET_SPEED_DETECT_TIMES,function(res){
 //失败
 if( res.length &lt; 1 ){
 _handleError();
 }
 //成功
 else{
 var time = 0;
 for( var i = 0,l = res.length; i &lt; l; i++){
 time += res[i] / ( l * 1000 );
 }
 //计算速度
 var speed = Config.NET_SPEED_DETECT_IMAGE_SIZE / time;
 //取小数点后两位
 speed = speed.toFixed(2);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
 me.isOver = true;&nbsp;&nbsp; &nbsp;
 }
 });</pre>
<h3>七、检测客户端分辨率</h3>
<p>直接获取window.screen的width与height即可。</p>
<h3>八、检测浏览器字体大小是否正常</h3>
<p>在IE6下，当使用px作为单位时，元素（字体大小）无法进行缩放，这在很多情况下都会造成页面混乱。另外，对于目前大多数浏览器，在默认字体设置 下，1em恰恰等于16px，于是可以根据这个原理来检测浏览器字体是否正常，具体的方式如下：</p>
<p>1.   创建一个DIV元素1，并设定其高为16px，宽为1px并使用CSS将其定位到可视范围之外（不能通过display或visibility隐藏）</p>
<p>2.   创建另一个DIV元素2，并设置其font-size为medium。在该DIV内部创建一个DIV元素3，并设置其高位1em，宽为1px并使用CSS 将其定位到可视范围之外</p>
<p>3. 比较元素1和元素3的高度，如果相等则字体大小正常否则异常</p>
<p>注意，元素3必须包含在元素2中，并且给元素2设置font-size:   medium。因为em是一个相对单位，1em的大小相当于其父元素字体的大小，为了使检测不受其他样式影响，将其放在一个字体大小为浏览器默认值的容器 中。</p>
<pre>
 //隐藏DIV的CSS
 var hideCSS = 'position:absolute;left:-2000px;';

 //以px为宽度单位的元素
 var pxBlock = document.createElement('div');
 pxBlock.style.cssText = 'width:16px;height:1px;' + hideCSS;
 document.body.appendChild(pxBlock);
 //构建一个字体大小为浏览器默认值的容器
 var emBlockWrapper = document.createElement('div');
 emBlockWrapper.style.fontSize = 'medium';

 //以em为字宽度单位的元素
 var emBlock = document.createElement('div');
 emBlock.style.cssText = 'width:1em;height:1px;' + hideCSS;

 emBlockWrapper.appendChild(emBlock);
 document.body.appendChild(emBlockWrapper);

 //获得固定和变化的div宽度
 var pxBlockWidth = pxBlock.offsetWidth;
 var emBlockWidth = emBlock.offsetWidth;

 if(pxBlockWidth == emBlockWidth){
 //字体正常
 }
 else{
 //字体异常
 }</pre>
<p>&nbsp;</p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=298" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=298</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[在WEB开发中怎样的代码才是可维护性高的代码]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-05-05T09:59:33+08:00</updated>
	  <published>2010-05-05T09:59:33+08:00</published>
		  <summary type="html"><![CDATA[<h2>&ldquo;大道至简，返璞归真&quot;</h2>
<p>在看到<a href="http://www.nczonline.net/" target="_blank">Nicholas C. Zakas</a>提出的<strong>可维护性的代码</strong>的观点后，这种感觉越发的强烈！</p>
<p>原文出处：</p>
<p><a href="http://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/" target="_blank">http://www.nczonline.net/blog/2010/03/02/maintainable-javascript-dont-modify-objects-you-down-own/</a></p>
<h3>可维护的Javascript代码</h3>
<p>当我们在开发WEB程序时，如何保证代码的可维护性？很简单，<strong>不要修改不是自己定义的对象</strong>。</p>
<h3>为什么不可以去修改不属于自己定义的对象？</h3>
<p>当我们去修改一个已有的并非我们自己定义的对象时，将发生多么糟糕的事情：</p>
<ul>
    <li><strong>不可信任，导致混乱</strong><br />
    <br />
    这样的修改不可信任，很有可能之前使用过此对象的地方发生BUG<br />
    &nbsp;</li>
    <li><strong>不兼容</strong><br />
    <br />
    在修改这些对象时，我们很可能会将一些新的方法添加进去，而没有考虑到这个对象很可能被应用在并没有实现这些方法的环境中<br />
    &nbsp;</li>
    <li><strong>维护的梦魇</strong><br />
    <br />
    试想，当这种情形发生在一个大项目，大团队中，对成员间开发的代码维护将会是件多么恐怖的事情。</li>
</ul>
<h3>在WEB开发中，怎样的代码才是可维护性高的代码？</h3>
<p>有一段代码，<strong>当浏览器发生改变时，它并不需要作出任何修改</strong>，这就是可维护性高的代码！</p>
<p>在WEB开发中，这不仅适用于Javascript，同样适用于Css!</p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=297" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=297</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[Aax History 实现分析]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-05-04T15:45:32+08:00</updated>
	  <published>2010-05-04T15:45:32+08:00</published>
		  <summary type="html"><![CDATA[<p>最近研究了一下Ajax History的实现，目前多数的实现是用一个Timer去定时check浏览器的hash是否改变，还有一些兼容性不强的unInterval的实现。</p>
<h3>IE：</h3>
<ul>
    <li>链接到一个锚点，如果该锚点在当前页未被定义，则不能产生history</li>
    <li>页面中的iframe，如果改变其hash，href，或重新写入新的HTML内容，都会产生history</li>
    <li>对iframe产生的history进行&ldquo;向前&rdquo;，&ldquo;向后&rdquo;操作时，页面地址栏的值不会改变</li>
    <li>iframe中使用hash change的方式，在操作历史记录时会相应回滚，可以以此作为历史记录改变的触发事件</li>
    <li>页面hash的改变，无法通过location.hash获取</li>
</ul>
<h3>其他浏览器：</h3>
<ul>
    <li>链接到一个锚点，如果该锚点在当前页未被定义，也能产生history</li>
    <li>页面hash的改变，可以通过location.hash获取</li>
    <li>iframe中使用hash change的方式，在操作历史记录时不会相应回滚，没办法以此作为历史记录改变的触发事件</li>
</ul>
<h3>实现方案：</h3>
<ul>
    <li>定时检测hash的变化</li>
</ul>
<p><a href="http://www.easyui.org.cn/ajaxHistory.html" target="_blank">ajax history demo: http://www.easyui.org.cn/ajaxHistory.html</a></p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=296" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=296</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[hasLayout in Microsoft Internet Explorer]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-04-26T15:36:45+08:00</updated>
	  <published>2010-04-26T15:36:45+08:00</published>
		  <summary type="html"><![CDATA[<h1>hasLayout Property</h1>
<hr size="1" />
<p>Retrieves a value that indicates whether the <span replace="1">object</span>   has layout.</p>
<p class="clsRef">Syntax</p>
<blockquote>
<table class="clsStd">
    <tbody>
        <tr>
            <th><b>HTML</b></th>
            <td>N/A</td>
        </tr>
        <tr>
            <th><b>Scripting</b></th>
            <td>[ <span class="clsRange">sHasLayout</span><b> =</b> ] <i><span class="moreinfo" title="an element from the Applies To list below">object</span></i>.<b>currentStyle.hasLayout</b></td>
        </tr>
    </tbody>
</table>
</blockquote>
<p class="clsRef">Possible Values</p>
<blockquote>
<table class="clsStd">
    <tbody>
        <tr>
            <td><span class="clsRange">sHasLayout</span></td>
            <td><b>Boolean</b> that receives one of the following  values.
            <table class="clsStd">
                <tbody>
                    <tr>
                        <td nowrap="nowrap"><span class="clsDefValue">false</span></td>
                        <td>Default. Object does not have layout.</td>
                    </tr>
                    <tr>
                        <td nowrap="nowrap"><span class="clsLiteral">true</span></td>
                        <td>Object has layout.</td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<p>The property is read-only. The property has a default value of <span class="clsDefValue">false</span>. The Microsoft Cascading Style Sheets  (CSS)  extension is not inherited.</p>
</blockquote>
<p class="clsRef">Remarks</p>
<blockquote>
<p>The following table shows Cascading Style Sheets (CSS) properties and   corresponding values that, if set, cause an element to have layout.
<table class="clsStd">
    <tbody>
        <tr>
            <th>CSS property</th>
            <th>Value</th>
        </tr>
        <tr>
            <td><a href="http://www.v-ec.com/dh20156/../properties/display.html">display</a></td>
            <td><span class="clsLiteral">inline-block</span></td>
        </tr>
        <tr>
            <td><a href="http://www.v-ec.com/dh20156/../properties/height_0.html">height</a></td>
            <td>any value</td>
        </tr>
        <tr>
            <td><a href="http://www.v-ec.com/dh20156/../properties/float.html">float</a></td>
            <td><span class="clsLiteral">left</span> or <span class="clsLiteral">right</span></td>
        </tr>
        <tr>
            <td><a href="http://www.v-ec.com/dh20156/../properties/position.html">position</a></td>
            <td><span class="clsLiteral">absolute</span></td>
        </tr>
        <tr>
            <td><a href="http://www.v-ec.com/dh20156/../properties/width_0.html">width</a></td>
            <td>any value</td>
        </tr>
        <tr>
            <td><a href="http://www.v-ec.com/dh20156/../properties/writingmode.html">writing-mode</a></td>
            <td><span class="clsLiteral">tb-rl</span></td>
        </tr>
        <tr>
            <td><a href="http://www.v-ec.com/dh20156/../properties/zoom.html">zoom</a></td>
            <td>any value</td>
        </tr>
    </tbody>
</table>
</p>
<p>As of Microsoft&reg; Internet Explorer 6, when the <a href="http://www.v-ec.com/dh20156/../objects/doctype.html">!DOCTYPE</a> declaration  specifies strict  standards compliance, inline elements will ignore the <b>width</b>  and  <b>height</b> properties, and setting the <b>width</b> and <b>height</b>   properties will not cause the element to have layout.</p>
<p>Setting the <a href="http://www.v-ec.com/dh20156/../properties/contenteditable.html">contentEditable</a>   property to <span class="clsLiteral">true</span> will cause an element  to have  layout.</p>
<p><strong>BODY</strong>, <strong>FIELDSET</strong>, <strong>IMG</strong>,  <strong>INPUT</strong>,  <strong>TABLE</strong> and <strong>TD</strong>  elements always have layout.</p>
<p>&nbsp;</p>
</blockquote>
<p><strong>当hasLayout为false的元素中包含了hasLayout为true的元素时，该子元素在应 用position类型的样式时将会遇到兼容问题。</strong></p>
<p>&nbsp;</p>
<p><strong>当 hasLayout为false的元素应用position类型的样式时，将会遇到兼容问题。</strong></p>
<p>&nbsp;</p>
<p>See  also:</p>
<p><a href="http://blog.doyoe.com/article.asp?id=165" target="_blank"><strong>background与 border的恩怨情仇</strong></a></p>
<p><a href="http://www.jslab.org.cn/?tag=hasLayoutBug" target="_blank"><strong>http://www.jslab.org.cn/?tag=hasLayoutBug</strong></a></p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=295" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=295</id>
  </entry>	
		
  <entry>
	  <title type="html"><![CDATA[重温High Performance Web Sites]]></title>
	  <author>
		 <name>dh20156</name>
		 <uri>http://www.v-ec.com/dh20156/</uri>
		 <email>dh20156@126.com</email>
	  </author>
	  <category term="" scheme="http://www.v-ec.com/dh20156/default.asp?cateID=2" label="Web Develop" /> 
	  <updated>2010-04-22T14:36:39+08:00</updated>
	  <published>2010-04-22T14:36:39+08:00</published>
		  <summary type="html"><![CDATA[<h2>High Performance Web Sites - yahoo14条</h2>
<p><strong>由谁提出的</strong><br />
&nbsp;&nbsp;&nbsp;  来自Yahoo! Exceptional Performance team<br />
<br />
<strong>什么时候开始发起的</strong><br />
&nbsp;&nbsp;&nbsp;  2004年开始研究，2007年4月开始，陆续发布,(5月,7月,9月)<br />
<br />
<strong>为什么</strong><br />
&nbsp;&nbsp;&nbsp;  Yahoo希望对自己的产品性能做出一些测量和改善<br />
<br />
<strong>成绩</strong><br />
&nbsp;&nbsp;&nbsp;  总结出14条提升WEB产品性能的准则（后续21条）</p>
<p>&nbsp;</p>
<h3>第一条：最小化HTTP请求(Frontend)</h3>
<p>&nbsp;&nbsp;&nbsp;  将CSS文件和JS文件合并（可行性不高）<br />
&nbsp;&nbsp;&nbsp; CSS Sprites<br />
&nbsp;&nbsp;&nbsp; Image  Maps(很久以前经常使用的&ldquo;热区&rdquo;)<br />
&nbsp;&nbsp;&nbsp; Inline Images,data:URL（浏览器兼容问题）<br />
<br />
&nbsp;&nbsp;&nbsp;  每天大概有40-60%的访问者去到我们的站点的时候都是empty cache，所以，<br />
&nbsp;&nbsp;&nbsp;  我们如果能够使得他们在第一次访问时速度更快，那对他们来说将获得很好的体验。</p>
<p>&nbsp;</p>
<h3>第二条：使用内容分发网络 (Server)</h3>
<p>&nbsp;&nbsp;&nbsp; 将静态文件分发到其他独立的服务器上。<br />
&nbsp;&nbsp;&nbsp;  目的：使得用户可以就近获取到静态文件，从而解决动态内容站点网络拥挤的状况，提高用户访问网站的响应速度。<br />
&nbsp;&nbsp;&nbsp; Performance  Golden Rule:<br />
&nbsp;&nbsp;&nbsp; 80-90%的用户响应时间都花费在了下载某个页面上的组件上，<br />
&nbsp;&nbsp;&nbsp;  如：images,stylesheets,scripts,flash等等，而这些文件都是静态的，完全可以分发出去。<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;  CDN很昂贵，可以租用，也可以退而求其次，采用部署多台Server进行反向代理</p>
<p>&nbsp;</p>
<h3>第三条：设置一个 Expires头(Server)</h3>
<p>&nbsp;&nbsp;&nbsp; 静态文件：永不过期<br />
&nbsp;&nbsp;&nbsp;  动态文件：适当设置&quot;Cache-Control&quot;头<br />
<br />
&nbsp;&nbsp;&nbsp;  现在的WEB页面设计越来越丰富，这也意味着页面上会有越来越多的script,stylesheets,images,flash等等<br />
&nbsp;&nbsp;&nbsp;  用户在第一次访问我们的站点时，会发出若干请求，但再次访问时或者继续访问其他页面时，<br />
&nbsp;&nbsp;&nbsp;  如果这些文件设置了Expires头，就可以避免再次为它们发出新的HTTP请求，<br />
&nbsp;&nbsp;&nbsp;  从而提高页面加载速度，减轻服务器压力，提升用户体验。</p>
<p>&nbsp;</p>
<h3>第四条：Gzip压缩静态文件(Server)</h3>
<p>&nbsp;&nbsp;&nbsp;  为所有静态文件开启GZip<br />
&nbsp;&nbsp;&nbsp; 压缩文件，节约带宽，提高下载速度</p>
<h3>第五条：将样式表放置在源文件的顶部 (Frontend)</h3>
<p>&nbsp;&nbsp;&nbsp; 将所有样式文件放置在接近源文件顶部的&lt;head&gt;标签内<br />
<br />
&nbsp;&nbsp;&nbsp;  页面按加载进度逐步渲染，给予访问者视觉上的反馈，尤其是内容较大，网速较慢的访问者，尤为明显。</p>
<p>&nbsp;</p>
<h3>第六 条：将Script脚本放置在源文件底部(Frontend)</h3>
<p>&nbsp;&nbsp;&nbsp;  在第二条中提到浏览器在同一主机上平行下载的进程是有限制的，HTTP/1.1规范中指定的是两个。<br />
&nbsp;&nbsp;&nbsp;  如果在页面下载进程中遇到了Scripts的下载，则它会将这种平行下载阻断，导致页面加载更慢。</p>
<p>&nbsp;</p>
<h3>第七 条：避免使用CSS表达式(Frontend)</h3>
<p>&nbsp;&nbsp;&nbsp; 不兼容<br />
&nbsp;&nbsp;&nbsp;  监听评估导致页面性能低下，移动一次鼠标可能导致超过10,000次的评估。<br />
<br />
第八条：将JavaScript和CSS全部放置到外部文件 进行调用(Frontend)<br />
&nbsp;&nbsp;&nbsp; 减小主文件大小，加快page加载速度<br />
&nbsp;&nbsp;&nbsp; 对XHTML进行兼容<br />
&nbsp;&nbsp;&nbsp;  可作为静态文件分发到CDN<br />
&nbsp;&nbsp;&nbsp; 可缓存<br />
&nbsp;&nbsp;&nbsp; 可共用</p>
<p>&nbsp;</p>
<h3>第九条：减少DNS查询 （Frontend）</h3>
<p>&nbsp;&nbsp;&nbsp; Domain Name System，域名系统，它将主机映射到某个IP地址。<br />
&nbsp;&nbsp;&nbsp;  当我们输入一个网址的时候，DNS会分析该网址，然后转换到具体的IP，这个过程大概会花20-120毫秒<br />
&nbsp;&nbsp;&nbsp;  显然，如果DNS的查找能够进行缓存，将会提高站点的访问速度。<br />
&nbsp;&nbsp;&nbsp;  当我们访问一个页面时，该页的URL，images,script,stylesheet,flash等等都会有一个DNS查询的过程<br />
&nbsp;&nbsp;&nbsp;  如果我们能够减少该页面上出现多个不同的主机地址，就可以减少DNS的查询<br />
&nbsp;&nbsp;&nbsp;  这样就会和之前讲到的平行下载有冲突，减少DNS查询会减少页面响应时间，<br />
&nbsp;&nbsp;&nbsp; 但是降低了平行下载数量，则会增大页面响应时间，<br />
&nbsp;&nbsp;&nbsp;  平衡的做法是，将所有静态文件分离到至少1个独立的主机，最多不超过4个。</p>
<p>&nbsp;</p>
<h3>第十条：最小化 JavaScript和CSS</h3>
<p>&nbsp;&nbsp;&nbsp; 将JavaScript和CSS中任何多余的字符移除，如：注释，换行，排版用的空格等等<br />
&nbsp;&nbsp;&nbsp;  减少文件大小，加速下载进度。</p>
<p>&nbsp;</p>
<h3>第十一条：避免重定向(Frontend)</h3>
<p>&nbsp;&nbsp;&nbsp;  重定向将导致用户响应时间增加<br />
&nbsp;&nbsp;&nbsp; 使用具体的URL<br />
&nbsp;&nbsp;&nbsp; 如果一定要重定向，可使用标准的3xx HTTP状态码</p>
<p>&nbsp;</p>
<h3>第 十二条：移除重复的脚本</h3>
<p>&nbsp;&nbsp;&nbsp; 使用外部脚本文件<br />
&nbsp;&nbsp;&nbsp; 引入这些脚本文件时给文件名加上版本号<br />
&nbsp;&nbsp;&nbsp;  &lt;script type=&quot;text/javascript&quot;  src=&quot;menu_1.0.17.js&quot;&gt;&lt;/script&gt;<br />
&nbsp;&nbsp;&nbsp; 养成提取公共方法，公共类的习惯<br />
&nbsp;&nbsp;&nbsp;  在编码的过程中，如果发现某段代码至少有两个地方用到，而且代码量挺大的，<br />
&nbsp;&nbsp;&nbsp;  就可以考虑将这部分代码提取成为公共的方法，在编写CSS的时候同样适用。</p>
<p>&nbsp;</p>
<h3>第十三条：配置ETag</h3>
<p>&nbsp;&nbsp;&nbsp;  ETag，Entity tags的简称，<br />
&nbsp;&nbsp;&nbsp;  它用来确定在浏览器向服务端请求一个组件时判断缓存的组件与服务器上的是否仍然还是同一份（即没有更改过）。<br />
&nbsp;&nbsp;&nbsp;  Entity，其实就是&ldquo;组件&rdquo;的另一种说法，也就是images,scripts,stylesheets等等这些东西。&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;  ETag的值由 INode（索引节点）, Size和MTime（最后修改时间）决定。<br />
&nbsp;&nbsp;&nbsp;  由于这个INode在不同的服务器上是不同的，所以导致同一个组件会有不同的ETag，<br />
&nbsp;&nbsp;&nbsp;  这就使得该组件不能发送304的状态，没有办法被用户缓存<br />
&nbsp;&nbsp;&nbsp; 由于这个原因，在大型多服务器的站点，一般建议将ETag配置关闭<br />
&nbsp;&nbsp;&nbsp;  如果可以保证各服务器对同一组件生成相同的ETag，则完全可以使用。</p>
<h3>第十四条：缓存AJAX请求</h3>
<p>&nbsp;&nbsp;&nbsp;  根据业务类型，为处理AJAX请求的Action文件的设置合适的到期时间<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;  动态更新AJAX请求的URL，如，给这个URL后面加上一个更新时间，如：<br />
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;  &amp;t=1190241612，只在请求的数据发生变化时动态修改该URL地址。</p>
<p>后续二十一条下次再过一遍! ^_^</p>
<p>&nbsp;</p>
<p><a target="_blank" href="http://www.w3cgroup.com/attachments/month_1004/High Performance Websites.ppt">High Performance Web Sites.ppt</a></p>]]></summary>
	  <link rel="alternate" type="text/html" href="http://www.v-ec.com/dh20156/article.asp?id=294" /> 
	  <id>http://www.v-ec.com/dh20156/default.asp?id=294</id>
  </entry>	
		
</feed>
