css / html5:拖放后悬停状态保持不变

Posted

技术标签:

【中文标题】css / html5:拖放后悬停状态保持不变【英文标题】:css / html5 :hover state remains after drag and drop 【发布时间】:2012-08-12 22:16:22 【问题描述】:

我正在使用 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;

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; 

【问题讨论】:

你有没有想过这个问题?体验这件事,更烦人的是,当通过拖放重新排序元素时,它会将悬停状态应用于移动到被重新排序的元素的位置的元素。 创建一个 JSFiddle 可能值得,总是有帮助:) 你试过解除绑定事件吗? $(this).unbind('mouseenter mouseleave') 你能为这个或你的 HTML 提供一个 JSFiddle 吗? 【参考方案1】:

状态(六年后)

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

工作修复

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

document.querySelectorAll('.segmentListItem a').forEach(function (item) 
  item.addEventListener('mouseenter', function () 
    this.classList.add('hover');
  );
  item.addEventListener('mouseleave', function () 
    this.classList.remove('hover');
  );
);

下面的代码sn-p:

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();
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;
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>

<ul>
  <li class="segmentListItem">
    <a href="#">test1</a>
  </li>
  <li class="segmentListItem">
    <a href="#">test2</a>
  </li>
  <li class="segmentListItem">
    <a href="#">test3</a>
  </li>
</ul>

【讨论】:

我仍然可以在 2019 年的 Chrome v73 中重现该问题。 两年后,Chrome 88 中仍然重现

以上是关于css / html5:拖放后悬停状态保持不变的主要内容,如果未能解决你的问题,请参考以下文章

jQuery 拖放后 CSS 未正确更新,但在 Inspector 中更新

CSS:将文本向下移动几个像素但保持背景不变?

使下拉式菜单在不悬停时保持不变

如何在悬停时使按钮内的文本透明?背景应该保持不变

css3动画如何在动作结束时保持该状态不变

鼠标移到链接上后,HTML 超链接的颜色保持不变