【DOM】实现一个课程表的拖拽功能

历史小剧场

一个皇帝从不需要用个人的良好品格来证明自己的英明,恰恰相反,在历史上,干皇帝这行的人基本都不是什么好人,因为好人干不了皇帝,朱匀炆就是铁证。----《明朝那些事儿》

1. 前置知识

1.1 DataTransfer接口

介绍一个属性:

  • dataTransfer.effectAllowed: 提供所有可用的操作类型。必须是 none、copy、copyLink、copyMove、link、linkMove、move、all or uninitialized

通过这个接口,我们可以控制拖拽元素的显示和操作类型。
例如:当effectAllowed设置为move时,拖拽元素不会出现+号

1.2 四个事件

一个拖拽元素操作过程会分别触发

  • dragstart: 当用户开始拖动元素或选择文本时触发此事件;
  • dragover: 当将元素或文本选择拖动到有效放置目标(每几百毫秒)上时,会触发此事件;
  • dragenter: 当拖动的元素或选择文本输入有效的放置目标时,会触发此事件;
  • drop:拖动元素或选择文本时放开时触发此事件。注意:需要阻止浏览器默认行为。

2. 实现课程表案例

2.1 准备静态页面

左侧课程,右侧表格

<div class="container">
  <div class="left" data-drop="move">
      <div data-effect="copy" draggable="true" class="item color1">语文</div>
      <div data-effect="copy" draggable="true" class="item color2">数学</div>
      <div data-effect="copy" draggable="true" class="item color3">英语</div>
      <div data-effect="copy" draggable="true" class="item color4">历史</div>
      <div data-effect="copy" draggable="true" class="item color5">地理</div>
      <div data-effect="copy" draggable="true" class="item color6">政治</div>
      <div data-effect="copy" draggable="true" class="item color7">体育</div>
  </div>
  <div class="right">
      <table border>
          <caption>
              <h1>课程表</h1>
          </caption>
          <colgroup>
              <col />
              <col />
              <col />
              <col />
              <col />
              <col />
              <col />
              <col />
          </colgroup>
          <thead>
              <tr>
                  <td></td>
                  <th>星期一</th>
                  <th>星期二</th>
                  <th>星期三</th>
                  <th>星期四</th>
                  <th>星期五</th>
                  <th>星期六</th>
                  <th>星期天</th>
              </tr>
          </thead>
          <tbody>
              <tr>
                  <th rowspan="4" class="span">上午</th>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
              </tr>
              <tr>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
              </tr>
              <tr>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
              </tr>
              <tr>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
              </tr>

              <tr>
                  <td colspan="8"></td>

              </tr>

              <tr>
                  <th rowspan="4" class="span">下午</th>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
              </tr>
              <tr>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
              </tr>
              <tr>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
                  <td data-drop="copy"></td>
              </tr>
          </tbody>
      </table>
  </div>
</div>
2.2 添加样式
* {
   margin: 0;
    padding: 0;
}

.container {
    margin: 0;
    display: flex;
    align-items: center;
    width: 100vw;
    height: 100vh;
}

.left {
    display: flex;
    justify-content: space-around;
    align-items: center;
    flex-direction: column;
    width: 100px;
    height: 400px;
    flex-shrink: 0;
    background-color: whitesmoke;
}

.item {
    width: 80px;
    height: 50px;
    text-align: center;
    line-height: 50px;
    color: white;
}

.color1 {
    background-color: skyblue;
}

.color2 {
    background-color: red;
}

.color3 {
    background-color: orange;
}

.color4 {
    background-color: deeppink;
}

.color5 {
    background-color: green;
}

.color6 {
    background-color: blue;
}
.color7 {
    background-color: salmon;
}

.right {
    background-color: whitesmoke;
    margin: 0 20px 0 12px;
}

.right table td {
    width: 80px;
    height: 50px;
    transition: all 1s ease-in-out;
}

.drop-over {
    background-color: #999;
}
2.3 添加拖拽事件逻辑
const container = document.querySelector(".container")

let source;
container.ondragstart = (e) => {
    console.log("start => ", e.target)
    // 设置鼠标状态为移动
    e.dataTransfer.effectAllowed = e.target.dataset.effect
    source = e.target;
}

// 会一直触发
container.ondragover = (e) => {
    // console.log("over => ", e.target)
    // 阻止浏览器默认行为
    e.preventDefault()
}

const clearDropStyle = () => {
    document.querySelectorAll('.drop-over').forEach(node => {
        node.classList.remove('drop-over')
    })
}

const getDropNode = (node) => {
    while (node) {
        if (node.dataset.drop) {
            return node;
        }
        node = node.parentNode;
    }
}

// 只会触发一次
container.ondragenter = (e) => {
    console.log("enter => ", e.target)
    // 清楚之前的drop-over
    clearDropStyle()
    const dropNode = getDropNode(e.target)
    if (dropNode && Object.is(dropNode.dataset.drop, e.dataTransfer.effectAllowed)) {
        dropNode.classList.add('drop-over')
    }
}

container.ondrop = (e) => {
    console.log("drop => ", e.target)
    clearDropStyle()
    const dropNode = getDropNode(e.target)
    if (dropNode && Object.is(dropNode.dataset.drop, e.dataTransfer.effectAllowed)) {
        if (dropNode.dataset.drop === 'copy') {
            dropNode.innerHTML = ''
            const cloned = source.cloneNode(true);
            cloned.dataset.effect = 'move'
            dropNode.appendChild(cloned)
        } else {
            // 清除
            source.remove()
        }
    }
}

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

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

相关文章

vb.netcad二开自学笔记3:启动与销毁

Imports Autodesk.AutoCAD.ApplicationServicesImports Autodesk.AutoCAD.EditorInputImports Autodesk.AutoCAD.RuntimePublic Class WellcomCADImplements IExtensionApplicationPublic Sub Initialize() Implements IExtensionApplication.InitializeMsgBox("net程序已…

ePTFE膜(膨体聚四氟乙烯膜)应用前景广阔 本土企业技术水平不断提升

ePTFE膜&#xff08;膨体聚四氟乙烯膜&#xff09;应用前景广阔 本土企业技术水平不断提升 ePTFE膜全称为膨体聚四氟乙烯膜&#xff0c;指以膨体聚四氟乙烯&#xff08;ePTFE&#xff09;为原材料制成的薄膜。ePTFE膜具有耐化学腐蚀、防水透气性好、耐候性佳、耐磨、抗撕裂等优…

【深度学习】-WASB-调试说明

要改这么几个地方&#xff1a; 代码仓库&#xff1a;/Desktop/code/python_project/WASB-SBDT-main/ 篮球数据集xx_xx_11.xml只保留最后一个11.xml 并把11下直接放置11 video&#xff1a; 这里的东西被我改了&#xff0c;要以仓库为准

git pull拉取显示Already up-to-date,但文件并没有更新

1、问题&#xff1a; 使用git pull拉取远程仓库代码&#xff0c;显示更新成功&#xff08;Already up-to-date&#xff09;&#xff0c;但是本地代码没有更新 这是因为本地有尚未提交的更改&#xff0c;和远程代码有冲突导致无法更新 2、解决方法&#xff1a; 可以使用git s…

Fastjson首字母大小写问题

1、问题 使用Fastjson转json之后发现首字母小写。实体类如下&#xff1a; Data public class DataIdentity {private String BYDBSM;private String SNWRSSJSJ;private Integer CJFS 20; } 测试代码如下&#xff1a; public static void main(String[] args) {DataIdentit…

多个tomcat同时使用 不设置CATALINA_HOME环境变量

通常一台服务器只使用一个tomcat&#xff0c;设置一个CATALINA_HOME的环境变量。但有些时候需要一台服务器启动多个tomcat&#xff0c;那就不能设置CATALINA_HOME了&#xff01;因为会串~ 我们可以在对应tomcat的startup.bat启动脚本中&#xff0c;加入对应的CATALINA_HOME。 …

Raylib 坐标系

draftx 符号调整为正数 发现采样坐标系原点0&#xff0c;0 在左上角&#xff0c;正方向 右&#xff0c;下 绘制坐标系 原点0&#xff0c;0 在左下角&#xff0c;正方向 右&#xff0c;上 拖拽可得 #include <raylib.h> // 重整原因&#xff1a;解决新函数放大缩小之下…

Appium+python自动化(四十一)-Appium自动化测试框架综合实践 - 即将落下帷幕(超详解)

1.简介 今天我们紧接着上一篇继续分享Appium自动化测试框架综合实践 - 代码实现。到今天为止&#xff0c;大功即将告成&#xff1b;框架所需要的代码实现都基本完成。 2.data数据封装 2.1使用背景 在实际项目过程中&#xff0c;我们的数据可能是存储在一个数据文件中&#x…

智慧交通运行监测与应急指挥中心方案

建设目标 建立感知层数据的实时采集以及数据处理&#xff0c;实现监测预警自动化和智能化&#xff1b;推动交通运输数据资源开放共享&#xff0c;打破数据资源壁垒&#xff0c;与城市各部门数据建立共享交换机制&#xff0c;实现应急指挥的协同化&#xff1b;充分运用大数据、互…

新产品或敏捷项目过程 SOP,附带流程图及流程规范

一、项目启动 项目背景和目标明确 市场调研结果分析&#xff0c;确定新产品的需求和市场机会。制定明确的项目目标&#xff0c;包括产品特性、上市时间、预期收益等。 组建项目团队 确定项目经理、产品经理、开发人员、测试人员、市场人员等角色。明确各成员的职责和权限。 项目…

Apache Seata应用侧启动过程剖析——注册中心与配置中心模块

本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 本文来自 Apache Seata官方文档&#xff0c;欢迎访问官网&#xff0c;查看更多深度文章。 Apache Seata应用侧启动过程剖析——注册中心与配置中心模块 前言 在Seata的应用侧&#xf…

Docker逃逸CVE-2019-5736、procfs云安全漏洞复现,全文5k字,超详细解析!

Docker容器挂载procfs 逃逸 procfs是展示系统进程状态的虚拟文件系统&#xff0c;包含敏感信息。直接将其挂载到不受控的容器内&#xff0c;特别是容器默认拥有root权限且未启用用户隔离时&#xff0c;将极大地增加安全风险。因此&#xff0c;需谨慎处理&#xff0c;确保容器环…

迅捷PDF编辑器合并PDF

迅捷PDF编辑器是一款专业的PDF编辑软件&#xff0c;不仅支持任意添加文本&#xff0c;而且可以任意编辑PDF原有内容&#xff0c;软件上方的工具栏中还有丰富的PDF标注、编辑功能&#xff0c;包括高亮、删除线、下划线这些基础的&#xff0c;还有规则或不规则框选、箭头、便利贴…

VRPTW(MATLAB):常春藤算法(IVY)求解带时间窗的车辆路径问题VRPTW,MATLAB代码

详细介绍 VRPTW&#xff08;MATLAB&#xff09;&#xff1a;常春藤算法&#xff08;Ivy algorithm&#xff0c;IVY&#xff09;求解带时间窗的车辆路径问题VRPTW&#xff08;提供MATLAB代码&#xff09;-CSDN博客 ********************************求解结果******************…

SpringBoot 生产实践:没有父 starter 的打包问题

文章目录 前言一、搜索引擎二、Chat GPT三、官方文档四、小结推荐阅读 前言 今天刚准备写点文章&#xff0c;需要 SpringBoot 项目来演示效果。一时心血来潮&#xff0c;没有采用传统的方式&#xff08;即通过引入 spring-boot-starter-parent 父工程的方式&#xff09;。 &l…

昇思25天学习打卡营第15天|linchenfengxue

Pix2Pix实现图像转换 Pix2Pix概述 Pix2Pix是基于条件生成对抗网络&#xff08;cGAN, Condition Generative Adversarial Networks &#xff09;实现的一种深度学习图像转换模型&#xff0c;该模型是由Phillip Isola等作者在2017年CVPR上提出的&#xff0c;可以实现语义/标签到…

16-JS封装:extend方法

目录 一、封装需求 二、实现1&#xff1a;jQuery.extend 三、实现2&#xff1a;通过原型jQuery.fn.extend 四、优化 一、封装需求 封装需求&#xff1a; $.extend&#xff1a; var obj{ name:"xxx",age:18} var obj3{ gender:"女"} var obj2{}; 将obj、…

如何注册微信公众号

如何注册微信公众号 如何注册一个微信公众号 &#x1f60a;&#x1f4f1;摘要引言正文内容1. 准备工作内容定位和受众群体公众号名称和头像 2. 网页注册流程第一步&#xff1a;访问微信公众平台第二步&#xff1a;选择账户注册类型第三步&#xff1a;填写基本信息第四步&#x…

单/多线程--协程--异步爬虫

免责声明:本文仅做技术交流与学习... 目录 了解进程和线程 单个线程(主线程)在执行 多线程 线程池 协程(爬虫多用) 假异步:(同步) 真异步: 爬虫代码模版 异步-爬虫 同步效果--19秒 异步效果--7秒 了解进程和线程 ​ # --------------------> # ------> # …

Multisim仿真-交流数字电压表

下图为整体的原理框图&#xff0c;交流电源经过整流滤波电路转换后&#xff0c;送入模数转换电路&#xff0c;经译码给到显示电路&#xff0c;由其显示交流电源的有效值。 信号发生器XFG1输出正弦波信号(峰峰值)&#xff0c;XMM1测量有效值&#xff0c;U6数码管显示有效值。仿真…