最近公司的项目想做一个拖拽生成标签的应用效果,在网上找了很多例子,都不能完成这个效果,自己就摸索了一下,再结合了大佬们的例子,做了一个简单的小demo;
具体的效果如下:
HTML和CSS就比较简单了,具体的样式大家可以自己进行编写~
HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>darp</title>
<meta content="width=device-width">
<style>
body {
padding: 25px;
}
.row {
width: 800px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
margin-bottom: 50px;
}
.tabsBox {
height: 350px;
}
#new {
display: none;
width: 100%;
height: 100%;
}
.tab,.oldTab{
padding:3px 5px;
margin: 0 10px 10px 0;
display: inline-block;
border:1px solid #2290ee;
border-radius: 3px;
}
.oldTab{
border:1px solid #cccccc;
}
.delect{
cursor: pointer;
color: red;
}
</style>
</head>
<body>
<div class="row">
<p id="old" draggable="false" data-id="">
<span class="oldTab" data-id="1">ID:1 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Blanditiis deleniti doloribus ea incidunt libero natus provident soluta tenetur voluptatem. Ad, dicta distinctio eveniet fugiat libero molestiae nulla quae rerum veniam.</span>
<span class="oldTab" data-id="2">ID:2 Lorem ipsum dolor sit amet, consectetur adipisicing elit. Accusamus, assumenda blanditiis culpa deleniti doloribus eius et in ipsa itaque minima minus nemo nobis nostrum perferendis praesentium repellat saepe ut veniam.</span>
<span class="oldTab" data-id="3">ID:3 Ab adipisci animi blanditiis cum, debitis ea expedita magni molestiae natus, nobis nostrum odio quibusdam quisquam quod repellat repudiandae saepe sapiente sit soluta tempora velit, veniam voluptas voluptate voluptates voluptatum.</span>
<span class="oldTab" data-id="4">ID:4 Aut consectetur cupiditate distinctio dolores exercitationem ipsum obcaecati quisquam reiciendis tenetur. Blanditiis consequatur delectus eveniet excepturi hic illum iure laborum laudantium mollitia necessitatibus nulla perspiciatis, reprehenderit, similique sit voluptatem voluptatibus!</span>
<span class="oldTab" data-id="5">ID:5 Ab amet assumenda doloribus fuga hic impedit ipsa iure magni necessitatibus sunt. Adipisci beatae blanditiis delectus dignissimos dolores, ipsam, iste laborum pariatur porro repellendus saepe similique vero, voluptatem! Eligendi, voluptatem?</span>
<span class="oldTab" data-id="6">ID:6 A deleniti eum nostrum tempore veniam? Culpa eum hic natus numquam perspiciatis placeat sequi tempore! Amet aperiam debitis dolorem ea eaque et hic magni molestias quidem repudiandae. Aspernatur, quis, tenetur.</span>
</p>
asdf
</div>
<div id="tabsBox" class="row tabsBox">
</div>
</body>
</html>
在这里样式一个小技巧:
用IDEA编辑器(或者是有类似功能的插件)的时候,我们可以用这个在HTML中进行一些文本的生成---“乱数假文”,
这些文字没有具体的意义,只是用于测试文字的排版效果。具体操作:
输入lorem 在按下 tab键就可以生成一行文本。也可以根据自己想要乱数假文的多少进行生成,例如生成5个单词的假文,可以写成 “lorem5”+ tab,如果是生成5行,可以使用 “lorem*5”+ tab;
下面是本文的重点了,拖拽生成标签
首先是为document绑定一个拖放的事件,也就是在拖拽目标元素是触发的事件,在本例子中你不想写这段代码也是可以完成生成标签的效果的,如果想在拖动的时候进行一些操作可以在这里面写,
document.addEventListener("drag", function( event ) {
}, false);
然后是开始拖拽 “dragstart”,
document.addEventListener("dragstart", function (event) {
var NY = false;
var elemClassName = event.target.parentNode.className;
event.dataTransfer.setData("id",);//设置id
event.dataTransfer.setData("NY",elemClassName == "oldTab"?true:false);//判断是否是可以拖拽的文本,并设置到事件的event参数中去
});
这里我们可以看到一个拖放事件参数的datatransfer属性,他就是这个例子的核心,具体用处在MDN上是这样描述的:
在进行拖放操作时,DataTransfer
对象用来保存,通过拖放动作,拖动到浏览器的数据。它可以保存一项或多项数据、一种或者多种数据类型。
这个就厉害了,你可以拖放txt文件,可以拖放图片等等。拖放的数据都是在这里面的。废话不多说,我们接着正题,dataTransfer下面有连个方法一个是setData()和getData(),就是用来设置存放数据和或者数据了。在我们进行拖放的时候dataTransfer.items和dataTransfer.files是数据和文件列表,在里面就使用getAsString()方法也是就可以拿到数据的,但是getAsString()是异步的,所有在本利中不建议使用。本利中我们拖拽的是页面上面的文本,我们获取选中拖拽的文本可以直接使用getData("text"),就可以直接拿到选中拖拽的文本,说名一下setData很很简单,直接写参数就可以了,例如我们把选中文本所在的元素自定义id传上去setData("id","***")。那传这些参数上去有什么用呢?,这个就是我们接下来要讲的。
当我们拖放的时候数据会自动按照类型存在dataTransfer上,伴随着整个拖放事件,这里补充一下,整个拖放包括以下
drag | 当元素或者选择的文本被拖动时触发 |
dragstart | 当用户开始拖动一个元素或者一个选择文本的时候触发 |
drop | 当一个元素或者选择的文字被拖拽释放到一个有效的释放目标位置是触发 |
dragend | 拖放事件在拖放操作结束时触发 |
dragenter | 当拖放元素或者文本进入有效的目标的时候触发 |
dragleave | 当拖放元素或者文本离开有效的目标的时候触发 |
dragover | 当元素或者选择的文本被拖拽到一个有效的放置目标上时,触发 |
dragexit | 当元素不再是拖放操作的直接选择元素时触发 |
就像是键盘的事件一样,也是keyup,keydown,keypress等。
而dataTransfer可以在拖放的任意一个事件获取到,这样我就可以在拖放选择的文本进入有效的区域时候在获取到选择的文本,在将文字放到这个有效的区域来,样式大家可以自己进行一些设置。
document.addEventListener("drop", function (event) {
// 阻止默认动作(如打开一些元素的链接)
event.preventDefault();
var id = event.dataTransfer.getData("id");//拖拽对应的id
var text = event.dataTransfer.getData("text");//获取拖拽的文本
var NY = event.dataTransfer.getData("NY");//获取判断拖拽的元素是否是数据所在元素
// 移动拖动的元素到所选择的放置目标节点时判断,如果是加添加tab,反之不添加
if(NY=="true"){
//判断是否是对应的元素
if ( == "tabsBox") {
var tab = document.createElement("span");//生成一个span元素包住拖放的文本内容
tab.className = "tab";
tab.innerText = "id:" + id + "'"+ text + "' ";
tab.dataset.id = id;
event.target.appendChild(tab);
}
}
}, false);
我们一个直接是用getData()获取到我们设置的id,和是否是我们想要拖出的文本所在的元素,等等。
如果想要设置可以删除的效果我们可以再加上一个小点击事件就可以了:
document.addEventListener("drop", function (event) {
// 阻止默认动作(如打开一些元素的链接)
event.preventDefault();
var id = event.dataTransfer.getData("id");//拖拽对应的id
var text = event.dataTransfer.getData("text");//获取拖拽的文本
var NY = event.dataTransfer.getData("NY");//获取判断拖拽的元素是否是数据所在元素
// 移动拖动的元素到所选择的放置目标节点时判断,如果是加添加tab,反之不添加
if(NY=="true"){
//判断是否是对应的元素
if ( == "tabsBox") {
var tab = document.createElement("span");
var delectBtn = document.createElement("b");//删除按钮
delectBtn.className = "delect";
delectBtn.innerHTML = "x";
tab.className = "tab";
tab.innerText = "id:" + id + "'"+ text + "' ";
tab.dataset.id = id;
tab.appendChild(delectBtn);//删除按钮
event.target.appendChild(tab);
delectBtn.addEventListener("click",function(e){
delectBtn.parentNode.parentNode.removeChild(delectBtn.parentNode);
});
}
}
}, false);
有些小伙伴想要加上编辑的效果怎么办呢?可以在span里面加上一个input标签,这样处理起来太麻烦了;我最近发现了一个方法 "contentedtiable",在HTML元素标签上加上这个属性,设置为true,可以是元素可编辑。
document.addEventListener("drop", function (event) {
// 阻止默认动作(如打开一些元素的链接)
event.preventDefault();
var id = event.dataTransfer.getData("id");//拖拽对应的id
var text = event.dataTransfer.getData("text");//获取拖拽的文本
var NY = event.dataTransfer.getData("NY");//获取判断拖拽的元素是否是数据所在元素
// 移动拖动的元素到所选择的放置目标节点时判断,如果是加添加tab,反之不添加
if(NY=="true"){
//判断是否是对应的元素
if ( == "tabsBox") {
var tab = document.createElement("span");
tab.className = "tab";
tab.innerText = "id:" + id + "'"+ text + "' ";
tab.setAttribute('contenteditable',true);
tab.dataset.id = id;
event.target.appendChild(tab);
}
}
}, false);
更多的效果,大家可以自己看着追加上去,好了这样我们的拖拽生成标签的demo就算完成了,如果后续有机会我会做多放文本文件,和图片的demo,完结撒花
===================2020-06-17=====================
应要求,加上全部源码,代码大家就自己优化了
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>darp</title>
<meta content="width=device-width" />
<style>
body {
padding: 25px;
}
.row {
width: 800px;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
margin-bottom: 50px;
}
.tabsBox {
height: 350px;
}
#new {
display: none;
width: 100%;
height: 100%;
}
.tag,
.oldTab {
padding: 3px 5px;
margin: 0 10px 10px 0;
display: inline-block;
border: 1px solid #2290ee;
border-radius: 3px;
}
.oldTab {
border: 1px solid #cccccc;
}
.delect {
cursor: pointer;
color: red;
}
</style>
</head>
<body>
<div class="row">
<p id="old" draggable="false" data-id="">
<span class="oldTab" data-id="1">ID:1 Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Blanditiis deleniti doloribus ea incidunt libero natus provident
soluta tenetur voluptatem. Ad, dicta distinctio eveniet fugiat libero
molestiae nulla quae rerum veniam.</span>
<span class="oldTab" data-id="2">ID:2 Lorem ipsum dolor sit amet, consectetur adipisicing elit.
Accusamus, assumenda blanditiis culpa deleniti doloribus eius et in
ipsa itaque minima minus nemo nobis nostrum perferendis praesentium
repellat saepe ut veniam.</span>
<span class="oldTab" data-id="3">ID:3 Ab adipisci animi blanditiis cum, debitis ea expedita magni
molestiae natus, nobis nostrum odio quibusdam quisquam quod repellat
repudiandae saepe sapiente sit soluta tempora velit, veniam voluptas
voluptate voluptates voluptatum.</span>
<span class="oldTab" data-id="4">ID:4 Aut consectetur cupiditate distinctio dolores exercitationem
ipsum obcaecati quisquam reiciendis tenetur. Blanditiis consequatur
delectus eveniet excepturi hic illum iure laborum laudantium mollitia
necessitatibus nulla perspiciatis, reprehenderit, similique sit
voluptatem voluptatibus!</span>
<span class="oldTab" data-id="5">ID:5 Ab amet assumenda doloribus fuga hic impedit ipsa iure magni
necessitatibus sunt. Adipisci beatae blanditiis delectus dignissimos
dolores, ipsam, iste laborum pariatur porro repellendus saepe
similique vero, voluptatem! Eligendi, voluptatem?</span>
<span class="oldTab" data-id="6">ID:6 A deleniti eum nostrum tempore veniam? Culpa eum hic natus
numquam perspiciatis placeat sequi tempore! Amet aperiam debitis
dolorem ea eaque et hic magni molestias quidem repudiandae.
Aspernatur, quis, tenetur.</span>
</p>
asdf
</div>
<div id="tabsBox" class="row tabsBox"></div>
<script src="jquery.min.js"></script>
<script type="text/javascript">
document.addEventListener('dragstart', function (event) {
console.log(event)
var NY = false
var elemClassName = event.target.parentNode.className
event.dataTransfer.setData('id', ) //设置id
event.dataTransfer.setData(
'NY',
elemClassName == 'oldTab' ? true : false
) //判断是否是可以拖拽的文本,并设置到事件的event参数中去
})
/* events fired on the drop targets */
document.addEventListener('dragover', function (event) {
// prevent default to allow drop
event.preventDefault()
}, false)
document.addEventListener('drop', function (event) {
// 阻止默认动作(如打开一些元素的链接)
event.preventDefault()
var id = event.dataTransfer.getData('id') //拖拽对应的id
var text = event.dataTransfer.getData('text') //获取拖拽的文本
var NY = event.dataTransfer.getData('NY') //获取判断拖拽的元素是否是数据所在元素
// 移动拖动的元素到所选择的放置目标节点时判断,如果是加添加tab,反之不添加
//判断是否是对应的元素
if ( == 'tabsBox' && NY == 'true') {
var tag = document.createElement('span')
var delectBtn = document.createElement('b')
delectBtn.className = 'delect'
delectBtn.innerHTML = 'x'
tag.className = 'tag'
tag.innerText = 'id:' + id + "'" + text + "' "
tag.setAttribute('contenteditable', true)//加上contenteditable,可以使HTML进行富文本编辑
= id
tag.appendChild(delectBtn)
event.target.appendChild(tag)
delectBtn.addEventListener('click', function (e) {
delectBtn.parentNode.parentNode.removeChild(
delectBtn.parentNode
)
})
}
}, false)
</script>
</body>
</html>