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

效果

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>

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

indexDB入门到精通

前言 由于开发3D可视化项目经常用到模型&#xff0c;而一个模型通常是几m甚至是几十m的大小对于一般的服务器来讲加载速度真的十分的慢&#xff0c;为了解决这个加载速度的问题&#xff0c;我想到了几个本地存储的。 首先是cookie,cookie肯定是不行的&#xff0c;因为最多以只…

WordPress主题Zing V2.2.1/模块化WordPress响应式通用企业商城主题

WordPress主题Zing V2.2.1&#xff0c;模块化WordPress响应式通用企业商城主题。 功能介绍 百度熊掌号文章实时推送、原创保护 多设备支持自适应布局&#xff0c;支持电脑、Pad、手机以及各种浏览器 SEO优化首页、文章、页面、分类均支持自定义标题、关键字和描述 速度优化…

龙芯2K1000LA移植交叉编译环境以及QT

嵌入式大赛结束了&#xff0c;根据这次比赛中记的凌乱的笔记&#xff0c;整理了一份龙芯2K1000LA的环境搭建过程&#xff0c;可能笔记缺少了一部分步骤或者错误&#xff0c;但是大致步骤可以当作参考。 一、交叉编译工具链 下载连接&#xff1a;龙芯 GNU 编译工具链 | 龙芯开…

jq插件:jqgrid和validform的二次封装

做久了vue和react框架项目&#xff0c;偶尔也需要做做原生的项目。不可否认vue的双向绑定机制确实很香&#xff0c;但是也是建立在原生js基础上。所以&#xff0c;只有做更多的原生js项目&#xff0c;才能更加了解vue框架的底层原理。在日常开发中&#xff0c;也会不可避免的会…

cortex-A7核PWM实验--STM32MP157

实验目的&#xff1a;驱动风扇&#xff0c;蜂鸣器&#xff0c;马达进行工作 目录 一&#xff0c;PWM相关概念 有源蜂鸣器和无源蜂鸣器 二&#xff0c;分析电路图&#xff0c;框图 三&#xff0c;分析RCC章节 1&#xff0c;确定总线连接 2&#xff0c;根据总线内容确定基…

SQL语句优化

当表中有百万数据的时候&#xff0c;我们要怎么去查询数据&#xff0c;平时写的sql也许就会很慢了。 SQL的执行顺序 SELECT DISTINCT <select_list> FROM <left_table> <join_type> JOIN <right_table> ON <join_condition> WHERE<where_co…

【Luniux】解决Ubuntu外接显示器不显示的问题

Luniux】解决Ubuntu外接显示器不显示的问题 文章目录 Luniux】解决Ubuntu外接显示器不显示的问题1. 检查nvidia显卡驱动是否正常2. 更新驱动3. 检查显示器是否能检测到Reference 1. 检查nvidia显卡驱动是否正常 使用命令行 nvidia-smi来检查显卡驱动是否正常&#xff0c;如果…

gRPC + Spring Boot 编程教程 - piot

在本文中&#xff0c;您将学习如何实现通过 gRPC 通信的 Spring Boot 应用程序。gRPC 是一个现代开源远程过程调用 (RPC) 框架&#xff0c;可以在任何环境中运行。默认情况下&#xff0c;它使用 Google 的 Protocol Buffer 来序列化和反序列化结构化数据。当然&#xff0c;我们…

Ceph入门到精通-LVS基础知识

LB集群: &#xff08;Load Balancing&#xff09;即负载均衡集群,其目的是为了提高访问的并发量及提升服务器的性能&#xff0c;其 实现方式分为硬件方式和软件方式。 硬件实现方式&#xff1a; 常用的有 F5公司的BIG-IP系列、A10公司的AX系列、Citrix公司的 NetScaler系列…

HUT23级训练赛

目录 A - tmn学长的字符串1 B - 帮帮神君先生 C - z学长的猫 D - 这题用来防ak E - 这题考察FFT卷积 F - 这题考察二进制 G - 这题考察高精度 H - 这题考察签到 I - 爱派克斯&#xff0c;启动! J - tmn学长的字符串2 K - 秋奕来买瓜 A - tmn学长的字符串1 思路&#x…

华为OD机试 - VLAN资源池 - 回溯、双指针(Java 2023 B卷 100分)

目录 专栏导读一、题目描述二、输入描述三、输出描述四、解题思路1、核心思想2、具体解题思路 五、Java算法源码六、效果展示1、输入2、输出 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&…

什么是NetDevOps

NetDevOps 是一种新兴的方法&#xff0c;它结合了 NetOps 和 DevOps 的流程&#xff0c;即将网络自动化集成到开发过程中。NetDevOps 的目标是将虚拟化、自动化和 API 集成到网络基础架构中&#xff0c;并实现开发和运营团队之间的无缝协作。 开发运营&#xff08;DevOps&…

敏捷研发管理软件及敏捷管理流程

Scrum中非常强调公开、透明、直接有效的沟通&#xff0c;这也是“可视化的管理工具”在敏捷开发中如此重要的原因之一。通过“可视化的管理工具”让所有人直观的看到需求&#xff0c;故事&#xff0c;任务之间的流转状态&#xff0c;可以使团队成员更加快速适应敏捷开发流程。 …

JVM知识点(二)

1、G1垃圾收集器 -XX:MaxGCPauseMillis10&#xff0c;G1的参数&#xff0c;表示在任意1s时间内&#xff0c;停顿时间不能超过10ms&#xff1b;G1将堆切分成很多小堆区&#xff08;Region&#xff09;&#xff0c;每一个Region可以是Eden、Survivor或Old区&#xff1b;这些区在…

【MySQL系列】MySQL复合查询的学习 _ 多表查询 | 自连接 | 子查询 | 合并查询

「前言」文章内容大致是对MySQL复合查询的学习。 「归属专栏」MySQL 「主页链接」个人主页 「笔者」枫叶先生(fy) 目录 一、基本查询回顾二、多表查询三、自连接四、子查询4.1 单行子查询4.2 多行子查询4.3 多列子查询4.4 在from子句中使用子查询 五、合并查询 一、基本查询回顾…

解密算法与数据结构面试:程序员如何应对挑战

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

Windows版本Docker安装详细步骤

文章目录 下载地址安装异常处理docker desktop requires a newer wsl 下载地址 https://desktop.docker.com/win/stable/Docker%20Desktop%20Installer.exe 安装 双击下载的文件Docker Desktop Installer.exe进行安装 点击OK 开始安装 安装完成点击Close and restart&…

电脑不安装软件,怎么将手机文件传输到电脑?

很多人都知道&#xff0c;AirDroid有网页版&#xff08;web.airdroid.com&#xff09;。 想要文件传输&#xff0c;却不想在电脑安装软件时&#xff0c;AirDroid的网页版其实也可以传输文件。 然而&#xff0c;要将文件从手机传输文件到网页端所在的电脑时&#xff0c;如果按…

“惠医通-医院挂号订单平台”

结合已学习过的vue3和TS完成的项目&#xff0c;便于患者对自己想要就诊的科室进行挂号&#xff0c;付款 一&#xff1a;项目简介 前端技术栈 Vue3 TS vue-router Element-ui Axios Pinia 项目架构 二&#xff1a;主要模块 1. axios二次封装 1.1 创建实例 //利用axios.creat…

视频融合平台EasyCVR视频汇聚平台关于小区高空坠物安全实施应用方案设计

近年来&#xff0c;随着我国城市化建设的推进&#xff0c;高楼大厦越来越多&#xff0c;高空坠物导致的伤害也屡见不鲜&#xff0c;严重的影响到人们的生命安全。像在日常生活中一些不起眼的小东西如烟头、鸡蛋、果核、易拉罐&#xff0c;看似伤害不大&#xff0c;但只要降落的…