首页 > 代码库 > 脚本化文档(二)
脚本化文档(二)
获取和设置非标准HTML属性:Element类型还定义了getAttribute()个setAttribute()方法来查询和设置非标准的HTML属性。也可以用来查询和设置XML文档中元素上的属性。这些方法和前面的基于API之间的区别有:1)属性都被看做是字符串。getAttribute()不返回数值、布尔值或对象;2)方法使用标准属性名,甚至当这些名称为JavaScript保留字时也不例外。对HTML元素来说,属性名不区分大小写。
hasAttribute()和removeAttribute():用来检测命名属性是否存在和完全删除属性。当属性为布尔值时这些方法特别有用:有些属性(如HTML的表单元素的disabled属性)在一个元素中是否存在是重点关键,而其值却无关紧要。
如果操作包含来自其他命名空间中属性的XML文档,可以使用这4个方法的命名空间版本:getAttributeNS()、setAttributeNS()、hasAttributeNS()和removeAttributeNS()。这些方法需要两个属性名字符串作为参数,而不是一个。第一个是标识命名空间的URL,第二个通常是属性的本地名字,在命名空间中是无效的。但特别地,setAttributeNS()的第二个参数应该是属性的有效名字,它包含命名空间的前缀。
HTML5文档中,任意以“data-”为前缀的小写的属性名字都是合法的。这些“数据集属性”将不会对其元素的表现产生影响,他们定义了一种标准的、附加额外数据的方法。HTML5还在Element对象上定义了dataset属性。该属性指代一个对象,它的各个属性对应于去掉前缀的data-属性。因此dataset.x应该保存data-x属性的值。带连字符的属性对应于驼峰命名法属性名:data-jquery-test属性就编程了dataset.jqueryTest。
textContent:获取或设置纯文本形式的元素内容。该属性除了IE外,其他浏览器都支持,在IE4中引入和innerText属性可替换该属性,不过innerText在Firefox中不支持。textContent属性就是将制定元素的所有后代Text节点简单地串联在一起。innerText没有一个明确指定的行为,但是和textContent有一些不同。innerText不返回<script>元素的内容。它忽略多余的空白,并试图保留表格格式。同时,innerText针对某些表格元素(如<table>、<tbody>、<tr>)是只读的属性。
createElement():创建新的Element节点。给方法传递元素的标签名:对HTML文档来说该名字不区分大小写。对xml文档则区分大小写。createTextNode():创建Text节点
cloneNode():方法来返回该节点的一个全新副本。给方法传递参数true也能够递归地复制所有的后代节点,或传递参数false只是执行一个浅复制,IE外的浏览器还有个类似的函数improtNode()。
appendChild():在节点中追加子节点。insertBefore()就像appendChild()一样,除了它接受两个参数。第一个参数就是待插入的节点,第二个参数是已存在的节点,新节点将插入该节点,新节点奖插入该节点的前面。该方法应该是在新节点的父节点上调用,方法的第二个参数必须是该父节点的子节点。如果传入null作为第二个参数,insertBefore()的行为类似appendChild(),它将节点插入在最后。
//将child节点插入到parent中,使其成为第n个节点
function insertAt(parent,child,n){
if(n<0||n>parent.childNodes.length)
throw new Error("invalidindex");
else if(n==parent.childNodes.length)
parent.appendChild(child);
else
parent.insertBefore(child,parent,childNodes[n]);
}
9.删除和替换节点:removeChild()方法是从文档中删除一个节点。但要小心:该方法不是在待删除的节点上调用,而是(就像其名字的一部分“chid”所暗示的一样)在其父节点上调用。在父节点上调用该方法,并将要删除的子节点作为方法的参数传递给它。在文档中删除n节点,代码可以这样写:
n.parentNode.removeChild(n);
replaceChild():方法删除一个子节点并用一个新的节点取而代之。在父节点上调用该方法,第一个参数是新节点,第二个参数是需要替换的节点。
//使用innerHTML实现outerHTML属性
//为不支持它的浏览器实现outerHTML属性
//假设浏览器确实支持innerHTML,并有个可扩展的Element.prototype,
//并且可以定义getter和setter
(function(){
//如果outerHTML存在,则直接返回
if(document.createElement("div").outerHTML)return;
//返回this所引用元素的外部HTML
function outerHTMLGetter(){
varcontainer=document.createElement("div");//虚拟元素
container.appendChild(this.cloneNode(true));
return container.innerHTML;
}
//用指定的值设置元素的外部HTML
function outerHTMLSetter(value){
//创建一个虚拟元素,设置其内容为指定的值
varcontainer=document.createElement("div");
container.innerHTML=value;
//将虚拟元素中的节点全部移动到文档中
while(container.firstChild){
this.parentNode.insertBefore(container.firstChild,this);
}
this.parentNode.removeChild(this);
}
//现在使用这两个函数作为所有Element对象的outerHTML属性的getter和setter
//如果它存在则使用ESS的Object.defineProperty()方法,
//否则退而求其次,使用__defineGetter__()和__defineSetter__()
if(Object.defineProperty){
Object.defineProperty(Element.prototype,"outerHTML",{
get:outerHTMLGetter,
set:outerHTMLSetter,
enumerable:false,
configurable:true
});
}else{
Element.prototype.__defineGetter__("outerHTML",outerHTMLGetter);
Element.prototype.__defineSetter__("ouerHTML",outerHTMLSetter);
}
}());
10.Window对象的pageXOffset和pageYOffset属性获取和设置浏览器窗口的滚动条的位置。但IE8及更早的版本不支持这个属性,IE(和所有现代浏览器)也可以通过scrollLeft和scrollTop属性来获得滚动条的位置。令人迷惑的是,正常情况下通过查询文档的根结点(document.documentElement)来获取这些属性值,但在怪异模式下,必须在文档的<body>元素(document.body)上查询它们。以下是一个获取滚动条位置的方法
//以一个对象的x和y属性的方式返回滚动条的偏移量
functiongetScrollOffsets(w){
//使用指定的窗口,如果不带参数则使用当前窗口
w=w||window;
//除IE8及更早的版本外,其他的浏览器都能用
if(w.pageXOffset!=null){
return {
x:w.pageXOffset,
y:w.pageYOffset
};
}
//对标准模式下的IE(或任何浏览器)
var d=w.document;
if(document.compatMode=="CSS1Compat"){
return {
x:d.documentElement.scrollLeft,
y:d.documentElement.scrollTop
};
}
//对怪异模式下的浏览器
return {
x:d.body.scrollLeft,
y:d.body.scrollTop
};
}
11.查询窗口的视口尺寸:一下提供一个兼容各个浏览器的方法:
//作为一个对象的w和h属性返回视口的尺寸
function getViewSize(w){
w=w||window;
//除IE8及更早的版本外,其他浏览器都能用
if(w.innerWidth!=null){
return {
w:w.innerWidth,
h:w.innerHeight
};
}
//对标准模式下的IE(或任何浏览器)
var d=w.document;
if(document.compatMode=="CSS1Compat"){
return {
w:d.documentElement.clientWidth,
h:d.documentElement.clientHeight
}
}
//对怪异模式下的浏览器
return {
w:d.body.clientWidth,
h:d.body.clientHeight
};
}
12.查询元素的集合尺寸:获取元素的尺寸和位置最简单的方法是调用它的getBoundingRect()方法,方法是IE5中引入的,而现在当前的所有浏览器都实现了,它不需要参数,返回一个有left,right,top,bottom属性的对象。分别是其左上、右下角的X和Y坐标。在很多浏览器(和W3C标准)中,getBoundingClientRect()返回的对象还包含width和height属性,但是在原始IE中未实现。为了简单起见,可以这样计算元素的width和height:
var box=e.getBoundingClientRect();
varw=box.width||(box.right-box.left);
varh=box.height||(box.bottom-box.top);
getBoundingClientRect()所返回的坐标包含 元素的边框和内边距,但不包含元素的外边距,它返回的矩形对象不是实时的。
13.所有HTML元素拥有offsetLeft和offsetTop属性来返回元素X和Y坐标。对于很多元素,这些值是文档坐标,并且直接指定元素的位置。但对于已定位元素的后代元素和一些其他元素(如表格单元),这些属性返回的坐标是相对于祖先元素的,而非文档。offsetParent属性指定这些属性所相对的父元素。如果offsetParent为null,这些属性都是文档坐标。
14.单选和复选框元素定义了checked属性。该属性是可读/写的布尔值,它指定了元素当前是否选中。defaultChecked属性也是布尔值,他是HTML属性checked的值,它指定了元素在第一次加载页面时是否选中。
15.当用户单击单选按钮或复选开关按钮,单选或复选框元素触发了onclick事件。如果由于单击开关按钮改变了它的状态,它也触发onchange事件。(但是,当用单击其他单选按钮而导致这个单选按钮状态的改变,后者不会触发onchange事件。)
16.文本域:在HTML5中placeholder属性指定了用户输入前在输入域中显式的提示信息。onchange事件处理程序是在用户输入新的文本或编辑已存在的文本时触发,它表明用户完成了编辑并将焦点移出文本域。
17密码输入元素只能防止眼睛窥视,但在提交表单时输入未经任何加密(除非通过安全的HTTPS连接提交它),当在网络上传输时,它可能被看见。
18.document.write():(曾经是百度的笔试题)会将字符串连接起来,然后将结果字符串插入到文档中调用它的脚本元素的位置。当脚本执行结束,浏览器解析生成的输出并显示它。只有在解析文档时才能使用write()方法输出HTML到当前文档中。也就是说能够在<script>元素中的顶层代码中调用document.write(),就是因为这些脚本的执行时文档解析流程的一部分。如果将document.write()放在一个函数的定义中。而该函数的调用是从一个事件处理程序中发起的,产生的结果未必是你想要的——事实上,它会擦除当前文档和它包含的脚本!同理,在设置了defer或async属性的脚本中不要使用document.write().
以上说的比较模糊:下面详细解读:
document.write()方法可以用在两个方面:页面载入过程中用实时脚本创建页面内容,以及用延时脚本创建本窗口或新窗口的内容。
在载入页面后,浏览器输出流自动关闭。在此之后,任何一个对当前页面进行操作的document.write()方法将打开—个新的输出流,它将清除当前页面内容(包括源文档的任何变量或值)。因此,假如希望用脚本生成的HTML替换当前页面,就必须把HTML内容连接起来赋给一个变量,使用一个document.write()方法完成写操作。不必清除文档并打开一个新数据流,一个document.write()调用就可完成所有的操作。
关于document.write()方法还有一点要说明的是它的相关方法document.close()。脚本向窗口(不管是本窗口或其他窗口)写完内容后,必须关闭输出流。在延时脚本的最后一个document.write()方法后面,必须确保含有document.close()方法,不这样做就不能显示图像和表单。并且,任何后面调用的document.write()方法只会把内容追加到页面后,而不会清除现有内容来写入新值。为了演示document.write()方法,我们提供了同一个应用程序的两个版本。一个向包含脚本的文档中写内容,另—个向—个单独的窗口写内容。请在文本编辑器中键人每个文档,以.html文件扩展名保存,并在浏览器中打开文档。
示例1创建一个按钮,它为文档组合新的HTML内容,包括新文档标题的HTML标记和标记的颜色属性。使用组合在newContent变量中的内容,document.write()语句可以把所有新内容写到文档中,完全清除示例1中的内容。然后需要调用document.close()语句关闭输出流。当载入该文档并单击按钮时,可以注意到浏览器标题栏中的文档标题因此而改变。当回到原始文档并再次单击该按钮时,可以看到动态写入的第二个页面的载入速度甚至比重载原始文档还要快。
示例1 在当前窗口使用document.write()。
<!DOCTYPEhtml PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml"><title>Writing to SameDoc</title>
<scriptlanguage="JavaScript">
function reWrite(){
// assemble content for new window
var newContent ="<html><head><title>A NewDoc</title></head>"
newContent += "<bodybgcolor=‘aqua‘><h1>This document is brand new.</h1>"
newContent += "Click the Back buttonto see original document."
newContent +="</body></html>"
// write HTML to new window document
document.write(newContent)
document.close() // close layout stream
}
</script>
</head>
<body>
<form>
<input type="button"value="http://www.mamicode.com/Replace Content" onClick="reWrite()">
</form>
</body>
</html>
示例2中,情况有点复杂,因为脚本创建了一个子窗口,整个脚本生成的文档都将写入该窗口中。为了使新窗口的引用在两个函数中保持激活状态,我们将newWindow变量声明为全局变量。页面载入时,onLoad事件处理调用makeNewWindow()函数,该函数生成一个空的子窗口。另外,我们在window.open()方法的第三个参数中加入一个属性,使子窗口的状态栏可见。
页面上的按钮调用subWrite()方法,它执行的第一个任务是检查子窗口的closed属性。假如关闭了引用窗口,该属性(只在较新的浏览器版本中存在)返回true。如果是这种情况(假如用户手动关闭窗口),该函数再次调用makeNewWindow()函数来重新打开那个窗口。
窗口打开后,新的内容作为字符串变量组合在一起。与示例1一样,一次性写入内容(虽然对单独的窗口没有必要),接下来调用close()方法。但是注意一个重要的区别:write() 和 close()方法都明显地指定了子窗口。
示例2 在另一个窗口中使用document.write()
<!DOCTYPEhtml PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml"><title>Writing toSubwindow</title>
<scriptlanguage="JavaScript">
var newWindow
function makeNewWindow(){
newWindow =window.open("","","status,height=200,width=300")
}
function subWrite(){
// make new window if someone has closed it
if(newWindow.closed){
makeNewWindow()
}
// bring subwindow to front
newWindow.focus()
// assemble content for new window
var newContent ="<html><head><title>A NewDoc</title></head>"
newContent += "<bodybgcolor=‘coral‘><h1>This document is brand new.</h1>"
newContent +="</body></html>"
// write HTML to new window document
newWindow.document.write(newContent)
newWindow.document.close() // 如果此处不关闭。可以看到文档会被连续的写入到子窗体中。
}
</script>
</head>
<bodyonLoad="makeNewWindow()">
<form>
<input type="button"value="http://www.mamicode.com/Write to Subwindow" onClick="subWrite()">
</form>
</body>
</html>
另外如果,将docume.write()函数绑定到事件中,可以看到,整个文档流将被重写,如果该方法调用后close掉,再写入内容,则close之前的内容将被忽略。eg:
function writetext(){
document.write("添加一些文本!");//这部分内容将被忽略
document.close();
document.write("添加一些文本2!");
}
19.查询用户选取的文本:
function getSelectedText(){
if(window.getSelection){//HTML5标准API
returnwindow.getSelection().toString();
}
elseif(document.selection){//IE特有技术
returndocument.selection.createRange().text;
}
}
20.可编辑的内容:有两种方法启用可编辑功能。其一,设置任何标签的HTML contenteditable属性;其二,设置对应元素的JavaScript contentededitable属性;这都将使得元素的内容可编辑。Document对象的designMode属性设置为字符串“on”使得整个文档可编辑(设置为off将恢复为只读文档)。
本文出自 “虎哥的博客” 博客,请务必保留此出处http://7613577.blog.51cto.com/7603577/1572701
脚本化文档(二)