上一课主要讲了属性的概念,用法,固有属性和自定义属性的区别,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属性操作的兼容性问题的更多相关文章

  1. NeHe OpenGL教程 第二十一课:线的游戏

    转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...

  2. [妙味JS基础]第一课:属性操作、图片切换、短信发送模拟

    知识点总结 HTML的属性操作:读.写 元素.属性名 => “读” 元素.属性名=新的值 => “写” 例如: oBtn.value => “读” oBtn.value='按钮' = ...

  3. JS属性操作

    一.属性读操作:元素.属性名   ( 获取.找到属性值 ) 属性写操作:元素.属性名 = 新的值   ( 替换.修改属性值 ) 二.没有属性名的,也可进行读.写操作: 读操作:元素.innerHTML ...

  4. 快学Scala 第二十一课 (初始化trait的抽象字段)

    初始化trait的抽象字段: trait Logged { println("Logged constructor") def log(msg: String){ println( ...

  5. Python学习第二十一课——Mysql 对数据库的基本操作

    数据库操作(DDL) 在数据库下创建表(create_table) 创建表代码块: CREATE TABLE employee( id TINYINT PRIMARY KEY auto_increme ...

  6. 潭州课堂25班:Ph201805201 django 项目 第二十一课 文章主页 新闻列表页面功能 (课堂笔记)

    新闻列表页功能 1.分析 业务处理流程: 判断前端传的标签分类id是否为空,是否为整数.是否超过范围 判断前端传的当前文章页数是否为空,是否为整数.是否超过范围 请求方法:GET url定义:/new ...

  7. python第二十一课——str中的常用函数(重要)

    演示str中常用的一些函数: 1.join():将容器对象以某种特定的格式(字符串)进行拼接组合,最后以字符串的形式返回 lt=['i','love','you','very','much'] str ...

  8. Spring入门第二十一课

    切面优先级 先看代码: package logan.study.aop.impl; public interface ArithmeticCalculator { int add(int i, int ...

  9. JAVA学习第二十一课(多线程(一)) - (初步了解)

    放假在家,歇了好几天了,也没学习,今天学习一下多线程.找找感觉.后天就要回学校了.sad... PS:包 没有什么技术含量,会用就可以,日后开发就必需要会用啦,所以打算先放一放,先来多线程 一.多线程 ...

随机推荐

  1. ubuntu自带的gedit编辑器添加Markdown预览插件

    gedit安装Markdown Preview Ubuntu自带的gedit编辑器也是有很强大的功能的,且支持插件的安装.对于喜欢用Markdown的我来说,这当然是很好的了,gedit本身 就支持M ...

  2. Vertica 项目常用代码

    1.查看目录下面有多少文件数 ls -l |grep "^-"|wc -l 思路很明显了,ls后通过grep进行过滤判断是文件还是文件夹, 如果是判断文件夹,可以使用ls -l | ...

  3. RCNN (Regions with CNN) 目标物检测 Fast RCNN的基础

    Abstract: 贡献主要有两点1:可以将卷积神经网络应用region proposal的策略,自底下上训练可以用来定位目标物和图像分割 2:当标注数据是比较稀疏的时候,在有监督的数据集上训练之后到 ...

  4. 边工作边刷题:70天一遍leetcode: day 71-1

    Longest Substring with At Most K Distinct Characters 要点:要搞清楚At Most Two Distinct和Longest Substring W ...

  5. CSS强制性换行word-break与word-wrap的使用

    一般情况下,元素拥有默认的white-space:normal(自动换行,不换行是white-space:nowrap),当录入的文字超过定义的宽度后会自动换行,但当录入的数据是一堆没有空格的字符或字 ...

  6. C++中不能声明为虚函数的有哪些函数

    常见的不不能声明为虚函数的有:普通函数(非成员函数):静态成员函数:内联成员函数:构造函数:友元函数. 1.为什么C++不支持普通函数为虚函数? 普通函数(非成员函数)只能被overload,不能被o ...

  7. C#泛型简化代码量示例

    泛型简化代码量 下是我在项目中通过泛型来简化工作的一个Demo,记录一下: using System; using System.Collections.Generic;   namespace My ...

  8. Linux由管道组成的值得学习的命令

    1.Linux查找不以#开头的行的命令如:cat /etc/vsftpd/vsftpd.conf | grep -v "#"

  9. java 8-5 抽象

    1. 抽象类的概述: 动物不应该定义为具体的东西,而且动物中的吃,睡等也不应该是具体的. 我们把一个不是具体的功能称为抽象的功能,而一个类中如果有抽象的功能,该类必须是抽象类. 抽象类的特点: A:抽 ...

  10. C语言 百炼成钢11

    //题目31:请输入星期几的第一个字母来判断一下是星期几,如果第一个字母一样,则继续 //判断第二个字母. #define _CRT_SECURE_NO_WARNINGS #include<st ...