DEV Community

Cover image for JavaScript mini challenge - solution
Julien Dephix
Julien Dephix

Posted on

JavaScript mini challenge - solution

Hi, coders!

Two days ago I posted a real world mini challenge that I was tasked to implement.

Specifications are simple enough:

users should be able to select as many cities as they like from a drop down as long as they're not located in more than 2 countries.

RTFM

As often is the case, reading the documentation goes a long way. This time is no exception.
If you head over to the events section of the doc you will see that you can listen to changed.bs.select which is fired right after the underlying select value changed.

$('#mySelect').on('changed.bs.select', function (e, clickedIndex, isSelected, previousValue) {
  // do something...
});
Enter fullscreen mode Exit fullscreen mode

What's important here is that we also get previousValue which, you guessed it, holds the drop down value before it was changed.
So if we can figure out when a user has selected a third country then we can just set the value back to previousValue by doing:

$("#cities")
    .selectpicker()
    .on(
        "changed.bs.select",
        function (event, clickedIndex, isSelected, previousValue) {
            const $this = $(this);
            if (someCondition) {  // <== gotta work on this next
                $this.selectpicker('val', previousValue);
            }
        }
    );
Enter fullscreen mode Exit fullscreen mode

Counting how many countries are selected

We don't just want the number of selected cities but the number of countries they belong to.
The only info we have is the optgroup label and we'll use just that.

const selectedCountries = $this
    .find("option:selected")
    .get()
    .map((o) => $(o).parent().attr("label"))
Enter fullscreen mode Exit fullscreen mode

We're basically looping on each selected option and grab their optgroup's label.
The problem is that country names are not unique if more than one city is selected.

If you've been reading JavaScript related posts here on dev.to then you've probably seen the following one liner which gets unique values from someArray:

const uniqueNames = [new Set(...someArray)];
Enter fullscreen mode Exit fullscreen mode

Exactly what we want so let's use it:

const uniqueCategories = [
    ...new Set(
        $this
            .find("option:selected")
            .get()
            .map((o) => $(o).parent().attr("label"))
        )
    ];
Enter fullscreen mode Exit fullscreen mode

Now that we have a unique list of countries we just need to count the number of elements and if it's greater than 2 then we just set the dropdown's value to previousValue.

if (uniqueCategories.length > 2) {
    $this.selectpicker('val', previousValue);
}
Enter fullscreen mode Exit fullscreen mode

Putting it all together

$(function () {
    const MAX_NUMBER_COUNTRIES = 2;
    $("#cities")
        .selectpicker()
        .on(
            "changed.bs.select",
            function (event, clickedIndex, isSelected, previousValue) {
                const $this = $(this);
                const uniqueCategories = [
                    ...new Set(
                        $this
                            .find("option:selected")
                            .get()
                            .map((o) => $(o).parent().attr("label"))
                    )
                ];

                if (uniqueCategories.length > MAX_NUMBER_COUNTRIES) {
                    $this.selectpicker('val', previousValue);
                }
            }
        );
});
Enter fullscreen mode Exit fullscreen mode

See it in action on CodePen.

Conclusion

Although this "challenge" was not difficult it shows how important it is to read the doc!
Back when I was a student our Java teacher challenged us to write the shortest possible program to manipulate some strings.
Some came up with a 7 lines program. Others had 4 lines.

The teacher's had ONE line. ✨
It was just a call to a native Java function which did exactly what was asked. His way of saying RTFM but in a politically correct way.

Happy coding! 💻

Top comments (0)