Javascript DOM 编程实例讲解--仿LightBox效果提示框

 在开发中经常要涉及到DOM编程,我想大家也跟我一样,经常要处理各种DOM编程的操作,今天我就拿一个提示框效果来作为实例,讲讲DOM编程的一些基础知识。由于个人能力有限,有什么不对的,也谢谢大家给我指出来,好了,让我们开始吧!

演示地址: http://www.yaohaixiao.com/code/alertbox/index.htm


图一



实现原理:
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种不同的类型,在这里我就用一段代码来做介绍了:

     提示:您可以先修改部分代码再运行

这么多的类型中,我们常用的就只有 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节点最直接的方法,很常用。

现在就来看看我们这个提示框的代码吧(终于回到我们的实例了,差点还以为要去写一本书了,^-^):

     提示:您可以先修改部分代码再运行

我们看到:

     提示:您可以先修改部分代码再运行

我们就通过document.getElementById("btnshow")获得了“显示信息层”这个节点,呵呵,再让我们回到上面的nodetype,我们用NodeType方法来看看这个节点是什么类型吧,我们要这么写:

     提示:您可以先修改部分代码再运行

看看我们得到了什么?


图三



1,对照上面给的nodetype的代码:1代表Element Node。当然按钮是个元素节点。再来验证下上面提到的在文档中的关系吧:parent(父)、child(子)、sibling(兄弟)

怎么查询节点的父节点,我们使用 element.parentNode来获得父节点,看看这个代码

     提示:您可以先修改部分代码再运行

看看我们又得到了什么?


图四



BODY!呵呵,对啊这个按钮的父亲节点就是body,看看我们的代码就知道了:

     提示:您可以先修改部分代码再运行

那么我们来看看这个按钮有没有子节点呢,我们使用 element.hasChildNodes()方法来判断它是否有子节点。代码我们这么写:

     提示:您可以先修改部分代码再运行


图五



false,当然是false,因为按纽是没有子节点的。

接着我们再来查找下他的兄弟节点吧,我们使用 element.nextSibling()方法来获得兄弟(邻居)节点,而我们这里的代码这么写:

     提示:您可以先修改部分代码再运行


图六



3?什么意思?呵呵,说明下我的这个图是在firefox中获取的,在firefox中会把换行的空格作为一个textNode处理,所以 btnShow.nextSibling.nodeType我们获得节点类型就是3了。所以要做兼容Firefox的DOM编程开发时,要调用 nextSibling方法时,在写XHTML代码时,有时候是需要在同一样写两个兄弟节点的,代码如下:

     提示:您可以先修改部分代码再运行

讲到现在,我们所接触的这些方法都是获取单个的节点,那么怎样获取一组节点呢?现在就要隆重介推出 document.getElementsByTagName()

getElementsByTagName:(核心[XML]DOM)用来返回一个包含所有tagName(标签名)特性等于某个指定值的元素的NodeList。还是用一段代码来看看,它是怎么工作的吧:

     提示:您可以先修改部分代码再运行

我 们首先用getElementById找到id为newslist的节点(UL),然后用getElementsByTagName("li")就获得了 UL下的全部LI元素Lines了。我们看到了,Lines是一个数组,我们就可以通过一个循环来获得每一个li的内容。这个也是我们使用 getElementsByTagName的一个很常用的方法。

怎么样?现在知道怎么查找一个节点了、怎么获取一组元素、如何判断一个节点的类型、怎么查找一个节点的parentNode(父节点)、判断节点是否有子节点和怎么来获得节点的下一个兄弟节点。那现在我们就运用刚才学习的东西,对节点的操作做个扩展,看看下面的代码:

     提示:您可以先修改部分代码再运行

DOM的高级操作--创建/追加/删除节点、设置CSS样式、设置节点属性

还是拿刚才的代码,看看怎么运用这个方法获得节点:

     提示:您可以先修改部分代码再运行

哈哈,活学活用,才是我们学习的目的,不是吗?

DOM的高级操作--创建/追加/删除节点、设置CSS样式、设置节点属性

document.createElement(tagName)--创建节点

通过对前面基础知识的学习,我们现在开始正式讲解这个实例的实现过程了,接着开实例下面代码:

     提示:您可以先修改部分代码再运行

这样我们就通过document.createElement("div");创建了一个div节点,但是只是创建节点还是远远不够的,看看我们开头的原理分析,我们创建的这个层有特殊的position定位,而我们怎么来实现给它添加这些属性(Attribute)呢?

element.setAttribute--设置CSS样式
为什么我要用Attribute而不是Property呢?因为我接下来要介绍的一个DOM操作的方法element.setAttribute(AttributeName,value)--给节点设置属性。还是回到例子

     提示:您可以先修改部分代码再运行

这样我就给我刚刚创建的div添加了一个id属性,值是shadow,相当于这么写:

     提示:您可以先修改部分代码再运行

为什么要给这个节点添加id?其实目的很简单,以便我们在以后的程序开发中使用document.getElementById查寻这个节点。

element.getAttribute(AttributeName)--获得属性

既然能够设置属性,我们就可以使用element.getAttribute(AttributeName)方法获得属性,举个例子:

     提示:您可以先修改部分代码再运行

接下来就是要设置这个节点的position属性了,怎么做?看看我的代码:

     提示:您可以先修改部分代码再运行

这么设置的结果就等于我们这么写CSS:

     提示:您可以先修改部分代码再运行

这么一写,我想大家就清楚现在的这个遮照层的样式是个什么样子了:一个用绝对定位的层,占满整个屏幕,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):

     提示:您可以先修改部分代码再运行

呵呵,我为什么单单要拿z-index这个属性来讲呢?这里要讲一下设置CSS样式的语法:属性都必须是小写的,但是如z-index,background-color,text-decoration这样中间有连接符的属性,就采用骆驼华的写法,就是这样:

     提示:您可以先修改部分代码再运行

现在大家清楚了怎么用javascript给一个节点设置样式了吧。其实还有更简单的方法,怎么个简单法?其实在我上面的代码就已经给出了答案,使用setAttribute()方法,大家看看下面的代码就清楚了。

     提示:您可以先修改部分代码再运行

发现了什么问题没有?对了,在这里我创建了节点后,只是使用setAttribute()方法给节点设置了id 属性,而没有像设置shadow节点那样再给它添加CSS样式了,但是它的样式已经获得了,因为我早已经在之前的CSS代码写好样式了。

     提示:您可以先修改部分代码再运行

所 以这个更简单的方法就是事先就把要创建的节点的样式写好,就可以直接使用setAttribute()方法给节点设置一个于写好的CSS对应的id或 class属性就可以了(给节点添加class属性,如:element.setAttribute("class",className))。

怎么给节点设置CSS样式,这里基本上就讲完了,还是回到我们的实例,看看,后来我又给shadow节点添加了什么样式:

     提示:您可以先修改部分代码再运行

对 了,我们的shadow(阴影)是有一个半透明的效果的,所以我分别使用了shadow.style.filter = "alpha(opacity=20)";和shadow.style.opacity = 0.2;给它设置了透明的滤镜。其实就是一般的设置CSS样式。不过这里要说是————如何判断浏览器类型?



判断浏览器类型

     提示:您可以先修改部分代码再运行

这些代码的作用就是用来判断用户使用的浏览器类型的。可是大家要问了,isOpear我们可以很清楚知道,是判断浏览器是否为opera,但是document.all是判断什么的?

这个问题问得好。接下来就是我要简单的讲一讲在javascript编程中另一个要经常面对的问题--对浏览器类型的判断。

首先我给出一段常用的判断浏览器类型的代码:

     提示:您可以先修改部分代码再运行

还有些其他的判断其他类型的浏览器的代码,这里就不多写了,大家使用这些常用的代码基本就能够应对常规的开发了。调用这个类(这里就是我们前面提到的 “用户定义对象(user-defined object)”)的方法:

     提示:您可以先修改部分代码再运行

使用起来很方便,不是吗?不过这里其实我重点要介绍的不是以这中方法来判断浏览器类型,而是重点介绍一下像if(document.all)这样的判断浏览器类型的方法。又是刚才的问题,这个怎么判断浏览器类型啊?来看看这段代码:

     提示:您可以先修改部分代码再运行

呵呵,看到了这段代码里面的注释了吗?再看看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)--给节点追加子节点

接着开下面的代码:

     提示:您可以先修改部分代码再运行

这里的代码,想必大家现在已经可以看明白了。我们又继续创建了其他的节点并给他们各自添加了不同的属性。不过在讲如何给节点追加子节点之前,先来介绍一下: element.createTextNode(data)

element.createTextNode(data)--创建文本节点

前面我们一开始介绍了,节点有不同的类型,我们常用的就只有 Element Node(元素节点)Attribute Node(属性节点)Text Node(文本节点)。 前面我们已经介绍了如何创建Element节点(Element.createElement(tagName)),其实创建属性节点的方法我们也介绍 了,就是element.setAttribute(AttributeName,value)。只是在XHTML中,我们一般不把属性作为一个节点来看 待。

现在要讲的就是如何创建文本节点(TextNode)。在我的代码中,不知道您注意看了没有,我在将一个节点里增加文本时,使用了两个方法:

     提示:您可以先修改部分代码再运行

怎 么看?先来看看element.createTextNode(data)/document.createTextNode("爱唱卡充值");这里的 date="爱唱卡充值";然后使用appendChild(Element)方法,添加到标题节点。用个不恰当,但是却很形象的比喻,看看我这么写:

     提示:您可以先修改部分代码再运行

呵 呵,现在是不是看出两个方法之间的关系了(虽然这些说不恰当)。那我这里使用了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,那么我们就创建一个标题栏节点:

     提示:您可以先修改部分代码再运行

标题栏里有3个子节点,h2,closeBar,win-tr,

那我们就创建它们:

     提示:您可以先修改部分代码再运行

而H2节点里又有一个img(元素)节点和一个文本节点,我们就创建并追加进去:

     提示:您可以先修改部分代码再运行

接着是关闭按钮,里面有a标签,A标签又有一个文本节点,我们接着创建并追加进去:

     提示:您可以先修改部分代码再运行

最后是这里的win-tr节点,我们创建完后,然后跟前面的H2和closeBar节点一起追加到标题节点(win-tl)中:

     提示:您可以先修改部分代码再运行

接下来是创建内容节点msg-content,里面包含左边框msg-leftbar、右边框msg-rightbar、正文msg和确定按钮:

     提示:您可以先修改部分代码再运行

而正文中有包含标题h3和提示内容p:

     提示:您可以先修改部分代码再运行

接着添加提示按钮,而它里面有A标签和A标签的文本节点

     提示:您可以先修改部分代码再运行

接下来就我就这样一步步的创建和追加。最后将这里的3大块,标题栏,提示内容和底边一起追加到提示框中,然后将shadow和提示框追加到文档中。

     提示:您可以先修改部分代码再运行

到这里,我们程序基本上算完成了.现在就是稍加修饰下.让我们的提示框定位在shadow层之上,而且最好是在屏幕中央,这些问题CSS就可以搞定了.

大结局

如何让层居中

     提示:您可以先修改部分代码再运行

看出来了吗?首先定位要用absolute,z-index:999,比shadow的10要高,在它上面了,left:50%,right:50%;然后margin:-(提示框高/2)px 0 0 -(提示框宽/2)px;

最后就是给关闭按钮和确定按钮添加事件(关闭窗口--移除shadow和window节点)

移除节点--element.removeChild(objId)

很简单的几行代码

     提示:您可以先修改部分代码再运行

唯 一要说明的是这段代码一定是要放到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文档,等下次有机会在跟大家一起讨论,今天收工了。

原文地址:http://bbs.51js.com/viewthread.php?tid=77238
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值