предотвратить нажатие на гиперссылку при перетаскивании - PullRequest
0 голосов
/ 01 июля 2018

У меня есть элементы div с якорными элементами в качестве детей. Размер дочерних элементов привязки растягивает родительский элемент item.

Я сделал элементы элемента перетаскиваемыми с помощью библиотеки interactive.js. Предметы становятся перетаскиваемыми, когда их удерживают 300 мс или дольше. Проблема заключается в том, что ссылка привязки дочернего элемента срабатывает при отпускании перетаскивания.

Как я могу запретить дочернему элементу запускать гиперссылку, когда родительский элемент удерживается / перетаскивается?

Вот небольшой пример проблемы

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

1 Ответ

0 голосов
/ 01 июля 2018

Возможно, не самое элегантное решение, но оно работает. Моя первая попытка не удалась, но я думаю, что у меня есть кое-что, что работает сейчас. Я создал систему флагов, чтобы отслеживать события. Обратите внимание, что я добавил onstart к перетаскиваемому экземпляру. Я должен был добавить время ожидания 300 мс, чтобы соответствовать времени ожидания. Кажется, onstart сразу же выстрелил в mousedown, несмотря на 300 мс. Я не уверен, как работает эта часть вашей библиотеки;)

В любом случае, подождите 300 мс, а затем установите флаг перетаскивания. Обратите внимание, что переменная является глобальной для справки. Проверьте область действия вашего проекта перед его реализацией. Вы могли бы хотеть создать открытый объект вместо этого, чтобы глобальный от смешивания вещей.

Я добавляю прослушиватель событий клика к каждой ссылке. Когда щелчок сработал, проверьте состояние флага удержания. Если это перетаскивание, предотвратите событие. В противном случае перейдите к регистрации клика. Примечание. Я попытался добавить этот код оценки флага в метод onend внутри перетаскиваемого экземпляра, но onend оказывается событием mouseup, которое срабатывает до click. Поэтому оценка должна проводиться с событием click. Лучший способ сделать это в области видимости - добавить событие 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>
...