第二十一课: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大小写问题
以前做企业项目的时候,用的都是oracle数据库,在新公司项目用的是mysql,有关mysql大小写的问题 1 windows下默认mysql是不区分大小写的,要想让其支持大小写.更改方法 在my ...
- folly
一.简介 Folly是,Facebook于2012年6月初开源的一个基于C++11的C++组件库,提供了类似Boost库和std库的功能,包括散列.字符串.向量.内存分配.位处理等,以满足大规模高性能 ...
- 《TCP/IP详解 卷一》读书笔记-----第三章 IP
1.Network byte order:数据在网络中的传输是按照大端模式来的,即如果需要传递一个四个字节的int变量,先传递最高的字节,然后依次类推.因此无论主机存储数据用的是大端模式还是小端模式, ...
- 边工作边刷题:70天一遍leetcode: day 82
Closest Binary Search Tree Value 要点: https://repl.it/CfhL/1 # Definition for a binary tree node. # c ...
- 查询各个商品分类中各有多少商品的SQL语句
SELECT goods_category_id ,count(*) FROM `sw_goods` group by goods_category_id
- easyui添加自定义验证规则
$.extend($.fn.validatebox.defaults.rules, { phone: { validator: function (value) { return /^(\d{3,4} ...
- Nginx反向代理+负载均衡简单实现(https方式)
背景:A服务器(192.168.1.8)作为nginx代理服务器B服务器(192.168.1.150)作为后端真实服务器 现在需要访问https://testwww.huanqiu.com请求时从A服 ...
- Redis缓存数据库详解
Redis最为常用的数据类型主要有以下五种: 1)String 2)Hash 3)List 4)Set 5)Sorted set 在具体描述这几种数据类型之前,我们先通过一张图了解下Redis内部内存 ...
- Windows客户端C/C++编程规范“建议”——风格
本文来自:http://blog.csdn.net/breaksoftware/article/details/37935459 命名风格也非常适用于C# 9 风格 9.1 优先使用匈牙利命名法 等级 ...
- 呵呵!手把手带你在 IIS 上运行 Python(转)
原文:http://blog.csdn.net/yangzhencheng_001/article/details/40342449 公司的网站让我头痛死了.在众多前辈高手的带领下,一大堆的 CMD ...