防止在 dragging/holding 时点击超链接
prevent click on hyperlink while dragging/holding
我有 item div 元素,其子元素为锚元素。锚点子项的大小拉伸了父项元素。
我已经使项目元素可以通过库拖动 interact.js。当项目保持 300 毫秒或更长时间时,它们会变得可拖动。问题是,当拖动被释放时,子项的锚点 link 被触发。
当父元素为 held/dragged 时,如何防止子元素触发 hyperlink?
下面是问题的一个小例子
let items = document.getElementsByClassName("item");
// add class .draggable to each item
for(var i = 0; i < items.length; i++)
{
items[i].classList.add("draggable");
}
// target elements with the "draggable" class
interact('.draggable').draggable({
autoScroll: true,
hold: 300,
// call this function on every dragmove event
onmove: dragMoveListener,
// call this function on every dragend event
onend: function (event) {
var target = event.target;
target.style.webkitTransform =
target.style.transform =
'translate(0px, 0px)';
target.setAttribute('data-x', 0);
target.setAttribute('data-y', 0);
}
});
// this function is calles on every dragmove event
function dragMoveListener (event) {
var target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
};
interact('.dropzone').dropzone({
ondropactivate: function (event) {
event.target.classList.add('drop-active');
},
ondragenter: function (event) {
var draggableElement = event.relatedTarget,
dropzoneElement = event.target;
// feedback the possibility of a drop
dropzoneElement.classList.add('drop-target');
draggableElement.classList.add('can-drop');
},
ondragleave: function (event) {
// remove the drop feedback style
event.target.classList.remove('drop-target');
event.relatedTarget.classList.remove('can-drop');
},
ondrop: function (event) {
//delete Bookmark here!
event.relatedTarget.classList.add('drop-ok');
},
ondropdeactivate: function (event) {
// remove active dropzone feedback
event.target.classList.remove('drop-active');
event.target.classList.remove('drop-target');
}
});
body {
background-color: #EDEFF3;
padding: 40px 48px;
}
.item {
display: inline-block;
margin: 8px;
background-color: RGBA(255, 255, 255, 1);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border-radius: 10px;
z-index: 999;
}
.item a {
position: relative;
display: inline-block;
border-radius: 10px;
line-height: 40px;
padding: 0 32px 0 48px;
font-weight: 400;
text-decoration: none;
font-size: 13px;
color: black;
font-size: 14px;
}
.item a .dott {
position: absolute;
top: 12px;
left: 20px;
height: 16px;
width: 16px;
background-color: tomato;
border-radius: 100%;
}
.item.can-drop a {
text-decoration: line-through;
}
.item.drop-ok {
display: none;
}
.category {
display: flex;
flex-wrap: wrap;
position: relative;
align-items: flex-start;
background-color: RGBA(127, 135, 147, 0.2);
margin: 16px;
padding: 8px;
}
.dropzone {
height: 20%;
width: 100%;
position: fixed;
bottom: 0;
left: 0;
background-color: tomato;
opacity: 0;
}
.dropzone.drop-active {
opacity: 1;
}
.dropzone.drop-target {
background-color: #F15B52;
}
<script src="https://cdn.jsdelivr.net/npm/interactjs@1.3.4/dist/interact.min.js"></script>
<div class="category">
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
<div class="item">
<a href="https://www.google.com/">
<span class="dott"></span>
bookmark</a>
</div>
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
</div>
<div class="dropzone"></div>
这是我目前在 Codepen 的状态:
https://codepen.io/iamrbn/pen/pKGPMz
也许不是最优雅的解决方案,但它确实有效。我的第一次尝试失败了,但我想我现在有一些东西可以用了。我创建了一个标志系统来跟踪事件。请注意,我将 onstart
添加到可拖动实例。我必须添加 300 毫秒超时以匹配保持时间。尽管保持了 300 毫秒,但似乎 onstart 在 mousedown 时立即触发。我不确定你图书馆的那部分是如何工作的 ;)
总之,等待300ms,然后设置拖动标志。请注意,该变量是全局变量以供参考。在实施之前检查您的项目变量范围。您可能想要创建一个 public 对象来防止全局混淆。
我为每个 link 添加了一个点击事件监听器。单击触发时,检查保持标志状态。如果是阻力,则阻止该事件。否则,继续注册点击。注意:我尝试将此标志评估程序代码添加到可拖动实例中的 onend 方法,但 onend
结果是一个 mouseup
事件,它在 click
之前触发。因此,评估需要发生在 click
事件中。在范围内做到这一点的最佳方法是向每个 link.
添加一个 click
事件
哇!天哪,这大概花了一个小时。让我知道它是否有效:)
let items = document.getElementsByClassName("item");
// add class .draggable to each item
for (var i = 0; i < items.length; i++) {
items[i].classList.add("draggable");
items[i].children[0].addEventListener('click',function(e){
if(drag){
drag = false;
e.preventDefault()
}
});
}
var drag = false;
// target elements with the "draggable" class
interact('.draggable').draggable({
autoScroll: true,
hold: 300,
// call this function on every dragmove event
onstart: function(){
setTimeout(function(){
drag = true;
},300);
},
onmove: dragMoveListener,
// call this function on every dragend event
onend: function(event) {
var target = event.target;
target.style.webkitTransform =
target.style.transform =
'translate(0px, 0px)';
target.setAttribute('data-x', 0);
target.setAttribute('data-y', 0);
}
});
// this function is calles on every dragmove event
function dragMoveListener(event) {
var target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
};
interact('.dropzone').dropzone({
ondropactivate: function(event) {
event.target.classList.add('drop-active');
},
ondragenter: function(event) {
var draggableElement = event.relatedTarget,
dropzoneElement = event.target;
// feedback the possibility of a drop
dropzoneElement.classList.add('drop-target');
draggableElement.classList.add('can-drop');
},
ondragleave: function(event) {
// remove the drop feedback style
event.target.classList.remove('drop-target');
event.relatedTarget.classList.remove('can-drop');
},
ondrop: function(event) {
//delete Bookmark here!
event.relatedTarget.classList.add('drop-ok');
},
ondropdeactivate: function(event) {
// remove active dropzone feedback
event.target.classList.remove('drop-active');
event.target.classList.remove('drop-target');
}
});
body {
background-color: #EDEFF3;
padding: 40px 48px;
}
.item {
display: inline-block;
margin: 8px;
background-color: RGBA(255, 255, 255, 1);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border-radius: 10px;
z-index: 999;
}
.item a {
position: relative;
display: inline-block;
border-radius: 10px;
line-height: 40px;
padding: 0 32px 0 48px;
font-weight: 400;
text-decoration: none;
font-size: 13px;
color: black;
font-size: 14px;
}
.item a .dott {
position: absolute;
top: 12px;
left: 20px;
height: 16px;
width: 16px;
background-color: tomato;
border-radius: 100%;
}
.item.can-drop a {
text-decoration: line-through;
}
.item.drop-ok {
display: none;
}
.category {
display: flex;
flex-wrap: wrap;
position: relative;
align-items: flex-start;
background-color: RGBA(127, 135, 147, 0.2);
margin: 16px;
padding: 8px;
}
.dropzone {
height: 20%;
width: 100%;
position: fixed;
bottom: 0;
left: 0;
background-color: tomato;
opacity: 0;
}
.dropzone.drop-active {
opacity: 1;
}
.dropzone.drop-target {
background-color: #F15B52;
}
<script src="https://cdn.jsdelivr.net/npm/interactjs@1.3.4/dist/interact.min.js"></script>
<div class="category">
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
<div class="item">
<a href="https://www.google.com/">
<span class="dott"></span> bookmark
</a>
</div>
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
</div>
<div class="dropzone"></div>
我有 item div 元素,其子元素为锚元素。锚点子项的大小拉伸了父项元素。
我已经使项目元素可以通过库拖动 interact.js。当项目保持 300 毫秒或更长时间时,它们会变得可拖动。问题是,当拖动被释放时,子项的锚点 link 被触发。
当父元素为 held/dragged 时,如何防止子元素触发 hyperlink?
下面是问题的一个小例子
let items = document.getElementsByClassName("item");
// add class .draggable to each item
for(var i = 0; i < items.length; i++)
{
items[i].classList.add("draggable");
}
// target elements with the "draggable" class
interact('.draggable').draggable({
autoScroll: true,
hold: 300,
// call this function on every dragmove event
onmove: dragMoveListener,
// call this function on every dragend event
onend: function (event) {
var target = event.target;
target.style.webkitTransform =
target.style.transform =
'translate(0px, 0px)';
target.setAttribute('data-x', 0);
target.setAttribute('data-y', 0);
}
});
// this function is calles on every dragmove event
function dragMoveListener (event) {
var target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
};
interact('.dropzone').dropzone({
ondropactivate: function (event) {
event.target.classList.add('drop-active');
},
ondragenter: function (event) {
var draggableElement = event.relatedTarget,
dropzoneElement = event.target;
// feedback the possibility of a drop
dropzoneElement.classList.add('drop-target');
draggableElement.classList.add('can-drop');
},
ondragleave: function (event) {
// remove the drop feedback style
event.target.classList.remove('drop-target');
event.relatedTarget.classList.remove('can-drop');
},
ondrop: function (event) {
//delete Bookmark here!
event.relatedTarget.classList.add('drop-ok');
},
ondropdeactivate: function (event) {
// remove active dropzone feedback
event.target.classList.remove('drop-active');
event.target.classList.remove('drop-target');
}
});
body {
background-color: #EDEFF3;
padding: 40px 48px;
}
.item {
display: inline-block;
margin: 8px;
background-color: RGBA(255, 255, 255, 1);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border-radius: 10px;
z-index: 999;
}
.item a {
position: relative;
display: inline-block;
border-radius: 10px;
line-height: 40px;
padding: 0 32px 0 48px;
font-weight: 400;
text-decoration: none;
font-size: 13px;
color: black;
font-size: 14px;
}
.item a .dott {
position: absolute;
top: 12px;
left: 20px;
height: 16px;
width: 16px;
background-color: tomato;
border-radius: 100%;
}
.item.can-drop a {
text-decoration: line-through;
}
.item.drop-ok {
display: none;
}
.category {
display: flex;
flex-wrap: wrap;
position: relative;
align-items: flex-start;
background-color: RGBA(127, 135, 147, 0.2);
margin: 16px;
padding: 8px;
}
.dropzone {
height: 20%;
width: 100%;
position: fixed;
bottom: 0;
left: 0;
background-color: tomato;
opacity: 0;
}
.dropzone.drop-active {
opacity: 1;
}
.dropzone.drop-target {
background-color: #F15B52;
}
<script src="https://cdn.jsdelivr.net/npm/interactjs@1.3.4/dist/interact.min.js"></script>
<div class="category">
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
<div class="item">
<a href="https://www.google.com/">
<span class="dott"></span>
bookmark</a>
</div>
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
</div>
<div class="dropzone"></div>
这是我目前在 Codepen 的状态: https://codepen.io/iamrbn/pen/pKGPMz
也许不是最优雅的解决方案,但它确实有效。我的第一次尝试失败了,但我想我现在有一些东西可以用了。我创建了一个标志系统来跟踪事件。请注意,我将 onstart
添加到可拖动实例。我必须添加 300 毫秒超时以匹配保持时间。尽管保持了 300 毫秒,但似乎 onstart 在 mousedown 时立即触发。我不确定你图书馆的那部分是如何工作的 ;)
总之,等待300ms,然后设置拖动标志。请注意,该变量是全局变量以供参考。在实施之前检查您的项目变量范围。您可能想要创建一个 public 对象来防止全局混淆。
我为每个 link 添加了一个点击事件监听器。单击触发时,检查保持标志状态。如果是阻力,则阻止该事件。否则,继续注册点击。注意:我尝试将此标志评估程序代码添加到可拖动实例中的 onend 方法,但 onend
结果是一个 mouseup
事件,它在 click
之前触发。因此,评估需要发生在 click
事件中。在范围内做到这一点的最佳方法是向每个 link.
click
事件
哇!天哪,这大概花了一个小时。让我知道它是否有效:)
let items = document.getElementsByClassName("item");
// add class .draggable to each item
for (var i = 0; i < items.length; i++) {
items[i].classList.add("draggable");
items[i].children[0].addEventListener('click',function(e){
if(drag){
drag = false;
e.preventDefault()
}
});
}
var drag = false;
// target elements with the "draggable" class
interact('.draggable').draggable({
autoScroll: true,
hold: 300,
// call this function on every dragmove event
onstart: function(){
setTimeout(function(){
drag = true;
},300);
},
onmove: dragMoveListener,
// call this function on every dragend event
onend: function(event) {
var target = event.target;
target.style.webkitTransform =
target.style.transform =
'translate(0px, 0px)';
target.setAttribute('data-x', 0);
target.setAttribute('data-y', 0);
}
});
// this function is calles on every dragmove event
function dragMoveListener(event) {
var target = event.target,
// keep the dragged position in the data-x/data-y attributes
x = (parseFloat(target.getAttribute('data-x')) || 0) + event.dx,
y = (parseFloat(target.getAttribute('data-y')) || 0) + event.dy;
// translate the element
target.style.webkitTransform =
target.style.transform =
'translate(' + x + 'px, ' + y + 'px)';
// update the posiion attributes
target.setAttribute('data-x', x);
target.setAttribute('data-y', y);
};
interact('.dropzone').dropzone({
ondropactivate: function(event) {
event.target.classList.add('drop-active');
},
ondragenter: function(event) {
var draggableElement = event.relatedTarget,
dropzoneElement = event.target;
// feedback the possibility of a drop
dropzoneElement.classList.add('drop-target');
draggableElement.classList.add('can-drop');
},
ondragleave: function(event) {
// remove the drop feedback style
event.target.classList.remove('drop-target');
event.relatedTarget.classList.remove('can-drop');
},
ondrop: function(event) {
//delete Bookmark here!
event.relatedTarget.classList.add('drop-ok');
},
ondropdeactivate: function(event) {
// remove active dropzone feedback
event.target.classList.remove('drop-active');
event.target.classList.remove('drop-target');
}
});
body {
background-color: #EDEFF3;
padding: 40px 48px;
}
.item {
display: inline-block;
margin: 8px;
background-color: RGBA(255, 255, 255, 1);
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
border-radius: 10px;
z-index: 999;
}
.item a {
position: relative;
display: inline-block;
border-radius: 10px;
line-height: 40px;
padding: 0 32px 0 48px;
font-weight: 400;
text-decoration: none;
font-size: 13px;
color: black;
font-size: 14px;
}
.item a .dott {
position: absolute;
top: 12px;
left: 20px;
height: 16px;
width: 16px;
background-color: tomato;
border-radius: 100%;
}
.item.can-drop a {
text-decoration: line-through;
}
.item.drop-ok {
display: none;
}
.category {
display: flex;
flex-wrap: wrap;
position: relative;
align-items: flex-start;
background-color: RGBA(127, 135, 147, 0.2);
margin: 16px;
padding: 8px;
}
.dropzone {
height: 20%;
width: 100%;
position: fixed;
bottom: 0;
left: 0;
background-color: tomato;
opacity: 0;
}
.dropzone.drop-active {
opacity: 1;
}
.dropzone.drop-target {
background-color: #F15B52;
}
<script src="https://cdn.jsdelivr.net/npm/interactjs@1.3.4/dist/interact.min.js"></script>
<div class="category">
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
<div class="item">
<a href="https://www.google.com/">
<span class="dott"></span> bookmark
</a>
</div>
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
<div class="item">
<a href="https://www.google.com/"><span class="dott"></span>bookmark</a>
</div>
</div>
<div class="dropzone"></div>