doctype与hover伪类

作者:nunumick 发布时间:25 Aug 2010 分类: front-end

开发过程中将demo中的内容拆分进各子模块,发现之前好好的 hover 效果失效了,我排查的结果是因为在模块中没有定义doctype,页面默认使用 quirks mode,会导致非链接<a>标签的 hover 伪类在 IE7/8 和 firefox 均失去效果。

我们通常认为的非 IE6 以下浏览器都支持链接以外元素的 hover 伪类,其实还需要依赖 doctype,比如这样的代码就在 IE7/8 和 firefox 失去效果:

<html>
    <head>
        <style>
        .hover-test:hover{color:#f00;}
    </style>
    </head>
    <body>
        <a class="hover-test" href="#">hover字体变红</a>
        <p class="hover-test">hover字体变红,Quirks mode下失效</p>
    </body>
</html>

MSDN找到相关说法:

Internet Explorer 7 and later, in standards-compliant mode (strict
!DOCTYPE), can apply the :hover pseudo-class to any element, not merely
 links.

而 Firefox 与 IE 也有区别,Firefox 下用标签名作为选择器可以使 hover 伪类恢复效用:

<html>
    <head>
        <style>
        p.hover-test:hover{color:#f00;}
        </style>
    </head>
    <body>
        <a class="hover-test" href="#">hover字体变红</a>
        <p class="hover-test">hover字体变红</p>
    </body>
</html>

延伸阅读

html5 doctype与图片多余空白

标签: doctype , hover , browser , html
<<< EOF

Embed标签src重载

作者:nunumick 发布时间:25 May 2010 分类: front-end

<embed>标签可用于在页面内嵌入 flash 文件,比较常见的就是在页面内嵌入视频,如:

<embed src="http://player.youku.com/player.php/sid/XMTU3NzUyMDUy/v.swf" quality="high" width="480" height="400" allowscriptaccess="sameDomain" type="application/x-shockwave-flash"></embed>

接到一个小需求:需要动态更新 embed 标签的 src 属性,拿上面的代码为例,很容易找到思路:

  1. 获取embed标签
  2. setAttribute(‘src’)

类似于对待 img 标签。

遗憾的是,此法对于 ie 浏览器并不奏效,给 src 加上时间戳也无济于事。

最后无奈用更新dom节点的方式才得以实现。

各浏览器在处理 embed 重载时并不尽相同,在此简单做了测试:Demo

测试结果:

Y:响应重载 N:不响应重载

  IE(6/7/8) Firefox Chrome Safari Opera
重载(refresh movie) N Y N N Y
更换(change movie) N Y N N Y
Display显示/隐藏 N Y Y Y Y
Visibility显示/隐藏 N N N N N
设置innerHTML Y Y Y Y Y
Display hide > Change movie > Display show N Y Y Y Y

标签: embed , flash , browser , compatibility , html
<<< EOF

慎用通配符选择器

作者:nunumick 发布时间:22 Apr 2010 分类: front-end

一、通配符选择器优先级低

div{background:#f00}
*{background:#000}

前者优先级更高。

*.hello{color:#f00}
.hello{color:#000}

两者优先级一样,后来至上。

二、通配符选择器样式污染

#showEveryThing * {display:block}

将使 showEveryThing 内部所有元素显示为块元素,包括 <style> <script> <noscript>标签。这会破坏这些标签的本来面目,造成不必要的麻烦。

<style> <script> <head> 等元素本不可见,如果被强制加上样式,多多少少都会有问题。

区别

  1. IE 不会输出内容,但可以控制边框。
  2. 非IE 基本可以当作普通元素对待,但不影响原有标签功能。如出现样式被修改情况,可以反方向重置。

因此,在使用通配符选择器时特别需要注意上下文环境,确认不会造成标签样式污染之后再使用

标签: selector , compatibility , css
<<< EOF

如何以get方式传递表单action中的额外参数

作者:nunumick 发布时间:12 Mar 2010 分类: front-end

###问题及背景

今天项目组的开发同学急冲冲地叫上我看一个他写的JS脚本,好端端的一个form提交时参数无法正常传递。代码是这样的

<form method="get" name="xxx" id="xxx" action="uri?xxx=xxx&yyy=yyy" >
   <input name="zzz"  type="text" value="zzz" />
   <input id="submit" type="button" value="提交" />
</form>
<script>
   document.getElementById('submit').onclick = function(){
       var form = document.xxx;
       form.action = form.action +
           (form.action.indexOf('?') > -1 ? '&' : '?') + form.zzz.value;
       form.submit();
   }
</script>

其本意是在提交是要同时提交xxx、yyy、zzz三个参数,但最终提交的参数只有zzz,即uri只是 uri?zzz=zzz。

###分析

这是为什么呢?脚本没有问题呀,感觉方法也没什么问题,在调试了多次无果之后,我把注意点移到了form本身:在禁用了脚本之后,form同样只提交了zzz参数。

最终查到原因是因为form使用了get方法。

HTML 4.01 specification的解释

If the method is "get" - -, the user agent takes the value of action,
appends a ? to it, then appends the form data set,
encoded using the application/x-www-form-urlencoded content type.
The user agent then traverses the link to this URI. In this scenario,
form data are restricted to ASCII codes.

get方式是method的默认值,其方式是将form表单中的数据集值对组织到action中的uri之后,不过其组织方式是有讲究的:

  1. uri在submit最后才进行组织
  2. 在添加’?’时,uri中额外参数会被舍弃,接着只拼接表单内的域值
  3. uri hash值会被保留:uri?xxx=xxx#here,#here会被保留

###改进

get方法需要传递额外参数时,可以选择在form表单内动态创建额外参数域,再提交

<script>
   var oInput = document.createElement('input');
   var oForm = document.xxx;
   oInput.name = 'yyy';
   oInput.value = 'yyy';
   oForm.appendChild(oInput);
   oForm.submit();
</script>

当然,用post方式会更方便,看你如何选择

<form method="post" name="xxx" id="xxx" action="uri?xxx=xxx&yyy=yyy" >
   <input name="zzz"  type="text" value="zzz" />
   <input id="submit" type="button" value="提交" />
</form>

###更多关于post和get的区别

####编码 HTML 4.01 specification指出,get只能向服务器发送ASCII字符,而post则可以发送整个ISO10646中的字符(如果同时指定enctype=”multipart/form-data”的话)。

注意get和post对应的enctype属性有区别。enctype有两个值,默认值为application/x-www-form-urlencoded,而另一个值multipart/form-data只能用于post。

####提交的数据的长度 HTTP specification并没有对URL长度进行限制,但是IE将请求的URL长度限制为2083个字符,从而限制了get提交的数据长度。测试表明如果URL超出这个限制,提交form时IE不会有任何响应。其它浏览器则没有URL的长度限制,因此其它浏览器能通过get提交的数据长度仅受限于服务器的设置。

而对于post,因为提交的数据不在url中,所以通常可以简单地认为数据长度限制仅受限于服务器的设置。

####缓存 由于一个get得到的结果直接对应到一个URI,所以get的结果页面有可能被浏览器缓存。而post一般则不能。

####引用和SEO 出于和上面相同的原因,我们可以用一个URI引用一个get的结果页面,而post的结果则不能,所以必然不能被搜索引擎搜到。

####使用场景 的W3C官方建议是:当且仅当form是幂等(idempotent)的时候,才使用get,比如搜索结果。其他情况则使用post方式。

###参考文献 Methods GET and POST in HTML forms – what’s the difference?
What is the difference between GET and POST?

标签: form , html
<<< EOF

JavaScript等同(==)与恒等(===)运算符

作者:nunumick 发布时间:07 Mar 2010 分类: front-end

Javascript开发中,需要与0,undefined,null,false进行等同比较时,我们知道,用’===’(恒等)比较靠谱,我是在第一次使用jslint时知道这点的,例如在Jslint中验证

var test = '';
alert(test==0);

会得到提示:

Use '===' to compare with '0'

看看ECMA规范中是如何对==和===操作符进行定义的,了解其深层的规则和jslint提示的缘由

首先介绍==

11.9.1 等同运算符( == )

运算符规则如下所示:
1. 计算运算符左侧表达式;
2. 对第1步的结果调用GetValue;
3. 计算运算符右侧表达式;
4. 对第1步的结果调用GetValue;
5. 对第4步的结果与第2步结果执行比对(参考 11.9.3);
6. 返回第5步结果;

再来详细了解比对过程(11.9.3)

11.9.3 抽象的等同比对算法

假设有 x,y 进行比较 ,则有 x == y;
1. 如果xy类型不同,转至第14步;
2. 如果xy类型均为Undefined,返回 true;
3. 如果xy类型均为Null,返回 true;
4. 如果xy类型均不是Number(数值类型),转至第11步;
5. 如果x的值为NaN,返回 false;
6. 如果y的值为NaN,返回 false;
7. 如果x与y的数值相同,返回 true;
8. 如果x是+0并且y是−0,返回 true;
9. 如果x是−0并且y是+0,返回 true;
10. 返回 false.
11. 如果xy类型均为String(字符串类型),判断x与y是否有相同的字符(对应位置字符相同),是则返回 true,否则返回 false;
12. 如果xy类型均为Boolean(布尔类型),xy均为true或均为false则返回 true,否则返回 false;
13. 如果x与y引用同一个对象(object)或者xy引用的对象是Joined关系(参考13.1.2)则返回 true,否则返回 false;
14. 如果x为null且y为undefined,返回 true;
15. 如果x为undefined且y为null,返回 true;
16. 如果x类型为Number,y类型为String,先将y转换为Number类型,再进行比对,返回结果;
17. 如果x类型为String,y类型为Number,先将x转换为Number类型,在进行比对,返回结果;
18. 如果x类型为Boolean,先将x转换为Number类型,再进行比对,返回结果;
19. 如果y类型为Boolean,先将y转换为Number类型,再进行比对,返回结果;
20. 如果x类型是String或者Number且y类型为Object,先将y转换为基本类型(ToPrimitive),再进行比对,返回结果。
21. 如果x类型为Object且y类型为String或者Number,先将x转换为基本类型(ToPrimitive),再进行比对,返回结果。
22. 返回 false.

接着看恒等运算符(===)

11.9.4 严格等同运算符( === )

运算符规则如下所示:
1. 计算运算符左侧表达式;
2. 对第1步的结果调用GetValue;
3. 计算运算符右侧表达式;
4. 对第1步的结果调用GetValue;
5. 对第4步的结果与第2步结果执行比对(参考 11.9.6);
6. 返回第5步结果;

这几步和==运算符是一样的,我们着重来看第5步的比对过程:

11.9.6 严格性等同运算比对算法

假设有 x,y 进行比较 ,则有 x === y;
1.如果xy类型不相同,返回 false;
2. 如果xy类型均为Undefined,返回 true;
3. 如果xy类型均为Null,返回 true;
4. 如果xy类型均不是Number(数值类型),转至第11步;
5. 如果x的值为NaN,返回 false;
6. 如果y的值为NaN,返回 false;
7. 如果x与y的数值相同,返回 true;
8. 如果x是+0并且y是−0,返回 true;
9. 如果x是−0并且y是+0,返回 true;
10. 返回 false.
11. 如果xy类型均为String(字符串类型),判断x与y是否有相同的字符(对应位置字符相同),是则返回 true,否则返回 false;
12. 如果xy类型均为Boolean(布尔类型),xy均为true或均为false则返回 true,否则返回 false;
13. 如果x与y引用同一个对象(object)或者xy引用的对象是Joined关系(参考13.1.2)则返回 true,否则返回 false;

可以做如下概括:

==运算符在做比对时存在类型转换的可能,而===运算符只在同类型之间比对,是==的严格模式。

  1. 类型相同:进行===比对。
  2. 类型不同:基本类型Boolean、Number、String这三者之间做比较时,总是向Number进行类型转换,然后再比较;如果类型有Object,那么将Object转化成基本类型,再进行比较;null仅和undefined匹配;其他都为false。

根据规范和概括,我们不难明白:

  1. undefined只等于(==)undefined或null,null亦然
  2. 空字串(”) == 0 == false ,因为Number(”),Number(false) : 0
  3. true == 1 ,因为Number(true) : 1
  4. false===0 一定返回flase ,因为类型不同

恒等必定等同,等同未必恒等,需择之而用!

延伸阅读

Javascript Type-Conversion

标签: javascript , operator
<<< EOF