onMouseMove doesn't fire over

2020-04-10 11:37发布

问题:

Say I have an onMouseMove listener which just logs the x and y position of the mouse.

If I expand a select element and move my mouse over the exposed <option> elements, the onMouseMove event never fires.

I think it might have something to do with this:

http://www.terminally-incoherent.com/blog/2009/01/12/ie-jquery-hovering-and-option-elements/

Does anybody know how to get around this? Specifically, I would like to get an instance of the <option> element I'm moving over at any given time.

I would prefer not to change the <select> or <option> elements as my code is injected by a chrome extension and it would be burdensome to change every page for this reason.

回答1:

As you suspected, the mouse events do not work on a select/option in Chrome

Possible workarounds might be:

  • Use an onclick listener when an option is selected.
  • Draw an options like drop down using DHTML
  • Use a select with the "size" attribute, typically used for multiselect. Options inside of a select with a "size" attribute do react to the mouse events in Chrome.

I created an example of the third option here:

http://jsfiddle.net/SNLzA/

This clones the original select and hides the clone. The clone is given a size attribute so that it can react to mouse events. Then, when the original select is clicked we temporarily show the clone which has been styled to sort of look like the options drop down. Then when a user clicks an option, we close the clone and set the value in the original select. A click event listener is attached to the body to close the clone when not on an option.

HTML

<select id="s">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
    <option value="5">5</option>
</select>

CSS

select { display: block; width: 60px; }

JS

var select = document.getElementById("s"),
    options = select.getElementsByTagName("option"),
    clone = select.cloneNode(true),
    body = document.body,
    isOpen = false,

    closeSelect = function() {     
        select.removeAttribute("size");
        clone.setAttribute("style", "display: none;");       
        isOpen = false;        
        select.value = options[clone.selectedInput];
    },

    openSelect = function(e) {
        isOpen = true;
        clone.setAttribute("style", "display: auto;");
        select.setAttribute("size", options.length); 
        clone.value = options[select.selectedInput];
    };

clone.setAttribute("style", "display: none;");

body.insertBefore(clone, select);

body.addEventListener("click", function(e) {
    if (isOpen === true && e.target != select) {
       closeSelect();
    } 
});

select.addEventListener("click", openSelect);

for (i = 0; i < options.length; i++) {
    options[i].addEventListener("click", function(e) {
        closeSelect();
    });

    options[i].addEventListener("mouseover", function(e) {
        console.log("on option: " + e.target.value);
    });
}