React-select: Option under mouse is focused when scrolling with ArrowUp/Down

Created on 16 Jan 2015  Â·  11Comments  Â·  Source: JedWatson/react-select

Replicate by clicking the first select on the demo page, putting your mouse cursor over the first option, and pressing ArrowDown. When you get to the bottom of the visible window and ArrowDown once more, the window scrolls causing the mouseEnter handler to fire on the top option and focus goes from Tasmania (which just scrolled into view) back up to the top option.

They way I've seen this handled is to keep a flag that tells whether or not the user is using the keyboard on the component, and then check it in the mouseEnter handler. Would look something like this:

var ex = {
    usingKeyboardOn: function() {
        if (this.usingKeyboard) { return; }
        document.removeEventListener("keydown", this.usingKeyboardOn, true);
        document.addEventListener("wheel", this.usingKeyboardOff, true);
        document.addEventListener("mousemove", this.usingKeyboardOff, true);
        this.usingKeyboard = true;
    },
    usingKeyboardOff: function() {
        if (!this.usingKeyboard) { return; }
        document.addEventListener("keydown", this.usingKeyboardOn, true);
        document.removeEventListener("wheel", this.usingKeyboardOff, true);
        document.removeEventListener("mousemove", this.usingKeyboardOff, true);
        this.usingKeyboard = false;
    },
    handleMouseEnter: function(op) {
        if (!this.usingKeyboard) { this.focusOption(op); }
    },
}

Most helpful comment

Is there any update on this? We are seeing this issue as well and it would be nice to get a solution in without having to work around it.

All 11 comments

Cheers @HeyImAlex, good catch and nice workaround. I'll implement it.

@JedWatson @HeyImAlex
I'm having a similar issue now (and this is still reproducable). Currently setting the focus onMouseEnter is fired by IE/FF on Windows as soon as the result list is rendered, always selecting the option below the cursor instead of the first one even if you do not touch the mouse at all. This is highly irritating to our users.

I would propose (and did implement) a similar fix to the above where the mouse events are ignored until mouse move.

I could implement both changes in a PR if you give me the go.

Alternatively, i wonder if the onMouseEnter handler is even needed anymore, because the option will be selected onMouseMove anyway. It seems that it was implemented at a later time.

So maybe the easier "fix" is to just remove the onEnter handling.

@FossiFoo I opened this issue while I was developing an internal select component and was checking out other implementations for inspiration, so I'm not really familiar with react-select as of today. I want to say the reason that I couldn't only rely on mousemove was that I wanted mouse-wheel scrolling to work even when the cursor wasn't _technically_ moving. But maybe I was wrong about mousemove not firing?

We also face the issue as described by @HeyImAlex. It is still reproducible on the demo page as well. Any updates on this one?

i fixed this in our copy. basically removing the unused onEnter handler fixes this. @JedWatson should i submit a PR?

@FossiFoo I think removing onEnter causes a minor bug with mousewheel scrolling when the mouse is completely still. Proof of concept. Hold your mouse still and wheel over the elements, and you might see them diverge like this:

ex

Effects Firefox but not Chrome, the difference being that Chrome fires a mousemove wherever the wheel stops and Firefox does not. I'm not sure what the spec has to say about it. IMO this is a less annoying bug than the original since all you need to do to get around it is move your mouse a little, and your hand is probably already on the mouse since you're using the wheel.

Hi @JedWatson,

Thank you for such a quality component.
I'm trying to port it to clojurescript (so I do not pay the price of converting from json to cljs many times on my render loop).
The way I'm trying the solve this problem mouseEnter and mouseMove is saving pageX and pageY. When focusAdjacentOption is called I grab that previously saved pageX and pageY and black-list them, so as long the mouse does not move mouseEnter and mouseMove will not select the option under the cursor.

;; on option
          :on-mouse-enter
          (fn [e]
            (let [page-xy [(.-pageX e) (.-pageY e)]
                  {:keys [last-page-xy black-listed-page-xy]} @memo-state]
              (when (not= page-xy last-page-xy)
                (swap! memo-state assoc
                       :last-page-xy page-xy))
              (when (and (not is-focused)
                        (not= black-listed-page-xy page-xy) )
                (focus-option state-atom option instance-prefix value-key)
                (swap! memo-state dissoc
                       :black-listed-page-xy))))

;; on focus-adjacent-option
(when new-focused-option
          ;; black-list last-page-xy saved by option in order
          ;; to ignore when mouse-enter and mouse-move be fired and prevent
          ;; the option under the mouse be selected
          (swap! memo-state
                (fn [{:as state :keys [last-page-xy]}]
                  (assoc state
                         :black-listed-page-xy last-page-xy)))
          (focus-option
            state-atom
            new-focused-option
            instance-prefix
            value-key))

@geraldodev ah, very cool. will you release that? i've been looking to do that too, but it was never high enough prio for me.

The suggested fix LGTM as well.

@FossiFoo,

It's not completed. I got multi selection and simple selection implemented.
Simple-value and Async are not implemented.
I have not decided yet to open, because different from @JedWatson I have no
authority over the code.
I'm porting (a lot of work) and I'm gaining confidence and getting to know
the design.

regards,
geraldodev

2016-10-19 3:42 GMT-02:00 FossiFoo [email protected]:

@geraldodev https://github.com/geraldodev ah, very cool. will you
release that? i've been looking to do that too, but it was never high
enough prio for me.

The suggested fix LGTM as well.

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/JedWatson/react-select/issues/48#issuecomment-254715596,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAvRCEIUY2dqBlukGnCTO3abNFrImOi4ks5q1a2vgaJpZM4DTkif
.

Is there any update on this? We are seeing this issue as well and it would be nice to get a solution in without having to work around it.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pgoldweic picture pgoldweic  Â·  3Comments

coder-guy22296 picture coder-guy22296  Â·  3Comments

AchinthaReemal picture AchinthaReemal  Â·  3Comments

batusai513 picture batusai513  Â·  3Comments

ericj17 picture ericj17  Â·  3Comments