Saturday 17 November 2018

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

Howdy, and welcome to today's web tutorial!

We're going to make what I call a Smart Drop-down List. Not only can you select from this list, you can type in text and the list will show you only the options corresponding to that text. It's one of the most ubiquitous features in many UI packages today and you could probably just download one from the plethora of packages out there... or we could have some fun instead and make our own.

For that, let's first implement a classic drop-down list. It will be a very standard select element, id ddlCountries. The first option will be blank, and after that, I simply copied an entire list of countries from this site.

<!DOCTYPE html>
<html>
    <head>
        <title>Smart Drop-down List</title>

        <style>

        </style>

        <script>

        </script>
    </head>

    <body>
        <select id="ddlCountries">
            <option value="">(select one)</option>
            <option value="AF">Afghanistan</option>
            <option value="AX">Åland Islands</option>
            <option value="AL">Albania</option>
            <option value="DZ">Algeria</option>
            <option value="AS">American Samoa</option>
            <option value="AD">Andorra</option>
            ... (get the rest of the code here)
        </select>
    </body>
</html>


That's a very long list...


And what comes next, is that we wrap this within a div with a class of ddl_wrapper.
        <div class="ddl_wrapper">
            <select id="ddlCountries">
                <option value="">(select one)</option>
                <option value="AF">Afghanistan</option>
                <option value="AX">Åland Islands</option>
                <option value="AL">Albania</option>
                <option value="DZ">Algeria</option>
                <option value="AS">American Samoa</option>
                <option value="AD">Andorra</option>
                ... (get the rest of the code here)
            </select>
        </div>



Let's write the style for ddl_wrapper. Give it a black outline so we can see what's going on, set overflow to visible so that nothing gets cut off, and maybe a width and height, though height isn't really necessary.
        <style>
            .ddl_wrapper
            {
                outline: 1px solid black;
                overflow: visible;
                width: 200px;
                height: 30px;
            }
        </style>


Now you see that your drop-down list is encased within the div!


OK, here's the deal. We'll create something that simulates what this drop-down list does, and later hide this drop-down list.

So first, let's put in a div.
        <div class="ddl_wrapper">
            <div>

            </div>

            <select id="ddlCountries">
                <option value="">(select one)</option>
                <option value="AF">Afghanistan</option>
                <option value="AX">Åland Islands</option>
                <option value="AL">Albania</option>
                <option value="DZ">Algeria</option>
                <option value="AS">American Samoa</option>
                <option value="AD">Andorra</option>
                ... (get the rest of the code here)
            </select>
        </div>


Then add in two things - a text box with an id of txtCountries and another div containing the &#9660; symbol.
        <div class="ddl_wrapper">
            <div>
                <input placeholder="Countries" id="txtCountries">
                <div>&#9660;</div>
            </div>

            <select id="ddlCountries">
                <option value="">(select one)</option>
                <option value="AF">Afghanistan</option>
                <option value="AX">Åland Islands</option>
                <option value="AL">Albania</option>
                <option value="DZ">Algeria</option>
                <option value="AS">American Samoa</option>
                <option value="AD">Andorra</option>
                ... (get the rest of the code here)
            </select>
        </div>


Things looking a bit messy at the moment. Not to worry, we'll clean it up with some styling.


First, remove the black border in the ddl_wrapper CSS class.
        <style>
            .ddl_wrapper
            {
                outline: 0px solid black;
                overflow: visible;
                width: 200px;
                height: 30px;
            }
        </style>


Now, for the main div within the ddl_wrapper CSS class, give it a light grey border, and set the width to 100%. That means it'll occupy the entirety of the parent div.
        <style>
            .ddl_wrapper
            {
                outline: 0px solid black;
                overflow: visible;
                width: 200px;
                height: 30px;
            }

            .ddl_wrapper div
            {
                border: 1px solid #DDDDDD;
                width: 100%;
            }
        </style>


For the div with the &#9660; symbol, it's supposed to be clickable. So set the cursor property to pointer, give it a width of 10% and make it float right. Text alignment, border and padding are up to you, though I think the values I've used below work best.
        <style>
            .ddl_wrapper
            {
                outline: 0px solid black;
                overflow: visible;
                width: 200px;
                height: 30px;
            }

            .ddl_wrapper div
            {
                border: 1px solid #DDDDDD;
                width: 100%;
            }

            .ddl_wrapper div div
            {
                width: 10%;
                float: right;
                text-align: center;
                cursor: pointer;
                padding: 0;
                border: none;
            }
        </style>


As for the text box, give it 80% width, 90% height and set both the border and outline properties to none. This will make it totally seamless.
        <style>
            .ddl_wrapper
            {
                outline: 0px solid black;
                overflow: visible;
                width: 200px;
                height: 30px;
            }

            .ddl_wrapper div
            {
                border: 1px solid #DDDDDD;
                width: 100%;
            }

            .ddl_wrapper div div
            {
                width: 10%;
                float: right;
                text-align: center;
                cursor: pointer;
                padding: 0;
                border: none;
            }

            .ddl_wrapper div input
            {
                width: 80%;
                height: 90%;
                border: none;
                outline: none;
            }
        </style>


Looking much better now.


Now let's make it perform like a drop-down list! Insert an unordered list after the first div inside the div styled with ddl_wrapper. The id will be ulCountries. Make it disappear using an inline style attribute and display: none. Then put an onclick event in the "button". It should run the showList() function, passing in "Countries" and true as arguments.
            <div>
                <input placeholder="Countries" id="txtCountries">
                <div onclick="showList('Countries', true)">&#9660;</div>
            </div>

            <ul id="ulCountries" style="display:none;"></ul>


Let's write some JavaScript! The showList() function accepts two parameters - objName and showAll. objName is the name of the object you'll be accessing. In this case, it will be "Countries". showAll is a Boolean variable that tells you if we need to show the entire list or filter it by search. If we're clicking on the "button", that value is true. Because clicking on that button will show all results.

Declare two variables - ddl and ul. We'll use the objName parameter and the getElementById() method to derive the drop-down list and the unordered list. Initially, the unordered list will be empty.
        <script>
            function showList(objName, showAll)
            {
                var ddl = document.getElementById("ddl" + objName);
                var ul = document.getElementById("ul" + objName);

                ul.innerHTML = "";
            }
        </script>


Now let's toggle the unordered list. Each time you click on the "button", if the ulCountries list is hidden, it'll be displayed. If it's displayed, it'll be hidden. Bear in mind that this is only if showAll is true, which means the "button" has been clicked.
        <script>
            function showList(objName, showAll)
            {
                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";
                    }
                    else
                    {
                        ul.style.display = "none";
                    }
                }
            }
        </script>


After that, iterate through ddlCountries's options and add them, one by one, into the ulCountries! We do this by calling the addListItem() function and passing in objName, the current option's value and text as arguments.
        <script>
            function showList(objName, showAll)
            {
                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";
                    }
                }
            }
        </script>


Now let's write the addListItem() function. It will accept the name of the object, and two other strings as parameters. val is the value of each option, and text is the displayed value.
        <script>
            function showList(objName, showAll)
            {
                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";
                    }
                }
            }

            function addListItem(objName, val, text)
            {

            }
        </script>


Here, we declare the variable ul and repeat what we did in the showList() function. Then we use the createElement() method to create a list item.
            function addListItem(objName, val, text)
            {
                var ul = document.getElementById("ul" + objName);

                var li = document.createElement("li");
            }


Next, set the list item's displayed text to text, and append it to ddlCountries. For the time being, we won't use the val parameter.
            function addListItem(objName, val, text)
            {
                var ul = document.getElementById("ul" + objName);

                var li = document.createElement("li");
                li.innerHTML = text;
                ul.appendChild(li);
            }


Let's test this! Clicking on the "button" should toggle the list on and off! I know it looks shitty right now, but our objective is first to get it to work.


Now, what else should we implement? The list toggles on and off, but we can't select anything. That's what we'll do next. After setting the text, add an onclick handler that will run the selectOption() function with objName, val and text as arguments. Then create said function.
            function addListItem(objName, val, text)
            {
                var ul = document.getElementById("ul" + objName);

                var li = document.createElement("li");
                li.innerHTML = text;
                li.onclick = function()
                {
                    selectOption(objName, val, text);
                }
                ul.appendChild(li);
            }

            function selectOption(objName, val, text)
            {

            }


Here, we use objName to first do pretty much what we did for the other two functions, except that now we'll grab the textbox, txtCountries as well.
            function selectOption(objName, val, text)
            {
                var txt = document.getElementById("txt" + objName);
                var ddl = document.getElementById("ddl" + objName);
                var ul = document.getElementById("ul" + objName);
            }


Then we set the text in the txtCountries text box to text and ensure that ddlCountries is also set to val. After that, hide ulCountries.
            function selectOption(objName, val, text)
            {
                var txt = document.getElementById("txt" + objName);
                var ddl = document.getElementById("ddl" + objName);
                var ul = document.getElementById("ul" + objName);

                txt.value = text;
                ddl.value = val;
                ul.style.display = "none";
            }


Now try this. Click on the "button" and select, say, Ghana. Does "Ghana" appear in the text box? Does ddlCountries select Ghana too?


Next

It looks messy right now, so in the next part, we're going to pretty it up a bit. Stay with me!

1 comment:

  1. This article is the great. This is very useful and helps to the understand Thanking to the publishing post.

    ReplyDelete