css/html5:拖放后悬停状态仍然存在

mhe*_*ers 6 javascript css jquery drag-and-drop hover

我正在使用html5的拖放功能来重新排列屏幕上的dom元素 - 当我这样做时,我将css行为附加到拖放的各种状态,但我遇到的问题是悬停状态甚至在我之后仍然存在从DOM元素中拖出,删除和挖出.这是我的代码:

JAVASCRIPT:

function addDragListeners(){
    $('.segmentListItem').each(function(index){
        $(this)[0].addEventListener('dragstart',handleDragStart,false); //rollover for current
        $(this)[0].addEventListener('drop',handleDrop,false); //drops dragged element
        $(this)[0].addEventListener('dragover',handleDragOver,false); //allows us to drop
        $(this)[0].addEventListener('dragenter',handleDragEnter,false); //rollover for target
        $(this)[0].addEventListener('dragleave',handleDragLeave,false); //sets dragged item back to normal
        $(this)[0].addEventListener('dragend',handleDragEnd,false); //sets all back to normal
    });
}

function handleDragEnter(e) {
        // this / e.target is the current hover target.
        this.classList.add('over');
}

function handleDragLeave(e) {
        this.classList.remove('over');  // this / e.target is previous target element.
}

function handleDragEnd(e){
    $('.segmentListItem').removeClass('over'); //removes the over class on all elements
}

function handleDragStart(e){
    draggedItem = this;
    e.dataTransfer.effectAllowed = 'move';
}

function handleDragOver(e) {
    if (e.preventDefault) {
        e.preventDefault(); // Necessary. Allows us to drop.
    }
    e.dataTransfer.dropEffect = 'move';  // See the section on the DataTransfer object.
    return false;
}

function handleDrop(e){
    if (e.stopPropagation) {
        e.stopPropagation(); 
    }

    if (draggedItem != this) { //MH - swap if we're not dragging the item onto itself

        var draggedIndex = $('.segmentListItem').index($(draggedItem));
        var targetIndex = $('.segmentListItem').index($(this));

        if (draggedIndex > targetIndex){
            $(draggedItem).insertBefore($(this));
        } else {
            $(draggedItem).insertAfter($(this));
        }
    } 

    return false;
}
Run Code Online (Sandbox Code Playgroud)

CSS:

a { border-radius: 10px; }
a:hover { background: #ccc; }
.segmentListItem { text-align:center; width: 50px; margin-right: 5px; font-size: 16px; display:inline-block; cursor:move; padding:10px; background: #fff; user-select: none; }
.segmentListItem.over { background: #000; color: #fff; }
Run Code Online (Sandbox Code Playgroud)

And*_*rei 2

现状(六年后)

根据https://bugs.webkit.org/show_bug.cgi?id=134555这曾经是一个错误。然而,它必须同时被修复,因为它不能再在现代浏览器中重现。我仍然可以复制它的唯一浏览器是 IE11。

工作修复

您可以将 CSS 替换:hover.hover从 JS 切换的类,以便更好地控制悬停状态:

document.querySelectorAll('.segmentListItem a').forEach(function (item) {
  item.addEventListener('mouseenter', function () {
    this.classList.add('hover');
  });
  item.addEventListener('mouseleave', function () {
    this.classList.remove('hover');
  });
});
Run Code Online (Sandbox Code Playgroud)

代码片段如下:

document.querySelectorAll('.segmentListItem a').forEach(function (item) {
  item.addEventListener('mouseenter', function () {
    this.classList.add('hover');
  });
  item.addEventListener('mouseleave', function () {
    this.classList.remove('hover');
  });
});
Run Code Online (Sandbox Code Playgroud)
function addDragListeners() {
  $(".segmentListItem").each(function(index) {
    $(this)[0].addEventListener("dragstart", handleDragStart, false); //rollover for current
    $(this)[0].addEventListener("drop", handleDrop, false); //drops dragged element
    $(this)[0].addEventListener("dragover", handleDragOver, false); //allows us to drop
    $(this)[0].addEventListener("dragenter", handleDragEnter, false); //rollover for target
    $(this)[0].addEventListener("dragleave", handleDragLeave, false); //sets dragged item back to normal
    $(this)[0].addEventListener("dragend", handleDragEnd, false); //sets all back to normal
  });
}

function handleDragEnter(e) {
  // this / e.target is the current hover target.
  this.classList.add("over");
}

function handleDragLeave(e) {
  this.classList.remove("over"); // this / e.target is previous target element.
}

function handleDragEnd(e) {
  e.preventDefault();
  $(".segmentListItem").removeClass("over"); //removes the over class on all elements
}

function handleDragStart(e) {
  draggedItem = this;
  e.dataTransfer.effectAllowed = "move";
}

function handleDragOver(e) {
  if (e.preventDefault) {
    e.preventDefault(); // Necessary. Allows us to drop.
  }
  e.dataTransfer.dropEffect = "move"; // See the section on the DataTransfer object.
  return false;
}

function handleDrop(e) {
  if (e.stopPropagation) e.stopPropagation();

  if (draggedItem != this) {
    //MH - swap if we're not dragging the item onto itself

    var draggedIndex = $(".segmentListItem").index($(draggedItem));
    var targetIndex = $(".segmentListItem").index($(this));

    if (draggedIndex > targetIndex) {
      $(draggedItem).insertBefore($(this));
    } else {
      $(draggedItem).insertAfter($(this));
    }
  }

  return false;
}

// JS fix starts here:
document.querySelectorAll('.segmentListItem a').forEach(function(item, idx) {
  item.addEventListener('mouseenter', function() {
    this.classList.add('hover');
  });
  item.addEventListener('mouseleave', function() {
    this.classList.remove('hover');
  });
});
// and ends here. Comment these lines, and uncomment the `a:hover` rule in CSS in order to see the initial code

addDragListeners();
Run Code Online (Sandbox Code Playgroud)
a {
  border-radius: 10px;
}


/* a:hover {
  background: #ccc;
} */

.segmentListItem {
  text-align: center;
  width: 50px;
  margin-right: 5px;
  font-size: 16px;
  display: inline-block;
  cursor: move;
  padding: 10px;
  background: #fff;
  user-select: none;
}

.segmentListItem.over {
  background: #000;
  color: #fff;
}

.hover {
  background: #ccc;
}
Run Code Online (Sandbox Code Playgroud)

  • 我仍然可以在 2019 年的 Chrome v73 中重现该问题。 (4认同)
  • 两年后,这仍然在 Chrome 88 中重现 (2认同)