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]: Tom Select auto trigger when we use edge autofill feature. #806

Open
Shivam7414 opened this issue Nov 19, 2024 · 8 comments
Open
Labels
bug Something isn't working

Comments

@Shivam7414
Copy link

Shivam7414 commented Nov 19, 2024

Bug description

Bug description

When we use multiple tom select in a single page and we use the Microsoft Edge autofill feature on input then all tom selects are automatically triggered and all start flickering.

Expected behavior

If one tom select is already open then the next tom select try to close previous tom select so this is create a loop event.

This issue occurs only on edge browser.

Steps to #reproduce

For Reproduce the bug I am attaching a video.

Tom.select.fliker.issue.mp4

Additional context

  • OS: [iOS, Windows]
  • Browser [Edge]
  • Version [Latest]
@Shivam7414 Shivam7414 added the bug Something isn't working label Nov 19, 2024
@nwalters512
Copy link
Contributor

Can you please fill out the "steps to reproduce" in the issue template? It'd be great if you could describe how to reproduce with an existing page, e.g. https://tom-select.js.org/examples/.

@Shivam7414
Copy link
Author

Shivam7414 commented Nov 20, 2024

Can you please fill out the "steps to reproduce" in the issue template? It'd be great if you could describe how to reproduce with an existing page, e.g. https://tom-select.js.org/examples/.

Hello @nwalters512 ,

I can't reproduce the bug on https://tom-select.js.org/examples/ existing page, But I attached a video of the problem.

Tom.select.fliker.issue.mp4

You can check my code and how I am initializing tom select

This issue occurs only in the edge browser when the user autofills the feature, and in other browsers tom select works fine.

I think this issue occurs because the edge browser creates a loop between all tom-select instances.

Please look into this issue, I tried many things, but nothing works.

let tomSelectInstances = [];
function initializeTomSelectInstances() {
    const selectors = {
        account_type: "#accountType",
        reporting_manager: '#reporting_manager',
        nationality: '#nationality',
        account_status: '#account_status',
    };

    tomSelectInstances = {};

    Object.entries(selectors).forEach(([key, selector]) => {
        const element = document.querySelector(selector);
        if (element) {
            tomSelectInstances[key] = new TomSelect(selector, {
                maxOptions: null,
            });
        }
    });

    Object.values(tomSelectInstances).forEach(instance => {
        setupMutationObserver(instance);
        instance.on('dropdown_open', () => {
            const $inputField = $(instance.control_input);
            $inputField.focus();
        });
    });

    updateInputClasses();
}

function updateInputClasses() {
    Object.values(tomSelectInstances).forEach(instance => {
        const $dropdownContainer = $(instance.control);
        const $item = $dropdownContainer.find('.item');
        const $inputField = $dropdownContainer.find('input');
        
        if ($item.length) {
            $inputField.addClass('has-item').removeClass('no-item');
        } else {
            $inputField.addClass('no-item').removeClass('has-item');
        }
    });
}
function setupMutationObserver(instance) {
    const $dropdownContainer = $(instance.control);
    const observer = new MutationObserver(function(mutations) {
        mutations.forEach(function(mutation) {
            if (mutation.type === 'childList') {
                updateInputClasses();
            }
        });
    });

    const config = { childList: true, subtree: true };
    observer.observe($dropdownContainer[0], config);
}
function reinitializeTomSelect() {
    initializeTomSelectInstances(); // Reinitialize instances
}
function setTomSelectValues(values) {
    Object.keys(tomSelectInstances).forEach(function(key) {
        if (values[key] !== undefined) {
            const instance = tomSelectInstances[key];
            instance.setValue(values[key]);
        }
    });
}

$(document).ready(function() {
    reinitializeTomSelect();
});

@nwalters512
Copy link
Contributor

nwalters512 commented Nov 20, 2024

There's quite a bit of code there, and also no markup to go with your script. Can you provide a minimal, self-contained reproduction with something like https://codepen.io/ or https://jsfiddle.net/? Please strip away anything that isn't required to reproduce this. Hopefully the process of isolating the issue will help you identify what causes it. I'm guessing it's something to do with your own code since you can't reproduce it on the documentation site.

@Shivam7414
Copy link
Author

Shivam7414 commented Nov 20, 2024

There's quite a bit of code there, and also no markup to go with your script. Can you provide a minimal, self-contained reproduction with something like https://codepen.io/ or https://jsfiddle.net/? Please strip away anything that isn't required to reproduce this. Hopefully, the process of isolating the issue will help you identify what causes it. I'm guessing it's something to do with your own code since you can't reproduce it on the documentation site.

Hello @nwalters512

I create a test environment on codepen.io
https://codepen.io/ucddmaxg-the-animator/pen/abegzBG

I also attached a video regarding this issue, and how you can reproduce this issue. Please check this issue only the edge browser in other browsers tom select is working fine for me.

tom.select.fliker.issue.-.Made.with.Clipchamp.mp4

@fuzzzerd
Copy link

After a little testing on that codepen, it seems to be specific to selected the Edge "Last used" from the autocomplete list; which goes through to fill out values in all other form fields. That does seem to cause an issue with tom-select for me.

I suspect this would also occur on the docs site, if there were a two field form, one regular input and a tom-select. If you fill out the regular input and submit, then go back to the form, Edge will give you an autocomplete in the regular input with two options: whatever you entered into the form previously plus whatever you entered into the form previously with a handy last used call out.

last used call out for edge autocomplete

For me, I don't get any weird behavior clicking the second option, but I do with the first.

Not sure if that's an Edge issue or tom-select issue, but figured I'd share what I found.

@nwalters512
Copy link
Contributor

Thanks, this was very helpful! I couldn't reproduce this directly in Codepen, but I was able to reproduce it by using Codepen's "export" feature and starting up a server in the dist directory in the resulting zip with python3 -m http.server 9000.

After setting some breakpoints, I think the callstack reveals what's going on here:

Screenshot 2024-11-20 at 09 12 52

First, Edge focuses the first input, which triggers this:

addEvent(focus_node,'focus', (e) => self.onFocus(e as MouseEvent) );

We then drill down into a few functions:

self.refreshOptions(!!self.settings.openOnFocus);

self.open();

self.focus();

tom-select/src/tom-select.ts

Lines 1292 to 1295 in 78c0d46

setTimeout(() => {
self.ignoreFocus = false;
self.onFocus();
}, 0);

Note that the final call to onFocus is in setTimeout(...). Before that can execute, Edge focuses the next input, which starts the above chain of calls again.

One the delayed call to onFocus triggers in the setTimeout(...) callback, we restart the loop and jump back here:

self.refreshOptions(!!self.settings.openOnFocus);

At this point we have three independent focus -> refresh options -> open -> focus loops going, and things proceed such that focus rapidly jumps around without ever settling on one input.

Unfortunately I don't currently have the time to figure out a fix for this, but maybe this is enough information for someone else to proceed.

@Shivam7414
Copy link
Author

Thank you so much for your detailed investigation and explanation, @nwalters512 Your analysis of the focus loop issue is extremely helpful and makes it much clearer what’s happening under the hood.

Based on your findings, it does seem like the setTimeout callback is unintentionally causing multiple focus -> refreshOptions -> open -> focus loops when autofill is triggered in Edge.

@Nick-PDS
Copy link

Nick-PDS commented Dec 9, 2024

+1 on this issue. Have a super similar issue with the loop when paired with bootstrap's OffCanvas. When an offcanvas is open with backdrop set to false, clicking on the dropdown causes it to go into a loop, and in my case the dropdown never opens.

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants