DOM模型概述
- DOM 是 文档对象模型(Document Object Model)的简称。
- DOM不是一种技术,它只是访问结构化文档(主要是XML文档和HTML文档)的一种思想。
- DOM解析器的作用是完成结构化文档和DOM树之间的转换关系。通常来说,DOM解析器解析结构化文档,就是将磁盘上的结构化文档转换成内存中的DOM树;而从DOM树输出结构化文档,就是将内存中的DOM树转换成磁盘上的结构化文档。
DOM模型和HTML文档
- 从页面的document对象到每个常用的HTML元素,DOM模型都提供了对应的类,每个类都提供了相应的方法来操作DOM元素本身、属性及其子元素。
- DOM模型允许以树的方式操作HTML文档中的每个元素。
访问HTML元素
根据ID访问HTML元素
通过 document.getElementByID(idVal)
访问文档中id属性值为idVal的HTML元素。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>Test</title>
<script type="text/javascript">
var accessById = function(){
alert(document.getElementById("a").innerHTML + "\n" + document.getElementById("b").value);
}
</script>
</head>
<body>
<div id="a">测试</div>
<textarea id="b" row="3" cols="25">测试区域</textarea>
<input type="button" value="访问以上元素" onclick="accessById();" />
</body>
</html>
- 当某个元素的开始标签、结束标签之间都是字符串内容时(不包含子元素),JavaScript子元素可以通过它的innerHTML属性返回这些字符串内容。
- 但<textarea…/>例外,因为它是一个表单控件,它的开始标签和结束标签之间的内容是它的值,因此只能通过value属性来访问。
- <input…/>元素所生成的表单控件,包括单行文本框、各种按钮等,它们的可视化文字都由value属性控制,包括列表
根据CSS选择器访问HTML元素
querySelector(selectors)
该方法返回HTML文档中第一个符合选择器参数的HTML参数。
querySelectorAll(selectors)
该方法返回所有符合选择器参数的HTML元素。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>Test</title>
<script type="text/javascript">
var accessById = function(){
alert(document.querySelector("#a").innerHTML + "\n" + document.querySelector("#b").value);
}
</script>
</head>
<body>
<div id="a">测试</div>
<textarea id="b" row="3" cols="25">测试区域</textarea>
<input type="button" value="访问以上元素" onclick="accessById();" />
</body>
</html>
利用节点关系访问HTML元素
parentNode
返回当前节点的父节点。
previousSibling
返回当前节点的前一个兄弟节点。
nextSibling
返回当前节点的后一个兄弟节点。
childNodes
返回当前节点的所有子节点。
getElementsByTagName(tagname)
返回当前节点的具有指定标签名的所有子节点。
firstChild
返回当前节点的第一个子节点。
lastChild
返回当前节点的最后一个子节点。
以上都是只读属性。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>Test</title>
</head>
<body>
<ol id="books">
<li id="java">JAVA</li>
<li id="ssh">SSH</li>
<li id="ajax">AJAX</li>
<li id="xml">XML</li>
<li id="ejb">EJB</li>
<li id="android">ANDROID</li>
</ol>
<input type="button" value="父节点" onclick="change(curTarget.parentNode);" />
<input type="button" value="第一个" onclick="change(curTarget.parentNode.firstChild.nextSibling);" />
<input type="button" value="上一个" onclick="change(curTarget.previousSibling.previousSibling);" />
<input type="button" value="下一个" onclick="change(curTarget.nextSibling.nextSibling);" />
<input type="button" value="最后一个" onclick="change(curTarget.parentNode.lastChild.previousSibling);" />
<script type="text/javascript">
var curTarget = document.getElementById("ajax");
var change = function(target){
alert(target.innerHTML);
}
</script>
</body>
</html>
访问表单控件
表单在DOM中由HTMLFormElement对象表示。
常用属性:
action
返回该表单的action属性值。(读写属性)
elements
返回表单内全部表单控件所组成的数组。
length
返回表单内表单域的个数。
method
返回该表单的method属性,该属性通常有POST和GET两个值,默认是GET。(读写属性)
target
用于确定提交表单时的结果窗口。(读写属性)
reset()
重设表单,将所有表单域的值设置为初始值。
submit()
提交表单。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>Test</title>
</head>
<body>
<form id="d" action="" method="get">
<input name="user" type="text" /><br>
<input name="pass" type="text" /><br>
<select name="color">
<option value="red">红色</option>
<option value="bule">蓝色</option>
</select><br>
<input type="button" value="第一个" onclick="alert(document.getElementById('d').elements[0].value);" />
<input type="button" value="第二个" onclick="alert(document.getElementById('d').elements['pass'].value);" />
<input type="button" value="第三个" onclick="alert(document.getElementById('d').color.value);" />
<input type="button" value="重置" onclick="document.getElementById('d').reset();" />
</form>
</body>
</html>
HTMLFormElement访问表单控件有3种语法:
formObj.elements[index]
返回表单中第index个表单控件。
formObj.elements['elementName']
返回表单中id或name为elementName的表单控件。
formObj.elementName
返回表单中id或name为elementName的表单控件。
访问列表框、下拉菜单的选项
HTMLSelectElement代表一个列表框或下拉菜单。
常用属性:
form
返回列表框、下拉菜单所在的表单对象。
length
返回列表框、下拉菜单的选个数。
options
返回列表框、下拉菜单里所有选项组成的数组。
selectedIndex
返回下拉列表中选中选项的索引。
type
返回下拉列表的类型,即是否允许多选。如果允许多选,则返回select-multiple;如果不支持多选,则返回select-one。
select.options[index] 返回列表框、下拉菜单的第index+1个选项。
列表框、下拉菜单的选项由HTMLOptionElement对象表示。
常用属性:
form
返回包含该选项所处列表框、下拉菜单的表单对象。
defaultSelected
返回该选项默认是否被选中。
index
返回该选项在列表框、下拉菜单中的索引。
selected
返回该选项是否被选中,通过修改该属性可以动态改变该选项是否被选中。
text
返回该选项呈现的文本,与innerHTML属性相同。
value
返回每个选项的value属性,可以改变选项的value值。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>Test</title>
</head>
<body>
<select id="mySelect" name="mySelect" size="6">
<option id="java">JAVA</option>
<option id="ssh">SSH</option>
<option id="ajax">AJAX</option>
<option id="xml">XML</option>
<option id="ejb">EJB</option>
<option id="android">ANDROID</option>
</select><br>
<input type="button" value="第一个" onclick="change(curTarget.options[0]);" />
<input type="button" value="上一个" onclick="change(curTarget.options[curTarget.selectedIndex - 1]);" />
<input type="button" value="下一个" onclick="change(curTarget.options[curTarget.selectedIndex + 1]);" />
<input type="button" value="最后一个" onclick="change(curTarget.options[curTarget.length - 1]);" />
<script type="text/javascript">
var curTarget = document.getElementById("mySelect");
var change = function(target){
alert(target.text);
}
</script>
</body>
</html>
访问表格子元素
HTMLTableElement 代表表格。
常用属性:
caption
返回表格的标题对象,可通过修改该属性来改变表格标题。
rows
返回该表格里的所有表格行。
tBodies
返回该表格里所有<tbody…/>元素组成的数组。
tFoot
返回该表格里的<tfoot…/>元素。
tHead
返回该表格里的<thead…/>元素。
table.rows[index] 返回该表格第index+1行表格行。
HTMLTableRowElement 代表表格行。
cells
返回该表格行内所有的单元格组成的数组。
rowIndex
返回该表格行内在表格内的索引值。
sectionRowIndex
返回该表格行在其所在元素的索引值。
HTMLTableCellElement 代表单元格。
cellIndex
返回该单元格在该表格行内的索引值。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>Test</title>
</head>
<body>
<table id="d" border="1">
<caption>表格</caption>
<tr>
<td>1.1</td>
<td>1.2</td>
</tr>
<tr>
<td>2.1</td>
<td>2.2</td>
</tr>
<tr>
<td>3.1</td>
<td>3.2</td>
</tr>
</table>
<input type="button" value="表格标题" onclick="alert(document.getElementById('d').caption.innerHTML);" />
<input type="button" value="第一行、第一列" onclick="alert(document.getElementById('d').rows[0].cells[0].innerHTML);" />
<input type="button" value="第二行、第二列" onclick="alert(document.getElementById('d').rows[1].cells[1].innerHTML);" />
<input type="button" value="第三行、第一列" onclick="alert(document.getElementById('d').rows[2].cells[0].innerHTML);" />
</body>
</html>
修改HTML元素
通常修改以下几个常用属性:
innerHTML
大部分HTML页面元素如<div…/>、<td…/>的呈现内容由该属性控制。
value
表单控件<input…/>、<textarea…/>的呈现内容由该属性控制。
className
修改HTML元素的CSS样式。
style
修改HTML元素的内联CSS样式。
options[index]
直接对<select…/>元素的指定列表赋值,可改变列表框、下拉菜单的指定列表项。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>Test</title>
</head>
<body>
改变第<input id="row" type="text" size="2" />行,
第<input id="cel" type="text" size="2" />列的值为:
<input id="celVal" type="text" size="16" /><br>
<input id="chg" type="button" value="改变" onclick="change();" />
<table id="d" border="1" style="width:580px;border-collapse:collapse;">
<tr>
<td>第一行第一列</td>
<td>第一行第二列</td>
</tr>
<tr>
<td>第二行第一列</td>
<td>第二行第二列</td>
</tr>
<tr>
<td>第三行第一列</td>
<td>第三行第二列</td>
</tr>
</table>
<script type="text/javascript">
var change = function(){
var tb = document.getElementById("d");
var row = document.getElementById("row").value;
row = parseInt(row);
if(isNaN(row)){
alert("您要修改的行必须是整数");
return false;
}
var cel = document.getElementById("cel").value;
row = parseInt(cel);
if(isNaN(row)){
alert("您要修改的列必须是整数");
return false;
}
if(row > tb.rows.length || cel > tb.rows.item(0).cells.length){
alert("要修改的单元格不再表格内");
return false;
}
tb.rows.item(row-1).cells.item(cel-1).innerHTML = document.getElementById("celVal").value;
}
</script>
</body>
</html>
增加HTML元素
创建或复制节点
document.createElement(Tag)
创建Tag标签对应的节点。
cloneNode(boolean deep)
复制当前节点。当deep为true时,表示在复制当前节点的同时,复制该节点的全部后代节点;当deep为false时,表示仅复制当前节点。
添加节点
对于普通的节点,可采用Node对象的如下方法来添加节点:
appendChild(Node newNode)
将newNode添加成当前节点的最后一个子节点。
insertBefore(Node newNode, Node refNode)
在refNode节点之前插入newNode节点。
replaceChild(Node newChild, Node oldNode)
将oldChild节点替换成newChild节点。
为列表框、下拉菜单添加选项
两种方法:
- 调用HTMLSelectElement的add()方法添加选项。
- 直接为<select…/>的指定选项赋值。
add(HTMLOptionElement option, HTMLOptionElement before)
在before选项之前添加option选项。如果想将option选项添加在最后,则将before指定为null即可。
创建选项
可使用creatElement() 方法。
还可使用如下构造器:
new Option(text, value, defaultSelected, selected)
参数说明:可以只指定一个或两个(按顺序指定)。
text
该选项的文本,即所呈现的内容。
value
选中该选项的值。
defaultSelected
设置默认是否选中该选项。
selected
设置该选项当前是否被选中。
动态添加表格内容
HTMLTableElement 对象有如下方法:
insertRow(index)
在index处插入一行。
insertCell(index)
在index处创建一个单元格。
createCaption()
为该表格创建标题。
createTFoot()
为该表格创建<tfoot…/>元素。
creatTHead()
为该表格创建<thead…/>元素。
删除HTML元素
删除节点
删除节点通常借助于其父节点,Node对象提供了如下方法来删除子节点。
removeChild(oldNode)
删除oldNode子节点。
删除列表框、下拉菜单的选项
两种方法:
- 利用HTMLSelectElement对象的remove() 方法删除选项。
- 直接将指定选项赋为null即可。
remover(index)
删除指定索引处的选项。
删除全部选项,直接将列表框或下拉菜单的innerHTML属性赋为null。
删除表格的行或单元格
deleteRow(index)
删除表格中index索引处的行。
deleteCell(index)
删除某行index索引处的单元格。
传统的DHTML模型
window对象代表整个窗口,该窗口可以是浏览器窗口,也可以只是浏览器页面内的一个Frame。
DHTML对象模型包含关系:
window对象:
navigator浏览器、frames框架页数组、location页面的URL、history访问历史、document文档本身、screen客户机屏幕。
document对象代表HTML文档本身
包含的属性:all所有元素、body页面体、forms所有表单、anchors所有命名锚点、links所有超级链接、images所有图片等。
访问页面控件方法:
- document.images[0] 返回页面第一个图片元素
- document.images[id] 返回页面内id或name为id的图片对象
- document.images.id 返回页面内id或name为id的图片对象
使用window对象
在定义了一个全局变量后,它仅仅在当前的window对象中具有全局性。如果在同一个页面里有多个Frame,则意味着有多个window对象,且每个window中的全局对象不会互相影响。
window对象所包含的方法,JavaScript脚本可以直接调用:
- alert()、confirm()、prompt() 分别用于弹出警告框、确认对话框和提示输入框。
- close() 关闭窗口
- focus()、blur() 让窗口获得焦点、失去焦点
- moveBy()、moveTo() 移动窗口
- open() 打开一个新的顶级窗口,用于装载新的URL所指向的地址,并可指定一系列的新属性
- print() 打印当前窗口或Frame
- resizeBy()、resizeTo() 重设窗口大小
- scrollBy()、scrollTo() 滑动当前窗口中的HTML文档
- setInterval()、clearInterval() 设置、删除定时器
- setTimeout()、cleraTimeout() 设置、删除定时器
常用属性:
- closed 返回一个布尔值,用于判断该窗口是否处于关闭状态
- defaultStatus、status 返回浏览器状态栏的文本
- document 返回该窗口内装载的HTML文档
- frames[] 返回该窗口内包含的Frame对象,每个Frame对象又是一个window对象
- history 返回该窗口的浏览历史
- location 返回该窗口装载的HTML文档的URL
- name 返回该窗口的名字
- navigator 返回浏览当前页面的浏览器
- parent 如果当前窗口是一个Frame,则该属性返回包含本Frame的窗口,即该Frame的直接父窗口
- screen 返回当前浏览者的屏幕对象
- self 返回自身
- top 如果当前窗口是一个Frame,则该属性指向包含本Frame的顶级父窗口
访问页面URL
location对象包含常用属性:
- hostname 文档所在地址的主机名
- href 文档所在地址的URL地址
- host 文档所在地址的主机地址
- port 文档所在地址的服务端口
- pathname 文档所在地址的文件地址
- protocol 装载该文档所使用的协议
客户机屏幕信息
screen对象包含常用属性:
- width 屏幕横向分辨率
- height 屏幕纵向分辨率
- colorDepth 当前屏幕色深
弹出新窗口
open() 方法用于打开一个新窗口,可以结合screen对象的属性,形成满屏效果。
尽量少用弹出式窗口。
确认对话框和输入对话框
- confirm() 弹出一个确认对话框,返回一个布尔值。
<a href="https://www.baidu.com" onclick="return confirm('请确认是否跳转百度');">百度</a>
上例中,当用户点击取消,返回false,将阻止a标签的默认事件。
- prompt() 弹出一个输入对话框,该对话框可获取用户的输入,返回用户输入的内容。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>Test</title>
</head>
<body onload="stack();">
<div id="status"></div>
<script type="text/javascript">
var statusText = "自定义的动画状态栏文字…";
var out = "";
var pause = 25;
var animateWidth = 20;
var position = animateWidth;
var i = 0;
var stack = function() {
if(statusText.charAt(i) != " "){
out = "";
for(var j=0; j<i; j++){
out += statusText.charAt(j);
}
for(j=i; j<position; j++){
out += " ";
}
out += statusText.charAt(i);
for(j=position; j<animateWidth; j++){
out += " ";
}
document.getElementById("status").innerHTML = out;
if(position == i){
animateWidth++;
position = animateWidth;
i++;
}else{
position--;
}
}else{
i++;
}
if(i < statusText.length){
setTimeout("stack()", pause);
}
}
</script>
</body>
</html>
定时器
- 如果需要让一段代码、一个JavaScript函数一固定频率重复执行,则应该使用setInterval()函数。
- 如果需要让一段代码、一个JavaScript函数在指定延迟后仅仅执行一次,则应该使用setTimeout()函数。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>Test</title>
</head>
<body onload="setTime();">
<span id="tm"></span>
<script type="text/javascript">
var timer;
var cur = new Date().getTime();
var setTime = function(){
document.getElementById("tm").innerHTML = new Date().toLocaleString();
if(new Date().getTime() - cur > 60*1000){
clearInterval(timer);
}
}
timer = window.setInterval("setTime();", 1000);
</script>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>Test</title>
</head>
<body>
<span id="tm"></span>
<script type="text/javascript">
var timer;
var cur = new Date().getTime();
var setTime = function(){
document.getElementById("tm").innerHTML = new Date().toLocaleString();
if(new Date().getTime() - cur <= 60*1000){
window.setTimeout("setTime();", 1000);
}
}
setTime();
</script>
</body>
</html>
navigator和地理定位
window对象有一个navigator属性,该属性对应于Navigator对象,该对象代表浏览该页面所使用的浏览器。其常用属性:
- appName 返回该浏览器的内核名称
- appVersion 返回该浏览器当前的版本号
- platform 返回当前浏览器所在的操作系统
HTML5新增的geolocation属性
HTML5为navigator新增了一个geolocation属性,该属性是一个Geolocation对象,通过该对象获取浏览者的地理位置。
提供以下方法:
- getCurrentPosition(onSuccess, onError, options) 请求获取地理位置。
1.第一个参数代表成功获取地理位置时触发的回调函数。形如function(position){}的回调函数,该回调函数中的position表示浏览器所获取的地理信息。position对象包含如下两个属性:
timestamp:返回获取地理位置时的时间。
coords:返回一个Coordinates对象。该对象包含如下属性:longitude:返回经度值。latitude:返回维度值。altitude:返回高度值。
2.第二个参数代表获取地理位置失败后触发的回调函数。(可选)形如function(error){}的回调函数,该回调函数中的error包含了错误信息。该error对象包含如下两个属性:code:返回错误代码,1代表用户拒绝了位置服务;2代表无法获取地址位置信息;3代表获取位置信息超时。message:返回错误描述信息。
3.第三个参数用于传入一些额外的选项。(可选)该参数应该是一个JavaScript对象,该对象支持如下属性:enableHighAccuracy:指定是否要求高精度的地理位置信息(true/false);timeout:指定获取地理位置信息时的超时时长;maximumAge:指定地理信息的缓存时间,以毫秒为单位。 - watchCurrentPosition(onSuccess, onError, options) 持续监听地理位置(相当于周期性地调用getCurrentPosition()方法),该方法返回一个int类型的标识,代表这个“监听器”的标识ID。
- clearWatch(watchID) 停止持续监听地理位置。
获取地理位置
<script type="text/javascript">
var geoHandler = function(position){
var geoMsg = "用户所在的地理位置是:<br>";
geoMsg += "timestamp属性为:" + position.timestamp + "<br>";
var coords = position.coords;
for(var prop in coords){
geoMsg += prop + ":" + coords[prop] + "<br>";
}
document.writeln(geoMsg);
};
var errorHandler = function(error){
var errMsg = {
1:'用户拒绝了位置服务',
2:'无法获取地址位置信息',
3:'获取地址位置信息超时'
};
alert(errMsg[error.code]);
};
navigator.geolocation.getCurrentPosition(geoHandler, errorHandler, {enableHighAccuracy:true,maximumAge:1000});
</script>
在高德地图上定位
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>定位</title>
<style type="text/css">
html {
height:100%
}
body {
height:100%;
margin:0px;
padding:0px
}
#container {
height:100%;
width:100%
}
</style>
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.14&key=0124a2c7b6441326c139bb619b602b15"></script>
<script type="text/javascript">
function initialize() {
navigator.geolocation.getCurrentPosition(
function(position){
var lnglat = [position.coords.longitude, position.coords.latitude];
var map = new AMap.Map('container', {resizeEnable:true, zoom:16, center:lnglat});
var infoWindow = new AMap.InfoWindow({content:"我在这里"});
infoWindow.open(map, lnglat);
},
function(error){
alert("不能提供位置信息");
},
{
enableHighAccuracy:true,
maximumAge:1000
}
);
}
</script>
</head>
<body onload="initialize();">
<div id="container"></div>
</body>
</html>
HTML5增强的History API
window的history属性是一个History对象,该对象表示当前窗口的浏览历史。
传统方法:
- back():后退到上一个浏览页面。
- forward() 前进到下一个浏览页面。
- go(intValue) 指定前进或后退多少个页面。
HTML5新增方法:
- pushState(data, title, url):向History对象的最后“压入”一个新的状态。
- replaceState(data, title, url):替换对象最后的状态。
参数:
- data 该状态所关联的数据,该参数可以是任意JavaScript对象。
- title 该状态的页面标题。
- url 该状态的页面URL。
pushState()、replaceState()和go()的区别:
- pushState()、replaceState()方法会改变浏览器地址栏的内容,但浏览器不会重新加载新地址并刷新页面。当History的state弹出导致浏览器地址栏发生改变时,如果开发者系统页面做出处理,则需要为window对象的onpopstate事件绑定处理函数。
- go()方法不仅会改变浏览器地址栏的地址,而且会让浏览器重新加载地址栏中新的地址,并刷新整个页面。
在实际应用中,pushState()、replaceState()这两个方法主要与Ajax结合使用:Ajax技术能以异步方式向服务器发送请求,获取服务器响应之后通过JavaScript更新在页面上。
- Ajax优势:避免页面的整体刷新,使用异步请求获取服务器响应实现页面的局部更新。
- Ajax缺陷:使用Ajax技术时,浏览器地址栏的内容不会发送任何改变,因此用户不能使用浏览器的“前进”“后退”按钮。
History对象的pushState()、replaceState()两个方法弥补了Ajax的缺陷,这两个方法既能改变浏览器地址栏的内容,又不会导致浏览器刷新页面。
下面实现一个简单的Ajax示例。
<%@page pageEncoding="UTF-8"%>
<%
String id = request.getParameter("id");
String result = null;
if(id.equals("java")){
result = "JS:是一种基于对象的客户端脚本语言。目的是解决服务器端语言。如:Perl,遗留的速度问题,为客户提供更流畅的浏览效果。JS可以直接嵌入到html代码中进行解析执行,非常简单易学,可以产生很多动态的效果。";
}
else if(id.equals("ee")){
result = "形象比较:JS是在客户端执行的,需要浏览器支持JavaScript。JSP是在服务器端执行的,需要服务器上部署支持Servlet的服务器程序。JS代码能够直接从服务器上download得到,对外是可见的,jsp(和翻译后的Servlet代码)是对外不可见的。";
}
else {
result = "JS和JSP相比较:虽然JS可以再客户端动态生成HTML,但是很难与服务器交互,因此不能提供复杂的服务。如:访问数据库和图像处理等等。JSP在HTML中用里面实现。JS在HTML中用<Scrippt></Script>实现。";
}
out.println(result);
%>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=utf-8"/>
<title>Test</title>
<style type="text/css">
table {
display:inline-table;
width:320px;
border:1px solid lightgrey;
border-collapse:collapse;
vertical-align:top;
margin-right:0px;
}
td {
padding:5px;
cursor:pointer;
border:1px solid lightgrey;
}
tr {
background:linear-gradient(to right, #f6f6f6, #fff);
}
tr:hover {
background:linear-gradient(to right, #eee, #f6f6f6);
}
div>div {
display:inline-block;
width:400px;
height:300px;
padding:10px;
box-sizing:border-box;
border:1px solid lightgrey;
margin-left:0px;
}
</style>
</head>
<body>
<div style="width:725px;">
<table border="1">
<tr><td title="java">JAVA</td></tr>
<tr><td title="ee">EE</td></tr>
<tr><td title="android">Android</td></tr>
</table>
<div id="show"></div>
</div>
<script type="text/javascript">
var xhr = new XMLHttpRequest();
window.onload = function(){
history.replaceState(null, "首页", "books.html?id=java")
};
var tdList = document.querySelectorAll("td");
for(var i=0; i<tdList.length; i++){
tdList[i].onclick = function(src){
sendGet("books.jsp?id=" + src.target.title);
history.pushState({"cellTitle":src.target.title},
"首页", "books.html?id=" + src.target.title);
var tdList = document.querySelectorAll("td");
for(var i=0; i<tdList.length; i++){
tdList[i].style = undefined;
}
src.target.style.background = "linear-gradient(to right, #ddd, #eee)";
}
}
function sendGet(url) {
xhr.onreadystatechange = function(){
if(xhr.readyState == 4 && xhr.status == 200){
document.querySelector("#show").innerHTML = xhr.responseText;
}
};
xhr.open("GET", url, true);
xhr.send();
}
window.addEventListener("popstate", function(){
var curTitle = history.state["cellTitle"];
var tdList = document.querySelectorAll("td");
for(var i=0; i<tdList.length; i++){
if(tdList[i].tilte == curTitle)
tdList[i].style.background = "line-gradient(to right, #ddd, #eee)";
else
tdList[i].style = undefined;
}
queryStr = window.location.href.split("?")[i];
sendGet("books.jsp?" + queryStr);
}
)
</script>
</body>
</html>