JavaScript编程实现tab选项卡切换的效果+1

简介: JavaScript编程实现tab选项卡切换的效果+1

之前在“圳品”信息系统使用了tab选项卡来显示信息,详见:

JavaScript编程实现tab选项卡切换的效果

在tab选项卡中使用其它<div>来显示信息就出现了问题,乱套了,比如下面的这段代码:

<!DOCTYPE html>
<html>
<head>
  <meta name="Author" content="PurpleEndurer">
  <title>“圳品”信息系统</title>
    <style type="text/css">
        *{padding:0px;margin: 0px;font:12px normal "microsoft yahei";}
        #tabs {width:1024px; padding:5px; height:850px; margin:20px;}
        #tabs ul {list-style:none; display: block; height:30px; line-height:30px; border-bottom:2px #33ffff solid;}
        #tabs ul li {background:#eee; cursor:pointer; float:left; list-style:none; height:28px; line-height:28px; margin:0px 3px; border:1px solid #aaaaaa; border-bottom:none; display:inline-block; width:180px; text-align: center; font-size: 15px;}
        #tabs ul li.show {background:#fff;border-top:2px solid #33ffff; border-left:2px solid #33ffff; border-right:2px solid #33ffff; border-bottom: 2px solid #fff; font-weight:bold; font-size: 20px;}
        #tabs div {height:800px; line-height: 25px; border:1px solid #33ffff; border-top:none; padding:5px;}
        .hide{display: none;}
  .blue{color:blue;}
    </style>
    <script type="text/javascript">
  function initTab()
  {
    var oTab = document.getElementById("tabs");
    var oUl = oTab.getElementsByTagName("ul")[0];
    var oLis = oUl.getElementsByTagName("li");
    var oDivs= oTab.getElementsByTagName("div");
 
    for (var i= 0; i<oLis.length; i++)
    {
      oLis[i].index = i;
      oLis[i].onmousemove = oLis[i].onclick = function (){activeTab(this.index);};
    }
  }//initTab()
 
 
  function activeTab(a)
  {
    var oTab = document.getElementById("tabs");
    var oTabUl = oTab.getElementsByTagName("ul")[0];
    var oTabLis = oTabUl.getElementsByTagName("li");
    var oTabDivs = oTab.getElementsByTagName("div");
    for (var n= 0; n < oTabLis.length; n++)
    {
      oTabLis[n].className = "";
      oTabDivs[n].className = "hide";
    }//for()
    oTabLis[a].className = "show";
        oTabDivs[a].className = "";
  } //activeTab(a)
 
         window.onload = function()
   {
     initTab();
   }
    </script>
 
</head>
<body>
<p>JavaScript编程实现tab选项卡切换的效果 @Edge浏览器</p>
<div id="tabs">
    <ul>
        <li class="show" title="符合条件的产品清单">清单</li>
        <li>区域分布分析</li>
        <li>产品类别分析</li>
    </ul>
    <div id="divZpList">
  符合条件的产品清单
  <div id="div1" class="blue">选项卡1</div>
    </div>
    <div class="tabHide" id="divZpAreaDistNow"><!-- Area distribution //-->
  区域分布分析
  <div id="div2" class="blue">选项卡2</div>
    </div>
    <div class="tabHide" id="divZpTypeDistNow"><!-- Type distribution //-->
   产品类别分析
     <div id="div3" class="blue">选项卡3</div>
</div>
 
</body>
</html>

image.png 可以看到,第1张选项卡中的<div id="div1" class="blue">选项卡1</div>消失了,而第2张和第3张选项卡的内容对调了。

导致问题的原因在于activeTab()函数中,根据函数参数a传递进来的活动选项卡的indax,默认为选项卡组中的每个项目卡里一对<li>的<div>的index是相同的,即第a个<li>对默认匹配第a个<div>,并将第a个<li>和第a个<div>设置为当前活动选项卡:

oTabLis[a].className = "show";
    oTabDivs[a].className = "";

在选项卡组中的<div>与<li>数量相同时,这样默认是可以的,如<li>区域分布分析</li>与 <div class="tabHide" id="divZpAreaDistNow">匹配,这也是 JavaScript编程实现tab选项卡切换的效果 可以正常工作的原因。

但我们在选项卡组的<div>内引入其它的<div>,比如上面代码中的:

<div id="divZpList">
        符合条件的产品清单
        <div id="div1" class="blue">选项卡1</div>
    </div>

这时选项卡组中的<div>数量大于<li>数量时,第a个<li>对匹配第a个<div>的这种默认关系就不一定准确了。在上面的演示代码中,第2个选项卡中的<li>(即<li>区域分布分析</li>)将会与第2个<div>(即<div id="div1" class="blue">选项卡1</div>)匹配,而不是与第3个<div>(即<div class="tabHide" id="divZpAreaDistNow">)匹配。

找到了原因后,就要想解决问题的办法。解决问题的关键是在进行选项卡切换时如何找到或确定与选项卡组中的与<li>匹配的<div>。

解决这个问题的方法有很多,最直接的办法是定义一个全局的二维数组,把每个选项卡中的<li>和与之匹配的<div>的id保存下来,再用一个全局变量来存放当前活动选项卡的index。但是这样做的话,使用全局变量太多,耦合度低,不够通用。

我使用的解决办法是,先为选项卡中与<li>匹配的<div>设置一个特定的id特征码,比如id都是以"ZpDiv"来开头,然后遍历选项卡中的<div>,并把id中具有id特征码的<div>筛选出来,将其id值保存在一维数组aDivs中,这样第i个<li>就与aDivs[i]存储的id所指向的<div>匹配,然后可以进行相应的操作了。

如果我们在activeTab()中实现上述遍历、筛选和匹配工作的话,每次选项卡切换都要重复进行一次,不划算。

如果我们在选项卡组初始化阶段initTab()完成实现上述遍历、筛选和匹配工作,再把这种匹配关系传递到activeTab()中,就方便多了。

那么如何把这种匹配关系传递到activeTab()中呢?

既然我们先前是通过给选择卡的<li>增加index属性来确定当前活动选项卡的,那么我们再给<li>再增加两个属性,一个是.linkedDivID 用来存与它匹配的<div>的id,另一个是.TabsID ,用来保存<li>所在选项卡组的id。

具体实现起来,我使用的解决办法是,分三步:

第一步,为选项卡中与<li>匹配的<div>设置一个特定的id特征码,比如id都是以"ZpDiv"来开头。

第二步,在选项卡组初始化阶段initTab(),我们先遍历选项卡中的<div>,并把id中具有id特征码的<div>筛选出来,将其id值保存在一个一维数组aDivs中;然后遍历选项卡中的<li>,为每个<li>增加index、.linkedDivID 和.TabsID属性并赋值,并把TabsID和index属性作为参数传递给activeTab(tabsId, a)。

第三步,在activeTab(tabsId, a)中,先根据tabsId建立选项卡中的<li>数组oTabLis ,然后遍历<li>数组oTabLis,将所有的选项卡设置为非活动状态,接着修改oTabLis[a]的className,把它设置为活动选项卡的<li>,最后修改oTabLis[a].linkedDivID指向的<div>的ClassName,把它设置为活动选项卡的<div>。

完整的代码如下,其中增加了一个<textarea>来显示程序运行数据,方便了解代码内部的运行情况:

<!DOCTYPE html>
<html>
<head>
  <meta name="Author" content="PurpleEndurer">
  <title>“圳品”信息系统</title>
    <style type="text/css">
        *{padding:0px;margin: 0px;font:12px normal "microsoft yahei";}
        #tabsId {width:800px; padding:5px; height:300px; margin:20px;}
        #tabsId ul {list-style:none; display: block; height:30px; line-height:30px; border-bottom:2px #33ffff solid; }
        #tabsId ul li {background:#eee; cursor:pointer; float:left; list-style:none; height:28px; line-height:28px; margin:0px 3px; border:1px solid #aaaaaa; border-bottom:none; display:inline-block; width:180px; text-align: center; font-size: 15px; border-radius: 5px;}
        #tabsId ul li.tabShow {background:#fff;border-top:2px solid #33ffff; border-left:2px solid #33ffff; border-right:2px solid #33ffff; border-bottom: 2px solid #fff; font-weight:bold; font-size: 20px; border-radius: 5px;}
        #tabsId div {height:280px; line-height: 25px; border:1px solid #33ffff; border-top:none; padding:5px;}
        div.tabHide {display: none;}
        .blue {color:blue;}
    </style>

</head>
<body>
<p>JavaScript编程实现tab选项卡切换的效果 @Edge浏览器</p>
<div id="tabsId">
    <ul>
        <li id="liZpList" class="tabShow" title="符合条件的产品清单">清单</li>
        <li id="liZpAreaDist">区域分布分析</li>
        <li id="liZppTypeDist">产品类别分析</li>
    </ul>
    <div id="divZpList">
  符合条件的产品清单
  <div id="div1"  class="blue">选项卡1</div>
    </div>
    <div class="tabHide" id="divZpAreaDistNow"><!-- Area distribution //-->
  区域分布分析
  <div id="div2" >选项卡2</div>
    </div>
    <div class="tabHide" id="divZpTypeDistNow"><!-- Type distribution //-->
   产品类别分析
   <div id="div3">选项卡3</div>
    </div>
</div>
<textarea border="1" id="taDebug"  cols="180" rows="15">debug</textarea>

<script type="text/javascript">
  var taDbg = document.getElementById("taDebug");
  const tabsIdZp = "tabsId";    //选项卡组(tabs)的id
  const tabDivIdTagZp = "divZp";//选项卡组(tabs) 中 与 <li> 配对的<div>的id特征码

  // 设置当前活动的选项卡
  //参数说明:tabsId:选项卡组(tabs)的id, a: 当前活动的选项卡中<li>的index
  function activeTab(tabsId, a)
  {
    taDbg.value += '\n\n activeTab begin------';
    taDbg.value += '\n activeTab.index=' + a;
    var oTab = document.getElementById(tabsId);

    var oTabUl = oTab.getElementsByTagName("ul")[0];
    var oTabLis = oTabUl.getElementsByTagName("li");

    //将所有选项卡设置为非活动状态
    var i; //divID
    for (var n = 0; n < oTabLis.length; n++)
    {
      oTabLis[n].className = "";
      i = oTabLis[n]. linkedDivID;
      taDbg.value += '\n oTabLis[' + n + ']. linkedDivID=' + i + '   .className=' + oTabLis[n].className;
      document.getElementById(i).className = "tabHide";
      taDbg.value += '\n oTabLis[' + n + '].id=' + oTabLis[n].id + '   .className=' + oTabLis[n].className;
      i = document.getElementById(i);
      taDbg.value += '\n Divs.id=' + i.id + '   .className=' + i.className;
    }//for()

    //设置当前活动的选项卡
    oTabLis[a].className =   "tabShow";
    i = oTabLis[a]. linkedDivID;
    document.getElementById(i).className = "";

    taDbg.value += '\nactiveTab end------';
  } //activeTab() 

  
  //初始化选项卡
  //参数说明:tabsId: 选项卡组(tabs) id, tabDivIdTag:选项卡组(tabs) 中与<li>配对的<div>的id特征码
  function initTab(tabsId, tabDivIdTag)
  {
    taDbg.value += '\n initTab() begin------';
    var oTab = document.getElementById(tabsId);

    var oTabUl = oTab.getElementsByTagName("ul")[0];
    var oTabLis = oTabUl.getElementsByTagName("li");

    var oTabDivs= oTab.getElementsByTagName("div");
    taDbg.value += '\n oTabDivs.length=' + oTabDivs.length;

    var aDivs = new Array();//用来存放选项卡组(tabs)中与<li>配对的<div>的id
    var iDividTagLen = tabDivIdTag.length;
    if (iDividTagLen==0)
    {
      //与<li>配对的<div>的id特征码为"",直接从oTabDivs生成
      aDivs = Array.from(oTabDivs);
    }
    else
    {
      //遍历所有的<div>
      for (var i = 0; i<oTabDivs.length; i++)
      {
        //检查<div>的id是否符合与<li>配对<div>的id特征码
        if (oTabDivs[i].id.substr(0, iDividTagLen) == tabDivIdTag)
        {
          //保存符合与<li>配对<div>的id特征码的<div> 的id
          aDivs.push(oTabDivs[i].id);
        }
      }
    }

    if (aDivs.length < oTabLis.length)
    {
      alert("<div>数量小于<li>数量,不能完成初始化");
    }
    else
    {
      //初始化
      for (var i = 0; i < oTabLis.length; i++)
      {
        oTabLis[i].index = i; //设置选项卡中<li>的index属性,用于确定当前活动选项卡
        oTabLis[i].linkedDivID = aDivs[i]; //设置选项卡中<li>的linkedDivID属性,保存与该<li>配对的<div>的id
        oTabLis[i].TabsID =   tabsId; //设置选项卡中<li>的TabsID属性,保存选项卡组的id
        taDbg.value += '\n oTabLis[' + i + '].id=' + oTabLis[i].id + '   linkedDivID=' + oTabLis[i].linkedDivID;
        oTabLis[i].onclick = function() {activeTab(this.TabsID, this.index);};
        //oTabLis[i].onmousemove = oTabLis[i].onclick = function() {activeTab(this.TabsID, this.index);};
      }   //for     
    }//if

    taDbg.value += '\n initTab() end------'
  }//initTab()

   
  window.onload = function()
  {
     //initTab(tabsId, tabLiId, tabDivId);
      initTab(tabsIdZp, tabDivIdTagZp);  
  }
</script>          
</body>
</html>

代码运行效果如下:

image.png 嵌套的<div>内容都能正常显示出来。

相关文章
|
2月前
|
JavaScript 前端开发 编译器
解锁JavaScript模块化编程新纪元:从CommonJS的基石到ES Modules的飞跃,探索代码组织的艺术与科学
【8月更文挑战第27天】随着Web应用复杂度的提升,JavaScript模块化编程变得至关重要,它能有效降低代码耦合度并提高项目可维护性及扩展性。从CommonJS到ES Modules,模块化标准经历了显著的发展。CommonJS最初专为服务器端设计,通过`require()`同步加载模块。而ES Modules作为官方标准,支持异步加载,更适合浏览器环境,并且能够进行静态分析以优化性能。这两种标准各有特色,但ES Modules凭借其更广泛的跨平台兼容性和现代语法逐渐成为主流。这一演进不仅标志着JavaScript模块化的成熟,也反映了整个JavaScript生态系统的不断完善。
41 3
|
1天前
|
JavaScript
js学习--制作选项卡
js学习--制作选项卡
14 4
|
20天前
用CSS+JavaScript打造网页中的选项卡
用CSS+JavaScript打造网页中的选项卡
|
18天前
|
JavaScript 前端开发
JavaScript编程实现tab选项卡切换的效果
JavaScript编程实现tab选项卡切换的效果
|
18天前
|
JavaScript 前端开发
用JavaScript编程控制网页上checkbox选择状态:全选、全部取消、反选
用JavaScript编程控制网页上checkbox选择状态:全选、全部取消、反选
|
20天前
|
JavaScript 前端开发 安全
JavaScript编程实现字符和字符串翻转
JavaScript编程实现字符和字符串翻转
|
20天前
|
JavaScript 前端开发
用JavaScript编程定义二维数组并初始化,然后输出元素值
用JavaScript编程定义二维数组并初始化,然后输出元素值
|
2月前
|
JavaScript 前端开发 安全
揭秘TypeScript的魔力:它是如何华丽变身为JavaScript的超能英雄,让您的代码飞入全新的编程维度!
【8月更文挑战第22天】在Web开发领域,JavaScript是最主流的编程语言之一。但随着应用规模的增长,其类型安全和模块化的不足逐渐显现。为解决这些问题,微软推出了TypeScript,这是JavaScript的一个超集,通过添加静态类型检查来提升开发效率。TypeScript兼容所有JavaScript代码,并引入类型注解功能。
34 2
|
2月前
|
JavaScript 前端开发 Oracle
|
2月前
|
JavaScript 前端开发 开发者
震撼揭秘!JS模块化进化史:从混沌到秩序,一场代码世界的华丽蜕变,你怎能错过这场编程盛宴?
【8月更文挑战第23天】在 Web 前端开发领域,JavaScript 模块化已成为处理日益复杂的 Web 应用程序的关键技术。通过将代码分解成独立且可重用的模块,开发者能够更有效地组织和管理代码,避免命名冲突和依赖混乱。从最早的全局函数模式到 IIFE,再到 CommonJS 和 AMD,最终进化到了 ES6 的原生模块支持以及 UMD 的跨环境兼容性。本文通过具体示例介绍了这些模块化规范的发展历程及其在实际开发中的应用。
34 0