仿LightBox效果提示
做WEB前台开发也有两年多,在开发中经常要涉及到DOM编程,我想大家也跟我一样,经常要处理各种DOM编程的操作,今天我就拿一个提示框效果来作为实例,讲讲DOM编程的一些基础知识。由于个人能力有限,有什么不对的,也谢谢大家给我指出来,好了,让我们开始吧!
演示地址:http://www.yaohaixiao.com/code/alertbox/index.htm
实际开发应用演示:http://vv8.ising99.com/
实现原理:
1、创建节点--利用docment.createElement()/element.createTextNode()方法动态创建节点,再通过使用element.appenChild()方法,向文档中添加创建的子节点。
2、利用position:absolute的特性--将遮照层和提示框节点的position设置为absolute,利用absolute的特性, position:absolute的节点的特点是不影响其周围节点的布局。所以我们将遮照层的position属性设置为absolute,这样遮照层即使覆盖了整个页面,但是却不影响其他节点的(正文)布局。
3、遮照--就是要覆盖到其他层上面,所以我们就利用Javascript给遮照设置了一个z-index:10;让它覆盖到正文之上(或者说他比较厚,把其的节点都包起来了)。接着我们把再提示框的z-index设置为999从而使它在最上面显示,模拟出提示框的效果。
4、透明--原本的遮照层是蓝色的背景,是会把它下面的正文全部遮住,但是我们使用了filter(IE)和 opacity属性设置层是透明的,以便让正文得以显示。
5、移除节点--使用removeChilde()方法移除提示框节点。
6、提示框居中--其实很简单,left:50%,top:50%;然后就是设置margin:-(element.height/2)px 0 0 -(element.width/2)px;,这样就做到了提示层在屏幕中间显示。
呵呵,效果我们看到,但是具体是如何来实现的呢?不要急,我在下面的内容会一步一步的给大家做分析。现在我们先来补习一些DOM编程的基础知识。
什么是DOM?
DOM是“Document Object Model”(文档对象模型)的首字母缩写。
D就是Document(文档),如果没有document(文档),DOM也就无从谈起。当创建了一个网页并把它加载到Web浏览器中时,DOM就在幕后悄然而生。它将根据你编写的网页文档创建一个文档对象。
O就是Object(对象),在人类语言中,“对象”这个词的含义往往不那么明确和具体,它几乎可以用来称呼任何一种客观存在的事物。但在程序设计语言中, “对象”这个词的含义非常明确和具体。Javascript中“对象”是一种独立的数据集合。与某个特定对象相关联的变量被称为这个对象的属性;可以通过某个特定对象去调用的函数被称为这个对象的方法。
JavaScript语言里的对象可以分为三种类型:
●用户定义对象(user-defined object):由程序员自行创建的对象(类)。这里我们不讨论这种对象。
●内建对象(native object):内建在JavaScript语言里的对象,如Array、Math和Date等。这里我们不讨论这种对象。
●宿主对象(host object):由浏览器提供的对象,这里是我要重点介绍的。
宿主对象它们当中最基础的是window对象,window对象对应着浏览器窗口本身,这个对象的属性和方法通常被统称为BOM(浏览器对象模型)————但我觉得称之为Window Object Model(窗口对象模型)更为贴切。
不过在这里我们将把注意力集中在浏览器窗口的内部,我们将着重探讨如何对网页的内容进行处理,而用来实现这一目标的载体就是document对象。(呵呵,在我们的代码中,“document”出现的频率十分频繁)
现在,我们已经对DOM中的字母“D”(document,文档)和字母“O”(object,对象)做了解释,那么字母“M”又代表着什么呢?
M就是Model(模型),但说它代表着“Map”(地图)也未尝不可。模型也好,地图也罢,它们的含义都是某种事物的表现形式。DOM代表着被加载到浏览器窗口里的当前网页:浏览器向我们提供了当前网页的地图(或者说模型),而我们可以通过JavaScript去读取这张地图。现在就让我们来看一个地图:
看到这个地图了吧。既然是地图,就必须有诸如方向、等高线和比例尺之类的记号。要想看懂和使用地图,就必须知道这些记号的含义和用途——这个道理同样适用于DOM。要想从DOM获得信息,我们必须先把各种用来表示和描述一份文档的记号弄明白。
DOM把一份文档表示为一棵树(这里所说的“树”是数学意义上的概念),这是我们理解和运用这一模型的关键。更具体地说,DOM把文档表示为一棵家谱树。
家谱树本身又是一种模型。家谱树的典型用法是表示一个人类家族的谱系并使用parent(父)、child(子)、sibling(兄弟)等记号来表明家族成员之间的关系。家谱树可以把一些相当复杂的关系简明地表示出来:一位特定的家族成员既是某些成员的父辈,又是另一位成员的子辈,同时还是另一位成员的兄弟。
NodeType(节点类型)
说到DOM的成员关系,我又不得不介绍一下另外一个概念--NodeType(节点类型),我们的DOM的NodeType有12种不同的类型,在这里我就用一段代码来做介绍了:
// 枚举DOM节点的NodeType类型
if(typeof Node == "undefined"){
var Node = {
ELEMENT_NODE: 1,
ATTRIBUTE_NOTE: 2,
TEXT_NODE: 3,
CDATA_SECTION_NODE: 4,
ENTITY_REFERENCE_NOTE: 5,
ENTITY_NODE: 6,
PROCESSING_INSTRUCTION_NOTE: 7,
COMMENT_NODE: 8,
DOCUMENT_NODE: 9,
DOCUMENT_TYPE_NODE: 10,
DOCUMENT_FRAGMENT_NODE: 11,
NOTATION_NODE:12
}
}这么多的类型中,我们常用的就只有Element Node(元素节点)、Attribute Node(属性节点)、Text Node(文本节点),而这3个中,我们接触最多的就是Element Node 。
DOM的基本操作--查找节点
好了,我们上面介绍了NodeType,那么我们要怎么才能知道某个节点(Node)的类型呢?我们可以用Element.NoteType来获得节点的类型。不过你看到了,在这里我们首先要做的是获得这个Element先。
下面我们就来介绍一下几种获取节点的方法--document.getElementById(elementId)\document.getElementsByTagName(tagName)\document.getElementsByName.
docment.getElementById(elementId)方法:它返回的是以ID为表示的节点,而大家都知道id在页面中是唯一的,所以getElementById是在页面中搜索DOM节点最直接的方法,很常用。
现在就来看看我们这个提示框的代码吧(终于回到我们的实例了,差点还以为要去写一本书了,^-^):
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>DEMO</title>
<style type="text/css">
<!--
*{
margin:0; padding:0;
}
body{
background-color:#FFF; color:#000; text-align:center; font:normal 12px Georgia, "Times New Roman", Times, serif;
}
a:link,a:visited{
text-decoration:none; color:#000;
}
a:hover{
text-decoration:underline; color:#F00;
}
html,body{
height:100%;
}
img{
max-width:100%; height:auto; border:0;
}
ul,dl{
list-style-type:none;
}
.clear{
clear:both; font-size:1px; width:1px; height:1px; visibility:hidden;
}
div,span,p,h1,h2,h3,h4,h5,h6{
text-align:left;
}
#btnshow{
margin-top:30px;
}
#window{
position:absolute; left:50%; top:50%; width:400px; height:180px; margin:-90px 0 0 -200px;
}
#win-tl{
margin:0 auto; width:394px; padding-left:6px; color:#15428b; font:bold 12px tahoma,arial,verdana,sans-serif; background:transparent url(img/window/left-corners.png) no-repeat 0 0; zoom:1; height:24px;
}
#win-tl h2{
float:left; width:369px; height:16px; overflow:hidden; padding:4px 0 4px 0; background:transparent url(img/window/top-bottom.png) 0 0 repeat-x;
font-size:12px; line-height:16px;
}
#win-tl h2 img{
float:left; width:16px; height:16px; margin:0 5px 0 3px; display:inline; vertical-align:middle;
}
#closebar{
float:left; width:15px; height:15px; text-align:right; padding:5px 4px 4px 0;
background:transparent url(img/window/top-bottom.png) 0 0 repeat-x; overflow:hidden;
}
#closebar a:link,
#closebar a:visited{
width:255px; height:15px; overflow:hidden; display:block; margin-left:4px; text-indent:-420px; color:transparent; background:url(img/tool-sprites.gif) 0 0 no-repeat;
}
#closebar a:hover,
#closebar a:active{
background:url(img/tool-sprites.gif) -15px 0 no-repeat;
}
#win-tr{
float:right; height:24px; width:6px; font-size:1px; overflow:hidden;
background-image:url(img/window/right-corners.png);
}
#msg-content{
margin:0 auto; width:400px; height:150px; overflow:hidden;
}
#msg-leftbar{
float:left; width:6px; height:150px; overflow:hidden;
background:transparent url(img/window/left-right.png) 0 0 repeat-y;
}
#msg-rightbar{
float:right; width:6px; height:150px; overflow:hidden;
background:transparent url(img/window/left-right.png) -6px 0 repeat-y;
}
#msg{
float:left; width:386px; height:148px; border:1px solid #84A0C4; background-color:#DFE8F6; color:#15428b;
}
#info{
margin:0 auto; width:294px; height:58px; padding:35px 10px 10px 82px;
background:#DFE8F6 url(img/window/icon-info.gif) 30px 38px no-repeat; text-align:left;
overflow:hidden;
}
#info h3{
font-size:12px; height:12px; overflow:hidden; letter-spacing:1px; padding-bottom:5px;
}
#info p{
line-height:150%; padding-right:30px;
}
#btns{
margin:0 auto; width:230px; height:22px; text-align:center;
}
#btns a:link,
#btns a:visited{
margin:0 auto; width:68px; height:20px; overflow:hidden; font-size:12px; display:block;
text-indent:-999px; background-image:url(img/btnEnter-normal.gif);
}
#btns a:hover,
#btns a:active{
background-image:url(img/btnEnter-hover.gif);
}
#msg-bottom{
height:6px; width:400px; margin:0 auto; overflow:hidden;
background:transparent url(img/window/top-bottom.png) 0 -294px repeat-x;
}
#msg-bottom-right{
float:right; width:6px; height:6px; overflow:hiddden;
background:transparent url(img/window/right-corners.png) 0 -294px no-repeat;
}
#msg-bottom-left{
float:left; width:6px; height:6px; overflow:hiddden;
background:transparent url(img/window/left-corners.png) 0 -294px no-repeat;
}
-->
</style>
<script language="javascript" type="text/javascript">
<!--
function CreateDiv(){
var btnShow = document.getElementById("btnshow");
if(!btnShow) return false;
btnShow.disabled=true;
// 判断是否为Opear浏览器
var isOpear=(navigator.userAgent.indexOf('Opera')>-1);
// 创建透明阴影遮照效果层
var shadow = document.createElement("id");
// 给新创建的节点设置各个属性
shadow.setAttribute("id","shadow");
shadow.style.position="absolute"; //
shadow.style.left="0";
shadow.style.top="0";
shadow.style.width="100%";
shadow.style.height="100%";
shadow.style.zIndex="10";
// 如果是Opera浏览器则给shadow设置背景色和透明效果
if(!isOpear){
shadow.style.backgroundColor="#06C";
if(document.all){
shadow.style.filter = "alpha(opacity=20)";
}
else{
shadow.style.opacity = 0.2;
}
}
var obj=document.createElement("div");
obj.setAttribute("id","window");
obj.style.zIndex="999";
var divTitle = document.createElement("div");
divTitle.setAttribute("id","win-tl");
var H2 = document.createElement("h2");
var IMG=document.createElement("img");
IMG.setAttribute("src","img/win.png");
IMG.setAttribute("alt","Window-Icon");
var txtTitle=document.createTextNode("爱唱卡充值");
H2.appendChild(IMG);
H2.appendChild(txtTitle);
var closeBar=document.createElement("div");
closeBar.setAttribute("id","closebar");
var A = document.createElement("a");
A.innerHTML="关闭窗口";
A.setAttribute("href","#1");
A.setAttribute("id","btnClose");
A.setAttribute("title","关闭窗口");
closeBar.appendChild(A);
var titleRight=document.createElement("div");
titleRight.setAttribute("id","win-tr");
divTitle.appendChild(H2);
divTitle.appendChild(closeBar);
divTitle.appendChild(titleRight);
var Container = document.createElement("div");
Container.setAttribute("id","msg-content");
var cntLeft=document.createElement("div");
cntLeft.setAttribute("id","msg-leftbar");
var MSG=document.createElement("div");
MSG.setAttribute("id","msg");
var INFO=document.createElement("div");
INFO.setAttribute("id","info");
var H3 = document.createElement("h3");
H3.innerHTML="恭喜您充值成功!";
var P = document.createElement("p");
P.innerHTML="充值单号为:<strong id=\"txtuid\">1653235</strong>(请您牢记,便于查询)";
INFO.appendChild(H3);
INFO.appendChild(P);
var Btns=document.createElement("div");
Btns.setAttribute("id","btns");
var btnEnter=document.createElement("a");
btnEnter.setAttribute("id","btnEnter");
btnEnter.setAttribute("href","#1");
var txtEnter=document.createTextNode("确定");
btnEnter.appendChild(txtEnter);
Btns.appendChild(btnEnter);
MSG.appendChild(INFO);
MSG.appendChild(Btns);
var cntRight=document.createElement("div");
cntRight.setAttribute("id","msg-rightbar");
Container.appendChild(cntLeft);
Container.appendChild(MSG);
Container.appendChild(cntRight);
var msgBottom = document.createElement("div");
msgBottom.setAttribute("id","msg-bottom");
var msgBLeft=document.createElement("div");
msgBLeft.setAttribute("id","msg-bottom-left");
var msgBRight=document.createElement("div");
msgBRight.setAttribute("id","msg-bottom-right");
msgBottom.appendChild(msgBLeft);
msgBottom.appendChild(msgBRight);
document.body.appendChild(shadow);
obj.appendChild(divTitle);
obj.appendChild(Container);
obj.appendChild(msgBottom);
document.body.appendChild(obj);
hiddenDiv();
}
function hiddenDiv(){
var objId = document.getElementById("window");
var shadow = document.getElementById("shadow");
var aClose = document.getElementById("btnClose");
var btnEnter = document.getElementById("btnEnter");
var btnShow = document.getElementById("btnshow");
/***
如果节点阴影、提示框、关闭按钮或确定按钮,
有一个节点不存在,则退出此程序(避免报错)
***/
if(!shadow || !objId || !aClose || !btnEnter || !btnShow) {
return false;
}
else{
// 设置关闭和确定按钮的功能--关闭(移除)提示框
btnEnter.onclick=aClose.onclick=function(){
document.body.removeChild(objId);
document.body.removeChild(shadow);
btnShow.disabled=false;
}
}
}
//-->
</script>
</head>
<body>
<input name="btnshow" id="btnshow" type="button" onclick="CreateDiv()" value="显示信息层" />
</body>
</html>
我们看到:
var btnShow = document.getElementById("btnshow");
if(!btnShow) return false;
btnShow.disabled=true;我们就通过document.getElementById("btnshow")获得了“显示信息层”这个节点,呵呵,再让我们回到上面的nodetype,我们用NodeType方法来看看这个节点是什么类型吧,我们要这么写:
/*****
IE浏览器要7.0 才支持nodeType属性,所以我上面才给出了那段枚举所
有节点类型的代码,以方便在低版本的IE浏览器中判断节点类型。
*****/
alert(btnShow.nodeType); 看看我们得到了什么?
1,对照上面给的nodetype的代码:1代表Element Node。按钮当然是个元素节点。再来验证下上面提到的在文档中的关系吧:parent(父)、child(子)、sibling(兄弟)
怎么查询节点的父节点,我们使用element.parentNode来获得父节点,看看这个代码
alert(btnShow.parentNode.tagName);看看我们又得到了什么?
BODY!呵呵,对啊这个按钮的父亲节点就是body,看看我们的代码就知道了:
<body>
<input name="btnshow" id="btnshow" type="button" onclick="CreateDiv()" value="显示信息层" />
</body>那么我们来看看这个按钮有没有子节点呢,我们使用element.hasChildNodes()方法来判断它是否有子节点。代码我们这么写:
alert(btnShow.hasChildNodes());
false,当然是false,因为按纽是没有子节点的。
接着我们再来查找下他的兄弟节点吧,我们使用element.nextSibling()方法来获得兄弟(邻居)节点,而我们这里的代码这么写:alert(btnShow.nextSibling.nodeType);
3?什么意思?呵呵,这里要先说明一下————我的这个图是在firefox中获取的,在firefox中会把换行的空格作为一个textNode处理,所以 btnShow.nextSibling.nodeType我们获得节点类型就是3了。所以要做兼容Firefox的DOM编程开发时,要调用 nextSibling方法时,在写XHTML代码时,有时候是需要在同一样写两个兄弟节点的,代码如下:
// ul作为btnShow的兄弟节点,需要紧接在<input />标签后写
<input name="btnshow" id="btnshow" type="button" onclick="CreateDiv()" value="显示信息层" /><ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>讲到现在,我们所接触的这些方法都是获取单个的节点,那么怎样获取一组节点呢?现在就要隆重介推出document.getElementsByTagName()。
getElementsByTagName:(核心[XML]DOM)用来返回一个包含所有tagName(标签名)特性等于某个指定值的元素的NodeList。还是用一段代码来看看,它是怎么工作的吧:
<li>First Line</li>
<li>Second Line</li>
<li>Third Line</li>
<li>Fourth Line</li>
<li>Fifth Line</li>
</ul>
<script language="javascript" type="text/javascript">
<!--
function demoGetElementsByTagName(){
var newsList = document.getElementById("newslist");
if(!newsList) return false;
var Lines = newsList.getElementsByTagName("li");
alert(Lines.length);
for(var i=0;i<Lines.length;i++){
alert(Lines[i].innerHTML);
}
}
demoGetElementsByTagName();
//-->
</script> 我们首先用getElementById找到id为newslist的节点(UL),然后用getElementsByTagName("li")就获得了UL下的全部LI元素Lines了。我们看到了,Lines是一个数组,我们就可以通过一个循环来获得每一个li的内容。这个也是我们使用 getElementsByTagName的一个很常用的方法。
怎么样?现在知道怎么查找一个节点了、怎么获取一组元素、如何判断一个节点的类型、怎么查找一个节点的parentNode(父节点)、判断节点是否有子节点和怎么来获得节点的下一个兄弟节点。那现在我们就运用刚才学习的东西,对节点的操作做个扩展,看看下面的代码:// 获取el节点内tag标签样式为name样式索引为size的DOM节点
function getElByClassName(tag,name,size,el){
if(!document.getElementsByTagName) return false;
var el=(el)?el:document;
var itm=el.getElementsByTagName(tag);
var num=1;
for(i=0;i<itm.length;i++){
if(itm[i].className===name&&size===num){
return itm[i];
}
else if(itm[i].className===name){
num++;
}
}
return false;
}
还是拿刚才的代码,看看怎么运用这个方法获得节点:
<!--为了演示,所以才会每个li都加了样式,我们实际开发的时候是很少这么做的-->
<ul id="newslist">
<li class="menu">First Line</li>
<li class="menu">Second Line</li>
<li class="menu">Third Line</li>
<li class="menu">Fourth Line</li>
<li class="menu">Fifth Line</li>
</ul>
<script language="javascript" type="text/javascript">
<!--
// 获取el节点内tag标签样式为name样式索引为size的DOM节点
function getElByClassName(tag,name,size,el){
if(!document.getElementsByTagName) return false;
var el=(el)?el:document;
var itm=el.getElementsByTagName(tag);
var num=1;
for(i=0;i<itm.length;i++){
if(itm[i].className===name&&size===num){
return itm[i];
}
else if(itm[i].className===name){
num++;
}
}
return false;
}
var liThree = getElByClassName("li","menu",3,document.getElementById("newslist"));
alert(liThree.innerHTML);
//-->
</script>哈哈,活学活用,才是我们学习的目的,不是吗?
document.createElement(tagName)--创建节点
通过对前面基础知识的学习,我们现在开始正式讲解这个实例的实现过程了,接着看实例下面代码:// 创建透明阴影遮照效果层
var shadow = document.createElement("div");这样我们就通过document.createElement("div");创建了一个div节点,但是只是创建节点还是远远不够的,看看我们开头的原理分析,我们创建的这个层有特殊的position定位,而我们怎么来实现给它添加这些属性(Attribute)呢?
element.setAttribute--设置CSS样式
为什么我要用Attribute而不是Property呢?因为我接下来要介绍的一个DOM操作的方法element.setAttribute(AttributeName,value)--给节点设置属性。还是回到例子shadow.setAttribute("id","shadow"); 这样我就给我刚刚创建的div添加了一个id属性,值是shadow,相当于这么写:<div id="shadow"></div>
为什么要给这个节点添加id?其实目的很简单,以便我们在以后的程序开发中使用document.getElementById查寻这个节点。
element.getAttribute(AttributeName)--获得属性
既然能够设置属性,我们就可以使用element.getAttribute(AttributeName)方法获得属性,举个例子:
<input name="btnshow" id="btnshow" type="button" onclick="CreateDiv()" value="显示信息层" />
<script language="javascript" type="javascript">
<!--
var btn=document.getElementById("btnshow");
alert(btn.getAttribute("value"));
//-->
</script>接下来就是要设置这个节点的position属性了,怎么做?看看我的代码:
shadow.style.position="absolute";
shadow.style.left="0";
shadow.style.top="0";
shadow.style.width="100%";
shadow.style.height="100%";
shadow.style.zIndex="10";这么设置的结果就等于我们这么写CSS:
#shadow{
position:absolute;
left:0;
top:0;
width:100%;
height:100%;
z-index:10;
}这么一写,我想大家就清楚现在的这个遮照层的样式是个什么样子了:一个用绝对定位的层,占满整个屏幕,z坐标为10。
这么一翻译,我想他的效果大家很清楚了,这里要说明是的position:absolute;达到的效果,虽然它占满了真个屏幕,但却不影响其他元素的布局,例子中的按钮的布局就没有受到影响。而至于position方法的说明,请看《[url=http://www.yaohaixiao.com/samples/articles/index.htm]Ajax标签导航实例详解[url]》一文中对position定位的说明。
而在这里我要重点介绍的是怎么使用Javascript给一个DOM节点添加CSS样式?在Javascript里我们是通过style这个关键字来设置的,然后就是接着属性,最后给属性付值。就像这样(element.style.property=value):shadow.style.zIndex="10";呵呵,我为什么单单要拿z-index这个属性来讲呢?这里要讲一下设置CSS样式的语法:属性都必须是小写的,但是如z-index,background-color,text-decoration这样中间有连接符的属性,就采用骆驼华的写法,就是这样:
shadow.style.zIndex="1";
shadow.style.backgroundColor="#FFF";
shadow.style.textDecoration="underline";现在大家清楚了怎么用javascript给一个节点设置样式了吧。其实还有更简单的方法,怎么个简单法?其实在我上面的代码就已经给出了答案,使用setAttribute()方法,大家看看下面的代码就清楚了。
// 创建提示框层节点
var obj=document.createElement("div");
obj.setAttribute("id","window");
obj.style.zIndex="999";发现了什么问题没有?对了,在这里我创建了节点后,只是使用setAttribute()方法给节点设置了id 属性,而没有像设置shadow节点那样再给它添加CSS样式了,但是它的样式已经获得了,因为我早已经在之前的CSS代码写好样式了。#window{
position:absolute;
left:50%;
top:50%;
width:400px;
height:180px;
margin:-90px 0 0 -200px;
}所以这个更简单的方法就是事先就把要创建的节点的样式写好,就可以直接使用setAttribute()方法给节点设置一个于写好的CSS对应的id或 class属性就可以了(给节点添加class属性,如:element.setAttribute("class",className))。
怎么给节点设置CSS样式,这里基本上就讲完了,还是回到我们的实例,看看,后来我又给shadow节点添加了什么样式:
// 如果是Opera浏览器则给shadow设置背景色和透明效果
if(!isOpear){
shadow.style.backgroundColor="#06C";
if(document.all){
shadow.style.filter = "alpha(opacity=20)";
}
else{
shadow.style.opacity = 0.2;
}
}对了,我们的shadow(阴影)是有一个半透明的效果的,所以我分别使用了shadow.style.filter = "alpha(opacity=20)";和shadow.style.opacity = 0.2;给它设置了透明的滤镜。其实就是一般的设置CSS样式。不过这里要说是————如何判断浏览器类型?
判断浏览器类型
// 判断是否为Opear浏览器
var isOpear=(navigator.userAgent.indexOf('Opera')>-1);
if(!isOpear){
...
if(document.all){
...
}
} 这些代码的作用就是用来判断用户使用的浏览器类型的。可是大家要问了,isOpear我们可以很清楚知道,是判断浏览器是否为opera,但是document.all是判断什么的?
这个问题问得好。接下来我要简单的讲一讲在javascript编程中另一个要经常面对的问题--对浏览器类型的判断。
首先我给出一段常用的判断浏览器类型的代码:
var Brower={
// 判断是否为IE6浏览器
isIE6:function(){return navigator.userAgent.search('MSIE')>0&&navigator.userAgent.search('6')>0;},
// 判断是否为IE浏览器
isIE:function(){return navigator.userAgent.search('MSIE')>0;},
// 判断是否为Opera浏览器
isOpera:function(){return navigator.userAgent.indexOf('Opera')>-1;},
// 判断是否为FireFox浏览器
isMoz:function(){return navigator.userAgent.indexOf('Mozilla/5.')>-1;}
}
// Do something
} 使用起来很方便,不是吗?不过这里其实我重点要介绍的不是以这中方法来判断浏览器类型,而是重点介绍一下像if(document.all)这样的判断浏览器类型的方法。又是刚才的问题,这个怎么判断浏览器类型啊?来看看这段代码:
// 获取DOM节点
function $(i){
if(!document.getElementById)return false;
if(typeof i==="string"){
if(document.getElementById && document.getElementById(i)) {
// W3C DOM
return document.getElementById(i);
}
else if (document.all && document.all(i)) {
// MSIE 4 DOM
return document.all(i);
}
else if (document.layers && document.layers[i]) {
// NN 4 DOM.. note: this won't find nested layers
return document.layers[i];
}
else {
return false;
}
}
else{return i;}
} 呵呵,看到了这段代码里面的注释了吗?再看看else if (document.all && document.all(i)),呵呵,我们在开发要面对的一个很头疼的问题————浏览器的兼容问题。原来我们做什么浏览器类型判断,其实根源就在于各大浏览器之间仍然存在着兼容问题。
各个浏览器之间都有着自己一些独特的标准,都有着自己的“专利”方法(对于以前的那段浏览器大战的历史,感兴趣的朋友可以GOOGLE一下),虽然现在我们的各个浏览器服务商都开始统一的支持W3C指定的标准,但是兼容性的问题仍然存在,也就是我刚才所的“专利”。
话题回到我们的实例,if(document.all) 是什么意思?这个就是我们的IE的“专利”(获得节点的“专利”),在IE浏览器中使用document.all[elementID]方法也可以同样获取指定ID的节点,效果跟document.getElementById一样,因为只有IE支持这么查找节点,所以如果支持docment.all(也就是if(document.all)),那么它就是IE浏览器了。
再看看,我上面给的代码,就是一个为了兼容浏览器而改写(document.getElementById)的一个函数,document.layers 就是基于Gecko内核浏览器支持的查询指定ID节点的方法。利用这些“专利”,我们就可以很方便的来判断浏览器的类型了,而不用花费大量时间和经历去分析userAgent的信息了。
顺便再多说一句,刚才的那些“专利”其实要是都改用支持W3C的document.getElementById,我们也就不用那么费力了。不过倒是真的要感谢我们IE的一些专利,比如我们著名的innerHTML。没有它,也就没有我们现在这个AJAX技术了。
又扯远了,还是回到我们的主题,由于浏览器的不兼容和各自的“专利”技术,所以我们这里要设置一个透明的效果,也针对IE和基于Gecko内核浏览器使用了filter和opacity属性来设置我们shadow层的透明值。
element.appendChild(element)--给节点追加子节点
接着看下面的代码:
var divTitle = document.createElement("div");
divTitle.setAttribute("id","win-tl");
var H2 = document.createElement("h2");
var IMG=document.createElement("img");
IMG.setAttribute("src","img/win.png");
IMG.setAttribute("alt","Window-Icon");
var txtTitle=document.createTextNode("爱唱卡充值");
H2.appendChild(IMG);
H2.appendChild(txtTitle);
var closeBar=document.createElement("div");
closeBar.setAttribute("id","closebar");
var A = document.createElement("a");
A.innerHTML="关闭窗口";
A.setAttribute("href","#1");
A.setAttribute("id","btnClose");
A.setAttribute("title","关闭窗口");
closeBar.appendChild(A);
var titleRight=document.createElement("div");
titleRight.setAttribute("id","win-tr");
divTitle.appendChild(H2);
divTitle.appendChild(closeBar);
divTitle.appendChild(titleRight);
var Container = document.createElement("div");
Container.setAttribute("id","msg-content");
var cntLeft=document.createElement("div");
cntLeft.setAttribute("id","msg-leftbar");
var MSG=document.createElement("div");
MSG.setAttribute("id","msg");
var INFO=document.createElement("div");
INFO.setAttribute("id","info");
var H3 = document.createElement("h3");
H3.innerHTML="恭喜您充值成功!";
var P = document.createElement("p");
P.innerHTML="充值单号为:<strong id=\"txtuid\">1653235</strong>(请您牢记,便于查询)";
INFO.appendChild(H3);
INFO.appendChild(P);
var Btns=document.createElement("div");
Btns.setAttribute("id","btns");
var btnEnter=document.createElement("a");
btnEnter.setAttribute("id","btnEnter");
btnEnter.setAttribute("href","#1");
var txtEnter=document.createTextNode("确定");
btnEnter.appendChild(txtEnter);
Btns.appendChild(btnEnter);
MSG.appendChild(INFO);
MSG.appendChild(Btns);
var cntRight=document.createElement("div");
cntRight.setAttribute("id","msg-rightbar");
Container.appendChild(cntLeft);
Container.appendChild(MSG);
Container.appendChild(cntRight);
var msgBottom = document.createElement("div");
msgBottom.setAttribute("id","msg-bottom");
var msgBLeft=document.createElement("div");
msgBLeft.setAttribute("id","msg-bottom-left");
var msgBRight=document.createElement("div");
msgBRight.setAttribute("id","msg-bottom-right");
msgBottom.appendChild(msgBLeft);
msgBottom.appendChild(msgBRight);
document.body.appendChild(shadow);
obj.appendChild(divTitle);
obj.appendChild(Container);
obj.appendChild(msgBottom);
document.body.appendChild(obj);这里的代码,想必大家现在已经可以看明白了。我们又继续创建了其他的节点并给他们各自添加了不同的属性。不过在讲如何给节点追加子节点之前,先来介绍一下:element.createTextNode(data)。
element.createTextNode(data)--创建文本节点
前面我们一开始介绍了,节点有不同的类型,我们常用的就只有Element Node(元素节点)、Attribute Node(属性节点)、Text Node(文本节点)。前面我们已经介绍了如何创建Element节点(Element.createElement(tagName)),其实创建属性节点的方法我们也介绍了,就是element.setAttribute(AttributeName,value)。只是在XHTML中,我们一般不把属性作为一个节点来看待。
现在要讲的就是如何创建文本节点(TextNode)。在我的代码中,不知道您注意看了没有,我在将一个节点里增加文本时,使用了两个方法:
P.innerHTML="充值单号为:<strong id=\"txtuid\">1653235</strong>(请您牢记,便于查询)";
var txtTitle=document.createTextNode("爱唱卡充值");
H2.appendChild(txtTitle);怎么看?先来看看element.createTextNode(data)/document.createTextNode("爱唱卡充值");这里的date="爱唱卡充值";然后使用appendChild(Element)方法,添加到标题节点。用个不恰当,但是却很形象的比喻,看看我这么写:
var date="爱唱卡充值";
H2.innerHTML=date;
P.innerHTML="充值单号为:<strong id=\"txtuid\">1653235</strong>(请您牢记,便于查询)";呵呵,现在是不是看出两个方法之间的关系了(虽然这么说不恰当)。那我这里使用了innerHTML方法将“充值单号为:<strong id=\"txtuid\">1653235</strong>(请您牢记,便于查询)”这段代码添加到了P节点里,要是我们用纯 DOM的方法,应该怎么做呢?
问题留给大家了,我这里就简单的给大家分析下,这段文档(document)的结构:
1、“充值单号为:”--是一个文本节点。
2、<strong/>标签是一个元素节点
3、strong标签有一个id属性(Attribute)
4、strong又包含了一个文本节点“1653235”
5、“(请您牢记,便于查询)”--是一个文本节点
这个问题大家好好想想,我接着介绍下面的问题,前面看到,只是创建了节点,是不够的。要想让用户看到他们,你必须要把这些节点添加到我们的文档(document) 中。
Element.appendChild(obj),看到了这个方法了吗?看看他的名字append(追加),child(孩子)。也就是说,我们要创建的那些节点是作为子节点来追加到文档中的。
在前面我已经简单的给大家演示了节点之间的关系,那我们现在倒过来,对照我生成完成后的文档目录树的结构土来分析一下我们现在的这个例子的节点关系。
我们有一个标题拦节点window-tl,那么我们就创建一个标题栏节点:
var divTitle = document.createElement("div");
divTitle.setAttribute("id","win-tl");标题栏里有3个子节点,h2,closeBar,win-tr,
那我们就创建它们:
var H2 = document.createElement("h2");
var closeBar=document.createElement("div");
closeBar.setAttribute("id","closebar");
var titleRight=document.createElement("div");
titleRight.setAttribute("id","win-tr"); 而H2节点里又有一个img(元素)节点和一个文本节点,我们就创建并追加进去:
var IMG=document.createElement("img");
IMG.setAttribute("src","img/win.png");
IMG.setAttribute("alt","Window-Icon");
var txtTitle=document.createTextNode("爱唱卡充值");
H2.appendChild(IMG);
H2.appendChild(txtTitle); 接着是关闭按钮,里面有a标签,A标签又有一个文本节点,我们接着创建并追加进去:
var closeBar=document.createElement("div");
closeBar.setAttribute("id","closebar");
var A = document.createElement("a");
/*
以纯DOM的方法,我们这么写:
var txtCloseWindow=document.createTextNode("关闭窗口");
A.appendChild(txtCloseWindow);
*/
A.innerHTML="关闭窗口";
A.setAttribute("href","#1");
A.setAttribute("id","btnClose");
A.setAttribute("title","关闭窗口");
closeBar.appendChild(A);最后是这里的win-tr节点,我们创建完后,然后跟前面的H2和closeBar节点一起追加到标题节点(win-tl)中:
var titleRight=document.createElement("div");
titleRight.setAttribute("id","win-tr");
divTitle.appendChild(H2);
divTitle.appendChild(closeBar);
divTitle.appendChild(titleRight);接下来是创建内容节点msg-content,里面包含左边框msg-leftbar、右边框msg-rightbar、正文msg和确定按钮:
var Container = document.createElement("div");
Container.setAttribute("id","msg-content");
var cntLeft=document.createElement("div");
cntLeft.setAttribute("id","msg-leftbar");
var MSG=document.createElement("div");
MSG.setAttribute("id","msg");
var cntRight=document.createElement("div");
cntRight.setAttribute("id","msg-rightbar");而正文中有包含标题h3和提示内容p:
var INFO=document.createElement("div");
INFO.setAttribute("id","info");
var H3 = document.createElement("h3");
H3.innerHTML="恭喜您充值成功!";
var P = document.createElement("p");
P.innerHTML="充值单号为:<strong id=\"txtuid\">1653235</strong>(请您牢记,便于查询)";
INFO.appendChild(H3);
INFO.appendChild(P);接着添加提示按钮,而它里面有A标签和A标签的文本节点
var Btns=document.createElement("div");
Btns.setAttribute("id","btns");
var btnEnter=document.createElement("a");
btnEnter.setAttribute("id","btnEnter");
btnEnter.setAttribute("href","#1");
var txtEnter=document.createTextNode("确定");
btnEnter.appendChild(txtEnter);
Btns.appendChild(btnEnter);接下来我们就这样一步步的创建和追加。最后将这里的3大块,标题栏,提示内容和底边一起追加到提示框中,然后将shadow和提示框追加到文档中。
document.body.appendChild(shadow);
obj.appendChild(divTitle);
obj.appendChild(Container);
obj.appendChild(msgBottom);
document.body.appendChild(obj);到这里,我们程序基本上算完成了。现在就是稍加修饰,让我们的提示框定位在shadow层之上,而且最好是在屏幕中央,这些问题CSS就可以搞定了。
如何让层居中#window{
position:absolute;
left:50%;
top:50%;
width:400px;
height:180px;
margin:-90px 0 0 -200px;
}看出来了吗?首先定位要用absolute,z-index:999,比shadow的10要高,在它上面了。left:50%,right:50%;然后margin:-(提示框高/2)px 0 0 -(提示框宽/2)px;
最后就是给关闭按钮和确定按钮添加事件(关闭窗口--移除shadow和window节点)
移除节点--element.removeChild(objId)
很简单的几行代码
// 设置关闭和确定按钮的功能--关闭(移除)提示框
btnEnter.onclick=aClose.onclick=function(){
document.body.removeChild(objId);
document.body.removeChild(shadow);
btnShow.disabled=false; 唯一要说明的是这段代码一定是要放到document.body.appendChild(obj);下面,为什么?因为没有这调语句,我们的关闭和确定按钮虽然是已经创建了,但是还没有添加到文档中,所以我们的JS还不能通过document.getElementById()方法查询到.
好了,现在我们的提示窗口就讲解完了.来复习下我们都学习到了哪些DOM编程的知识:
1.什么是DOM?
2.NodeType (节点类型)
3.document.getElementById() 查找单个节点
4.document.getElementsByTagName() 查找多个节点
5.parentNode() 如何查找一个节点的父节点
6.nextSibling() 如何查找一个节点的兄弟(邻居)节点
7.hasChildNodes() 判断一个节点时候有子节点
8.document.createElement() 创建节点
9.setAttribute(setAttributeName,value) 给节点设置属性
10.使用JS给节点设置CSS样式
11.如何判断浏览器类型
12.appendChild()如何给节点追加子节点
13.使用CSS,如何让层居中.
14.removeChild() 如何移除一个节点的子节点
看看,一个小小的程序,包含的知识点还真不少。而至于更深层的,如何使用javascript DOM编程处理XML文档,等下次有机会再跟大家一起讨论,今天收工了。
(说明:本文中有部分内容截选至《Javascript DOM 编程艺术》一书。还有,由于个人能力有限,文章中有什么错误和疏漏请大家谅解,也欢迎大家及时指正。)
http://www.yaohaixiao.com/article.asp?id=195
- 没有评论