元素(类似于 getElementsByTagName("em"))
var ems = document.getElementById("myDiv").querySelectorAll("em");
//取得类为"selected"的所有元素
var selecteds = document.querySelectorAll(".selected");
//取得所有元素中的所有元素
var strongs = document.querySelectorAll("p strong");
//要取得返回的 NodeList 中的每一个元素,可以使用 item()方法,也可以使用方括号语法,比如:
var i, len, strong;
for (i=0, len=strongs.length; i < len; i++){
strong = strongs[i]; //或者 strongs.item(i)
strong.className = "important";
}
```
**3.元素遍历**
Element Traversal API 为 DOM 元素添加了以下 5 个属性。
- childElementCount:返回子元素(不包括文本节点和注释)的个数。
- firstElementChild:指向第一个子元素; firstChild 的元素版。
- lastElementChild:指向最后一个子元素; lastChild 的元素版。
- previousElementSibling:指向前一个同辈元素; previousSibling 的元素版。
- nextElementSibling:指向后一个同辈元素; nextSibling 的元素版。
**支持的浏览器为 DOM 元素添加了这些属性,利用这些元素不必担心空白文本节点。**
**4.getElementsByClassName()方法**
```javascript
//取得所有类中包含"username"和"current"的元素,类名的先后顺序无所谓
var allCurrentUsernames = document.getElementsByClassName("username current");
//取得 ID 为"myDiv"的元素中带有类名"selected"的所有元素
var selected = document.getElementById("myDiv").getElementsByClassName("selected");
```
**5.classList 属性**
classList 属性是新集合类型 DOMTokenList 的实例。与其他 DOM 集合类似,OMTokenList 有一个表示自己包含多少元素的 length 属性,而要取得每个元素可以使用 item()方法,也可以使用方括号语法。此外,这个新类型还定义如下方法。
- add(value):将给定的字符串值添加到列表中。如果值已经存在,就不添加了。
- contains(value):表示列表中是否存在给定的值,如果存在则返回 true,否则返回 false。
- remove(value):从列表中删除给定的字符串。
- toggle(value):如果列表中已经存在给定的值,删除它;如果列表中没有给定的值,添加它。
```javascript
...
//删除"disabled"类
div.classList.remove("disabled");
//添加"current"类
div.classList.add("current");
//切换"user"类
div.classList.toggle("user");
//确定元素中是否包含既定的类名
if (div.classList.contains("bd") && !div.classList.contains("disabled")){
//执行操作
)
//迭代类名
for (var i=0, len=div.classList.length; i < len; i++){
doSomething(div.classList[i]);
}
```
**6. 焦点管理**
```javascript
var button = document.getElementById("myButton");
button.focus();
alert(document.activeElement === button); //true
var button = document.getElementById("myButton");
button.focus();
alert(document.hasFocus()); //true
```
**7.readyState 属性**
```javascript
//loading,正在加载文档;
//complete,已经加载完文档。
if (document.readyState == "complete"){
//执行操作
}
```
**8.自定义属性**
```javascript
//本例中使用的方法仅用于演示
var div = document.getElementById("myDiv");
//取得自定义属性的值
var appId = div.dataset.appId;
var myName = div.dataset.myname;
//设置值
div.dataset.appId = 23456;
div.dataset.myname = "Michael";
//有没有"myname"值呢?
if (div.dataset.myname){
alert("Hello, " + div.dataset.myname);
}
```
**9.innerHTML 属性 和 outerHTML 属性**
在读模式下, **innerHTML** 属性返回与调用元素的所有子节点(包括元素、注释和文本节点)对应的 HTML 标记。在写模式下, innerHTML 会根据指定的值创建新的 DOM 树,然后用这个 DOM 树完全替换调用元素原先的所有子节点。下面是一个例子。
在读模式下, **outerHTML** 返回调用它的元素及所有子节点的 HTML 标签。在写模式下, outerHTML会根据指定的 HTML 字符串创建新的 DOM 子树,然后用这个 DOM 子树完全替换调用元素。
**10.insertAdjacentHTML()方法**
- "**beforebegin**",在当前元素之前插入一个紧邻的同辈元素;
- "**afterbegin**",在当前元素之下插入一个新的子元素或在第一个子元素之前再插入新的子元素;
- "**beforeend**",在当前元素之下插入一个新的子元素或在最后一个子元素之后再插入新的子元素;
- "**afterend**",在当前元素之后插入一个紧邻的同辈元素。
```javascript
//作为前一个同辈元素插入
element.insertAdjacentHTML("beforebegin", "Hello world!
");
//作为第一个子元素插入
element.insertAdjacentHTML("afterbegin", "Hello world!
");
//作为最后一个子元素插入
element.insertAdjacentHTML("beforeend", "Hello world!
");
//作为后一个同辈元素插入
element.insertAdjacentHTML("afterend", "Hello world!
");
```
**11.滚动**
**scrollIntoView()** :可以在所有 HTML 元素上调用,通过滚动浏览器窗口或某个容器元素,调用元素就可以出现在视口中。如果给这个方法传入 true 作为参数,或者不传入任何参数,那么窗口滚动之后会让调用元素的顶部与视口顶部尽可能平齐。如果传入 false 作为参数,调用元素会尽可能全部出现在视口中,(可能的话,调用元素的底部会与视口顶部平齐。)不过顶部不一定平齐。
**scrollIntoViewIfNeeded(alignCenter)** :只在当前元素在视口中不可见的情况下,才滚动浏览器窗口或容器元素,最终让它可见。如果当前元素在视口中可见,这个方法什么也不做。如果将可选的 alignCenter 参数设置为 true,则表示尽量将元素显示在视口中部(垂直方向)。Safari 和 Chrome 实现了这个方法。
**scrollByLines(lineCount):**将元素的内容滚动指定的行高, lineCount 值可以是正值,也可以是负值。 Safari 和 Chrome 实现了这个方法。
**scrollByPages(pageCount):**将元素的内容滚动指定的页面高度,具体高度由元素的高度决定。 Safari 和 Chrome 实现了这个方法。
```javascript
//让元素可见
document.forms[0].scrollIntoView();
//将页面主体滚动 5 行
document.body.scrollByLines(5);
//在当前元素不可见的时候,让它进入浏览器的视口
document.images[0].scrollIntoViewIfNeeded();
//将页面主体往回滚动 1 页
document.body.scrollByPages(-1);
```
**12.contains()方法**
判断某个节点是不是另一个节点的后代。
```javascript
alert(document.documentElement.contains(document.body)); //true
```
## 第十二章 DOM2和DOM3
**1.偏移量、客户区大小、滚动大小**
## 第十三 事件
### 13.1 DOM事件流
“DOM2级事件”规定的事件流包括三个阶段:事件捕获阶段、处于目标阶段和事件冒泡阶段。首先发生的是事件捕获,为截获事件提供了机会。然后是实际的目标接收到事件。最后一个阶段是冒泡阶段,可以在这个阶段对事件做出响应。
### 13.2 事件处理程序
#### 1. DOM0 级事件处理程序
使用 DOM0 级方法指定的事件处理程序被认为是元素的方法。因此,这时候的事件处理程序是在元素的作用域中运行;换句话说,程序中的 this 引用当前元素。
```javascript
// 绑定事件
var btn = document.getElementById("myBtn");
btn.onclick = function(){
alert(this.id); //"myBtn"
};
btn.onclick = null; //删除事件处理程序
```
#### 2. DOM2 级事件处理程序
“DOM2 级事件” 定义了两个方法,用于处理指定和删除事件处理程序的操作: addEventListener()和 removeEventListener()。所有 DOM 节点中都包含这两个方法,并且它们都接受 3 个参数:要处理的事件名、作为事件处理程序的函数和一个布尔值。最后这个布尔值参数如果是 true,表示在捕获阶段调用事件处理程序;如果是 false,表示在冒泡阶段调用事件处理程序。 **使用 DOM2 级方法添加事件处理程序的主要好处是可以添加多个事件处理程序。**
```javascript
var btn = document.getElementById("myBtn");
btn.addEventListener("click", function(){
alert(this.id);
}, false);
btn.addEventListener("click", function(){
alert("Hello world!");
}, false);
btn.removeEventListener("click", function(){ //没有用!
alert(this.id);
}, false);
//有效解绑
var btn = document.getElementById("myBtn");
var handler = function(){
alert(this.id);
};
btn.addEventListener("click", handler, false);
//这里省略了其他代码
btn.removeEventListener("click", handler, false); //有效
```
#### 3.兼容IE
```javascript
var EventUtil = {
addHandler: function(element, type, handler){
if (element.addEventListener){
element.addEventListener(type, handler, false);
} else if (element.attachEvent){
element.attachEvent("on" + type, handler);
} else {
element["on" + type] = handler;
}
},
removeHandler: function(element, type, handler){
if (element.removeEventListener){
element.removeEventListener(type, handler, false);
} else if (element.detachEvent){
element.detachEvent("on" + type, handler);
} else {
element["on" + type] = null;
}
}
};
```
### 13.3 事件处理程序
兼容 DOM 的浏览器会将一个 event 对象传入到事件处理程序中。无论指定事件处理程序时使用什么方法(DOM0 级或 DOM2 级),都会传入 event 对象。
```javascript
var btn = document.getElementById("myBtn");
btn.onclick = function(event){
alert(event.type); //"click"
};
btn.addEventListener("click", function(event){
alert(event.type); //"click"
}, false);
```
event 对象包含与创建它的特定事件有关的属性和方法。触发的事件类型不一样,可用的属性和方法也不一样。不过,所有事件都会有下表列出的成员。
| 属性/方法 | 类 型 | 读/写 | 说 明 |
| :------------------------: | :----------: | :---: | :----------------------------------------------------------- |
| target | Element | 只读 | 事件的目标 |
| bubbles | Boolean | 只读 | 表明事件是否冒泡 |
| cancelable | Boolean | 只读 | 表明是否可以取消事件的默认行为 |
| currentTarget | Element | 只读 | 其事件处理程序当前正在处理事件的那个元素 |
| defaultPrevented | Boolean | 只读 | 为 true 表 示 已 经 调 用 了 preventDefault()(DOM3级事件中新增) |
| detail | Integer | 只读 | 与事件相关的细节信息 |
| eventPhase | Integer | 只读 | 调用事件处理程序的阶段: 1表示捕获阶段, 2表示“处于目标”, 3表示冒泡阶段 |
| preventDefault() | Function | 只读 | 取 消 事 件 的 默 认 行 为 。 如 果 cancelable是true,则可以使用这个方法 |
| stopImmediatePropagation() | Function | 只读 | 取消事件的进一步捕获或冒泡,同时阻止任何事件处理程序被调用(DOM3级事件中新增) |
| stopPropagation() | Function | 只读 | 取消事件的进一步捕获或冒泡。如果bubbles为true,则可以使用这个方法 |
| trusted | Boolean | 只读 | 为true表示事件是浏览器生成的。为false表示 事 件 是 由 开 发 人 员 通 过 JavaScript 创 建 的(DOM3级事件中新增) |
| type | String | 只读 | 被触发的事件的类型 |
| view | AbstractView | 只读 | 与事件关联的抽象视图。等同于发生事件的window对象 |
```javascript
//点击myBtn元素
var btn = document.getElementById("myBtn");
btn.onclick = function(event){
alert(event.currentTarget === this); //true
alert(event.target === this); //true
};
document.body.onclick = function(event){
alert(event.currentTarget === document.body); //true
alert(this === document.body); //true
alert(event.target === document.getElementById("myBtn")); //true
};
//阻止默认行为
var link = document.getElementById("myLink");
link.onclick = function(event){
event.preventDefault();
};
//阻止冒泡
var btn = document.getElementById("myBtn");
btn.onclick = function(event){
alert("Clicked");
event.stopPropagation();
};
```
事件对象的 eventPhase 属性,可以用来确定事件当前正位于事件流的哪个阶段。如果是在捕获阶段调用的事件处理程序,那么 eventPhase 等于 1;如果事件处理程序处于目标对象上,则 eventPhase 等于 2;如果是在冒泡阶段调用的事件处理程序,eventPhase 等于 3。这里要注意的是,尽管“处于目标”发生在冒泡阶段,但 eventPhase 仍然一直等于 2。
```javascript
var btn = document.getElementById("myBtn");
btn.onclick = function(event){
alert(event.eventPhase); //2
};
document.body.addEventListener("click", function(event){
alert(event.eventPhase); //1
}, true);
document.body.onclick = function(event){
alert(event.eventPhase); //3
};
```
### 13.4 事件类型
#### 1.UI 事件
UI 事件指的是那些不一定与用户操作有关的事件。这些事件在 DOM 规范出现之前,都是以这种或那种形式存在的,而在 DOM 规范中保留是为了向后兼容。现有的 UI 事件如下。
- **load**:当页面完全加载后在 window 上面触发,当所有框架都加载完毕时在框架集上面触发,当图像加载完毕时在\
元素上面触发,或者当嵌入的内容加载完毕时在\