事情经过是这样的:今天某同学用Matrix滤镜实现了IE下的一个旋转效果,但在IE6、7下页面样式全部被搞乱掉,滤镜之后的CSS样式完全没生效。剥离无关代码后类似于这样:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Jerry Qu's HTML document</title>
    <style type="text/css">
    #img {
      filter:progid:DXImageTransform.Microsoft.Matrix(M11=-0.707,M12=-0.707,M21=0.707,M22=-0.707,SizingMethod='auto expand');
    }
    body {color:red;}
    </style>
  </head>
  <body>
    <img id="img" src="http://st.qgy18.com/uploads/2011/07/ququ_1_1_1.jpg" />这行文字应该是红色的。
  </body>
</html>

用IE6或7打开这个页面,可以看到滤镜之后定义的样式没有生效。

这个问题产生的原因到现在我仍然没搞明白,先当作是浏览器bug了。经过测试,也很好绕过:

方法1:在filter值里插入一个空格。例如在M12前加上空格就正常了。测试地址

方法2:用obj.style.cssText这种方式设置filter,也不会有问题。

我们的css代码上线前,都会经过yui压缩,所以方法1不管用,那个空格会被yui压掉。而方法2对代码改动较大。最后采用方案是:css build工具在yui压缩完,再对css文件按方法1额外处理下。

个人感觉,IE滤镜可以实现很多CSS3才加入的效果,微软实际上是非常超前的。只是这东西有点年老失修,时不时会出这样那样的问题,还是能少碰就少碰了。

--EOF--

上一篇博客提到09年初WED团队开发的浏览器环境检测工具时,忘记说这个是aoao同学的创意了。不过没关系,据说他又在秘密规划新版本了,再据说新版要增加的DNS解析时间计算已经开发完成,点上面那个链接就可以抢先体验。。。

好吧,参加过11年Velocity大会的同学应该都知道facebook那个算DNS解析时间的方法了,像我这种穷人家孩子参加不起VC大会的,主办方很厚道的提供有PPT可供观看。看完PPT觉得不过瘾,还是来动手实战下吧。

首先看原理:

a <= <random number>

t1  http://a-doppler.facebook.com/test_pixel?HTTP1.0&t=1&size=0k
t2  http://a-doppler.facebook.com/test_pixel?HTTP1.1&t=2&size=0k
t3  http://a-doppler.facebook.com/test_pixel?HTTP1.1&t=3&size=0k
t4  http://a-doppler.facebook.com/test_pixel?HTTP1.1&t=4&size=10k

t1 = DNS + New Connection +RTT
t2 = New Connection + RTT
t3 = RTT
10k /(t4–t3)~TCP bandwidth

来源:《MobilePerformanceVelocity2011.pdf》 by DavidWei.

这方案有两个关键点:

1、为了避免各种DNS缓存,每组请求必须用一个从来没被用过的全新N级域名。这就要求你的域名支持泛解析。例如我为了这个实践,开了*.qgy18.com的解析。

2、每组的第一个请求响应必须以HTTP/1.0返回。我开始还没注意这个,经aoao提醒才明白,这样才可以确保后面的请求会重建Connection。

t2和t1指向同一个域名,且都需要重新建立连接,所以t2-t1是DNS解析时间;t2返回Connection: Keep-Alive,t3是在Keep-Alive指定的timeout时间内发起的新请求,且返回内容为空,所以是RTT(Round-Trip Time);t4在t3的基础上只是把返回内容大小由0k变成10k,所以t4-t3是加载这10k资源花费的时间,这就可以得到网络带宽了。为了减少网络波动,也可以多测几次取平均值。

明白了原理就好办了,剩下的几行代码相信大家都会写,略过。

相比Navigation Timing提供的统计,这种方法好处是兼容绝大部分浏览器,没有浏览器实现上的差异和bug,能较准确的反应浏览器查询DNS所花费的时长;缺点是部署起来比较麻烦。

--EOF--

在我之前参与过的某产品上线后,我们经常会收到用户反馈的各种奇怪问题,很多都和浏览器环境有关,每次跟进起来费时费力。09年初,JKMiller开发了一个页面工具用来排查浏览器环境相关问题,挺好用的。这个工具在我的小站也存放了一份,去掉了无关内容并改了一些提示文字,版权属于原作者。可以通过这个地址来访问:

http://qgy18.imququ.com/browser-doctor/

-----分割线-----

对于跟进用户反馈这个事情,再多说点。有时候用户在论坛或微博抱怨自己啥啥功能用不了,但这个问题没办法复现,也没有其他人反馈,要怎么解决呢?如果能联系到用户并且用户配合,能用上面的工具跑出结果来当然最好了;联系不上呢?那得从侧面下手:

如果有截图,大概扫一眼可以排查样式是否加载失败和样式兼容性问题,也可以排查缺少字体、缩放文本、调整DPI等常见问题。有些截图还能看到当时使用的浏览器,这就可以把问题定位到某个浏览器的某个版本。如果图上没浏览器,根据一些元素例如表单的默认样式差异,也差不多可以定位OS和浏览器类型。看截图还可以判断页面内容是否加载正常,例如页面上空了一块,那就要考虑是不是Ajax请求失败,或者被用户浏览器当广告屏蔽了一部分内容等等情况。

如果没截图,或者截图提供的信息太有限,那么可以设法确定用户身份,根据用户唯一标识和提交反馈的时间点,可以拿到web server访问日志,access log一般都有记userAgent,这就可以确认用户的OS和浏览器信息。还可以根据连续的日志还原用户操作流程,排查特定分支下出现的bug。有时候用户某个功能不能用是因为他的网络运营商劫持了某个域名造成的,服务器根本就没有他的访问日志。

我遇到的用户反馈的奇怪问题,大部分都是代码bug,剩下小部分问题就各种原因了,有页面被运营商篡改的;有浏览器设置不当或系统组件被破坏如msxml3.dll被反注册的;还有国内各种Shell把IE改坏的等等。

每件事背后都有它发生的原因,能通过种种蛛丝马迹成功解决用户的疑难杂症还是非常有幸福感的,虽说很多时候让用户“Ctrl+F5”、“换台电脑试试”同样能解决问题。

--EOF--

今天看到某大牛之前写的某段代码里,用到了"| 0"这种写法将字符串取整。这本来没什么,很多人都这样做,但他那段代码里处理的是一个时间戳。如:

"1325239449538" | 0;

结果是-1905444926,这显然不是我们想要的。这个问题产生的原因是:A | B是将A、B先ToInt32再运算,返回结果是32位符号型整数。只要A超过2147483647,也就是231-1,就杯具了。

另一个常用的parseInt函数也容易发生杯具,如:

parseInt(0.0000001);

在大部分浏览器上,结果是1(新版firefox会得到0),这也显然不符合预期。原因是parseInt(A)第一步会执行ToString(A)。上面的例子中,0.0000001会转成"1e-7",后面的事情应该都知道的。

--EOF--

最近改用mac后,最纠结是割舍不能用了数年的Editplus,一时间甚至有了装XP虚拟机继续用EP的213想法,每天茶不思饭不想,码也不想写了。这样过了大半个星期,期间尝试Coda、BBEditor等等各种号称Mac下最好用的编辑器后仍不满意,终于在快要放弃的时候遇到Sublime Text2,成功的解救了我。

关于它的介绍,网上已经有很多文章了,可以先了解下:

Sublime Text 2 入门及技巧
Sublime Text 2 实用快捷键[Mac OS X]

然后就可以动手了,直接去官网下载最新的安装包,支持win/mac/linux三大系统。再参考上面的文章换个icon;从自带的丰富配色里选一个自己看着顺眼的;体验下无比爽快的cmd/ctrl+p实时文件切换功能;打开一些js、css或者php,cmd/ctrl+r看看有什么;创建一个project;了解每个菜单项;熟悉下各种快捷键。。。这个过程可长可短,总之一定会让你眼前一亮~

Read the rest of this entry »

最近负责的某项目,提供了文件下载功能。有用户反馈,下载的.lnk文件,后缀名变成了.download。

经查,只有chrome系列浏览器才有这个问题。

抓包看下请求,发现服务端在response的header里给出了正确的文件名,如:

Content-Disposition: attachment; filename="xxx.lnk"

那么,这个重命名肯定是浏览器的默认行为。实际上,lnk类型的文件是一个软链,运行后会执行什么完全取决于不同的系统环境,没办法预期,Chrome认为这比较危险,就在底层强制对其重命名了。所以,这不是web应用所能决定的。

到此,问题就解决了。总共花费1分钟,就把bug resolved掉,还不用改一行代码,happy呀~

--EOF--

围观过QWrap的同学可能会注意到其官方的特性介绍里有这么一条:

提供YUI2一样的静态方法库,同时又用所谓的Helper规范来做到真正的绝对静态,让组件开发者可以发布出无依赖的组件。

其中,组件无依赖化,也就是核心库定制这个特性,在某些场景下还是非常有用的。QWrap提供了相应的工具来实现,JK这篇文章有详细说明。只是这个工具藏得很深没多少人知道,好酒也怕巷子深~ 最近我在这个工具的基础上增加了代码选取的功能,一起再给大家介绍下。

首先,访问代码选取小工具页面。

第一步,选择要用到的方法。这一步比较好理解,例如要用到数组迭代就选中ArrayH下的forEach,需要格式化日期功能就选择DateH下的format,依此类推。特别的,Browser(浏览器UA相关)、Selector、CustEvent(自定义事件)这三个模块目前是不能拆分的,只能按模块选择,并不能细化到每个方法。

Read the rest of this entry »

恭喜月影结婚啦

In: 默认分类  

23 09 2011

月影姐姐终于嫁人了~

为此咱WED北京分舵的同学们录了一段小视频以表祝贺。

尽管同学们分散在各大公司,尽管我们设备简陋,时间、技术有限,但大家还是齐心合力完成了这么一段完全能够展示WED文化(脑残?快乐?创新?无拘无束?太多了。。。)的视频。

为了给月影一个惊喜,我们组建了《WED-北京》项目群联络大家、录制视频、后期制作。整个项目一直在有条不紊的推进着,预期十月一日准时上线。但考虑到国庆期间维护人员放假,按BD惯例长假前一周不上线,临时决定提前一周发布。非常感谢大家的转发,我也被感动了~

首创特辑(by XMM):

Read the rest of this entry »

先来句题外话,最开始Ajax应该是用来特指用XMLHttpRequest传输数据这门技术,但就像最近大家把一切web新技术都归到html5名下一样,现在一切异步获取数据的手段都被人称之为Ajax。

由于JavaScript同源策略的存在,跨域数据交互是个老生常谈的话题了。网上相关文章很多,不过随着时间的推移和浏览器的更新,一部分解决方案已经不适用了,同时也出现了一些更好的方法。抛开纯服务器Proxy这种跟前端没什么关系的方案不说,这里简单总结下常见的其他几种方式。

JSONP

JSONP是最常见的跨域数据交互的方式,原理是html的script标签可以加载并执行其他域JS文件。站点B把要提供的数据作为参数传给一个站点A定义的全局函数,站点A引用这个文件就可以跨域获取数据了,A站还可以把少量参数放在script标签的src里提交给B站。外链JS这种方案只支持GET,受IE下url长度不能超过2083个字节的限制和出于安全考虑,一般不用来提交数据。

有人通过后端Proxy使得这种方式可以获取任意页面内容,还增加了对POST的支持,如:

<script type="text/javascript" src="http://www.ajax-cross-domain.com/cgi-bin/ACD/ACD.js?uri=(http://www.google.com)"></script>
<script type="text/javascript">
	alert(ACD.responseText);
</script>
<script type="text/javascript" src="http://www.ajax-cross-domain.com/cgi-bin/ACD/ACD.js?uri=(http://216.92.131.147/dotserv/ACD/runit/post.cgi)&method=post&postdata=(name=fred&email=fred@fred.com)"></script>
<script type="text/javascript">
	alert(ACD.responseText);
</script>

实际上这个方案是借助后端把任意页面输出为JS变量,后端根据url中相关标识来决定请求方式和参数,并不能解决大数据提交问题。

原生表单+Redirect+Callback

原生的form表单支持提交数据到其他域,我们只需要把form的target指向页面上的隐藏iframe,那就实现了无刷新提交,剩下的问题就是怎么获取提交后的结果。例如站点A表单提交数据到站点B,通常我们会在站点B处理完请求,重定向到站点A下某个Proxy页面,并在url带上参数标识处理结果。接着,A站下的Proxy页面就可以解析url参数,传给父页面的Callback函数来处理了。

Read the rest of this entry »

大家都知道FaceBook发明了BigPipe,把页面分为多个PageLet来加载,让服务端运算与客户端加载并行进行,使得页面可交互时间往前提了不少。我这里不谈如何实现BigPipe,而是分析下FaceBook如何处理不支持JavaScript的场景。

对于不支持BP的浏览器,服务端必须一次生成所有HTML,每个模块用到的JS和CSS也需要合并。那怎么让服务器尽早知道客户端不支持JS呢?FaceBook的办法是在BP模式的HTML里加上了NoScript标签和Meta跳转:

<noscript><meta http-equiv="refresh" content="0; URL=/?_fb_noscript=1" /></noscript>

这样,如果用户的浏览器不支持JS,那访问FaceBook的任何一个页面,都会重定向原URL,并带上_fb_noscript=1这个参数。接着,服务端根据这个标记就可以按照非BP模式输出完整的页面。

如果用户访问每一个页面都需要多一次重定向,是不是很浪费时间和带宽呢?确实如此!FaceBook已经考虑到这个问题了:服务端在收到_fb_noscript=1标记时,会给客户端设置noscript=1的Cookie,这样下次请求哪怕没有URL参数标记,服务端也可以根据Cookie标记适配到非BP模式。

但是,如果客户端突然又支持JS了呢?这种情况多半是在测试,理论上继续用非BP模式也没什么问题,但FaceBook还是很厚道的处理了这种情况:在非BP模式的HTML里有这么一段JS:

Read the rest of this entry »

关于我

JerryQu,当前从事前端开发,@中国北京
这里是我随便记录东西的地方~
需要找我,我的联系方式在这里»
查找QGYWebIM相关信息,请点这里»

  • Hafeyang http://www.useragentman.com/blog/2010/03/09/cross-[...]
  • Jerry Qu @dron,parseInt(0.0000001) 改成 parseInt("0.0000001")[...]
  • 小米 快说服老板去使用lenovo的call center吧。当然,这是个玩笑。 如果用户连 brows[...]
  • dron 地址收藏了,备用。
  • Jerry Qu @welefen,你们的页面截图工具上了没?
  • welefen 恩,截图是一个还原现场一个非常好的功能,尤其是交互上的一些问题。 并且我们监控发现,由于用户环[...]
  • welefen 囧啊,把修改后的pjax发我一份吧, 我更新下
  • dron 如此看来,目前就 +n.split(".")[0] 最安全了。
  • afei 膜拜啊,百度的牛人。 哈哈,也是黄冈的...
  • Jerry Qu @UECSS,目前是可以免费无限期试用,只是保存文件时经常会弹出提示让购买,如果要去掉这个限制就要花[...]
  • UECSS 轻巧好用,就是收费$59?
  • L.J 为神马你们又换编辑器了呢,不再玩editplus了,我又out了,继续紧跟时代脉搏,学习使用subl[...]
  • dron @JQuery: 几个月前,我不是在微博上宣布换了么?
  • a4 @唠叨下 没错涅,ctrl+shirt+p 和ctrl+p是不同功能滴。文中说滴是实时文件切换是ct[...]
  • Jerry Qu @dron,没想到龙兄你这个ep忠实粉丝也换了呀~st2有原生插件可以玩,感觉很有前途