15

I have simple ol-li construction and want to add drag'n'drop to it. Additionaly I want to highlight hover item and dragover item in different colors. But it is an unusual bug in WebKit.

  1. Capture last item.
  2. Drag it to the top.
  3. Drop it to the first item.

And last element capture the hover pseudoclass! Why? How can I prevent it?

Hover bug

This is an example:

http://jsfiddle.net/zFk2V/3/

var lis = document.querySelectorAll("li"),
    ol = document.querySelector("ol"),
    dragged = false,
    dragover = false;
ol.addEventListener("drop", function(event) {
    ol.insertBefore(dragged,dragover);
    this.classList.remove("insistent");
}, false);
for (var i=0, n = lis.length; i < n; i++) {
    lis[i].addEventListener("dragstart", function(event) {
        dragged = this;
        ol.classList.add("insistent");
    }, false);
    lis[i].addEventListener("dragover", function(event) {
        if (dragover) {
            dragover.classList.remove("dragover");
        }
        event.preventDefault();
        dragover = this;
        this.classList.add("dragover");
    }, false);
}
isqua
  • 1,551
  • 2
  • 14
  • 16
  • What browser are you seeing that in specifically? The jsfiddle does not break for me. – TimHayes Jul 30 '13 at 17:15
  • I have this same issue on edge chrome (35.0.1916.153). This is annoying, and must be a bug. I'm not satisfied with using JS to do the hover state, I think there's a more surgical solution. – SimplGy Jul 02 '14 at 18:35
  • Possible duplicate of [Chrome won't apply css hover style when left mouse button is held down](https://stackoverflow.com/questions/8057499/chrome-wont-apply-css-hover-style-when-left-mouse-button-is-held-down) – adabru Sep 21 '18 at 11:17

2 Answers2

5

Use the mouseover and mouseout functions and add/remove a class called hovered instead of using CSS's :hover pseudo-class. Here is the updated jsFiddle

Javascript to add (inside for loop)

li.addEventListener("mouseover", () => {
  li.classList.add("hovered");
});
li.addEventListener("mouseout", () => {
  li.classList.remove("hovered");
});

CSS

.hovered {
    background: #fc9;
}

Side note: Be careful not so select all li on your page when selecting the variable.

Zach Saucier
  • 24,871
  • 12
  • 85
  • 147
  • Resisting this solution which just replaces css hover behavior with JS behavior, I tried many things to get the browser to notice that the mouse wasn't actually hovering any element, including triggering `mouseleave` and other events, reading the height of elements to trigger a reflow, and toggling a class that should have a visual effect. This is a webkit bug, right? How is this still hanging out after a year? – SimplGy Jul 02 '14 at 19:26
  • @SimpleAsCouldBe I'm curious why you resist a working solution simply because it uses javascript... A bug is a bug, many get overlooked – Zach Saucier Jul 02 '14 at 19:54
  • I anticipate a performance downside with binding to `mouseover`, `mouseout`, and modifying class structure for every list item. My application has several types of lists that share some behavior. Most types of list items in the application react to a css hover, some can click-to-select, and some are `[draggable]`. `:hover` works great, is likely the fastest, and requires no event cleanup. For me, it would be much better to flush the errant `:hover` than to override css behavior w/ js globally. – SimplGy Jul 02 '14 at 20:02
  • 1
    @SimpleAsCouldBe I am simply referencing the fact that *there is no CSS way*. So a js way is better than nothing. Changing class names really has little performance effect – Zach Saucier Jul 02 '14 at 20:06
0

Here is how I solved it. I had to resort to a little bit of JS unfortunately.

My page has collapsed records that highlight on hover. Clicking the record will expand it and disable the highlighting. Clicking again will re-collapse and resume hovering:

$(document).on('click', ".container.clickable", function(e){
  var $this = $(this);
  $this.toggleClass('expandable');
  if ($this.hasClass('expandable')) {
    $this.on('mouseenter', function(){
      // workaround to stop a stuck :hover
      $this.addClass('hilitable');
      $this.off('mouseenter');
    })
  } else {
    $this.removeClass('hilitable');
  }
});
Dex
  • 12,527
  • 15
  • 69
  • 90
  • I experienced browser bugs (blurry custom SVG borders in FF 50.0.0 or so), but I highly not recommend patching stuff in the website: a browser's bug must be solved in the browser. Reporting the bug to them and leting them fix it for everyone is more efficient. – Xenos Mar 17 '17 at 09:21