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>内容都能正常显示出来。

相关文章
|
12天前
|
弹性计算 人工智能 架构师
阿里云携手Altair共拓云上工业仿真新机遇
2024年9月12日,「2024 Altair 技术大会杭州站」成功召开,阿里云弹性计算产品运营与生态负责人何川,与Altair中国技术总监赵阳在会上联合发布了最新的“云上CAE一体机”。
阿里云携手Altair共拓云上工业仿真新机遇
|
8天前
|
机器学习/深度学习 算法 大数据
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
2024“华为杯”数学建模竞赛,对ABCDEF每个题进行详细的分析,涵盖风电场功率优化、WLAN网络吞吐量、磁性元件损耗建模、地理环境问题、高速公路应急车道启用和X射线脉冲星建模等多领域问题,解析了问题类型、专业和技能的需要。
2522 18
【BetterBench博士】2024 “华为杯”第二十一届中国研究生数学建模竞赛 选题分析
|
8天前
|
机器学习/深度学习 算法 数据可视化
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
2024年中国研究生数学建模竞赛C题聚焦磁性元件磁芯损耗建模。题目背景介绍了电能变换技术的发展与应用,强调磁性元件在功率变换器中的重要性。磁芯损耗受多种因素影响,现有模型难以精确预测。题目要求通过数据分析建立高精度磁芯损耗模型。具体任务包括励磁波形分类、修正斯坦麦茨方程、分析影响因素、构建预测模型及优化设计条件。涉及数据预处理、特征提取、机器学习及优化算法等技术。适合电气、材料、计算机等多个专业学生参与。
1525 15
【BetterBench博士】2024年中国研究生数学建模竞赛 C题:数据驱动下磁性元件的磁芯损耗建模 问题分析、数学模型、python 代码
|
4天前
|
存储 关系型数据库 分布式数据库
GraphRAG:基于PolarDB+通义千问+LangChain的知识图谱+大模型最佳实践
本文介绍了如何使用PolarDB、通义千问和LangChain搭建GraphRAG系统,结合知识图谱和向量检索提升问答质量。通过实例展示了单独使用向量检索和图检索的局限性,并通过图+向量联合搜索增强了问答准确性。PolarDB支持AGE图引擎和pgvector插件,实现图数据和向量数据的统一存储与检索,提升了RAG系统的性能和效果。
|
10天前
|
编解码 JSON 自然语言处理
通义千问重磅开源Qwen2.5,性能超越Llama
击败Meta,阿里Qwen2.5再登全球开源大模型王座
596 14
|
1月前
|
运维 Cloud Native Devops
一线实战:运维人少,我们从 0 到 1 实践 DevOps 和云原生
上海经证科技有限公司为有效推进软件项目管理和开发工作,选择了阿里云云效作为 DevOps 解决方案。通过云效,实现了从 0 开始,到现在近百个微服务、数百条流水线与应用交付的全面覆盖,有效支撑了敏捷开发流程。
19283 30
|
10天前
|
人工智能 自动驾驶 机器人
吴泳铭:AI最大的想象力不在手机屏幕,而是改变物理世界
过去22个月,AI发展速度超过任何历史时期,但我们依然还处于AGI变革的早期。生成式AI最大的想象力,绝不是在手机屏幕上做一两个新的超级app,而是接管数字世界,改变物理世界。
498 49
吴泳铭:AI最大的想象力不在手机屏幕,而是改变物理世界
|
1月前
|
人工智能 自然语言处理 搜索推荐
阿里云Elasticsearch AI搜索实践
本文介绍了阿里云 Elasticsearch 在AI 搜索方面的技术实践与探索。
18842 20
|
1月前
|
Rust Apache 对象存储
Apache Paimon V0.9最新进展
Apache Paimon V0.9 版本即将发布,此版本带来了多项新特性并解决了关键挑战。Paimon自2022年从Flink社区诞生以来迅速成长,已成为Apache顶级项目,并广泛应用于阿里集团内外的多家企业。
17530 13
Apache Paimon V0.9最新进展
|
3天前
|
云安全 存储 运维
叮咚!您有一份六大必做安全操作清单,请查收
云安全态势管理(CSPM)开启免费试用
368 4
叮咚!您有一份六大必做安全操作清单,请查收