Thursday, 22 November 2018

Web Tutorial: The Smart Drop-down List (Part 3/3)

And now for the next step!

The drop-down list looks presentable and behaves like an actual drop-down list. But we want more, don't we? What if you could actually filter this long-ass list of countries?

To do that, we add an oninput event handler to the textbox (which should have its readonly attribute removed now). It should run the showList() function, which we've already written, passing in "Countries" and false as an argument. The second argument is to tell the function that it was not called from clicking the "button", but rather, from entering text in the txtCountries text box.
            <div>
                <input placeholder="(select one)" id="txtCountries" oninput="showList('Countries', false)">
                <div onclick="showList('Countries', true)">&#9660;</div>
            </div>


Now, on to the showList() function. Here, we add an else block to the main conditional. This tells the function what to do if we're supposed to filter, as opposed to just displaying the entire list. The first action is to reveal the list. At the same time, declare the variable txt and grab the element txtCountries.
            function showList(objName, showAll)
            {
                var txt = document.getElementById("txt" + objName);
                var ddl = document.getElementById("ddl" + objName);
                var ul = document.getElementById("ul" + objName);

                ul.innerHTML = "";

                if (showAll)
                {
                    if (ul.style.display == "none")
                    {
                        ul.style.display = "block";

                        for (var i = 0; i < ddl.options.length; i++)
                        {
                            var opt = ddl.options[i];

                            addListItem(objName, opt.value, opt.text);
                        }
                    }
                    else
                    {
                        ul.style.display = "none";
                    }
                }
                else
                {
                    ul.style.display = "block";               
                }
            }


And then we iterate through the options of the ddlCountries drop-down list.
                else
                {
                    ul.style.display = "block";

                    for (var i = 0; i < ddl.options.length; i++)
                    {

                    }                   
                }


Then we declare a variable, opt, and set it to the current option. Next, we use the indexOf() method on the text property of opt to see if it contains the text currently entered in the txtCountries text box. We should also ensure that the value is not an empty string. If it satisfies those conditions, add the item to the list using the addListItem() function we created earlier.
                else
                {
                    ul.style.display = "block";

                    for (var i = 0; i < ddl.options.length; i++)
                    {
                        var opt = ddl.options[i];

                        if (opt.text.indexOf(txt.value) != -1 && opt.text != "")
                        {
                            addListItem(objName, opt.value, opt.text);
                        }
                    }                   
                }


Try it! Type in "h" into the text box. The list should pop up, showing all countries with a "h" in the name.


But that list is still too long. Try adding "a" after the "h". The list is dramatically shortened! Select "Ghana". Does Ghana get selected?


Hold your horses, we're not done!

What happens when you type in some random text with no matches and then try to close the list by clicking on the "button"? Looks like the value is left there. That's not what we want, so let's fix that.


Go to the showList() function and get into the conditional that handles the toggling of the "button". After it hides the list, check if the list is empty. If it is, that means there were no matches for the string in the text box.
                if (showAll)
                {
                    if (ul.style.display == "none")
                    {
                        ul.style.display = "block";

                        for (var i = 0; i < ddl.options.length; i++)
                        {
                            var opt = ddl.options[i];

                            addListItem(objName, opt.value, opt.text);
                        }
                    }
                    else
                    {
                        ul.style.display = "none";

                        if (ul.innerHTML == "")
                        {

                        }
                    }
                }


In that case, we want to reset the value of the text box. Check if the value of ddlCountries is empty.
                if (showAll)
                {
                    if (ul.style.display == "none")
                    {
                        ul.style.display = "block";

                        for (var i = 0; i < ddl.options.length; i++)
                        {
                            var opt = ddl.options[i];

                            addListItem(objName, opt.value, opt.text);
                        }
                    }
                    else
                    {
                        ul.style.display = "none";

                        if (ul.innerHTML == "")
                        {
                            if (ddl.value == "")
                            {

                            }
                            else
                            {

                            }
                        }
                    }
                }


If so, set the value of the txtCountries text box to an empty string too. If not, set it to the current displayed text in the ddlCountries drop-down list. This way, the text box doesn't get stuck displaying some nonsense value.
                if (showAll)
                {
                    if (ul.style.display == "none")
                    {
                        ul.style.display = "block";

                        for (var i = 0; i < ddl.options.length; i++)
                        {
                            var opt = ddl.options[i];

                            addListItem(objName, opt.value, opt.text);
                        }
                    }
                    else
                    {
                        ul.style.display = "none";

                        if (ul.innerHTML == "")
                        {
                            if (ddl.value == "")
                            {
                                txt.value = "";
                            }
                            else
                            {
                                txt.value = ddl.options[ddl.selectedIndex].innerHTML;
                            }
                        }
                    }
                }


And now, after hiding the ddlCountries drop-down list like I showed you in Part 2, we're done. Check it out below.


How do we use this?

Well, although the ddlCountries drop-down list is invisible, it's still there. The drop-down list we made is simply a prettier and smarter display version of it. When you send the values over via a form, though, you should still grab the value of ddlCountries.

Why all the abstraction?

Yes, you notice a lot of this code is indirect referencing. That's so you can reuse the code for multiple drop-down lists! Remember DRY (Don't Repeat Yourself)!

I'm Ghana go now, see you next time!
T___T

No comments:

Post a Comment