Avatar of maaknplan
maaknplanFlag for South Africa

asked on 

JavaScript Sort Ordering and Choice Limiting

Hi

I have a simple form where the user can make up to three selections. The user can select the checkboxes in any order, but as they click on each one, the order in which they were checked is remembered, and the position is set to either 1, 2 or 3 when the checkbox is checked, or 0 if the checkbox is unchecked.

The catch is that if a user selects 3 checkboxes, but then unselects the checkbox in position 2, position 3 needs to become 2, so the order is 1,2 and not 1,3.

Example in w3schools

<!DOCTYPE html>
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script>
        function IsChecked(chk) {

            if (TotalChecked() > 3) {
                alert('Only 3 boxes can be checked!');
                $(chk).prop("checked", false);
                return;
            }

            SetPosition();
        }

        function TotalChecked() {
            var total = 0;
            $(".chk").each(function () {
                if ($(this).prop("checked")) {
                    total++;
                }
            });

            return total;
        }

        function SetPosition() {
            var items = [];

            //Get the items and their values first
            $(".position").each(function () {
                var id = $(this).attr('id');
                var val = $(this).val();
                var item = { id: id, value: val };
                var chk = $("#" + id.replace("p", "c"));
                if ($(chk).prop("checked")) {
                    items.push(item);
                }
            });

            //Sort items

            items.sort(function (a, b) {
                return a.value - b.value;
            });

            $(".position").each(function () {
                var id = $(this).attr('id');
                var chk = $("#" + id.replace("p", "c"));
                var len = items.length;



                if ($(chk).prop("checked")) {
                    var val = $(this).val();

                    if (len == 0) {
                        if (val == 0) { val++ };
                    }
                    else if (len == 1) {
                        items[0].value = 1;
                    }
                    else if (len == 2) {
                        items[0].value = 2;
                        items[1].value = 1;
                    }
                    else {
                        items[0].value = 3;
                        items[1].value = 2;
                        items[2].value = 1;
                    }
                }
                else {
                    $(this).val(0);
                }
            });

            var i;
            for (i = 0; i < items.length; i++) {
                $("#" + items[i].id).val(items[i].value);
            }

        }
    </script>
</head>
<body>

    <input id="c1" onchange="IsChecked(this)" class="chk" type="checkbox" />
    <input id="p1" class="form-control position" type="text" value="0" /><br />
    <input id="c2" onchange="IsChecked(this)" class="chk" type="checkbox" />
    <input id="p2" class="form-control position" value="0" /><br />
    <input id="c3" onchange="IsChecked(this)" class="chk" type="checkbox" />
    <input id="p3" class="form-control position" value="0" /><br />
    <input id="c4" onchange="IsChecked(this)" class="chk" type="checkbox" />
    <input id="p4" class="form-control position" value="0" /><br />
    <hr />
    <p id="message"></p>
</body>
</html>

Open in new window


I just can't seem to get this to work, any help is much appreciated.

Thanks.
JavaScriptjQuery

Avatar of undefined
Last Comment
Julian Hansen
ASKER CERTIFIED SOLUTION
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Blurred text
THIS SOLUTION IS ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
Avatar of maaknplan
maaknplan
Flag of South Africa image

ASKER

Thanks for the reply. Your solution is pretty elegant. The only issue is it doesn't reverse if you uncheck the checkboxes.

Here is what I ended up with - w3schools example.

<!DOCTYPE html>
<html>
<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
    <script>
        function IsChecked(chk) {
            var total = TotalChecked();
            if (total > 3) {
                alert('Only 3 boxes can be checked!');
                $(chk).prop("checked", false);
                return;
            }
            var id = $(chk).attr('id');
            var pos = $("#" + id.replace("c", "p")); //Find the corresponding input
            var initVal = pos.val(); //Get the initial value of the corresponding input

            if ($(chk).prop("checked") == false) {
                pos.val(0); //Reset the corresponding input to 0 if the checkbox is unchecked
            }

            //If the corresponding input value of the function checkbox is 3, no changes need to be made as the other
            //inputs will be correctly set.
            if (initVal == 3) { return };

            switch (total) {
                case 1: //Only one checkbox is selected, so the corresponding input must be 1
                    if ($(chk).prop("checked") == true) {
                        pos.val(1); //If the function checkbox is checked, set the corresponding input to 1
                    }
                    else { //If the function checkbox is not checked, find the checked checkbox, and set its corresponding input to 1
                        $(".chk").each(function () {
                            if ($(this).prop("checked")) {
                                var id = $(this).attr('id');
                                var pos2 = $("#" + id.replace("c", "p"));
                                pos2.val(1);
                            }
                        });
                    }
                    break;
                case 2: //Two checkboxes are selected, so the corresponding inputs must be 1 and 2
                    if ($(chk).prop("checked") == true) {
                        pos.val(2); //If the function checkbox is checked, set the corresponding input to 2
                    }
                    else {//If the function checkbox is not checked, find the checked checkboxes, and set the corresponding inputs
                        $(".chk").each(function () {
                            if ($(this).prop("checked")) {
                                var id = $(this).attr('id');
                                var pos2 = $("#" + id.replace("c", "p")); //Find the corresponding input for the checked checkbox
                                //It doesn't matter if pos2.val() == 1
                                if (pos2.val() == 2) { 
                                    pos2.val(1);
                                }
                                else if (pos2.val() == 3) {
                                    pos2.val(2);
                                }
                            }
                        });
                    }
                    break;
                case 3:
                    if ($(chk).prop("checked") == true) {
                        pos.val(3);
                    }
                    break;
            }
        }

        function TotalChecked() {
            var total = 0;
            $(".chk").each(function () {
                if ($(this).prop("checked")) {
                    total++;
                }
            });
            return total;
        }

    </script>
</head>
<body>

    <input id="c1" onchange="IsChecked(this)" class="chk" type="checkbox" />
    <input id="p1" class="form-control position" disabled="disabled" type="text" value="0" /><br />
    <input id="c2" onchange="IsChecked(this)" class="chk" type="checkbox" />
    <input id="p2" class="form-control position" disabled="disabled" value="0" /><br />
    <input id="c3" onchange="IsChecked(this)" class="chk" type="checkbox" />
    <input id="p3" class="form-control position" disabled="disabled" value="0" /><br />
    <input id="c4" onchange="IsChecked(this)" class="chk" type="checkbox" />
    <input id="p4" class="form-control position" disabled="disabled" value="0" /><br />
    <hr />
    <p id="message"></p>
</body>
</html>

Open in new window

Avatar of maaknplan
maaknplan
Flag of South Africa image

ASKER

The solution offered is simple and elegant, however it does not allow the order selected to be reversed.
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

however it does not allow the order selected to be reversed.

Please explain by reversed?
Avatar of Julian Hansen
Julian Hansen
Flag of South Africa image

Just to explain the solution a bit more.

The paradigm of this solution is to use a progressive counter - like the queue tickets you sometimes get in a store. Each click represents a new arrival and so gets the next number in the queue. A click off represents the leaving of the queue so the number goes down to 0.

The checkbox with the lowest (non-zero) value is the one that was clicked first out of all the remaining clicked items.

The actual value in this case is not relevant - only its magnitude relative to the values of the other clicked items - which provides an ordering on the selected checkboxes.

Trying to see how this solution does not meet the requirements of the questions asked?
JavaScript
JavaScript

JavaScript is a dynamic, object-based language commonly used for client-side scripting in web browsers. Recently, server side JavaScript frameworks have also emerged. JavaScript runs on nearly every operating system and in almost every mainstream web browser.

127K
Questions
--
Followers
--
Top Experts
Get a personalized solution from industry experts
Ask the experts
Read over 600 more reviews

TRUSTED BY

IBM logoIntel logoMicrosoft logoUbisoft logoSAP logo
Qualcomm logoCitrix Systems logoWorkday logoErnst & Young logo
High performer badgeUsers love us badge
LinkedIn logoFacebook logoX logoInstagram logoTikTok logoYouTube logo