Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug Report] Tab focus from v-select returns to the first focusable element #6608

Closed
oti opened this issue Feb 26, 2019 · 27 comments
Closed
Assignees
Labels
C: VSelect VSelect platform specific The issue only occurs on a specific platform T: bug Functionality that does not work as intended/expected
Milestone

Comments

@oti
Copy link

oti commented Feb 26, 2019

Versions and Environment

Vuetify: 1.5.1
Vue: 2.6.6
Browsers: Safari, Internet Explorer
OS: Mac OS 10.13.6, Windows

Steps to reproduce

Using macOS Safari 12.0.3 or IE11.

  1. after focusing on v-select
  2. pressing the tab key
  3. does not focus to next focusable element
  • but focus on the beginning of document.

It can be confirmed in the sample of the official document.

In Google Chrome, tab focus move from v-select is works normally.

Expected Behavior

Tab focus move to next focusable element from v-select in Safari and IE11

Actual Behavior

Tab focus does not move to next focusable element from v-select in Safari and IE11

Reproduction Link

https://codepen.io/anon/pen/RdwyQQ?editors=1010

@dsseng dsseng added the platform specific The issue only occurs on a specific platform label Feb 26, 2019
@KaelWD KaelWD changed the title [Bug Report] Tab focus move from v-select does not working in partial browser [Bug Report] Tab focus from v-select returns to the first focusable element Feb 27, 2019
@KaelWD KaelWD added the T: bug Functionality that does not work as intended/expected label Feb 27, 2019
@ghost
Copy link

ghost commented Mar 7, 2019

This issue is also happening on chrome windows 10 not only v-select but also on v-autocomplete or any dropdown input. When the user selecting an item with the help of the mouse and then press tab key is not working properly as expected. When the mosue click to select an item and tab three times then focus moving onto first input.

@blakenorman37
Copy link

Is there any work around for this?

@userquin
Copy link
Member

Any news about this? A month has passed and there is still no work around for this!!!

@userquin
Copy link
Member

It seems that the order in which the events are emitted by the browser are disparate, so when one component lost focus and other receive it may be diffferent in sequence between disparate browsers. So, the solution could be to give a chance to the browser to do its work and then process the event to work around this problem.

A simple work around is to extends for example VAutocomplete:

import { VAutocomplete } from "vuetify/lib";
export default {
  name: "your-autocomplete",
  extends: VAutocomplete,
  methods: {
    blur(e) {
      setTimeout(() => VAutocomplete.methods.blur.call(this, e), 0);
    }
  }
};

On MS Edge this work around works, I need to check it on Safari: by the way, this is a pen to prove that works: https://codepen.io/userquin/pen/rRaYgP

@userquin
Copy link
Member

also working on safari macosx

@KaelWD
Copy link
Member

KaelWD commented Mar 28, 2019

Blame: 8a2a1a1

@johnleider that logic needs to be in a separate method, this fix is also emitting blur twice.

@userquin
Copy link
Member

userquin commented Mar 28, 2019

I'll try to fix that, maybe we need to stop first one to avoid bubbling and just propagate only from onBlur inside VXXX: just add e.stopPropagation() to cancel bubbling.

From w3c, event bubbling:

Any event handler may choose to prevent further event propagation by calling the stopPropagation method of the Event interface. If any EventListener calls this method, all additional EventListeners on the current EventTarget will be triggered but bubbling will cease at that level. Only one call to stopPropagation is required to prevent further bubbling.

@userquin
Copy link
Member

I have version 1.5.5, the code on VSelect is the following (why calling input blur if the event comes from it??):

/** @public */
blur: function blur(e) {
	this.isMenuActive = false;
	this.isFocused = false;
	this.$refs.input && this.$refs.input.blur();
	this.selectedIndex = -1;
	this.onBlur(e);
},

/** @public */
activateMenu: function activateMenu() {
	this.isMenuActive = true;
},

onBlur: function onBlur(e) {
	this.$emit('blur', e);
},

If I just change my autocomplete to this one, just only 1 blur event is fired:

import { VAutocomplete } from "vuetify/lib";
export default {
  name: "your-autocomplete",
  extends: VAutocomplete,
  methods: {
    blur() {
      setTimeout(this.handleBlur, 0);
    },
    handleBlur() {
      this.isMenuActive = false;
      this.isFocused = false;
      this.selectedIndex = -1;
    }
  }
};

@blakenorman37
Copy link

The above fix works for the autocomplete, any solution for the VSelects being broken?

@userquin
Copy link
Member

userquin commented Mar 28, 2019

Just extends from VSelect instead VAutocomplete, the code for blur method resides on VSelect (test if this works, I dont use VSelect on my projects) :

import { VSelect } from "vuetify/lib";
export default {
  name: "your-select",
  extends: VSelect,
  methods: {
    blur() {
      setTimeout(this.handleBlur, 0);
    },
    handleBlur() {
      this.isMenuActive = false;
      this.isFocused = false;
      this.selectedIndex = -1;
    }
  }
};

@userquin
Copy link
Member

also the fix is for 1.5.5, not tested on 1.5.6, 1.5.7

@userquin
Copy link
Member

well, it is a little more complicated, just because VSelect is a functional wrapper over VSelect, so we need to import VSelect manually. This fix is tested only on MS Edge:

import VSelect from "vuetify/lib/components/VSelect/VSelect";
// work around for https://github.com/vuetifyjs/vuetify/issues/6608
export default {
  name: "your-select",
  extends: VSelect,
  data: () => ({
    blurHandled: false
  }),
  methods: {
    blur() {
      if (!this.blurHandled) {
        setTimeout(this.handleBlur, 0);
      }
    },
    onTabDown(e) {
      this.blurHandled = true;
      setTimeout(() => this.handleTabDown(e), 0);
    },
    handleBlur() {
      this.isMenuActive = false;
      this.isFocused = false;
      this.selectedIndex = -1;
      this.$nextTick(() => (this.blurHandled = false));
    },
    handleTabDown(e) {
      if (this.isMenuActive) {
        VSelect.options.methods.onTabDown.call(this, e);
      } else {
        this.handleBlur();
      }
    }
  }
};

@blakenorman37
Copy link

Thanks, that fix works for 1.57 in IE 11.

@userquin
Copy link
Member

a simplified version of VSelect:

import VSelect from "vuetify/lib/components/VSelect/VSelect";
// work around for https://github.com/vuetifyjs/vuetify/issues/6608
export default {
  name: "your-select",
  extends: VSelect,
  methods: {
    blur() {},
    onTabDown(e) {
      setTimeout(() => this.handleTabDown(e), 0);
    },
    handleBlur() {
      this.isMenuActive = false;
      this.isFocused = false;
      this.selectedIndex = -1;
    },
    handleTabDown(e) {
      if (this.isMenuActive) {
        VSelect.options.methods.onTabDown.call(this, e);
      } else {
        this.handleBlur();
      }
    }
  }
};

@blakenorman37
Copy link

@KaelWD , will this be fixed any time soon?

@userquin
Copy link
Member

both fixes tested on windows 10: edge. chrome and firefox and macosx: chrome, firefox and safari

@userquin
Copy link
Member

userquin commented Mar 28, 2019

@KaelWD I think vuetify team must review focus/blur behavior in deep, not just for these 2 components.

Another example (not yet reported): I use a VTextField with a mask for edition (component is focused) and no mask when no focused. All works fine but on safari this VTextField on blur just focus its input again and there is no way to focus another element on the page, I must close the browser. On MS Edge, this VTextField lost the focus on second Tab key.

@userquin
Copy link
Member

ok, I just have found what's the problem, it is a problem in the Maskable mixin.

As you can see in the next image (MS Edge), once the tab key is pressed on Fecha Nacimiento (birth date) , then Lugar de nacimiento (Place of birth) gets focused, but the caret is on the first one.

image

What happens here: well, the date component just remove the mask on blur, but Maskable do this:

  watch: {
    /**
     * Make sure the cursor is in the correct
     * location when the mask changes
     */
    mask () {
      ... (some code)
      this.$nextTick(() => {
        this.$refs.input.value = newValue
        this.setCaretPosition(selection)
      })
    }
}
  methods: {
    setCaretPosition (selection) {
      this.selection = selection
      window.setTimeout(() => {
        this.$refs.input && this.$refs.input.setSelectionRange(this.selection, this.selection)
      }, 0)
    },
  ....

In the case of MS Edge, just works and if we press tab key again, the focus moves to the next one bellow Lugar de nacimiento (birth place), and looks like the focus jumps 2 fields (but only jumps 1, the focus is on the second one).

On Safari, the problem is that when you call setSelectionRange, then the field gets focused.

So my work around is very simple:

import VTextField from "vuetify/lib/components/VTextField/VTextField";
export default {
  name: "my-maskable-text-field",
  extends: VTextField,
  methods: {
    setCaretPosition(selection) {
      this.selection = selection;
      setTimeout(() => {
        this.$refs.input &&
          this.isFocused && /*<=== fix here */
          this.$refs.input.setSelectionRange(this.selection, this.selection);
      }, 0);
    }
  }
};

@MajesticPotatoe MajesticPotatoe added the C: VSelect VSelect label Apr 9, 2019
@avishapiro01

This comment has been minimized.

@mseele
Copy link
Contributor

mseele commented Apr 16, 2019

Any update on this? It's a showstopper for us :(

@Akii
Copy link

Akii commented May 20, 2019

Using this for VCombobox which is also affected by this bug:

import { VCombobox } from 'vuetify/lib'

export default {
  name: 'combobox',
  extends: VCombobox,
  methods: {
    onTabDown(e) {
      setTimeout(() => VCombobox.methods.onTabDown.call(this, e), 0)
    }
  }
}

They apparently changed it to onTabDown instead of blur.

johnleider added a commit that referenced this issue Jun 19, 2019
the ordering of events in safari/ie11 caused our manual blur of the input to break tabbing through
inputs. also resolved duplicate blur events.

fixes #6608, fixes #5913
@johnleider
Copy link
Member

This is resolved with 5fa6a68 . Thank you to everyone for your patience on this.

This was referenced Jul 23, 2019
@robhuska
Copy link

robhuska commented Aug 1, 2019

So these fixes are not going to be in v1.5.x? I am in final stages of beta on a product and we don't have time to try and upgrade to v2.x before launch.

@maxshuty
Copy link

maxshuty commented Feb 19, 2020

For all who make it this far - I have put up the PR to v1.5 here: #10620. Once this is merged then it should be fixed for all of us who are unable to upgrade to 2.x at this time.

Update It was merged so v1.5.23 has the tabbing fix I applied now.

@xfyre
Copy link

xfyre commented May 22, 2021

This is still happening in Safari with Vuetify 2.5.0, although it's supposed to be fixed according to commit history. Am I missing something?

@johnleider
Copy link
Member

We kindly ask users to not comment on closed/resolved issues. If you believe that this issue has not been correctly resolved, please create a new issue showing the regression or create a new discussion.

If you have any questions, please reach out to us in our Discord community.

@vuetifyjs vuetifyjs locked as resolved and limited conversation to collaborators May 24, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
C: VSelect VSelect platform specific The issue only occurs on a specific platform T: bug Functionality that does not work as intended/expected
Projects
None yet
Development

No branches or pull requests