您的位置: 首页 > 技术文档 > 网页制作 > Ajax标签导航实例详解
再谈文字溢出问题 回到列表 XMLHTTPRequest的属性和方法简介
 Ajax标签导航实例详解

作者:yaohaixiao 时间: 2008-02-25 文档类型:原创 来自:蓝色理想

第 1 页 代码篇
第 2 页 CSS技巧篇
第 3 页 Javascript技巧篇
第 4 页 DOM技巧篇
第 5 页 大结局

DOM技巧篇(DOM基础知识)

讲到这里,我们就要了解一下DOM的一些基础知识了。

DOM(Document Object Model 文档对象模型)是HTML和XML的应用程序接口(API)。DOM将把整个页面规划成有节点层级构成的文档。HTML或XML页面的每一个部分都是一个节点的衍生物。

光说可能还不怎么好理解,那么来看看我们ajax标签导航的DOM结构吧,如图五(截取的FIXFOX中的DOM图象):

DOM通过创建树来表示文档,从而使开发着对文档的内容和结构具有空前的控制力。用DOM API可以轻松地删除,添加和替换节点。

简单的了解了什么是DOM后(要想了解更多的Javascript DOM 编程知识,推荐大家看看《Javascript DOM 编程艺术》和《Javascript高级编程》这两本书,还有到作者的网站去看看,也可以直接到W3C去查询相关信息。),来看看我们这个程序里需要用到的DOM知识吧:document.getElementsByTagName()还有之前提到的$(i)函数,它们都是做什么用的呢?

document.getElementById("DOMId"):它返回的是以ID为表示的节点,而大家都知道id在页面中是唯一的,所以getElementById是在页面中搜索DOM节点最直接的方法,很常用。不过它只能查寻单个的DOM节点,我们要查询一组怎么办呢? 我们可以使用getElementsByTagName和getElementsByName。

从方法名字中的“Elements”我们也可以知道,这两个方法返回的是一组元素(数组)

getElementsByTagName:(核心[XML]DOM)用来返回一个包含所有tagName(标签名)特性等于某个指定值的元素的NodeList。

getElementsByName:(HTML DOM)用来获取所有name特性等于指定值的元素。但是这个方法在IE6和opera7.5中支持不是很好,会有错误产生,所以(个人)建议一般不要用。

OK,在对使用DOM来查寻节点的知识有了了解后,我们再来看这段代码:

/* ===========================================================
* 函数名称:$(i)
* 参数说明:i - 目标节点名称
* 函数功能:获取指定的目标DOM节点
* 返 回 值:返回要搜索的目标DOM节点
* 使用方法:$("frmSearch")
============================================================ */
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;}
}

这个函数主要是来查找指定的DOM节点的,主要是通过document.getElementById()方法,但是我们又看到了document.all()和document.layers[]方法,这个就是浏览器大战时期(各个浏览器对DOM标准支持不程度不同),各大浏览器提供商制定的各自的DOM支持规范而造成的,我们的CSS HACKS其实也是由于这个原因才会出现的。扯远了,document.all()是IE浏览器(IE5以上版本)中特有的查询节点的方法,而document.layers[i]则是其他浏览器(主要是NetScape的)的浏览器特有的。我们通过$(i)函数来统一调用,从而解决了浏览器兼容的问题。

而下面这里的代码:

// DOM节点(tabs)不存在或者浏览器不支持getElementsByTagName()函数不执行
if(!tabs || !document.getElementsByTagName) return false;

这里if(!tabs || !document.getElementsByTagName) return false;这么写是很有必要的,这里是一种预留退路的思想(在《Javascript DOM 编程艺术》一书一直灌输的思想),这么写在不支持getElementsByTagName()方法时我们的函数就不会执行,在不tabs($("news")和$("sports")),不存在的时候(可能是我们把参数名写错了),函数也不执行了,从而避免了弹出或显示脚本错误的信息。下面我们还将看到这一思想的体现,不过我们还是先来看看紧接的代码:

var theList = tabs.getElementsByTagName("li"); // 搜寻导航标签(ID为tabs)里的所有li标签
var theLink = tabs.getElementsByTagName("a");  // 搜寻导航标签(ID为tabs)里的所有a标签

为什么要找出所有的li和a标签呢?呵呵,这个是由于我这里采取的设置样式的结构决定的(其实我也老是觉得不怎么好,不过这个思维个人比较好理解--头疼医头,脚疼医脚的方法)。看看我们上边的CSS样式,大家看到了,我们是用改变标签菜单(li)的样式来实现特别显示当前标签的。那么我这里就自然要获取所有的li标签,然后给他添加onclick来调用ajaxInject(ListName,tabId,tarObj,URL),从而改变标签的样式。看看我来实现这个功能的代码吧:

for(var j=0;j<theList.length;j++){
                 var theTab = theList[j];
                 if(theTab.parentNode!=tabs) continue;
                    
                 var theA = theLink[j];
                 // 屏蔽掉a标签默认的处理(打开新链接)事件
                 theA.onclick = function(){
                     return false;   
                 }
                
                 // 为导航TAB菜单(li)设置onclick处理方法(函数)   
                 theTab.onclick = function(){
                  var theClass = this.className;
                  if(theClass!="current" && theClass!="first"){
                            var objId = this.getAttribute("id").split("-")[1]; // 当前选中标签(li)在菜单(ul)中的索引值
                            var tarObj = this.getAttribute("id").split("-")[0]; // 要显示信息的目标DOM节点ID值
                       var theURL = tarObj + "/" + tarObj + objId + ".htm"; // 要异步加载的URL地址
                         ajaxInject($(tarObj),objId,tarObj,theURL);   
                         return false;
                     }
               }
           }

我们通过使用一个for循环来遍历所有的li和a标签(由于它们个数相同,所以索引的值相同),然后分别为它们设置onclick事件。先看我们给a标签添加的事件的代码:

var theA = theLink[j];
// 屏蔽掉a标签默认的处理(打开新链接)事件
theA.onclick = function(){
       return false;   
}

一个简单的return false,可别小看它哦,有几个作用哦,首先a标签是嵌套在li标签里的,我们点li时就一定会出发a标签的默认行为,打开链接的页面。而我们ajax标签导航就是希望不刷(打开)新页面,在指定的DOM节点显示信息。当然就不能让a标签的默认行为启动了,而简单的一个return false;就解决了这个问题。哦,这里还有个问题就是DOM事件的冒泡的顺序,详细的介绍大家可以在《Javascript高级编程》一书中查到。

那有些朋友会问,为什么要在里面加个a标签呢?反正你是改变的是li的样式,点了li,改变li的样式,然后刷新指定DOM节点的信息不就完成了ajax标签导航的功能(效果)了吗?

是啊,不过我在这里要提的就是刚才提到的一个预留退路的思想,如果想上面说的那样做了,当然是没有什么问题,但前提是用户的浏览器支持javascript脚本,或者说用户打开了执行脚本的权限。一旦用户的浏览器不支持javascript或者出于安全原因关闭了脚本执行功能。这个时候,当用户点li时是没有任何反映的。而我这里的处理就考虑到了当javascript执行不了的情况,这时候,用户点链接就可以打开我们原本要用ajax加载的内容了。

其实这里还有各个比较简单的方法来达成我提到的相同的效果,就是对li使用onmouseover事件,想想为什么?因为只要鼠标划过时,就触发了ajaxInject($(tarObj),objId,tarObj,theURL);改变了标签的样式,刷新了内容。当点击链接时,就可以弹出页面了。现在网易和雅虎中国就是这么处理的。其实我这么做主要是处于个人习惯,比较喜欢用onclick,还有就是这里有个分隔线的效果,看上去比网易的只用一个背景图片酷,当然我的效果是学的雅虎(不是雅虎中国)的。不过雅虎的标签样式的处理方式要比我现在的更巧妙,下次有时间再跟大家分析下雅虎的标签导航效果。

又扯远了,OK,接下来我们就是要改变样式和ajax刷新内容了。不过在这个之前,看看我做了什么准备。

<ul class="tabs" id="news">
         <li class="first" id="news-0"><a href="news/news0.htm">网站重构</a><span></span></li>
         <li id="news-1"><a href="news/news1.htm">CSS布局实录</a><span></span></li>
         <li id="news-2"><a href="news/news2.htm">海啸的地盘</a><span></span></li>
         <li id="news-3"><a href="news/news3.htm">Ajax高级编程</a><span></span></li>
</ul>

var objId = this.getAttribute("id").split("-")[1]; // 当前选中标签(li)在菜单(ul)中的索引值
var tarObj = this.getAttribute("id").split("-")[0]; // 要显示信息的目标DOM节点ID值
var theURL = tarObj + "/" + tarObj + objId + ".htm"; // 要异步加载的URL地址

看看我文章前面部分罗列的东西,现在就在这里有了回应了

id="news"      - news就是我们的导航标签的ID;
id="news-0"    - news-0 通过”-“分开,我们就分别可以得到news(导航标签ID),0(标签[li]在导航标签中的索引值)

好现在就要改变标签的样式了

/* ===========================================================
* 函数名称:ajaxInject(ListName,tabId,tarObj,URL)
* 参数说明:ListName - 标签菜单DOM节点ID
*           tabId - 选中的标签(在ListName中的)索引值
*           tarObj - 要显示返回信息的目标DOM节点ID值
*           URL - 要异步处理的URL地址
* 函数功能:设置当前选中标签(li)的样式,
*           将返回信息写到指定DOM节点中。
* 返 回 值:无
* 使用方法:ajaxInject($(tarObj),objId,tarObj,theURL);
============================================================ */
function ajaxInject(ListName,tabId,tarObj,URL){
    if(!ListName || !document.getElementsByTagName) return false;
      var Tabs = ListName;
      var theLi = Tabs.getElementsByTagName("li");
      for(var i=0;i<theLi.length;i++){
            // 设置当前选中标签的样式
          if(i==tabId){
                if(i==0){
                     theLi[tabId].className = "first"; // 当选中第一项的样式
                }
                else{//
                     theLi[tabId].className = "current"; // 选中其他项的样式
                }    
                var msgBox = tarObj+"Cnt";
                var loadstatustext="<div class='loading'><img src='img/loading.gif' alt='正在加载内容, 请稍候...' />正在加载内容, 请稍候...</div>";     
              $(msgBox).innerHTML = loadstatustext; // 加载信息时的提示信息
              var para = "?d=" + Math.random(); // URL后的参数,接Math.random()(一个随机数),目的是处理ajax的缓存问题
              var myAjax = ajaxUpdater(msgBox,"get",URL,para);
          }
          else{// 设置其他标签的样式
              theLi[i].className = "";
              if(tabId!=0){
                    theLi[tabId-1].className = "off"; // 当不是第一项时,隐藏选中项的前一项的分隔标签
                 } 
          }   
      }
}
      

这里又跟前面的

id="newsCnt"   - newsCnt就是我们要写入信息的目标DOM节点;
class="first"  - first当前(第一个)标签的样式;

对应起来了。

for(var i=0;i<theLi.length;i++){
            // 设置当前选中标签的样式
          if(i==tabId){
                if(i==0){
                     theLi[tabId].className = "first"; // 当选中第一项的样式
                }
                else{
                     theLi[tabId].className = "current"; // 选中其他项的样式
                }
            }   
            else{// 设置其他标签的样式
              theLi[i].className = "";
              if(tabId!=0){
                    theLi[tabId-1].className = "off"; // 当不是第一项时,隐藏选中项的前一项的分隔标签
                 }  
          } 
}
   

上面这段代码就是具体改变样式的,i==tabId比较当前标签的索引值(作用就是确认是否是选中的标签),相等了就给标签设置样式了。i==0表明第一项被选种(由于我的第一项的背景特殊的)给它加上“first”样式,其余项被选中则加上“current”样式。

接这就是处理分隔钱的样式了,跟设置背景大同小意,这里要说的是我们在写CSS的时候要把li(选中和失去焦点)的样式设置好。还是我之前提到的,YAHOO的做得很好,我记得网上也有关于滑动门技术CSS写法的介绍,大家可以看看是怎么来设置样式的,还有这里给大家推荐个小软件《CSS Tab Designer 2》。

恩,现在要刷新指定DOM节点的内容了,用一个简单的var myAjax = ajaxUpdater(msgBox,"get",URL,para);就解决问题了。不过我们看看在把信息写到指定DOM节点前,我做了什么:

var msgBox = tarObj+"Cnt";
var loadstatustext="<div class='loading'><img src='img/loading.gif' alt='正在加载内容, 请稍候...' />正在加载内容, 请稍候...</div>";     
$(msgBox).innerHTML = loadstatustext; // 加载信息时的提示信息

这里做了一个提示的处理,因为ajax是异步的加载,在获取很长(信息量很大)的内容时,会有一个延时,如果在这个期间不给任何提示信息的话,我们要刷新的DOM节点会出现白白的一片,这个当然是不美观的。所以在这之前,我们给用户一个提示信息,说明正在加载信息会显得更人性化些。当然,大家知道的网易的处理会更好些,做一个延迟的window.setTimeout效果。

出处:蓝色理想
责任编辑:moby

上一页 Javascript技巧篇 下一页 大结局

◎进入论坛网页制作WEB标准化版块参加讨论,我还想发表评论

相关文章 更多相关链接
不用组件实现Ajax效果
用 AjaxTags 简化 Ajax 开发
静态页面分页的AJAX实现
Ajax的小贴士
AJAX通用类:AJAXRequest v0.3
作者文章
XMLHTTPRequest的属性和方法简介
Ajax标签导航效果
关键字搜索 常规搜索 推荐文档
热门搜索:CSS Fireworks 设计比赛 网页制作 web标准 用户体验 UE photoshop Dreamweaver Studio8 Flash 手绘 CG
站点最新 站点最新列表
周大福“敬•自然”设计大赛开启
国际体验设计大会7月将在京举行
中国国防科技信息中心标志征集
云计算如何让安全问题可控
云计算是多数企业唯一拥抱互联网的机会
阿里行云
云手机年终巨献,送礼标配299起
阿里巴巴CTO王坚的"云和互联网观"
1499元买真八核 云OS双蛋大促
首届COCO桌面手机主题设计大赛
栏目最新 栏目最新列表
浅谈JavaScript编程语言的编码规范
如何在illustrator中绘制台历
Ps简单绘制一个可爱的铅笔图标
数据同步算法研究
用ps作简单的作品展示页面
CSS定位机制之一:普通流
25个最佳最闪亮的Eclipse开发项目
Illustrator中制作针线缝制文字效果
Photoshop制作印刷凹凸字体
VS2010中创建自定义SQL Rule
>> 分页 首页 前页 后页 尾页 页次:4/51个记录/页 转到 页 共5个记录

蓝色理想版权申明:除部分特别声明不要转载,或者授权我站独家播发的文章外,大家可以自由转载我站点的原创文章,但原作者和来自我站的链接必须保留(非我站原创的,按照原来自一节,自行链接)。文章版权归我站和作者共有。

转载要求:转载之图片、文件,链接请不要盗链到本站,且不准打上各自站点的水印,亦不能抹去我站点水印。

特别注意:本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有,文章若有侵犯作者版权,请与我们联系,我们将立即删除修改。

您的评论
用户名:  口令:
说明:输入正确的用户名和密码才能参与评论。如果您不是本站会员,你可以注册 为本站会员。
注意:文章中的链接、内容等需要修改的错误,请用报告错误,以利文档及时修改。
不评分 1 2 3 4 5
注意:请不要在评论中含与内容无关的广告链接,违者封ID
请您注意:
·不良评论请用报告管理员,以利管理员及时删除。
·尊重网上道德,遵守中华人民共和国的各项有关法律法规
·承担一切因您的行为而直接或间接导致的民事或刑事法律责任
·本站评论管理人员有权保留或删除其管辖评论中的任意内容
·您在本站发表的作品,本站有权在网站内转载或引用
·参与本评论即表明您已经阅读并接受上述条款
推荐文档 | 打印文档 | 评论文档 | 报告错误  
专业书推荐 更多内容
网站可用性测试及优化指南
《写给大家看的色彩书1》
《跟我去香港》
众妙之门—网站UI 设计之道
《Flex 4.0 RIA开发宝典》
《赢在设计》
犀利开发—jQuery内核详解与实践
作品集 更多内容

杂⑦杂⑧ Gold NORMANA V2