前端:html实现页面切换、顶部标签栏,类似于浏览器的顶部标签栏(完整版)

news2025/1/19 7:59:26

效果

image preview代码

<!DOCTYPE html>
<html>

  <head>
    <style>
    /* 左侧超链接列表 */
    .link {
      display: block;
      padding: 8px;
      background-color: #f2f2f2;
      cursor: pointer;
    }

    /* 顶部标签栏 */
    #tabsContainer {
      width:98%;
      display: flex;
      align-items: center;
      overflow-x: auto; /* 添加横向滚动 */
      white-space: nowrap; /* 防止标签换行 */
    }
    #tabsContainer::-webkit-scrollbar {
      display: none; /* 隐藏Webkit浏览器的滚动条 */
    }
    /* 关闭按钮的宽度 */
    .line2{
      width:2%;
    }
    #all_close{
      cursor: pointer;
      display: none;
    }
    .tab_position:hover #all_close {
      display: block;
    }
    .tab_position {
			display: flex;
			align-items: center;/*垂直居中*/
		}
    .tab {
      display: flex;
      align-items: center;
      background-color: #f2f2f2;
      cursor: pointer;
      position: relative;
      margin-right: 10px;
      border-radius: 3px;
    }

    /* 标签标题 */
    .tab .title {
      padding: 5px 15px 5px 15px;
      user-select: none; /* 禁止文字复制 */
    }

    /* 标签关闭按钮 */
    .tab .close-btn {
      font-size: 10px;
      font-weight: bold;
      cursor: pointer;
      padding: 5px 5px 5px 0;
      user-select: none; /* 禁止文字复制 */
    }

    .tab.active {
      background-color: #ccc;
    }

    /* 左侧内容 */
    #links {
      float: left;
      width: 200px;
      padding: 10px;
    }

    #tabs {
      padding: 10px;
    }
    /* 右侧 */
    #content {
      border: 1px solid #ccc;
      padding: 10px;
      overflow: auto;
    }
  </style>
  </head>

  <body>
    <div id="links">
      <!-- 在这里添加你的超链接 -->
      <a href="#" onclick="loadContent('page1.html', '这是我的超链接标题1,我要测试滚动条');
        return
        false;"
        class="link">超链接1</a>
      <a href="#" onclick="loadContent('page2.html', '这是我的超链接标题2,我要测试滚动条');
        return
        false;"
        class="link">超链接2</a>
      <a href="#" onclick="loadContent('page3.html', '这是我的超链接标题3,我要测试滚动条');
        return
        false;"
        class="link">超链接3</a>
      <a href="#" onclick="loadContent('page4.html', '这是我的超链接标题4,我要测试滚动条');
        return
        false;"
        class="link">超链接4</a>
      <a href="#" onclick="loadContent('page5.html', '这是我的超链接标题5,我要测试滚动条');
        return
        false;"
        class="link">超链接5</a>
      <a href="#" onclick="loadContent('page6.html', '这是我的超链接标题6,我要测试滚动条');
        return
        false;"
        class="link">超链接6</a>
      <a href="#" onclick="loadContent('page7.html', '这是我的超链接标题7,我要测试滚动条');
        return
        false;"
        class="link">超链接7</a>
      <a href="#" onclick="loadContent('page8.html', '这是我的超链接标题8,我要测试滚动条');
        return
        false;"
        class="link">超链接8</a>
      <a href="#" onclick="loadContent('page9.html', '这是我的超链接标题9,我要测试滚动条');
        return
        false;"
        class="link">超链接9</a>
    </div>
    <div class="tab_position">
      <div id="tabsContainer"></div>
      <div id="line2">
        <div id="all_close" onclick="all_close()">X</div>
      </div>
    </div>
    <div id="content"></div>
    <script>
    var tabsContainer = document.getElementById('tabsContainer');
    var contentContainer = document.getElementById('content');
    var activeTab = null;

    // 加载内容到右侧窗口
    function loadContent(url, tabName) {
      var existingTab = tabsContainer.querySelector('[data-url="' + url + '"]');
      if (existingTab) {
        setActiveTab(existingTab);
        return;
      }

      // 检查标签页数量是否已达上限
      var tabs = Array.from(tabsContainer.getElementsByClassName('tab'));
      if (tabs.length >= 7) {
        alert('已达到标签页数量上限');
        return;
      }

      // 隐藏当前页面内容
      if (activeTab) {
        activeTab.classList.remove('active');
        var activeUrl = activeTab.getAttribute('data-url');
        var activeContent = document.getElementById(activeUrl);
        activeContent.style.display = 'none';
      }

      // 显示新页面内容
      var content = document.getElementById(url);
      if (content) {
        content.style.display = 'block';
      } else {
        content = document.createElement('div');
        content.id = url;
        content.style.display = 'block';
        contentContainer.appendChild(content);

        var iframe = document.createElement('iframe');
        iframe.src = url;
        iframe.frameborder = '0';
        iframe.style.width = '100%';
        iframe.style.height = '100%';
        content.appendChild(iframe);
      }

      createTabAndSetActive(url, tabName);
    }


    function createTabAndSetActive(url, tabName) {
      // 如果标签已存在,则激活该标签
      var tab = tabsContainer.querySelector('[data-url="' + url + '"]');
      if (tab) {
        setActiveTab(tab);
        return;
      }

      // 创建新的标签
      tab = document.createElement('div');
      tab.className = 'tab';
      tab.setAttribute('data-url', url);

      var title = document.createElement('span');
      title.className = 'title';
      title.innerText = tabName;
      tab.appendChild(title);

      var closeBtn = document.createElement('span');
      closeBtn.innerText = 'X';
      closeBtn.className = 'close-btn';
      closeBtn.addEventListener('click', function (event) {
        event.stopPropagation();
        closeTab(tab);
      });
      tab.appendChild(closeBtn);

      // 点击标签页切换内容
      tab.addEventListener('click', function () {
        loadContent(url, tabName);
        setActiveTab(tab);
      });

      tabsContainer.appendChild(tab);
      setActiveTab(tab);
    }

    // 设置活动标签页样式
    function setActiveTab(tab) {
      var tabs = Array.from(tabsContainer.getElementsByClassName('tab'));
      tabs.forEach(function (t) {
        t.classList.remove('active');

        // 隐藏标签页对应的内容
        var tabUrl = t.getAttribute('data-url');
        var tabContent = document.getElementById(tabUrl);
        if (tabContent) {
          tabContent.style.display = 'none';
        }
      });

      tab.classList.add('active');
      activeTab = tab;

      // 显示当前标签页对应的内容
      var url = tab.getAttribute('data-url');
      var content = document.getElementById(url);
      if (content) {
        content.style.display = 'block';
      }
    }

    // 关闭标签页
    function closeTab(tab) {
      var isActiveTab = (tab === activeTab);
      var nextActiveTab = tab.previousElementSibling || tab.nextElementSibling;

      tab.parentNode.removeChild(tab);

      // 如果关闭的是活动标签页且还有其他标签页存在,则将页面锁定到下一个标签页
      if (isActiveTab && nextActiveTab) {
        setActiveTab(nextActiveTab);
        loadContent(nextActiveTab.getAttribute('data-url'), nextActiveTab.querySelector('.title').innerText);
      }

      // 如果关闭的是活动标签页且没有其他标签页存在,则清空内容和活动标签页
      if (isActiveTab && !nextActiveTab) {
        contentContainer.innerHTML = '';
        activeTab = null;
      }
      // 隐藏当前页面内容
      if (isActiveTab) {
        var activeUrl = tab.getAttribute('data-url');
        var activeContent = document.getElementById(activeUrl);
        activeContent.style.display = 'none';
      }
    }

    // 关闭全部未激活标签页
    function all_close() {     
      var confirmation = confirm('是否关闭全部标签页?'); // 显示确认和取消提示框
      if (confirmation) {
        var tabs = Array.from(tabsContainer.getElementsByClassName('tab'));
        tabs.forEach(function (tab) {
          if (!tab.classList.contains('active')) {
            closeTab(tab);
          }
        });
        // 清空内容、活动标签页和标签导航栏
        contentContainer.innerHTML = '';
        activeTab = null;
        tabsContainer.innerHTML = '';
      } else {
        console.log('取消')
      }       
    }
    

    var isMouseDown = false;
    var startX = 0;
    var scrollLeft = 0;

    tabsContainer.addEventListener('mousedown', function (e) {
      isMouseDown = true;
      startX = e.pageX - tabsContainer.offsetLeft;
      scrollLeft = tabsContainer.scrollLeft;
    });

    tabsContainer.addEventListener('mouseleave', function () {
      isMouseDown = false;
    });

    tabsContainer.addEventListener('mouseup', function () {
      isMouseDown = false;
    });

    tabsContainer.addEventListener('mousemove', function (e) {
      if (!isMouseDown) return;
      e.preventDefault();
      var x = e.pageX - tabsContainer.offsetLeft;
      var walk = (x - startX) * 2; // 调整滚动速度
      tabsContainer.scrollLeft = scrollLeft - walk;
    });
  </script>
  </body>

</html>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/943792.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深度学习——感受野

在CNN中&#xff0c;决定某一层输出结果中一个元素所对应的输入层的区域大小被称作感受野&#xff08;receptive field&#xff09;&#xff0c;指的是神经网络中一个神经元可以感知到的区域&#xff0c;在CNN中&#xff0c;即 上某个元素的计算受输入图像上影响的区域&#xf…

Android DataBinding 基础入门

DataBinding 是谷歌官方发布的一个框架&#xff0c;顾名思义即为数据绑定&#xff0c;是 MVVM 模式在 Android 上的一种实现&#xff0c;用于降低布局和逻辑的耦合性&#xff0c;使代码逻辑更加清晰。MVVM 相对于 MVP&#xff0c;其实就是将 Presenter 层替换成了 ViewModel 层…

github加速的方法

一、UU加速器 1、下载软件 网易UU加速器——不止快&#xff0c;还很稳 (163.com) 2、搜索学术两个字&#xff0c;点击启动游戏 二、Steam加速器 1、下载软件 Watt Toolkit - 瓦特工具箱(Steam官网) (steampp.net) 2、选择按钮之后&#xff0c;点击一键启动

聚焦磷酸铁锂产线革新,宏工科技一站式解决方案

兼顾了低成本与安全性两大属性&#xff0c;磷酸铁锂市场在全球范围内持续升温&#xff0c;并有望保持较高的景气度。巨大的需求空间之下&#xff0c;行业对于锂电装备企业的自动化与智能化水平、整线交付能力、产品效率与稳定性等均提出了新的要求。 以宏工科技股份有限公司&a…

【IOTE】物联网射频模组和芯片级方案提供商——深圳信驰达科技将精彩亮相IOTE物联网展

►►►强势来袭 Strong Attack 主物联场&#xff0c;相约深圳&#xff1b;2023&#xff0c;共论商机&#xff01;IOTE2023第二十届国际物联网展深圳站将于2023年9月20-22日在深圳国际会展中心(宝安新馆)开展&#xff01;汇聚全球超800家参展企业&#xff0c;呈现更多数字化纷呈…

恒运资本:两市迎普涨,创业板指涨超3%,汽车配件等板块走强

29日早盘&#xff0c;A股两市低开高走&#xff0c;沪指涨幅超1%&#xff0c;创业板指涨超3%。截至午间收盘&#xff0c;沪指涨1.39%报3141.82点&#xff0c;深成指涨2.41%&#xff0c;创业板指涨3.47%%&#xff0c;两市算计成交6265亿元。北向资金净流入超38亿元。盘面上&#…

基于面向对象的空间自相关指数,即插即用!Moran‘s I,局部莫兰指数,Geary‘s C指数,附完整可行使用案例

Geary’s C Geary’s C&#xff08;也称为Geary’s coefficient&#xff09;是一种用于衡量空间自相关性的统计指标&#xff0c;它可以用来评估地理数据中的空间聚集或离散程度。Geary’s指数的计算公式如下&#xff1a; G ( n − 1 ) ∗ ( Σ Σ w i j ∗ ( x i − x j ) 2…

windows下Node版本的切换方式

为了避免应用构建出错&#xff0c;我们在本地开发环境的 Node 版本与在 CI/CD 流程中指定的 Node 版本需保持一致。在这种需要频繁切换 Node 版本的情况下&#xff0c;我们不可能手动卸载又安装不同的版本&#xff0c;这时我们可以借助 NVM 工具来帮助我们快速地切换 Node 版本…

轻量、便捷、高效—经纬恒润AETP助力车载以太网测试

随着自动驾驶技术和智能座舱的不断发展&#xff0c;高宽带、高速率的数据通信对主干网提出了稳定、高效的传输要求&#xff0c;CAN(FD)、LIN已无法充分满足汽车的通信需求。车载以太网作为一种快速且扩展性好的网络技术&#xff0c;已经逐步成为了汽车主干网的首选。 此外&…

无涯教程-Android - Services

服务是在后台运行以执行长时间运行的操作而无需与用户交互的组件&#xff0c;并且即使应用程序被破坏&#xff0c;它也可以工作。服务实际上可以采取两种状态- Sr.No.State & Remark1 Started 当应用程序组件(如Activity)通过调用 startService()启动服务&#xff0c;启动后…

vue数组对象中按某一字段排序

给下列数组字段中的month排序 第一步&#xff1a;methods中写一个方法如下&#xff1a; sortBy(attr, rev) {//第二个参数没有传递 默认升序排列if(rev undefined) {rev 1;} else {rev (rev) ? 1 : -1;}return function(a, b) {a a[attr];b b[attr];if(a < b) {retu…

概念解析 | 合成孔径雷达在海洋动力学研究中的应用

注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:合成孔径雷达海洋动力研究。 揭秘海洋的心跳:合成孔径雷达与海洋动力学的交响乐 海洋,那个占据地球表面三分之二的神秘世界,它的运动和变化直接影响着全球气候系统,以及…

解决maven仓库无法自动下载程序包的问题

在调试idea项目报错&#xff1a;未解析的依赖项:de.fhpotsdam:unfolding:jar:0.9.6 问题描述解决方法总结 问题描述 在调试idea项目时报如上所示错误&#xff0c;并尝试了网上所说的更改maven仓库为阿里云仓库等方法&#xff0c;但是maven均无法自动下载unfolding程序包。 解…

企业重要数据怎么加密?企业数据加密软件哪个好?

企业的数据安全至关重要&#xff0c;关系到企业的健康发展&#xff0c;我们可以采用加密的方法来保护企业数据安全。那么&#xff0c;企业重要数据该怎么加密呢&#xff1f;企业数据加密软件哪个好&#xff1f;下面我们就来了解一下。 企业数据加密要求 企业数据加密的要求往…

YOLOv5模型压缩:综述

YOLOv5模型压缩:综述 AbstractIntroduction剪枝基于ln-范数修剪模型Feature map activationBatch normalization scaling factor (BNSF)First-order derivativeMutual informationGranularity of Pruning非结构化剪枝结构化剪枝基于通道的修剪基于滤波器的修剪基于核的剪枝关于…

AutoRunner自动化测试工具新版本智能识别算法之视觉识别

泽众AutoRunner&#xff08;简称AR&#xff09;是国内专业的支持C/S、B/S各种技术框架的、基于组件识别的自动化测试工具&#xff0c;实现7*24小时的自动化回归测试和功能测试&#xff0c;让测试更智能。 视觉识别是一种通过计算机技术对图像或视频进行分析和理解的方法。这种算…

checkstyle检查Java编程样式:final参数

checkstyle可以利用FinalParameters检查方法、构造器、catch和for-each块的参数是final的&#xff1a; https://checkstyle.sourceforge.io/checks/misc/finalparameters.html 背后的原理&#xff1a;程序执行期间修改参数的值会引起混乱&#xff0c;所以应该避免。 要配置使…

一道经典面试题:@Configuration 和 @Component 有何区别?

关于 Configuration 注解有一个特别经典的面试题&#xff1a; Configuration 和 Component 有什么区别&#xff1f; 无论小伙伴们之前是否背过相关的面试题&#xff0c;今天这篇文章学完之后相信大家对这个问题都会有更深一层的理解&#xff0c;废话不多少&#xff0c;咱们开…

地理空间数据的定义、收集和应用

简介 地理空间数据是指与地球表面特定位置相关的数据。它包含多种数据类型&#xff0c;包括地图、卫星图像和GIS&#xff08;地理信息系统&#xff09;数据。近年来&#xff0c;由于技术的进步以及对有关物理世界的准确和最新信息的需求不断增长&#xff0c;地理空间数据的…

9、监测数据采集物联网应用开发步骤(7)

监测数据采集物联网应用开发步骤(6) 串口(COM)通讯开发 本章节测试使用了 Configure Virtual Serial Port Driver虚拟串口工具和本人自写的串口调试工具&#xff0c;请自行baidu下载对应工具 在com.zxy.common.Com_Para.py中添加如下内容 #RS232串口通讯列表 串口号,波特率,…