第二十一课:js属性操作的兼容性问题
上一课主要讲了属性的概念,用法,固有属性和自定义属性的区别,class属性操作的方法等,这一课主要讲一些有关属性操作的兼容性问题。
IE6-IE8在一些表示URL的属性会返回补全的改过编码的路径,比如:href,action,background,cite,data,src,url等。我们只需要用getAttribute(href,2),就能很好的兼容各种浏览器了。标准浏览器不支持第二个参数,因此忽略第二个参数。而IE支持第二个参数,2代表只取出原字符串的值。
IE6-7下,对于form元素,调用getAttribute取属性值,会取到它的子元素input(ID值或name值等于属性值的input)。举个例子:
<form action="#">
<input id="action" >
<input name="length">
</form>
var el = document.getElementsByTagName("form")[0];
el.getAttribute("action"); //会取到<input id="action" >,IE6-7下
el.getAttribute("length"); //<input name="length">,IE6-7下
对于布尔属性,比如checked,IE6-IE8都无法取得用户预设值(<input type="radio" checked="chaojidan">),无论是通过elem.getAttribute("checked"),加上第二个参数2,还是elem.checked,都得不到"chaojidan"。
注释节点的nodeType等于8。
tabindex的取值问题
tabindex 属性规定元素的 tab 键控制次序(当 tab 键用于导航时)。<element tabindex="number">,number 规定元素的 tab 键控制次序(1 是第一个)。tabindex默认情况下只对表单元素与链接有效,对于这些元素,如果你没有显式设置tabindex,标准浏览器下,它会返回0,而对于div这样的默认不支持tabindex属性的,会返回-1.但IE6-8下都返回0.
在chrome中,如果你把固有属性从原型中删掉(delete操作符),会导致下次赋值时出错。
IE7不能修改表单元素的type属性。
这里讲一下判定一个元素的属性是否是布尔属性的方法:
function isBoolAttr(node,prop){
var isBool = typeof node[prop] ==="boolean" && typeof defaultProp(node,prop) ==="boolean";
//如果元素的属性值是boolean类型,就证明它有机会是布尔属性。(还要排除用户强制执行node[prop]=true(false)的情况,这时不是元素默认的情况,而是用户强制赋值)
return isBool;
}
function defaultProp(node,prop){
return document.createElement(node.tagName)[prop]; //创建一个新的node元素,然后判断这个新节点的prop属性是否是boolean类型。
}
IE6-IE8下有一个href属性的bug,书上的例子没看懂,直接去http://gabriel.nagmay.com/2008/11/javascript-href-bug-in-ie/看了一下,我的理解是:
<a href="http://www.google.com">google.com</a> // fine - changing href will not change text
<a href="http://www.google.com">http://www.google.com</a> // bad - changing href will change the inner html text
address = "@pcc.edu addresses"
$(this).attr("href","http://www.pcc.edu/resources/web/forms/email/?to="+address);
以上代码的意思就是,当a链接的href属性值和a链接的text值相同时,当你改变href的属性值时,会把text值一起替换掉。
解决办法:
(1)text跟href的值不一样,就行了。(这里需要参考下面的讲解,其实如果text里面没有标签元素,同时以www.开头,或者包含@字符,都会引起上面的问题,这里所说的解决办法,只是针对以上例子的特殊情况,比如:google.com不等于http://www.google.com)
(2)在替换href时,我们用相对地址就行了。$(this).attr("href","/resources/web/forms/email/?to="+address);(这里只能解决text跟href相同的情况,不能解决a链接的text里面没有标签元素,同时以www.开头,或者包含@字符的情况)
(3)var linkHtml = $(this).html();先把text的值取出来,$(this).attr("href","http://www.pcc.edu/resources/web/forms/email/?to="+address).html(linkHtml);替换了href后,再恢复成原来的text的值。(这里也有问题,如果<a> 元素里面可能不是一段文本,而是一个 <img>,并且这个 <img> 上绑定了事件,那么,再将 innerHTML 写回去时,就会生成新的节点,原来绑定的事件也就失效了。)
司徒正美的书上有另外一个href属性的bug,在IE6-8下,链接地址:http://oldj.net/article/ie-bug-at-href-innerhtml/,我的理解是:
<a id="a-test" href="http://www.taobao.com">链接@BABY</a>
setTimeout(function () {
var a = document.getElementById("a-test");
a.href = "http://rate.taobao.com/";
}, 3000);
页面打开时,链接的内容为“链接@BABY”,一切正常,但当 js 函数执行,修改了 <a> 元素的 href 属性时,它的 innerHTML 值也变成了同样的值(http://rate.taobao.com/)。除了直接给 a.href 赋值外,使用 a.setAttribute 方法也是一样的效果。
解决办法:
var a = document.getElementById("a-test"), s;
s = a.innerHTML; // 先记下 innerHTML
a.href = "http://rate.taobao.com/";
a.innerHTML = s; // 再将 innerHTML 的值写回去
上面那种先记下 innerHTML 的值,修改 href 之后再将它写回去的做法是有隐患的。比如,<a> 元素里面可能不是一段文本,而是一个 <img>,并且这个 <img> 上绑定了事件,那么,再将 innerHTML 写回去时,就会生成新的节点,原来绑定的事件也就失效了。
一个更好的方法,只需在要写入的 href 的值前面加一个半角空格即可,而现代浏览器会安全地忽略掉 href 值前后的多余的空白字符。即:
a.href = " " + "http://rate.taobao.com/";
或者:
a.href = " http://rate.taobao.com/"; // 注意前面的空格
在 href 前面加一个空格的方式副作用太多,最后决定使用先加一个 <b></b> 节点然后再删除的方法。
var b,
inner_html = anchor.innerHTML;
if (inner_html && inner_html.indexOf("<") == -1) { //如果a链接有值,并且它的innerHTML没有标签(子元素节点),就创建一个子节点
b = doc.createElement("b");
b.style.display = "none";
anchor.appendChild(b);
}
anchor.href = href;
if (b) {
anchor.removeChild(b);
}
上面代码的意思是:如果a标签的值里面包含其他元素节点,那么改变它的href属性值时,不会改变a标签的值。
进一步测试发现,如果a标签没有子元素, <a> 链接的内容(值)以“www.”开头,也会有这个问题。
总结以上所有讨论,得到chaojidan的结论:
在a标签没有子元素的情况下,凡是形如电子邮件(包含“@”字符)或网址(以“www.”开头)的字符串,在 IE6/7/8 中都有这种行为。同时,如果a链接的href属性值和a链接的text值相同,也会出现这样的行为。
以上属于超级变态,了解就行。
value的操作
select元素,它的value值就是其被选中的option孩子的value值。不过,select有两种形态。一种type为select-one,一种是select-multiple。option元素,它的value值可以使value属性的值,也可以是其中间文本的值。当用户没有显式设置value属性时,就可以使用其文本的值。取文本可以使用text,或者innerHTML这两种方法,但是option元素的text属性会做trim操作,支持所有浏览器。但只有旧版本的IE,在innerHTML会做trim操作,标准浏览器不会。如何判定option设置了value属性,IE6-7可以使用specified,标准浏览器使用hasAttribute来判定,具体操作请看上一课.
button,它的取值在IE6-7下是取它的text,IE8以及以上IE浏览器才会取value属性的值。标准浏览器,button标签只有当其为提交按钮,(type = submit)时,点击按钮,才会提交其value属性的值。
在safari5下,如果设置了select为disable,那么它的所有孩子都是disable的。
checkbox的value属性值默认为on,只有chrome是空字符串。
在旧版本IE下,form表reset后,select中的option不会改变为默认的selected值。举个例子:默认情况下,select的第一个option有selected属性,就代表第一个option显示在select中。当你做了操作后,把第二个option变成了selected,这时select中显示的是第二个option。这时你点击reset按钮,恢复默认值。在IE旧版本下,select中的option不会把selected值赋给第一个option,恢复默认。而不做任何改变,还是在第二个option中。但是其他浏览器就会恢复默认值,显示在第一个option中。
加油!
第二十一课:js属性操作的兼容性问题的更多相关文章
- NeHe OpenGL教程 第二十一课:线的游戏
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- [妙味JS基础]第一课:属性操作、图片切换、短信发送模拟
知识点总结 HTML的属性操作:读.写 元素.属性名 => “读” 元素.属性名=新的值 => “写” 例如: oBtn.value => “读” oBtn.value='按钮' = ...
- JS属性操作
一.属性读操作:元素.属性名 ( 获取.找到属性值 ) 属性写操作:元素.属性名 = 新的值 ( 替换.修改属性值 ) 二.没有属性名的,也可进行读.写操作: 读操作:元素.innerHTML ...
- 快学Scala 第二十一课 (初始化trait的抽象字段)
初始化trait的抽象字段: trait Logged { println("Logged constructor") def log(msg: String){ println( ...
- Python学习第二十一课——Mysql 对数据库的基本操作
数据库操作(DDL) 在数据库下创建表(create_table) 创建表代码块: CREATE TABLE employee( id TINYINT PRIMARY KEY auto_increme ...
- 潭州课堂25班:Ph201805201 django 项目 第二十一课 文章主页 新闻列表页面功能 (课堂笔记)
新闻列表页功能 1.分析 业务处理流程: 判断前端传的标签分类id是否为空,是否为整数.是否超过范围 判断前端传的当前文章页数是否为空,是否为整数.是否超过范围 请求方法:GET url定义:/new ...
- python第二十一课——str中的常用函数(重要)
演示str中常用的一些函数: 1.join():将容器对象以某种特定的格式(字符串)进行拼接组合,最后以字符串的形式返回 lt=['i','love','you','very','much'] str ...
- Spring入门第二十一课
切面优先级 先看代码: package logan.study.aop.impl; public interface ArithmeticCalculator { int add(int i, int ...
- JAVA学习第二十一课(多线程(一)) - (初步了解)
放假在家,歇了好几天了,也没学习,今天学习一下多线程.找找感觉.后天就要回学校了.sad... PS:包 没有什么技术含量,会用就可以,日后开发就必需要会用啦,所以打算先放一放,先来多线程 一.多线程 ...
随机推荐
- 有用的MySQL语句
摘自onefish资料库 1. 计算年数你想通过生日来计算这个人有几岁了. SELECT DATE_FORMAT(FROM_DAYS(TO_DAYS(now()) - TO_DAYS(@dateofb ...
- Xamarin.Android splash页面瞬间响应_避免APP启动闪白屏
Application和Activity中的onCreate都进行了优化,基本没有耗时操作,但是启动应用之后还是会闪现一下白色背景,然后才进入Splash页面,对比了一下QQ.微信.微博等客户端,点击 ...
- redis master配置了密码进行主从同步
1.如果master不设置密码,那么直接在slave服务器配置slaveof即可 配置如下 #slaveof ip 端口 slaveof 配置好我们看下redis的日志 看是否同步成功 :S Jan ...
- 原始的2文件的makefile错误
从来没系统的看过makefile文档,平时属于复制模板,用完即忘,下午尝试按自己的理解写一个最简单的makefile,含2个.c文件,1个.h文件,费了个把小时,参考别人的文章才弄出来,特记录. ma ...
- HFSS 边界条件
Ansoft HFSS求解就是对微分形式的麦克斯韦方程采取有限元方法进行数值求解,在场矢量和导数是都单值.有界而且沿空间连续分布的假设下,这些方程才可以使用.在边界和场 源处,场是不连续的,场的导数变 ...
- Ubuntu 14.04 LTS Server 无法挂载光盘 启动initramfs等问题
今天需要在戴尔R410服务器上装64位的Linux,师兄给了个14.04的server 64位镜像.一开始打算用U盘安装,用软碟通烧写镜像之后,在服务器端设置从U盘启动,但是安装到一半出现了光盘无法挂 ...
- 【Javascript Demo】移动端访问PC端网页时跳转到对应的移动端网页
不想通过CSS自适应在PC端和移动端分别显示不同的样式,那么只能通过在移动端访问PC端网页时跳转到对应的移动端网页了,那么怎么跳转呢,网上也有很多文章说明,下面是本人测试有效的方式. 1.效果图 PC ...
- HDU 5047 推公式+别样输出
题意:给n个‘M'形,问最多能把平面分成多少区域 解法:推公式 : f(n) = 4n(4n+1)/2 - 9n + 1 = (8n+1)(n-1)+2 前面部分有可能超long long,所以要转化 ...
- AC日记——热浪 codevs 1557 (最短路模板题)
1557 热浪 时间限制: 1 s 空间限制: 256000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 题目描述 Description 德克萨斯纯朴的民眾们这个夏 ...
- cotangent Laplacian
几何网格处理经常用到 cotangent laplacian矩阵.前几天把这个功能整合到我的Maya 转 Matlab插件了. 这里发一个利用cotangent laplacian计算特征向量并显示的 ...