No-API: как предотвратить клик на parent?

Я сделал свою собственную систему drag’n drop, которая заключается в создании divэлемента (= draggable element), содержащего другие элементы. Я не использую jQuery или HTML5.

Вот как это работает :

Когда пользователь запускает MouseDown событие, мы делаем элемент перетаскиваемым.
Затем: если, когда он запускает MouseUp событие (т. е. конец перетаскивания), программа обнаруживает, что он не перемещал элемент, это означает, что это был простой щелчок.
В противном случае, это означает, что это было фактическое падение drag’N.
Таким образом, программа способна действовать правильно (т. е. в зависимости от наличия драг-н-дропа или простого клика)
Простой щелчок скроет содержимое элемента. В противном случае элемент просто отбрасывается (= становится не перетаскиваемым).

Моя проблема: когда я делаю простой щелчок по элементу моего окна, он скрыт. Это означает, что события перетаскиваемого элемента обрабатываются.

Я бы хотел предотвратить перетаскиваемый элемент, который будет щелкаться, когда пользователь нажимает на один из его элементов.

Вы знаете, как я мог бы сделать это чисто ? Не стесняйтесь спросить меня код, если это необходимо.

2 ответа

  1. Я бы хотел предотвратить перетаскиваемый элемент, который будет щелкаться, когда пользователь нажимает на один из его элементов.

    Первое, что нужно сделать в обработчике событий: проверьте, что event.targetэто то же самое, что this. Если нет, немедленно выходите. В противном случае: вы уверены, что это divщелчок, а не один из его потомков.

    Демонстрация:

    document.getElementById('dv').addEventListener('mousedown', function (e) {
        if(e.target !== this) {
          console.log('skip');
          return; // skip
        }
        console.log('mousedown');
    });
    div {
      border: 1px solid;
      padding: 10px;
    }
    <div id="dv">
       test test: mouse down here
       <div>don't respond on this nested element
          <div>And not on this one either</div>
       </div>
       mouse down here
    </div>

    Альтернатива: остановить распространение

    Другой способ добиться того же-остановить распространение события к родительскому элементу:

    document.getElementById('child').addEventListener('mousedown', function (e) {
        console.log('skip');
        e.stopPropagation();
    });
    
    document.getElementById('dv').addEventListener('mousedown', function (e) {
        console.log('mousedown');
    });
    div {
      border: 1px solid;
      padding: 10px;
    }
    <div id="dv">
       test test: mouse down here
       <div id="child">don't respond on this nested element
          <div>And not on this one either</div>
       </div>
       mouse down here
    </div>

  2. Если расстояние xдвижения и yдвижения меньше, чем 10и разница между mouseDownи mouseUpбольше , что300, пользователь собирается инициировать clickсобытие или продолжить с Drag-Dropсобытием!

    См. псевдо-код из iScroll.js:

    var point = e.touches ? e.touches[0] : e,
      deltaX = point.pageX - this.pointX,
      deltaY = point.pageY - this.pointY,
      timestamp = utils.getTime(),
      newX, newY,
      absDistX, absDistY;
    
    this.pointX = point.pageX;
    this.pointY = point.pageY;
    
    this.distX += deltaX;
    this.distY += deltaY;
    absDistX = Math.abs(this.distX);
    absDistY = Math.abs(this.distY);
    
    // We need to move at least 10 pixels for the scrolling to initiate
    if (timestamp - this.endTime > 300 && (absDistX < 10 && absDistY < 10)) { // Click event
      return;
    }