Show / Hide datalist on event

In FireFox, by default on clicking the input element the data list shows/hides. I need the same functionality on Chrome.

<!DOCTYPE html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />    
    <title>HTML5 Data List</title>
    <style type="text/css">
    .hidden { display:none; }    
    </style>
    <script>
    document.addEventListener("DOMContentLoaded", () =>
    {        
        document.getElementById("ice-cream-choice").addEventListener("click", () =>
        {
            document.getElementById("ice-cream-flavors").classList.toggle('hidden');            
        }); 
    });        
    </script>
</head>
<body>

<label for="ice-cream-choice">Choose a flavor:</label>
<input list="ice-cream-flavors" id="ice-cream-choice" name="ice-cream-choice">

<datalist id="ice-cream-flavors">
    <option value="Chocolate">
    <option value="Coconut">
    <option value="Mint">
    <option value="Strawberry">
    <option value="Vanilla">
</datalist>

</body>
</html>

Well the datalist shows when clicked on in Chrome as well. What exact behavior are you trying to create? (I’m not 100% sure you can, because a datalist’s presentation is a browser element, not a page one, but…)

1 Like

If you click on the input box the input box the list appears, but you click on the input box again the list disappears in firefox which is what I want - in chrome the list disappears on blur.

I got this from chatGPT :

<!DOCTYPE html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />    
    <title>HTML5 Data List</title>
    <style type="text/css">
    .hidden { display:none; }    
    </style>
    <script>
    let firstTime = true;
    let gFlag = true;
    document.addEventListener("DOMContentLoaded", () =>
    {        
        let is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1;

        if (is_chrome)
        {
            const input = document.getElementById("ice-cream-choice");
            const datalist = document.getElementById("ice-cream-flavors");

            input.addEventListener("click", () =>
            {
                if (firstTime)
                {
                    firstTime = false;
                    return ;
                }
                if (gFlag) input.setAttribute("list", "ice-cream-flavors");
                else input.removeAttribute("list");
                gFlag = !gFlag;
            });        
        }

    });        
    </script>
</head>
<body>

<label for="ice-cream-choice">Choose a flavor:</label>
<input list="ice-cream-flavors" id="ice-cream-choice" name="ice-cream-choice">

<datalist id="ice-cream-flavors">
    <option value="Chocolate">
    <option value="Coconut">
    <option value="Mint">
    <option value="Strawberry">
    <option value="Vanilla">
</datalist>

</body>
</html>

Actually if i click the box again in my firefox, it disappears and reappears, which feels rather annoying to me.

The code provided by chatGPT… would work… feels like a bit of a club, but it would work. It could be simplified to remove the firstTime flag by removing the list attribute from the HTML, and relying on the Javascript to put it back, but that would make the behavior in a non-JS environment poorer.

Odd - because I made sure the code is application only to chrome.

Did this fail in FireFox ?

is_chrome = navigator.userAgent.toLowerCase().indexOf('chrome') > -1

No i mean the DEFAULT behavior in firefox, without the code. Sorry, i should have been more specific.

The code you have would work in any browser though… so…

So the requirement is the default behaviour in FireFox, had to do this instead of implementing something like select2 which is jQuery dependent. We want to have 0 dependency on jQuery. Even ES2022 would do.

As i said, the script you’ve got now will work in any browser with standard vanilla javascript, because it just disassociates the datalist from the text input. The browser would then revert to displaying the element like any other input element, until the list is reattached.

I thought this would be a simpler task.

const toggleList = (elem, value) => {
  if (elem.list === null) {
    elem.setAttribute('list', value)
    return
  }
  elem.removeAttribute('list')
}

document.addEventListener("DOMContentLoaded", () => {
  // test if chromium browser
  if (Object.hasOwn(window, 'chrome')) {
    const input = document.querySelector('#ice-cream-choice')

    input.addEventListener('click', (event) => {
      toggleList(event.target, 'ice-cream-flavors')
    })
  }
})

toggleList could instead be written as

const toggleList = (elem, value) => {
  return (elem.list === null)
    ? elem.setAttribute('list', value)
    : elem.removeAttribute('list')
}

both versions will return undefined.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.