HTML table鼠标拖拽排序功能

下面是关于"HTML table鼠标拖拽排序功能"的完整攻略。

一、原理说明

在HTML表格中添加鼠标拖拽排序功能,本质上是通过监听鼠标在表格中的操作事件,动态调整表格中行或列的位置。

其中,主要的步骤可以分为以下几点:

  1. 监听鼠标操作事件,包括鼠标按下、鼠标移动、鼠标松开等事件;
  2. 在鼠标按下时,记录当前鼠标所在行或列的位置信息,包括其所在的表格、行或列号,以及点击时相对于其左上角的偏移量;
  3. 在鼠标移动时,根据鼠标当前的位置信息,计算出相对于按下时的偏移量,然后动态调整表格中行或列的位置;
  4. 在鼠标松开时,更新表格的行或列顺序,同时移除拖拽过程中添加的样式和事件监听。

二、示例说明

1. 示例一:拖拽排序表格行

下面是一个简单的示例,演示如何在HTML表格中添加拖拽排序表格行的功能。

<table>
  <thead>
    <tr>
      <th>姓名</th>
      <th>性别</th>
      <th>年龄</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>小明</td>
      <td>男</td>
      <td>18</td>
    </tr>
    <tr>
      <td>小红</td>
      <td>女</td>
      <td>20</td>
    </tr>
    <tr>
      <td>小刚</td>
      <td>男</td>
      <td>22</td>
    </tr>
  </tbody>
</table>

实现步骤如下:

  1. 通过JavaScript代码,遍历表格中的每个行元素,设置鼠标按下、移动和松开事件监听器;
  2. 在鼠标按下时,记录当前行的信息,包括其当前的位置、所在的表格、行数和鼠标相对于其左上角的偏移量;
  3. 在鼠标移动时,更新当前拖拽行的位置,同时检测是否需要交换位置;
  4. 在鼠标松开时,更新表格的行顺序,同时移除拖拽过程中添加的样式和事件监听。

具体实现方式可以参考下面的代码示例:

// 获取表格元素
const table = document.querySelector('table');

// 获取所有行元素
const rows = table.querySelectorAll('tr');

// 记录拖拽行的信息
let dragRow = null;
let dragY = 0;
let targetRow = null;

// 遍历所有行元素
rows.forEach((row, index) => {
  // 设置鼠标按下事件监听
  row.addEventListener('mousedown', (event) => {
    // 记录鼠标按下时的偏移量
    dragY = event.clientY - row.getBoundingClientRect().top;
    // 记录拖拽行的信息
    dragRow = {
      table: table,
      rowNum: index,
      top: row.getBoundingClientRect().top,
      height: row.getBoundingClientRect().height,
      y: event.clientY - row.getBoundingClientRect().top
    };
    // 添加样式
    row.style.opacity = '0.5';
    row.style.position = 'absolute';
    row.style.top = dragRow.top + 'px';
    row.style.left = row.getBoundingClientRect().left + 'px';
    // 阻止事件冒泡
    event.stopPropagation();
  });

  // 设置鼠标移动事件监听
  row.addEventListener('mousemove', (event) => {
    if (dragRow === null) return;
    // 计算偏移量
    const offset = event.clientY - dragRow.y - dragRow.top;
    // 移动行
    row.style.top = (dragRow.top + offset) + 'px';
    // 计算目标行
    targetRow = null;
    rows.forEach((r, i) => {
      if (i === dragRow.rowNum) return;
      const top = r.getBoundingClientRect().top + r.getBoundingClientRect().height / 2;
      if (event.clientY >= top) {
        targetRow = {
          table: table,
          rowNum: i,
          top: top,
          height: r.getBoundingClientRect().height
        };
      }
    });
  });

  // 设置鼠标松开事件监听
  row.addEventListener('mouseup', (event) => {
    if (dragRow === null) return;
    if (targetRow !== null) {
      // 交换位置
      const target = rows[targetRow.rowNum];
      target.parentNode.insertBefore(row, target);
      target.parentNode.insertBefore(target, rows[dragRow.rowNum + 1]);
    }
    // 移除样式
    row.style.opacity = '1';
    row.style.position = '';
    row.style.top = '';
    row.style.left = '';
    // 清除记录
    dragRow = null;
    targetRow = null;
  });

  // 设置鼠标松开事件监听
  row.addEventListener('mouseleave', (event) => {
    if (dragRow === null) return;
    // 更新目标行为最后一行
    targetRow = {
      table: table,
      rowNum: rows.length - 1,
      top: rows[rows.length - 1].getBoundingClientRect().bottom,
      height: rows[rows.length - 1].getBoundingClientRect().height
    };
    // 更新位置
    row.style.top = (targetRow.top - row.getBoundingClientRect().height) + 'px';
  });
});

2. 示例二:拖拽排序表格列

除了拖拽排序表格行,我们也可以通过类似的方式实现拖拽排序表格列的功能。下面是一个示例代码,演示如何实现该功能。

<table>
  <thead>
    <tr>
      <th>姓名</th>
      <th>性别</th>
      <th>年龄</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>小明</td>
      <td>男</td>
      <td>18</td>
    </tr>
    <tr>
      <td>小红</td>
      <td>女</td>
      <td>20</td>
    </tr>
    <tr>
      <td>小刚</td>
      <td>男</td>
      <td>22</td>
    </tr>
  </tbody>
</table>

实现步骤如下:

  1. 在表头中的每个列元素上添加鼠标按下、移动和松开事件监听器;
  2. 在鼠标按下时,记录当前列的信息,包括其当前的位置、所在的表格、列数和鼠标相对于其左上角的偏移量;
  3. 在鼠标移动时,更新当前拖拽列的位置,同时检测是否需要交换位置;
  4. 在鼠标松开时,更新表格的列顺序,同时移除拖拽过程中添加的样式和事件监听器。

具体实现方式可以参考下面的代码示例:

// 获取表格元素
const table = document.querySelector('table');

// 获取表头中每个列元素
const headers = table.querySelectorAll('thead th');

// 记录拖拽列的信息
let dragCol = null;
let dragX = 0;
let targetCol = null;

// 遍历所有列元素
headers.forEach((col, index) => {
  // 设置鼠标按下事件监听
  col.addEventListener('mousedown', (event) => {
    // 记录鼠标按下时的偏移量
    dragX = event.clientX - col.getBoundingClientRect().left;
    // 记录拖拽列的信息
    dragCol = {
      table: table,
      colNum: index,
      left: col.getBoundingClientRect().left,
      width: col.getBoundingClientRect().width,
      x: event.clientX - col.getBoundingClientRect().left
    };
    // 添加样式
    col.style.opacity = '0.5';
    col.style.position = 'absolute';
    col.style.left = dragCol.left + 'px';
    col.style.top = col.getBoundingClientRect().top + 'px';
    // 设置列宽度
    table.querySelectorAll('col')[index].style.width = dragCol.width + 'px';
    // 阻止事件冒泡
    event.stopPropagation();
  });

  // 设置鼠标移动事件监听
  col.addEventListener('mousemove', (event) => {
    if (dragCol === null) return;
    // 计算偏移量
    const offset = event.clientX - dragCol.x - dragCol.left;
    // 移动列
    col.style.left = (dragCol.left + offset) + 'px';
    // 计算目标列
    targetCol = null;
    headers.forEach((c, i) => {
      if (i === dragCol.colNum) return;
      const left = c.getBoundingClientRect().left + c.getBoundingClientRect().width / 2;
      if (event.clientX >= left) {
        targetCol = {
          table: table,
          colNum: i,
          left: left,
          width: c.getBoundingClientRect().width
        };
      }
    });
  });

  // 设置鼠标松开事件监听
  col.addEventListener('mouseup', (event) => {
    if (dragCol === null) return;
    if (targetCol !== null) {
      // 交换位置
      const target = headers[targetCol.colNum];
      target.parentNode.insertBefore(col, target);
      const cols = table.querySelectorAll('tr td:nth-child(' + (dragCol.colNum + 1) + ')');
      cols.forEach((cell, index) => {
        const target = target.parentNode.querySelectorAll('td:nth-child(' + (targetCol.colNum + 1) + ')')[index];
        target.parentNode.insertBefore(cell, target);
      });
      table.querySelectorAll('col')[dragCol.colNum].style.width = targetCol.width + 'px';
      table.querySelectorAll('col')[targetCol.colNum].style.width = dragCol.width + 'px';
    }
    // 移除样式
    col.style.opacity = '1';
    col.style.position = '';
    col.style.left = '';
    col.style.top = '';
    // 清除记录
    dragCol = null;
    targetCol = null;
  });

  // 设置鼠标松开事件监听
  col.addEventListener('mouseleave', (event) => {
    if (dragCol === null) return;
    // 更新目标列为最后一列
    targetCol = {
      table: table,
      colNum: headers.length - 1,
      left: headers[headers.length - 1].getBoundingClientRect().right,
      width: headers[headers.length - 1].getBoundingClientRect().width
    };
    // 更新位置
    col.style.left = targetCol.left - col.getBoundingClientRect().width + 'px';
  });
});

三、总结

HTML table鼠标拖拽排序功能的实现有很多种方式,上面的示例只是其中的一种。在实际开发中,需结合实际情况进行应用。另外,在实现时,需要注意操作的流畅性和界面的美观度。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:HTML table鼠标拖拽排序功能 - Python技术站

(0)
上一篇 2023年6月10日
下一篇 2023年6月10日

相关文章

  • 关于带有”显示更多”按钮的多行文本截断思考

    关于带有”显示更多”按钮的多行文本截断思考攻略,可以从下列步骤入手: 步骤1:确定截断长度 首先,需要确定文本截断的长度。可以根据实际需要来确定,通常情况下,为了不让页面显得过于拥挤,建议将多于两行的文本进行截断。 步骤2:截断文本 使用CSS的text-overflow属性可以将多行文本截断并显示”…”。但是,这样做的效果并不好,用户难以知道截断的文本…

    css 2023年6月10日
    00
  • JavaScript闭包原理与用法学习笔记

    JavaScript闭包原理与用法学习笔记 什么是JavaScript闭包 闭包(Closure)是指有权访问另一个函数作用域中变量的函数。在JavaScript中,函数可以作为另一个函数的参数或者返回值,如果在一个函数内部定义了另一个函数,并且内部函数可以访问外部函数的变量,则形成了一个闭包。闭包是JavaScript强大的特性之一,能够帮助我们实现诸如数…

    css 2023年6月10日
    00
  • javascript基础知识之html5轮播图实例讲解(44)

    下面是“javascript基础知识之html5轮播图实例讲解(44)”的详细攻略。 标题 本文主要介绍如何使用JavaScript实现HTML5轮播图,包含代码实现和一些关键点的讲解。 简介 轮播图是现代网页设计中常见的一种效果,它可以让网站更加生动和互动,提高用户体验。HTML5提供了一种实现轮播图的新方法——使用<canvas>元素和Jav…

    css 2023年6月10日
    00
  • jQuery实现的记住帐号密码功能完整示例

    下面我将详细讲解如何使用jQuery实现记住帐号密码功能的完整攻略,主要包括以下几个步骤: 1. 创建HTML文件和CSS样式 首先,在项目目录下创建一个HTML文件。这个HTML文件主要用于展示登录页面以及记住账号密码的功能。同时,我们也要使用CSS文件来美化页面样式。 示例代码: <!DOCTYPE html> <html> &l…

    css 2023年6月9日
    00
  • Bootstrap标签页(Tab)插件切换echarts不显示问题的解决

    下面是“Bootstrap标签页(Tab)插件切换echarts不显示问题的解决”的完整攻略: 问题描述 在使用Bootstrap标签页(Tab)插件切换echarts图表时,切换后的图表不显示。查询代码后发现,echarts图表在第一个tab中是正常显示的,但是在切换到第二个tab后却不显示了。 解决方案 Step 1 确认问题 首先,我们需要确认此问题是…

    css 2023年6月11日
    00
  • 实例讲解使用CSS实现多边框和透明边框的方法

    为了实现多边框和透明边框,可以使用CSS中的伪元素以及内外边距来模拟实现。具体步骤如下: 使用CSS实现多边框的方法 首先,需要为元素设置一个基本的边框样式:border:1px solid black; 接着,为元素设置内边距:padding:10px; 使用CSS伪元素 before 和 after 创建两个新的边框。before 代表在元素内容之前创建…

    css 2023年6月9日
    00
  • 前端开发中一些常用技巧总结

    前端开发中一些常用技巧总结 前言 作为前端开发者,了解并掌握一些常用技巧对于提高工作的效率和质量来说是非常重要的。在本文中,我将总结一些前端开发中常用的技巧,并给出相关的示例说明。 技巧1:使用CSS Sprites优化页面加载 CSS Sprites是将多个图像合并到一个大图中,并使用CSS的background-position属性控制显示区域的技术。使…

    css 2023年6月10日
    00
  • CSS中calc(100%-100px)不加空格不生效

    下面是详细讲解CSS中calc(100%-100px)不加空格不生效的攻略。 问题概述 当我们在 CSS 中使用 calc() 函数计算元素的属性值时,需要注意的是减号两侧必须要有空格分隔符,如 calc(100% – 100px),否则计算无法生效。比如,我们把减号和百分号紧挨着写成 calc(100%-100px) 是无法正确计算的。 解决方法 为了让 …

    css 2023年6月9日
    00
合作推广
合作推广
分享本页
返回顶部