防止在 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>