user786423
user786423

Reputation: 125

HTML Selected Value Reordering via JavaScript

Given the following HTML selects:

<select id="HtmlSelect1">
    <option value="1" selected="selected">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
</select>

<select id="HtmlSelect2">
    <option value="1">1</option>
    <option value="2" selected="selected">2</option>
    <option value="3">3</option>
    <option value="4">4</option>
</select>

<select id="HtmlSelect3">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3" selected="selected">3</option>
    <option value="4">4</option>
</select>

<select id="HtmlSelect4">
    <option value="1">1</option>
    <option value="2">2</option>
    <option value="3">3</option>
    <option value="4" selected="selected">4</option>
</select>

Scenario 1: If I change the selected value in HtmlSelect4 to 2, the selected value for HtmlSelect2 should change to 3 and the selected value for HtmlSelect3 should change to 4.

Scenario 2: If I change the selected value for HtmlSelect2 to 3, the selected value for HtmlSelect3 should change to 2.

In summary, I am reordering the selected value of the other drop down lists based upon one of the other drop down lists being changed. How do I accomplish this in JavaScript?

Note: The number of drop down lists and options could vary as these are being driven by data in a database.

Below is what I tried that should have theoretically worked for scenario 1, but didn't. It's a start in the direction of what I am trying to do.

<script>
        function SelectChange(selectControl)
        {
            var controlDiv = document.getElementById("SomeDiv");
            var controlSelects = controlDiv.getElementsByTagName("select");
            for (var selectIndex = 0; selectIndex < controlSelects.length; selectIndex++)
            {
                if (controlSelects[selectIndex].id.indexOf("SelectControlPrefix") != -1)
                {
                    if (controlSelects[selectIndex].value >= selectControl.value)
                    {
                        for (var optionIndex = 0; optionIndex < controlSelects[selectIndex].options.length; optionIndex++)
                        {
                            if (controlSelects[selectIndex].options[optionIndex].value == controlSelects[selectIndex].options.value + 1)
                            {
                                controlSelects[selectIndex].options[optionIndex].selected = "selected";
                            }
                        }
                    }
                }
            }
        }
    </script>

Upvotes: 1

Views: 254

Answers (1)

mgibsonbr
mgibsonbr

Reputation: 22007

I'm having some trouble understanding the expected behavior, so I'll abstract it away in a function (Update 2 working as intended; added some comments to better explain my solution):

/* Returns a list of pairs [#element, value] to be updated */
function myBehaviour(n,o,v) {
    var ret = [["#HtmlSelect" + n, v]]; // The new value should be what the user selected
    // Shifts the other values, to the left of right
    while ( n > o ) {
        var next = $("#HtmlSelect" + (o+1));
        ret.push(["#HtmlSelect" + o, next.val()]);
        o++;
    }
    while ( n < o ) {
        var next = $("#HtmlSelect" + (o-1));
        ret.push(["#HtmlSelect" + o, next.val()]);
        o--;
    }
    return ret;
}

That said, here's how you could accomplish this using jQuery:

var old;
$("select").focus(function() {
    old = $(this).val(); // Saves the old value, before the change
}).change(function(e) {
    var newValue = $(this).val(); // Save the new value
    $(this).val(old); // Reverts to old, will change later

    var oldPosition = parseInt(findOld(newValue)); // Find where the old value was
    var newPosition = parseInt(this.id.substring("HtmlSelect".length));
    $.each(myBehaviour(newPosition,oldPosition,newValue), function(i,pair) {
        $(pair[0]).val(pair[1]); // Updates all them only after the correct positions were found
    });
    old = $(this).val(); // Saves the old again, in case the select is changed again
});

function findOld(value) {
    return $("select").filter(function() {
        return $(this).val() == value;
    }).attr("id").substring("HtmlSelect".length);
}

If you need pure JavaScript, the code will get a little longer, but it can be accomplished by using document.getElementById, onchange, childNodes, nodeValue etc.

Upvotes: 1

Related Questions