Не работает element.style если у element есть какое-либо значение display

Рейтинг: 0Ответов: 1Опубликовано: 21.02.2023

var DragManager = new function() {

  /**
   * составной объект для хранения информации о переносе:
   * {
   *   elem - элемент, на котором была зажата мышь
   *   avatar - аватар
   *   downX/downY - координаты, на которых был mousedown
   *   shiftX/shiftY - относительный сдвиг курсора от угла элемента
   * }
   */
  var dragObject = {};

  var self = this;

  function onMouseDown(e) {

    if (e.which != 1) return;

    var elem = e.target.closest('.draggable');
    if (!elem) return;

    dragObject.elem = elem;

    // запомним, что элемент нажат на текущих координатах pageX/pageY
    dragObject.downX = e.pageX;
    dragObject.downY = e.pageY;

    return false;
  }

  function onMouseMove(e) {
    if (!dragObject.elem) return; // элемент не зажат

    if (!dragObject.avatar) { // если перенос не начат...
      var moveX = e.pageX - dragObject.downX;
      var moveY = e.pageY - dragObject.downY;

      // если мышь передвинулась в нажатом состоянии недостаточно далеко
      if (Math.abs(moveX) < 3 && Math.abs(moveY) < 3) {
        return;
      }

      // начинаем перенос
      dragObject.avatar = createAvatar(e); // создать аватар
      if (!dragObject.avatar) { // отмена переноса, нельзя "захватить" за эту часть элемента
        dragObject = {};
        return;
      }

      // аватар создан успешно
      // создать вспомогательные свойства shiftX/shiftY
      var coords = getCoords(dragObject.avatar);
      dragObject.shiftX = dragObject.downX - coords.left;
      dragObject.shiftY = dragObject.downY - coords.top;

      startDrag(e); // отобразить начало переноса
    }

    // отобразить перенос объекта при каждом движении мыши
    dragObject.avatar.style.left = e.pageX - dragObject.shiftX + 'px';
    dragObject.avatar.style.top = e.pageY - dragObject.shiftY + 'px';

    return false;
  }

  function onMouseUp(e) {
    if (dragObject.avatar) { // если перенос идет
      finishDrag(e);
    }

    // перенос либо не начинался, либо завершился
    // в любом случае очистим "состояние переноса" dragObject
    dragObject = {};
  }

  function finishDrag(e) {
    var dropElem = findDroppable(e);

    if (!dropElem) {
      self.onDragCancel(dragObject);
    } else {
      self.onDragEnd(dragObject, dropElem);
    }
  }

  function createAvatar(e) {

    // запомнить старые свойства, чтобы вернуться к ним при отмене переноса
    var avatar = dragObject.elem;
    var old = {
      parent: avatar.parentNode,
      nextSibling: avatar.nextSibling,
      position: avatar.position || '',
      left: avatar.left || '',
      top: avatar.top || '',
      zIndex: avatar.zIndex || ''
    };

    // функция для отмены переноса
    avatar.rollback = function() {
      old.parent.insertBefore(avatar, old.nextSibling);
      avatar.style.position = old.position;
      avatar.style.left = old.left;
      avatar.style.top = old.top;
      avatar.style.zIndex = old.zIndex
    };

    return avatar;
  }

  function startDrag(e) {
    var avatar = dragObject.avatar;

    // инициировать начало переноса
    document.body.appendChild(avatar);
    avatar.style.zIndex = 9999;
    avatar.style.position = 'absolute';
  }

  function findDroppable(event) {
    // спрячем переносимый элемент
    dragObject.avatar.hidden = true;

    // получить самый вложенный элемент под курсором мыши
    var elem = document.elementFromPoint(event.clientX, event.clientY);

    // показать переносимый элемент обратно
    dragObject.avatar.hidden = false;

    if (elem == null) {
      // такое возможно, если курсор мыши "вылетел" за границу окна
      return null;
    }

    return elem.closest('.droppable');
  }

  document.onmousemove = onMouseMove;
  document.onmouseup = onMouseUp;
  document.onmousedown = onMouseDown;

  this.onDragEnd = function(dragObject, dropElem) {};
  this.onDragCancel = function(dragObject) {};

};


function getCoords(elem) { // кроме IE8-
  var box = elem.getBoundingClientRect();

  return {
    top: box.top + pageYOffset,
    left: box.left + pageXOffset
  };

}
.computer {
  width: 93px;
  height: 98px;
  background: url(https://js.cx/clipart/computer.gif) no-repeat;
  padding: 5px;
  font-style: italic;
}

.computer-smile {
  background: url(https://js.cx/clipart/computer-smile.gif) no-repeat;
}

.draggable {
  cursor: pointer;
  /*Если добавить display, то элементы перестанут исчезать при бросании в компьютер*/
  /*display: inline-block*/
}
<!DOCTYPE HTML>
<html>

<head>
  <meta charset="UTF-8">
  <script src="https://cdn.polyfill.io/v1/polyfill.js?features=Element.prototype.closest"></script>
  <script src="DragManager.js"></script>
  <link rel="stylesheet" href="dragDemo.css">
  <script>
    DragManager.onDragCancel = function(dragObject) {
      dragObject.avatar.rollback();
    };

    DragManager.onDragEnd = function(dragObject, dropElem) {
      dragObject.elem.style.display = 'none';
      dropElem.classList.add('computer-smile');
      setTimeout(function() {
        dropElem.classList.remove('computer-smile');
      }, 200);
    };
  </script>
</head>

<body>

  <div style="height:64px">
    <img src="https://js.cx/browsers/chrome.svg" class="draggable">
    <img src="https://js.cx/browsers/firefox.svg" class="draggable">
    <img src="https://js.cx/browsers/ie.svg" class="draggable">
    <img src="https://js.cx/browsers/opera.svg" class="draggable">
    <img src="https://js.cx/browsers/safari.svg" class="draggable">
  </div>

  <p>Браузер переносить сюда:</p>

  <div class="computer droppable">
  </div>

</body>

</html>

Делаю Drag and Drop на сайте. Столкнулся с проблемой. Брал код из этой статьи: https://learn.javascript.ru/drag-and-drop-objects (в конце есть полный код)

Ради интереса полностью скопировал пример и оказалось, что если у draggable элемента есть какой-либо display в css, то эта строчка (она находится в head файла html)...

dragObject.elem.style.display = 'none';

она просто не работает. Причём даже если display в строчке поменять на любой другой стиль, то она всё равно не будет работать, если в css уже есть любой display. Почему так происходит не могу разобраться уже второй день. Помогите пожалуйста объяснить этот феномен...

Ответы

▲ 0

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

Могу предложить альтернативное решение в виде оберток к иконках браузеров чтобы добавить стилизацию и не посыпался js скрипт:

<body>

<div class="icon-list">
    <div class="icon-item">
        <img src="https://js.cx/browsers/chrome.svg" class="draggable">
    </div>
    <div class="icon-item">
        <img src="https://js.cx/browsers/firefox.svg" class="draggable">
    </div>
    <div class="icon-item">
        <img src="https://js.cx/browsers/ie.svg" class="draggable">
    </div>
    <div class="icon-item">
        <img src="https://js.cx/browsers/opera.svg" class="draggable">
    </div>
    <div class="icon-item">
        <img src="https://js.cx/browsers/safari.svg" class="draggable">
    </div>
</div>

<p>Браузер переносить сюда:</p>

<div class="computer droppable">
</div>

<style>

    .computer {
        width: 93px;
        height: 98px;
        background: url(https://js.cx/clipart/computer.gif) no-repeat;
        padding: 5px;
        font-style: italic;
    }

    .computer-smile {
        background: url(https://js.cx/clipart/computer-smile.gif) no-repeat;
    }

    .draggable {
        cursor: pointer;
    }

    .icon-list {
        display: flex;
    }

    .icon-item img {
        margin: 10px;
    }

</style>

</body>