0%

align-self

CSS属性 align-self 会对齐当前 grid 或 flex 行中的元素,并覆盖已有的 align-items 的值。In Grid, it aligns the item inside the grid area. 在 Flexbox 中,会按照 cross axis(当前 flex 元素排列方向的垂直方向)进行排列。

auto:设置为父元素的 align-items 值。

normal:

效果取决于当前的布局模式:

  • 绝对定位布局中,normal在绝对定位的替代元素上表现为start,在所有其他绝对定位元素上表现为stretch

  • 在绝对定位的静态元素上表现为stretch

  • flex布局中表现为stretch。

  • 在网格布局中表现为stretch,除了有部分比例或者一个固定大小的盒子的效果像start

  • 在块级和表格单元中无效。

flex-start:对齐到cross-axis的首端

flex-end:对齐到cross-axis的尾端

center:对齐到cross-axis的中间,如果该元素的 cross-size 尺寸大于 flex 容器,将在两个方向均等溢出。

safe:如果元素大小溢出对齐的容器,则将元素改为对齐,就像start

unsafe:无论元素和对齐容器的相对大小如何都遵循给定的对齐值

eg

HTML

1
2
3
4
5
6
7
8
9
10
11
<section>
<div>
Item#1
</div>
<div>
Item#2
</div>
<div>
Item#3
</div>
</section>

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
section {
display: flex;
align-items: center;
height: 120px;
background: beige;
}

div {
height: 60px;
background: cyan;
margin: 5px;
}

div:nth-child(3) {
align-self: flex-end;
background: pink;
}

align-items

CSS align-items属性将所有直接子节点上的align-self值设置为一个组。 目前,Flexbox和CSS网格布局支持此属性。在Flexbox中,它控制十字轴上项目的对齐方式,在网格布局中,它控制块轴上项目的对齐方式。

align-content

align-content 属性设置了浏览器如何沿着弹性盒子布局的纵轴和网格布局的主轴在内容项之间和周围分配空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/* 基本位置对齐 */
/*align-content不采用左右值 */
align-content: center; /* 将项目放置在中点 */
align-content: start; /* 最先放置项目 */
align-content: end; /* 最后放置项目 */
align-content: flex-start; /* 从起始点开始放置flex元素 */
align-content: flex-end; /* 从终止点开始放置flex元素 */

/* 默认对齐 */
align-content: normal;

/*基线对齐*/
align-content: baseline;
align-content: first baseline;
align-content: last baseline;

/* 分布式对齐 */
align-content: space-between; /* 均匀分布项目
第一项与起始点齐平,
最后一项与终止点齐平 */
align-content: space-around; /* 均匀分布项目
项目在两端有一半大小的空间*/
align-content: space-evenly; /* 均匀分布项目
项目周围有相等的空间 */
align-content: stretch; /* 均匀分布项目
拉伸‘自动’-大小的项目以充满容器 */

/* 溢出对齐 */
align-content: safe center;
align-content: unsafe center;

/* 全局属性 */
align-content: inherit; /* 继承 */
align-content: initial; /* 初始值 */
align-content: unset; /* 未设置 */

justify-items

justify-items 属性为所有盒中的项目定义了默认的 justify-self , 可以使这些项目以默认方式沿适当轴线对齐到每个盒子。

justify-content

justify-content 属性定义了浏览器之间,如何分配顺着弹性容器主轴(或者网格行轴) 的元素之间及其周围的空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/* Positional alignment */
justify-content: center; /* 居中排列 */
justify-content: start; /* Pack items from the start */
justify-content: end; /* Pack items from the end */
justify-content: flex-start; /* 从行首起始位置开始排列 */
justify-content: flex-end; /* 从行尾位置开始排列 */
justify-content: left; /* Pack items from the left */
justify-content: right; /* Pack items from the right */

/* Baseline alignment */
justify-content: baseline;
justify-content: first baseline;
justify-content: last baseline;

/* Distributed alignment */
justify-content: space-between; /* 均匀排列每个元素
首个元素放置于起点,末尾元素放置于终点 */
justify-content: space-around; /* 均匀排列每个元素
每个元素周围分配相同的空间 */
justify-content: space-evenly; /* 均匀排列每个元素
每个元素之间的间隔相等 */
justify-content: stretch; /* 均匀排列每个元素
'auto'-sized 的元素会被拉伸以适应容器的大小 */

/* Overflow alignment */
justify-content: safe center;
justify-content: unsafe center;

/* Global values */
justify-content: inherit;
justify-content: initial;
justify-content: unset;

justify-self

[justify-self 在 Flexbox布局中失效]

在主轴上,Flexbox将我们的内容作为一个组进行处理。 计算布置子元素所需的空间量,然后剩余空间可用于分配。 justify-content属性控制剩余空间的使用方式。 设置justify-content:flex-end,额外空间放在所有子元素之前,justify-content:space-around,它放在该维度的子元素的两侧,等等。

这意味着在Flexbox中,justify-self属性没有意义,因为我们总是处理移动整个元素组。

在十字轴上,align-self是有意义的,因为我们可能在该维度中的flex容器中有额外的空间,其中单个元素可以移动到开始和结束位置。

富文本编辑

在空白 HTML 文件中嵌入一个iframe。通过 designMode 属性,可以将这个空白文档变成可以编辑的,实际编辑的则是元素
的 HTML。designMode 属性有两个可能的值:”off”(默认值)和”on”。设置为”on”时

富文本交互

使用 document.execCommand()。这个方法在文档上执行既定
的命令,可以实现大多数格式化任务。document.execCommand()可以接收 3 个参数:要执行的命令、表示浏览器是否为命令提供用户界面的布尔值和执行命令必需的值

1
2
3
4
5
6
7
8
9
10
// 在内嵌窗格中切换粗体文本样式
frames["richedit"].document.execCommand("bold", false, null);
// 在内嵌窗格中切换斜体文本样式
frames["richedit"].document.execCommand("italic", false, null);
// 在内嵌窗格中创建指向 www.wrox.com 的链接
frames["richedit"].document.execCommand("createlink", false,
"http://www.wrox.com");
// 在内嵌窗格中为内容添加<h1>标签
frames["richedit"].document.execCommand("formatblock", false, "<h1>");

富文本选择

在内嵌窗格中使用 getSelection()方法,可以获得富文本编辑器的选区。这个方法暴露在document 和 window 对象上,返回表示当前选中文本的 Selection 对象

1
2
3
4
5
6
7
8
9
10
let selection = frames["richedit"].getSelection();
// 取得选中的文本
let selectedText = selection.toString();
// 取得表示选区的范围
let range = selection.getRangeAt(0);
// 高亮选中的文本
let span = frames["richedit"].document.createElement("span");
span.style.backgroundColor = "yellow";
range.surroundContents(span);

通过表单提交富文本

1
2
3
4
5
form.addEventListener("submit",(event)=>{
let target=event.target;
target.elements["comments"].value=frames["richedit"].document.body.innerHTML;//使用内嵌窗格
//target.elements["comments"].value=document.getElementById("richedit").innerHTML;//使用contenteditable
})

表单在js中可以使用表单字段的type属性连同其name属性和value属性来进行序列化

  • 字段名和值是 URL 编码的并以和号(&)分隔。

  • 禁用字段不会发送。

  • 复选框或单选按钮只在被选中时才发送。

  • 类型为”reset”或”button”的按钮不会发送。

  • 多选字段的每个选中项都有一个值。

  • 通过点击提交按钮提交表单时,会发送该提交按钮;否则,不会发送提交按钮。类型为”image”
    元素视同提交按钮。

  • select元素的值是被选中option元素的 value 属性。如果

    返回的结果是查询字符串的格式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
function serialize(form){
let parts=[];
let optValue;
for(let field of form.elements){
switch(field.type){
case "select-one":
case "select-multiple":
if(field.name.length){
for(let option of field.options){
if(option.selected){
if(option.hasAttribute){
optValue=(option.hasAttribute("value")?option.value:option.text);
}else{
optValue=(option.attributes["value"].specified?option.value:option.text);
}
parts.push(`${encodeURIComponent(field.name)}=`+`${encodeURIComponent(optValue)}`);
}
}
}
break;
case undefined://字段集
case "file"://文件输入
case "submit"://提交按钮
case "reset"://重置按钮
case "button"://自定义按钮
break;
case "radio"://单选按钮
case "checkbox"://复选框
if(!field.checked){//没被选中,跳出switch,否则进入default分支,将字段的名字和值编码后添加进parts数组
break;
}
default:
//不包含没有名字的表单字段
if(field.name.length){
parts.push(`${encodeURIComponent(field.name)}=`+`${encodeURIComponent(field.value)}`)
}
}
}
return parts.join("&");
}

DOM编程

动态脚本

1
2
3
4
5
6
7
8
9
10
11
function loadScriptString(code){
var script=document.createElement("script");
script.type="text/javascript";
try{
script.appendChild(document.createTextNode(code));//旧版本的IE浏览器可能出问题
}catch(ex){
script.text=code;
}
document.body.appendChild(script);
}
loadScriptString("function sayHi(){alert('hi');}");

动态样式

1
2
3
4
5
6
7
8
9
10
11
12
function loadStyleString(css){
let style=document.createElement("style");
style.type="text/css";
try{
style.appendChild(document.createTextNode(css));
}catch(ex){
style.styleSheet.cssText=css;
}
let head=document.getElementsByTagName("head")[0];
head.appendChild(style);
}
loadStyleString("body[background-color:red}");

对于IE,要小心使用styleSheet.cssText,如果重用同一个style元素并设置该属性超过一次,则可能导致浏览器崩溃,将cssText设置为空字符串也可能导致浏览器崩溃

表单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
let table=document.createElement("table");
table.border=1;
table.width="100%";
let tbody=document.createElement("tbody");
table.appendChild(tbody);

table.insertRow(0);
tbody.rows[0].insertCell(0);
tbody.rows[0].cells[0].appendChild(document.createTextNode("Cell 1,1"));
tbody.rows[0].insertCell(1);
tbody.rows[0].cells[1].appendChild(document.createTextNode("Cell 2,1"));

table.insertRow(1);
tbody.rows[1].insertCell(0);
tbody.rows[1].cells[0].appendChild(document.createTextNode("Cell 1,2"));
tbody.rows[1].insertCell(1);
tbody.rows[1].cells[1].appendChild(document.createTextNode("Cell 2,2"));

document.body.appendChild(table);

NodeList

1
2
3
4
5
let divs=document.getElementsByTagName("div");
for(let i=0,len=divs.length;i<len;i++){
let div=doocument.createElement("div");
document.body.appendChild(div);
}//避免导致无穷循环

Mutationobserver接口

在DOM被修改时异步执行回调,使用MutationObserver可以观察整个文档,DOM树的一部分或某个元素

MutationObserver的实例通过调用MutationObserver构造函数并传入一个回调函数创建

1
let observer=new MutationObserver(()=>console.log('DOM was mutated'));

observe()方法

接收两个参数:要观察其变化的DOM节点,以及一个MutationObserverInit对象(用于控制观察哪些方面的变化,是一个键值对形式配置选项的字典)

1
2
let observer=new MutationObserver(()=>console.log('<body> attributes changed'));
observer.observe(document.body,{attributes:true});

body元素上任何属性发生变化都会被这个MutationObserver实例发现,然后异步执行注册的回调函数,body元素后代修改或其他非属性修改不会触发回调进入任务

1
2
3
4
5
6
let observer=new MutationObserver(()=>console.log('<body> attributes changed'));
observer.observe(document.body,{attributes:true});
document.body.className='foo';
console.log('Changed body class');
//Changed body class
//<body> attributes changed

回调与MutationRecord

每次回调都会收到一个MutationRecord实例的数组,包含的信息发生了什么变化以及DOM哪一部分受到影响

1
2
3
4
5
6
7
8
9
let observer=new MutationObserver((mutationRecords)=>console.log(mutationRecords));[
observer.observe(document.body,{attributes:true});
document.body.setAttributeNS('foo','bar','baz');
//连续修改多个MutationRecord实例,回调函数就会受到包含这些实例的数组,顺序为变化事件的顺序
let observer=new MutationObserver((mutationRecords)=>console.log(mutationRecords));
observer.observe(document.body,{attributes:true});
document.body.className='foo';
document.body.className='bar';
//[MutationRecord, MutationRecord]

disconnect()方法

会停止此后变化事件的回调,也会抛弃已经加入任务队列要异步执行的回调

1
2
3
4
5
6
7
8
9
10
11
let observer=new MutationObserver(()=>console.log('<body>attributes changed'));
observer.observe(document.body,{attributes:true});
document.body.className='foo';
observer.disconnect();
document.body.className='bar';//无日志输出
//让已经入队的回调函数执行完毕后再调用disconnect()
setTimeout(()=>{
observer.disconnect();
document.body.className='bar';

},0);

复用MutationObserver

1
2
3
4
5
6
7
8
9
10
let observer=new MutationObserver((mutationRecords)=>console.log(mutationRecords.map((x)=>x.target)));
let childA=document.createElement('div');
childB=document.createElement('span');
document.body.appendChild(childA);
document.body.appendChild(childB);
observer.observe(childA,{attributes:true});
observer.observe(childB,{attributes:true});
childA.setAttribute('foo','bar');
childB.setAttribute('foo','bar');
//[div, span]

重用MutationObserver

调用diaconnect()不会结束MutationObserver的生命,还可以重新使用这个观察者,再将它关联到新的目标结点

MutationObserverInit与观察范围

观察属性

设置attributes为true,观察所有属性

1
2
3
4
5
6
7
8
9
let observer=new MutationObserver((mutationRecords)=>console.log(mutationRecords));
observer.observe(document.body,{attributes:true});
//添加属性
document.body.setAttribute('foo','bar');
//修改属性
document.body.setAttribute('foo','baz');
//移除属性
document.body.removeAttribute('foo');

用attributeFilter添加白名单属性

1
2
3
4
5
6
let observer=new MutationObserver((mutationRecords)=>console.log(mutationRecords));
observer.observe(document.body,{attributeFilter:['foo']});
//添加白名单属性
document.body.setAttribute('foo','bar');
//添加被排除的属性
document.body.setAttribute('baz','qux');

在记录中保存属性原来的值

1
2
3
4
5
6
let observer=new MutationObserver((mutationRecords)=>console.log(mutationRecords.map((x)=>x.oldValue)));
observer.observe(document.body,{attributeOldValue:true});
document.body.setAttribute('foo','bar');
document.body.setAttribute('foo','baz');
document.body.setAttribute('foo','qux');
//[null, 'bar', 'baz']

观察字符数据

1
2
3
4
5
6
7
8
9
10
11
12
13
let observer=new MutationObserver(document.body.firstChild,{characterData:true});
document.body.firstChild.textContent='foo';//创建要观察的文本节点
observer.observe(document.body.firstChild,{characterData:true});
document.body.firstChild.textContent='foo';
document.body.firstChild.textContent='bar';
document.body.firstChild.textContent='baz';
//使用characterDataOldValue
let observer=new MutationObserver((mutationRecords)=>console.log(mutationRecords.map((x)=>x.oldValue)));
document.body.firstChild.textContent='foo';//创建要观察的文本节点
observer.observe(document.body.firstChild,{characterDataOldValue:true});
document.body.firstChild.textContent='foo';
document.body.firstChild.textContent='bar';
document.body.firstChild.textContent='baz';

观察子节点

1
2
3
4
5
6
7
8
document.body.innerHTML='';
let observer=new MutationObserver((mutationRecords)=>console.log(mutationRecords));
//创建两个初始子节点
document.body.appendChild(document.createElement('div'));
document.body.appendChild(document.createElement('span'));
observer.observe(document.body,{childList:true});
document.body.insertBefore(document.body.lastChild,document.body.firstChild);
//发生两次变化,先移除节点再添加节点

观察子树

1
2
3
4
5
document.body.innerHTML='';
let observer=new MutationObserver((mutationRecords)=>console.log(mutationRecords));
document.body.appendChild(document.createElement('div'));
observer.observe(document.body,{attributes:true,subtree:true});
document.body.firstChild.setAttribute('foo','baz');

异步回调与记录队列

takeRecords()方法

清空记录队列,取出并·返回其中的所有MutationRecord实例,可以用在希望断开与观察目标的联系,但又希望处理由于disconnect()而被抛弃的记录队列中的MutationRecord实例

1
2
3
4
5
6
7
8
let observer=new MutationObserver((mutationRecords)=>console.log(mutationRecords));
observer.observe(document.body,{attributes:true});
document.body.className='foo';
document.body.className='bar';
console.log(observer.takeRecords());
console.log(observer.takeRecords());
//[MutationRecord, MutationRecord]
//[]

Node类型

DOM Level 描述为名为Node的接口,Node接口在JavaScript中被实现为Node类型,所有结点都继承Node类型,因此所有类型都共享相同的基本属性和方法。

节点类型可通过与这些常量比较来确定

1
2
3
4
5
6
7
8
//节点类型可通过与这些常量比较确定,如果两者相等,则意味着someNode是一个元素节点
if(someNode.nodeType==Node.ELEMENT_NODE){
alert("Node is an element");
}
//nodeName和nodeValue保存着有关节点的信息
if(someNode.nodeType==1){
value=someNode.nodeName;//会显示元素的标签名
}

节点关系

节点与其他节点的关系可形容为家族关系,每个节点有一个childNodes属性其中包含一个NodeList的实例,NodeList是一个类数组对象,它是DOM结构的查询,DOM结构的变化会自动地在NodeList中反映出来,用于存储可以按位置存取的有序节点。可以使用中括号或者item()方法访问它的值

1
2
3
4
let firstChild=someNode.childNodes[0];
let secondChild=someNode.childNodes.item(1);
let count=someNode.childNodes.length;
let arrayofNodes=Array.from(someNode.childNodes);

parentNode指向DOM树中的父元素,childNode中所有节点都有同一个父元素,parentNode指向同一个节点,childNodes列表中每个结点都是同一列表中其他节点的同胞节点,使用previousSibling和nextSibling可以在这个列表的节点间导航。

hasChildNodes()节点返回true则说明节点有一个或多个子节点。

ownerDocument属性是一个指向代表整个文档的文档节点的指针

操纵节点

appendChild():用于在childNodes列表末尾添加节点,返回新添加的节点。

1
2
3
let returnedNode=someNode.appendChild(newNode);
alert(returnedNode==newNode);//true
alert(someNode.lastChild==newNode);//true

inserBefore():接收两个参数,要插入的节点和参照节点。要插入的节点会变成参照节点的前一个同胞节点,并被返回

1
2
3
4
5
6
7
8
9
10
returnedNode=someNode.insertBefore(newNode,null);
alert(newNode==someNode.lastChild);//true
//作为新的第一个子节点插入
retunedNode=someNode.insertBefore(newNode,someNode.firstChild);
alert(returnedNode==newNode);//true
alert(newNode==someNode.fiestChild);//true
//插入最后一个子节点的前面
returnedNode==someNode.insertBefore(newNode,someNode.lastChild);
alert(newNode==someNode.childNodes[someNode.childNodes.length-2]);//true

replaceChild():接收两个参数,要插入的节点和要替换的节点。要替换的节点被返回并从文档中被移除

1
returnedNode=someNode.replaceChild(newNode,someNode.lastChild);//替换最后一个子节点

removeChild():接收一个参数,即要被移除的节点,被移除的节点会被返回

1
let formerFirstChild=someNode.removeChild(someNode.firstChild);

cloneNode():传入true参数会进行深复制,即复制节点和整个子DOM树;传入false进行浅复制,只会复制该方法的节点。复制返回的节点属于文档所有,但未指定父节点,称为孤儿节点,通过appendChild()和insertBefore(),replaceChild()方法把孤儿节点添加到文档中

normalize():处理文本节点,如果发现空文本节点则将其删除否则如果两个同胞节点相邻则将其合并为一个文本节点

Document类型

表示文档节点的类型,document是HTMLDocument的实例(HTMLDocument继承Document),表示整个HTML页面,document是window对象的属性是一个全局对象。

  • nodetype等于9

  • nodeName值为“#document”

  • nodevalue值为null

  • parentNode值为null

  • ownerDocument值为null

  • 子节点可以使DocumentType(最多一个),Element(最多一个),ProcessingInstruction或Comment类型

文档子节点

documentElement:始终指向HTML页面中的元素

1
2
3
4
5
6
7
<html>
<body>
</body>
</html>
let html=document.documentElement;//取得对<html>的引用
alert(html===document.childNodes[0]);
alert(html===document.firstChild);

document.body:直接指向body元素,取得对body的引用

文档信息

title:显示浏览器窗口或标签页的标题栏

URL:包含当前页面的完整URL

domain:包含页面的域名

referrer:包含空字符串

1
2
3
//document.URL="http://www.wrox.com/WileyCDA/",document.domain就是www.wrox.com
document="wrrox.com";//成功
document="nczonline.net";//出错,不能给这个属性设置URL中不包含的值

当页面中包含来自某个不同子域的窗格()或内嵌窗格(

1
2
document.domain="wrox.com";//放松,成功
document.doman="p2p2.wrox.com";//收紧,失败,一旦放松就不能收紧

定位元素

getElementById():接收一个要获取元素的ID,如果找到这个元素则返回,没找到返回null。参数I必须跟元素在页面中大的id属性完全匹配,包括大小写

1
2
<div id="myDiv">ome text</div>
let div=document.getElementById("myDiv");//取得对<div>的引用,如果存在多个相同ID的元素则返回在文档中的第一个元素

getElementsByTagName():接收一个参数,即要获取元素的标签名,返回包含0个或多个元素的NodeList,在HTML文档中返回一个HTMLCollection对象

1
2
3
4
5
6
7
8
9
10
let images=document.getElementsByTagName("img");
alert(images.length);//图片数量
alert(images[0].src);//第一张图片的src属性
alert(images.item(0).src);
//通过name属性获得引用
<img src="myImage.gif" name="myImage">;
let myImage=images.namedItem("myImage");
//images["myImage"]
//取得文档的所有元素
let allElements=document.getElementsByTagName("*");

getElementsByName():返回具有给定name属性的所有元素,常用于单选按钮

1
2
3
4
5
6
7
8
9
10
<fieldset>
<legend>Which color do you prefer?</legend>
<ul>
<li>
<input type="radio" value="red" name="color" id="colorRed"><label for="colorRed">Red</label>
</li>
<li> <input type="radio" value="blue" name="color" id="colorBlue"><label for="colorBlue">Blue</label>
</li>
let radios=document.getElementsByName("color");

Element类型

  • nodeType=1

  • nodeName值为元素的标签名

  • nodeValue的值为null

  • parentNode值为Document或Element对象

  • 子节点可以是Element,Text,Comment,ProcessingInstruction等类型

通过nodeName或tagName属性获得元素的标签名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//使用对象属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="myDiv"></div>
<script>
let div=document.getElementById("myDiv");
alert(div.tagName);//"DIV"
alert(div.tagName==div.nodeName);//true
if(element.tagName.toLowerCase()=="div"){
//,HTML中,元素标签名以答谢表示,XML中标签名与代码中的大小写一致,不确定脚本是HTML还是XML运行,推荐将标签名转换为小写形式,适合所有文档
</script>
</body>
</html>

HTML元素

  • id:元素在文档中的唯一标识符

  • title:包含元素的额外信息,通常以提示条形式展示

  • lang:元素内容的语言代码

  • dir:语言的书写方向(ltr从左到右,rtl从右到左)

  • className:相当于class属性,用于指定元素的CSS类

取得属性
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
//使用对象属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="myDiv" class="bd" title="Body text" lang="en" dir="ltr">2</div>
<script>
var div=document.getElementById("myDiv");
alert(div.id);
alert(div.className);
alert(div.title);
alert(div.lang);
alert(div.dir);
</script>
</body>
</html>
//使用getAttribute()方法
alert(div.getAttribute("class"));

getAttribute()主要用于取得自定义属性的值,其他情况使用对象属性

设置属性

setAttribute():接收两个参数,要设置的属性名和属性值,如果属性存在则用指定的值替换原来的值

1
2
3
4
5
6
7
//直接给对象属性赋值
div.id="someOtherId"
//在对象属性上添加自定义属性,不会让它变成元素的属性
div.mycolor="red";
alert(div.getAttribute("mycolor"));//null
//使用setAttribute赋值
div.setAttribute("id","someOtherId");
attributes属性

attributes属性包含一个NamedNodeMap实例,是一个类似NodeList的“实时”集合,元素的每个属性都表示为一个Attr节点,并保存在NamedNodeMap对象中

attributed属性中的每个节点的nodeName是对应属性的名字,nodeValue是属性的值

1
2
3
4
5
6
7
8
function outputAttributes(element){
let pairs=[];
for(let i=0,len=element.attributes.length;i<len;++i){
const attribute=element.attributes[i];
pairs.push(`${attribute.nodeName}=${attribute.nodeValue}`);
return pairs.join(" ");
}
}
创建元素

document.createElement():一个参数,即要创建元素的标签名

1
2
3
4
let div=document.createElement("div");
div.id="myNewDiv";
div.className="box";
document.body.appendChild(div);

Text 类型

Text节点由Text类型表示,包含按字面解释的纯文本,也可能包含转义后的HTML字符,Text节点中包含的文本可以通过nodeValue或者data属性访问

  • nodetype=3

  • nodeName=”#text”

  • nodeValue值为节点中包含的文本

  • parentNode值为Element对象

  • 不支持子节点

  • appendData(text):向节点末尾添加文本text

  • deleteData(offset,count),从位置offset开始删除count个字符

  • insertData(offset,text),在位置offset插入text;

  • replaceData(offset,count,text),用text替换从位置offset到offset+count大的文本

  • splitText(offset),在位置offset将当前文本节点拆分为两个文本节点

  • substringData(offset,count),提取从位置offset到offset+count的文本

包含文本内容的每个元素最多只能有一个文本节点

创建文本节点

document.createTextNode():创建新文本节点,接收一个参数,即要插入节点的文本

1
2
3
4
5
6
7
8
9
let element=document.createElement("div");
element.className="message";

let textNode=document.createTextNode("Hello world!");
element.appendChild(textNode);
let anotherTextNode=document.createTextNode("Yippee");
element.appendChild(anotherTextNode);
document.body.appendChild(element);

规范化文本节点

合并文本节点
1
2
3
4
5
6
7
8
9
10
11
let element=document.createElement("div");
element.className="message";
let textNode=document.createTextNode("Hello World");
element.appendChild(textNode);
let anotherTextNode=document.createTextNode("Yippee");
element.appendChild(anotherTextNode);
document.body.appendChild(element);
alert(element.childNodes.length);//2
element.normalize();
alert(element.childNodes.length);//1
alert(element.firstChild.nodeValue);
拆分文本节点
1
2
3
4
5
6
7
8
9
10
let element=document.createElement("div");
element.className="message";
let textNode=document.createTextNode("Hello World");
element.appendChild(textNode);
document.body.appendChild(element);
let newNode=element.firstChild.splitText(5);
alert(element.fiestChild.nodeValue);//"Hello"
alert(newNode.nodeValue);//"world"
alert(element.chileNodes.length);//2

Comment类型

  • nodeType=8

  • nodeName=”#comment”

  • nodeValue值为注释内容

  • parentNode值为Document或Element对象

  • 不支持子节点

Comment类型与Text类型继承自同一个基类(CharacterData),因此拥有除splitText之外的Text节点所有的字符串操作方法

CDATASection类型

继承Text类型,拥有除splitText之外的Text节点所有的字符串操作方法

DocumentType类型

  • 在DOM Level1中不支持动态创建,只能在解析文档代码时创建,DocumentType对象保存在document.doctype属性中.

  • DocumentType对象有3个属性:name,entities,notations.

  • name是文档名称,entities是这个文档类型描述实体的NameNodeMap,而notations是这个文档类型描述的表示法的NamedNodeMap.

  • 浏览器文档通常是HTML或XHTML类型,所以entities和notations列表为空,只有name属性有用,包含文档类型的名称

DocumentFragment类型

  • nodeType=11

  • nodeName=”#document-fragment”

  • nodeValue=null

  • parentNode=null

  • 子节点可以是Element,ProcessingInstruction,Comment,Text,CDATASection

充当其他要被添加的文档节点的仓库

1
2
3
4
5
6
7
8
9
<ul id="myList"></ul>
let fragment=document.createDocumentFragment();
let ul=document.getElementById("myList");
for(let i=0;i<3;i++){
let li=document.createElement("li");
li.appendChild(document.createTextNode(`Item ${i+1}`));
fragment.appendChild(li);
}
ul.appendChild(fragment);

Attr类型

属性是存在于元素attributes属性中的节点

  • nodeType=2

  • nodeName值为属性名

  • nodeValue值为属性值

  • parentNode值为null

Attr对象上3个属性

  • name包含属性名

  • value包含属性值

  • specified是一个布尔值,表示属性使用的是默认值和还是被指定的值

1
2
3
4
5
6
7
let attr=document.createAttribute("align");//创建新的Attr节点,参数为属性名
attr.value="left";
element.setAttributeNode(attr);//添加属性节点
alert(element.attributes["align"].value);//返回对应属性节点
alert(element.getAttributeNode("align").value);//返回对应属性节点
alert(element.getAttribute("align"));//只返回属性值

选项处理

使用选择框的selectedIndex属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  <form method="post">
<select name="location" id="selLocation">
<option value="Sunnyvalue,CA">Sunnyvalue</option>
<option value="Los Angeles,CA">Los Angeles</option>
<option value="Mountain View,CA">Mountain View</option>
<option value="">China</option>
<option >Australia</option>
</select>

</form>

<script src="example3.js"></script>

let selectbox=document.forms[0].elements["location"];
function getSelectedOptions(selectbox){
let result=new Array();
for(let option of selectbox.options){
if(option.selected){
result.push(option);
}
}
return result;
}
let selectedOptions=getSelectedOptions(selectbox);
let message="";
for(let option of selectedOptions){
message+=`Selected index:${option.index}\n`+`Selected text:${option.text}\n`+`Selected value:${option.value}\n`;

}
console.log(message);

添加选项

动态创建选项

1
2
3
4
let newOption=document.createElement("option");
newOption.appendChild(document.createTextNode("Option text"));
newOption.setAttribute("value","Option value");
selectbox.appendChild(newOption);

使用Option构造函数创建选项,接收两个参数:text和value,用选择框的add方法添加选项

1
2
let newOption=new Option("Option text","Option value");
selectbox.add(newOption,undefined);//在列表末尾添加选项

移除选项

1
2
3
4
5
6
7
8
9
selectbox.removeChild(selectbox.options[0]);//移除第一项
selectbox.remove(0);//移除第一项
selectbox.options[0]=null;
//清除选项框的所有选项
function clearSelectbox(selectbox){
for(let option of selectbox.options){
selectbox.remove(0);
}
}

移动和重排选项

1
2
3
4
let selectbox1=document.getElementById("selLocations1");
let selectbox2=document.getElementById("selLocations2");
selectbox2.appendChild(selectbox1.options[0]);//将选项从第一个选择框移动到另一个选择框

重排选项

1
2
3
4
5
6
let selectbox1=document.getElementById("selLocations1");
let optionToMove=selectbox1.options[1];
selectbox1.insertBefore(optionToMove,selectbox1.options[optionToMove.index-1]);//将要重排的选项移动到它原先位置的前前面
let selectbox1=document.getElementById("selLocations1");
let optionToMove=selectbox1.options[1];
selectbox1.insertBefore(optionToMove,selectbox1.options[optionToMove.index+2]);//将要重排的选项移动到它原先位置的后面一位

文本框编程

表示文本框的两种方式

1
2
3
4
5
6
<input type="text" size="25" maxlength="50" value="initial value">
//创建多行文本框
<textarea rows="25" cols="5">initial value</textarea>
//用使用value属性读写文本框
let textbox=document.forms[0].elements["textbox1"];
textbox.value="Some new value";

选择文本

select()用于全选文本

1
2
3
4
5
6
let form=document.getElementById("myForm");
let textbox=form.elements[0];
textbox.addEventListener("focus",(event)=>{
event.target.select();
console.log(`Text selected:${textbox.value}`);
});

setSelectionRange()用于部分选择文本

1
2
3
4
5
6
7
let form=document.getElementById("myForm");
let textbox=form.elements[0];
textbox.addEventListener("focus",(event)=>{
event.target.select();
textbox.setSelectionRange(0,1);
console.log(`Text selected:${textbox.value}`);
});

屏蔽按键

1
2
3
4
5
textbox.addEventListener("keypress",(event)=>{
if(!/\d/.test(String.fromCharCode(event.charCode))&&event.charCode>9&&!event.ctrlKey){//屏蔽非数字字符但允许同样触发keypress事件的所有基础按键以及ctrl键
event.preventDefault();
}
})

自动切换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<form method="post">
<input type="text " name="tel1" id="textTel1" maxlength="3">
<input type="text" name="tel2" id="textTel2" maxlength="3">
<input type="text" name="tel3" id="textTel3" maxlength="4">


</form>
let inputIds=["textTel1","textTel2","textTel3"];
for(let id of inputIds){
let textbox=document.getElementById(id);
textbox.addEventListener("keyup",(event)=>{
let target=event.target;
if(target.value.length==target.maxLength){
let form=target.form;
for(let i=0,len=form.elements.length;i<len;i++){
if(form.elements[i]==target){
if(form.elements[i+1]){
form.elements[i+1].focus();
}
return;
}
}
}
});

};

表单

禁用表单

避免多次提交表单可以在第一次点击后禁用表单

1
2
3
4
5
6
7
8
let form=document.getElementById("myForm");
form.addEventListener("submit",(event)=>{
let target=event.target;
//取得提交按钮
let btn=target.elements["submit-btn"];
//禁用提交按钮
btn.disabled=true;
})

focus()

把焦点设置到表单字段,这意味着该字段会变成活动字段并可以响应键盘事件,autofocus()会自动为带有该属性的元素设置焦点

1
2
3
4
5
6
7
8
let form=document.getElementById("myForm");
window.addEventListener("load",(event)=>{
let element=form.elements[0];
if(element.autofocus!==true){
element.focus();
console.log("JS focus");
}
})

表单的公共事件

BOM

location对象

提供当前窗口加载文档的信息,以及通常的导航功能,它既是window的属性也是document的属性。

查询字符串

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let getQueryStringArgs=function(){
//取得没有开头问号的查询字符串

let qs=(location.search.length>0)?location.search.substring(1):"";
let args={};
for(let item of(qs.split('&').map(kv=>kv.split('=')))){
let name=item[0];
value=item[1];
if(name.length){
args[name]=value;
}
}
return args;
}
//qs="?q=javaScript&num=10";
let args=getQueryStringArgs();
alert(args["q"]);
alert(args['num']);

使用USLSearchParams检查和修改查询字符串

1
2
3
4
5
6
7
8
9
10
11
12
let qs="?q=javaScript&num=10";
let searchParams=new URLSearchParams(qs);
alert(searchParams.toString());
searchParams.has("num");
searchParams.get("num");
searchParams.set("page","3");
alert(searchParams.toString());
searchParams.delete("q");
alert(searchParams.toString());
for(let param of searchParams){
console.log(param);
}

操作地址

通过修改location对象修改浏览器地址,使用assign方法传进一个URL,会导航到新URL同时在浏览器历史记录增加一条记录,下面三种方法功能相同

1
2
3
location.assign("http://www.wrox.com");
window.location="http://www.wrox.com";
location.href="http://www.wrox.com";

通过修改location属性可以修改当前加载的页面,hash,search,hostname,pathname.port属性被设置为新值后会修改当前的URL

1
2
3
4
5
6
7
8
9
10
11
12
//假设当前URL为http://www.wrox.com/WileyCDA/
location.assign("http://www.wrox.com/WileyCDA");
//把URL修改为http://www.wrox.com/WileyCDA/#section1
location.hash="#section1";
//把URL修改为http://www.wrox.com/WileyCDA/?q=javascript
location.search="?q=javascript";
//把URL修改为http://www.somewhere.com/WileyCDA/
location.hostname="www.somewhere.com";
//把URL修改为http://www.somewhere.com/mydir/
location.pathname="mydir";
//把URL修改为http://www.somewhere.com:8080/WileyCDA/
location.port=8080;

以上的修改会在浏览器中增加记录,点击后退即可导航到前一个界面,不希望增加历史记录可以使用replace()方法,reload()可以重新加载当前页面,如果页面自从上次请求后没有修改过,则浏览器可能会从缓存中加载页面,如果想强制从服务器中加载,必须传入true

history对象

history用来导航历史记录,同时不会暴露用户访问过的URL。

1
2
3
4
5
6
7
8
history.go(-1);//后退一页
history.go(1);//前进一页
history.go("wrox.com")//导航到最近的wrox.com页面
//go有两个简写方法:back()和forward()
history.back();//后退一页
history.forward()//前进一页
//history的length属性记录历史记录有多少条目
if(history.length==1){//这是用户窗口第一个页面}

navigator对象通常用来确定浏览器的类型

检测插件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
function hasPlugin(name){
name=name.toLowerCase();
for(let plugin of window.navigator.plugins){
if(plugin.name.toLowerCase().indexOf(name)>-1){return true;}

}
return false;
}
//alert(hasPlugin("Flash"));
//alert(hasPlugin("QuickTime"));
function hasIEPlugin(name){
try{
new ActiveXObject(name);
return true;
}catch(ex){
return false;
}
}
//在所有浏览器中检测插件
function hasFlash(){
var result=hasPlugin("Flash");
if(!result){
result=hasIEPlugin("ShockwaveFlash.ShockwaveFlash");
}return result;
}
function hasQuickTime(){
var res=hasPlugin("QuickTime");
if(!res){
res=hasIEPlugin("QuickTime.QuickTime");

}
return res;

}
alert(hasFlash());
alert(hasQuickTime());

注册处理程序

registerProtocolHandler()方法可以把一个网站注册处理为某种特定类型信息应用程序,传入3个参数:要处理的协议(“mailto或ftp),处理该协议的URL,以及应用名称

例如,把一个Web应用程序注册为默认客户端

1
navigator.registerProtocolHandler("mailto","http://www.somemailclient.com?cmd=%s","Some Mail Client");

定位

定位总结:

  1. static: 不脱标,不能使用边偏移
  2. relative:不脱标(占有位置),可用margin,相对于自身位置移动
  3. absolute:脱标(不占有位置),不可用margin,带有定位的父级
  4. fixed:脱标(不占有位置),浏览器可视区
  5. sticky:不脱标(占有位置),浏览器可视区
  • 绝对定位特点:如果没有祖先元素或者祖先元素没有定位,则以浏览器为准定位

  • 如果祖先元素有定位(相对,绝对,固定定位)则以最近一级的有定位的祖先元素为参考点移动位置

  • 绝对定位不占有原先的位置(脱标)

叠放次序 z-index

在使用定位布局时,可以使用z-index来控制盒子的前后次序

语法:

选择器{z-index:1;}

  • 数值可以是正整数,负整数或者0,默认是auto,数值越大,盒子越靠上
  • 如果属性相同,则按照书写顺序,后来居上
  • 数字后面不能加单位
  • 只有定位的盒子才有z-index属性

定位的拓展

1.绝对定位盒子居中

  • left:50%
  • margin-left:-100px;

2.定位特殊性:

绝对定位固定定位和浮动相似

  1. 行内元素添加绝对或者固定定位,可以直接设置高度和宽度(span)

  2. 块级元素添加绝对或者固定定位,如果不给宽度或者高度,默认大小是内容的大小

  3. 脱标的盒子不会触发外边距合并问题

3.绝对定位(固定定位)会完全压住盒子

浮动元素只会压住下面标准流的盒子,但是不会压住下面标准流的文字(图片)但是绝对定位(固定定位)会压住下面标准流的所有内容

浮动之所以不会压住下面文字是因为浮动最初的目的是为了做文字环绕效果

元素里的显示和隐藏

display 显示隐藏元素 但是不保留位置 隐藏元素不想要原来位置,用none,否则用block

visibility显示隐藏元素 但是保留原来的位置,visible为元素可见,hidden为元素隐藏

overflow 溢出显示隐藏 但是只是对于溢出的部分处理,scoll:溢出的部分显示滚动条,visible:溢出部分可见,hidden:溢出部分不可见,auto:没溢出则不显示滚动条,溢出则超出部分显示滚动条。

用户界面样式

鼠标样式cursor

li {cursor: pointer; }

default 默认小白鼠标

pointer 小手

move 移动

text 文本

not-allowed 禁止

vertical-align实现行内块和文字居中对齐

vertical-align:middle

解决图片底部默认空白空隙:图片底侧会有一个空白缝隙,原因是行内块元素会和文字的基线对齐

解决方法:

1.给图片添加vertical-align:middle或者top或者bottom

2.把图片转为块级元素 display:block

单行文字溢出显示省略号

white-space:nomal:如果文字显示不开自动换行

white-space:nowrap:如果文字显示不开强制一行内显示

overflow:hidden(溢出部分隐藏)

text-overflow:ellipsis(文字溢出部分用省略号显示)

多行文本溢出显示省略号

width: 150px;

height: 65px;

background-color: pink;

margin: 100px auto;

overflow: hidden;

text-overflow: ellipsis;

display: -webkit-box;

/* 从第几行开始省略 */

-webkit-line-clamp: 3;

-webkit-box-orient: vertical;

常见布局技巧

margin负值使用

让每个盒子margin往左移动-1px,正好压住相邻盒子的边框

鼠标经过盒子提高当前盒子层级(如果没有定位,则加相对定位(保留位置)如果都有定位则用z-index)

文字围绕浮动元素

三角形制作

weight:0;

height:0;

border-color:transparent red transparent transprent;

border-style:solid;

border-width:22px 8px 0 0;(上面的宽,右边的小一些)

HTML新标签

header:头部标签

nav:导航标签

article:内容标签

section:定义文档某个区域

aside:侧边栏标签

footer:尾部标签

主要针对搜索引擎,这些新标签页面中可以使用多次,在IE9中,需要把这些元素转换为块级元素

视频

用mp4格式

autoplay:自动播放

controls:向用户使用播放控件

width:设置播放器宽度

height:设置高度

loop:是否循环播放

src:url(视频url地址)

poster:加载等待的画面图片

muted:静音播放

新增input表单

type=”email”

type=”url”

type=”date”

type=”time”

type=”month”

type=”week”

type=”numbers”

type=”tel”

type=”search”

type=”color”

input属性

required=”requied”表示该内容不能为空,必填

placeholder=”placeholder”提示文本,表单提示信息

autofocus=”autofocus”自动聚焦属性,页面加载完成自动聚焦到指定表单

autocomplete:默认为on,当用户键入字段时基于之前键入的值显示出字段,关闭为off

multiple:可以多选文件提交

新增选择器

属性选择器(特殊性0,0,1,0)

E[att]选择具有att属性的E元素

E[att=”val”]选择具有att属性且属性值等于val的E元素

E[att^=”val”]选择具有att属性且属性值以val开头

E[att$=”val”]选择具有att属性且属性值中含有val的E元素

伪类选择器

E:first-child:匹配父元素的第一个子元素

E:last-child:匹配父元素的最后一个元素

E:nth-child(n)匹配父元素的第n个元素

E:nth-child(even)匹配父元素的第偶数个元素,odd则第奇数个元素

E:nth-child(n),从0开始计算,但是第0个元素或者超出元素个数会被忽略

nth-child(2n):偶数,2n+1:奇数 5n:5 10 15…

n+5:从第5个开始到最后

-n+5:前5个(包含第5个)

nth-of-type():会把指定孩子排序号,执行的时候先看E指定的元素,之后根据E回去看是第几个孩子

nth-child:对于父元素里面所有孩子进行排序选择,先找到第n个孩子,然后看着是否和E匹配

无序列表用nth-child比较多

类选择器,属性选择器和伪类选择器权重为10

伪元素选择器

::before:在元素内部的前面插入内容

::after:在元素内部的后面插入内容

  • before和after创建一个元素,属于行内元素
  • 新创建的这个元素在文档树中找不到,因此称为伪元素
  • 语法:element::before{},
  • before和after必须有content属性
  • 伪元素和标签选择器一样,权重为1
伪元素选择器:清除浮动

.clearfix:after {

content:’’;

display:block;//插入的元素必须是块级

height:0;//不要看见这个元素

clear:both;

visibility:hidden;//不要看见这个元素

}

.clearfix:before,.clearfix:after {

content:’’;

diaplay:table;//元素在一行显示且转化为块级元素

}

CSS盒子模型

box-sizing:content-box,盒子大小为width+padding+border(CSS3之前默认)

box-sizing:border-box,盒子大小为width

如果盒子模型我们改为了box-sizing:border-box,那padding和border就不会撑大盒子(前提padding和border不会超过width宽度)

CSS过渡(重点)

transition:要过渡的属性 花费时间 运动曲线 何时开始

1属性:想要变化的CSS属性,宽度高度 背景颜色内外边距都可以 如果想要所有属性都变化过度则用all

2花费时间:单位是秒(必需写单位

3运动曲线默认为ease

4何时开始:单位是秒 可以设置延迟触发时间 默认是0s

CSS filter属性

修改图片的颜色为黑白

1
img{filter:grayscale(100%)}