Archive for the ‘前端技术’ Category
新版本的IE collection——目前最好的多版本IE并存方案
一直找不到比较完美的多版本IE并存的方法,因为IE 8的出现,它的developer toolbar成为必备的调试工具,然而multiple IE的IE 6无法和ie 8并存,在装有ie 8的机器上装multiple IE的话,IE 6内无法选择文本,并且不支持cookie,而IEtester尽管勉强可用,但是同样不支持cookie,所以无法登陆,调试的意义也就不大。
上一个版本的IE collection 1.4.2.0将各种版本的IE集成在一个安装包内,但是bug太多,可用性实在是很差,并且它的IE8自带的调试工具是不可用的,前段时间给作者发了一个feature request,希望他能让修好IE8的developer toolbar,前两天收到答复,他已经将IE collection升级到了1.5.0.0版本,立即很兴奋地下下来测试,当时在公司用自带IE6的xp sp3,安装完毕之后ie 8的toolbar是可用了,但是IE6又坏掉了,总之bug还是较多,后来为了修好IE,又把系统默认的浏览器升级到了IE 8,重新测试ie collection,这次发现它和IE 8能很完美的共存,IE6,IE7的文字高亮和输入框获取焦点都没有任何问题。
所以目前最好的多版本IE并存方案是:将系统自带的IE升级到IE8,然后安装IE collection 1.5.0.0,记得不要在系统自带浏览器版本为IE 6的情况下安装,否则会遇到很多问题。
预载:hover背景图
我们经常会遇到鼠标划过链接时需要改变背景图的情况,其实做起来挺简单,就是给链接的:hover伪类设置一张背景图。但这是问题便出现了,设置在:hover下的背景图并没有随html文档一同被载入,而是在我们把鼠标放在链接上时才开始像服务器发出请求。
例如,如果我们在一个a链接上写了以下样式:
a.test {
background: url(images/bgImg.png) no-repeat;
}
a.test:hover {
background: url(images/bgImgHover.png) no-repeat;
}
那么当用户把鼠标移到a链接上时,原先设置在a上的背景图消失了,而设置在:hover上的背景图bgImgHover.png又正在载入,这是就会出现没有背景图的瞬间,这种用户体验是很糟糕的,特别是当背景图比较大时,可能还不止是一瞬间,用户需要等上一段时间才能见到背景图。
解决这个问题的办法是预载背景图,就是说强迫设置在hover上的背景图随HTML文档一起被载入,这样当用户的鼠标放到链接上时:hover上的背景图已经被下载到本地,也就不会出现上述的情况。下面提供几种方法:
方法一:采用CSS Sprite技术
CSS sprite技术是一种将许多小背景图合成到一张大图以减少http连接数从而提升页面载入速度的技术。用过YSlow的人都知道Yahoo把减少HTTP连接数列为提高网站速度效率的第一要素。但此处采用sprite是为了解决预载:hover背景图的问题,将:hover背景图与任意一张非hover、非active、非focus下的背景图合成到一张图片,这样图片就会随html文档一起被载入。
方法二:将需要预载的背景图设置在文档内任意一个元素上,并通过backgroud-position让其不可见
文档内有如下html代码:
<li class="test"><a href="#">test</a></li>
css代码如下:
.test {
/* 把li的背景设置成这张需要预载的图片,但是让其不可见 */
background:url(images/bgImgHover.png) no-repeat -999px -999px;
}
.test a {
background:url(images/bgImg.png) no-repeat; /* 正常状态下的背景图 */
}
.test a:hover {
background:url(images/bgImgHover.png) no-repeat; /* hover状态下的背景图 */
}
由于在li上设置了bgImgHover.png这张背景图,尽管我们看不到它,但是图片在文档载入之前就已经下载到了本地。
方法三:用JavaScript预载图片
有些时候假如我们需要预载的图片有十几张,并且由于种种原因我们无法使用Sprite的时候,用JavaScript便成为更好的选择。
<script type="text/javascript">
for ( var i = 1; i <= 15; i++ ) ( new Image() ).src = './images/bgImg' + i + '.png';
</script>
这样会预载从bgImg1.png,bgImg2.png…直到bgImg15.png。
《精通javascript》中的几个错误
第86页,代码清单5-28中有这样一段:
//向后遍历数组,
//因为我们向前添加元素
for ( var i = elems.length - 1; i >= 0; i-- ) {
parent.insertBefore( elems[i], before );
}
此处用一个反循环反而把被添加元素的顺序搞反了,用一个正循环才能得到正确的顺序。
另一个错误:在103页,表单事件那部分有这样一句:“select事件在<select>元素更新后触发”。事实上,<select>元素更新后只会触发onchange事件,不会触发onselect事件,参见这里:“Broadly speaking, buttons can generate click events, and text and select items can generate focus, blur, select, and change events. The one potentially confusing aspect of this organization of events is that selection lists cannot generate the select event. This is because they have no editable text. ”
用editplus查看或修改文件编码的方法
editplus里面自带有更改文件编码的功能:依次点击菜单Document-File Encoding-Change File Encoding这里可以查看和修改文件编码。
还有一个办法是打开文件之后点击菜单File-Save as,在弹出的对话框的最下面就是当前文件的编码,更改编码之后保存并覆盖原文件就相当于修改了此文件的编码。
神奇的exec()方法
今天发现《JavaScript高级程序设计》中对正则表达式的exec()方法的讲解完全就是错误的,书中说exec()方法以一个字符串作为参数并且返回一个数组包含所有的匹配项,并且说执行下面这段代码之后,arrMatches就是’at’,'at’,'At’,'aT’,'aT’,'at’这几个字符串组成的一个数组:
var sToMatch = “a bat, a Cat, a fAt baT, a faT cat”; var reAt = /at/gi; var arrMatches = reAt.exec(sToMatch);
可事实上测试这段代码之后结果并非如此,arrMatches只返回的数组中只包含了一项’at’,也就是第一个匹配项。
mozilla上的一篇文章对exec()方法做了比较详细的说明,exec()方法并不像书中所说的跟字符串的match()方法相似,match()方法一次性返回包含了所有匹配项的一个数组,而exec()方法执行一次只返回包含一个匹配项和这次匹配中的所有反向引用的数组,看看下面的例子就比较容易明白:
var myRe = /d(b+)(d)/ig;
var myArray = myRe.exec("cdbBdbsbzDBBBBD");
执行这段代码之后,myArray就变成了这样一个数组:["dbBd", "bB", "d"],很显然数组中的第一项是第一个匹配项,而另外两项则是这次匹配中的反向引用。如果再次执行这句:myArray = myRe.exec("cdbBdbsbzDBBBBD");,那么myArray就变成了这个数组:["DBBBBD","BBBB","D"],也就是第二个匹配项和其中的反向引用组成的数组。每执行一次exec()方法就会从上一次匹配项的末尾开始寻找下一个匹配项,直到找完所有的匹配,如果还继续执行exec()就会返回null。
不用try catch创建XMLHttpRequest对象
一直搞不明白为什么许多书上在创建XMLHttpRequest对象的时候一定要用try catch方法来做,用对象检测方法不是要简单得多吗?今天看kkp on JavaScript看到Data Retrieval这一章时决定好好分析一下这个问题,首先用以下代码测试:
if (XMLHttpRequest) alert('supported!');
马上就有新的发现,原来IE 7内部已经有了XMLHttpRequest这个对象,此前还一直以为所有的IE都不支持XMLHttpRequest对象的,原来是我读的基本JS的书籍都太老了,根本没有提及IE7已经开始支持XHR这个问题。
刚才的代码在IE6里面会报错,提示XMLHttpRequest未定义,if语句有一个特点很有意思:当遇到未定义的变量的时候会报错,而遇到未定义的属性时则不会报错。在支持XHR的浏览器里面XMLHttpRequest可以看成是一个全局变量,而所有的全局变量同时也是window对象的属性,那么方法就出来了,在if语句里面把XMLHttpRequest写成window的属性,即if (window.XMLHttpRequest),这样IE6就不会报错了。
做了一个小小的搜索看快就发现原来IE的开发人员正是用对象检测来创建XHR对象的:
if (window.XMLHttpRequest) {
// If IE7, Mozilla, Safari, etc: Use native object
var xmlHttp = new XMLHttpRequest()
}
else if (window.ActiveXObject) {
// ...otherwise, use the ActiveX control for IE5.x and IE6
var xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
Update:projs中介绍一种更好的方法:
if ( typeof XMLHttpRequest == 'undefined' )
XMLHttpRequest = function() {
// Internet Explorer uses an ActiveXObject to create a new XMLHttpRequest object
return new ActiveXObject(
// IE 5 uses a different XMLHTTP object from IE 6
navigator.userAgent.indexOf('MSIE 5') >= 0 ?
'Microsoft.XMLHTTP' : 'Msxml2.XMLHTTP' );
};
//Create the request object
var xml = new XMLHttpRequest;
淘宝2007年的一道面试题
淘宝2007年有这样一个面试题:
小贤是一条可爱的小狗(Dog),它的叫声很好听(wow),每次看到主人的时候就会乖乖叫一声(yelp)。
从这段描述可以得到以下对象:
function Dog() { this.wow = function() { alert(’Wow’); } this.yelp = function() { this.wow(); } }小芒和小贤一样,原来也是一条可爱的小狗,可是突然有一天疯了(MadDog),一看到人就会每隔半秒叫一声(wow)地不停叫唤(yelp)。
请根据描述,按示例的形式用代码来实现(提示关键字: 继承,原型,setInterval)。
淘宝UED上给出的答案是:
function MadDog() {
this.yelp = function() {
var self = this;
setInterval(function() {
self.wow();
}, 500);
}
}
MadDog.prototype = new Dog();
//for test
var dog = new Dog();
dog.yelp();
var madDog = new MadDog();
madDog.yelp();
经过我的测试发现:如果把self.wow后面的括号去掉,那么外面那层匿名函数也是可以去掉了,所以setInterval部分可以这么写:
setInterval(self.wow,500);
后来我又尝试了两外一种解法:
MadDog=new Function;
MadDog.prototype=new Dog();
MadDog.prototype.yelp=function() {
setInterval(this.wow,500);
}
//for test
var madDog=new MadDog();
madDog.yelp();
这种写法看上去要比淘宝上的答案要简单,经测试也是可以达到题目要求的。既然MadDog的yelp方法要变,那就就直接在后面把从Dog继承来的prototype属性覆盖一遍就OK了,不知道这种写法有没有什么不妥,毕竟人家都是高手,而我只是菜鸟一个。
《无懈可击的web设计》小结
《无懈可击的web设计》这本书讲了许多提高网站灵活性、可维护性和可访问性的一些小技巧,读过之后发现里面讲的许多方法都是以前没有注意到的,所以有必要对其中的一些内容做一个小小的归纳总结,一方面可以加深印象,另一方面也可以作为一个备忘录以便将来查阅。
1.用关键字和百分比来确定文字大小以便使用户也能控制其大小,并且最大化网页的灵活性。
在body上使用font-size:small来设置全局的文字大小,然后在其他地方全部用百分比来控制,这样不仅可以使得IE用户可以通过菜单栏的“查看>文字大小”来控制文字大小,而且以后要对文字大小进行调整的时候只需要调整一条声明就可以让整个网页的文字大小按比例缩放,使得灵活性大大提高。
2.让导航菜单能够适应任意的文字大小和任意多的内容。
对导航菜单既不要定宽也不要定高,对于菜单内文字和边缘之间的间隙则用padding来填充,这样就适应了任意的文字大小和任意多的内容,对于滑动门菜单也是如此,我以前在写滑动门的时候习惯把高度定死,这并不是一个好习惯。此处还要注意的是如果背景图是渐变效果则要将背景图适当地加长和加高以适应各种长度和高度的内容。
3.用em来作为line-height的单位,同样的,对于两行文字之间margin值也用em为单位。
用em做单位的好处是当文字大小改变的时候此处的line-height和margin也会相应地改变。
4.对一些水平的区块也不要定高,让其高度自适应。
一些水平区块如头部、登录区、搜索区和一些单行文字的区域也不要定高,一方面是为了适应文字大小的变化,另一方面也使得以后在该区块增加内容后不至于使页面变形,例如单行的文字有可能在以后增加到两行。所以以前通过定高度和行高来处理单行文字的做法要改为不定高度并用padding填充文字上下的空白区域。
5.确保页面在禁用图片和CSS的时候仍然不影响正常阅读。
背景图未加载有可能造成文字和下面的背景颜色太接近而使网页阅读困难,解决方法是在凡是有背景图的地方都写上一个背景颜色。作者把裸奔测试称为“十秒钟可用性测试”,就是禁用CSS之后再看页面结构是否清晰,这就要求做好HTML的语义化。一些方便做此类测试的小工具:
- FAVELETS 实际上就是一些JavaScript代码写成的书签
- Web Developer Toolbar For Firefox
- Web Accessibility Toolbar For IE
6.用border-collapse:collapse;实际上可以替代talble上的属性cellspacing=0,唯有IE/MAC不支持border-collapse,但是IE/MAC现在可以忽略掉了吧。
7.在使用百分比宽度的流体布局中为栏间设定固定像素间距的方法是在每栏的里面加入一个div并在这个里层的div上加上padding。
8.即便是对使用百分比宽度的流体布局也可以使用背景图垂直重复的方法来造成貌似两栏等高的假象,方法是将背景图的水平位置也用百分比来设置。
阻止IE在浏览本地文件时发出安全警告
IE浏览器在打开本地文件的时候,如果文件内有JavaScript或者flash等活动内容,就会弹出一个安全警告:“为了有利于保护安全性,Internet Explorer已限制此网页运行可以访问计算机的脚本或ActiveX控件。请单击这里获取选项…”。对于普通用户来说这不会有太大的影响,但是对与一个经常需要调试JavaScript的网页开发者来说这个东西就相当令人烦恼了。不过幸好我在这里找到了解决办法。一位网友提出了三种解决方案:
方案一:用firefox作为你的默认浏览器。
方案二:让IE允许运行本地脚本文件:
- 在IE的工具菜单选择Internet选项;
- 在Internet选项窗口中选择高级选项卡;
- 在安全部分勾选“允许活动内容在我的计算机上的文件中运行”。
设置完毕之后重启IE就不再会出现烦人的安全警告了。
方案三(不推荐):
在你的页面文件中加入如下代码:
<!-- saved from url=(0014)about:internet -->
或者
<!-- saved from url=(0016)www.yoursite.com -->
注意:括号中的数字是后面网址的长度,你可以把这段代码加入HTML文件的head区域。
问题是加入了这段代码的文件无法链接到不含这段代码的页面,所以只有在你确定没有外部链接时才推荐方案三。
很显然对一个开发人员来说,方案一是不可取的,因为即使默认用firefox,也不可避免要在IE中调试,方案三也不好,方案二则比较完美。