Search code examples
javascripthtmlweb

Javascript only select every other list item in multi-select list boxes


Description: I'm trying to build a page wherein a list of people in a list box can be selected and moved to the right list box. (It will do other things eventually but I'll spare you the inconsequential details.)

Problem: When multiple list items are selected in the "available" box and the "move right" (select) button is clicked, only every other element selected is moved to the "selected" list box. Put differently, in a list of 0-9, items 0,2,4,6 and 8 are moved, and all others remain selected in the "available" list box.

Below is the full code:

<!DOCTYPE html>
<html>
<head>
    <title>Player Selection</title>
    <style>
        .container {
            display: flex;
            justify-content: space-between;
        }
        .list-box {
            width: 200px;
            height: 200px;
        }
    </style>
    <script>
        function moveSelectedPlayers(direction) {
            var sourceSelect, targetSelect;

            if (direction === 'right') {
                sourceSelect = document.getElementById('available_players');
                targetSelect = document.getElementById('selected_players');
                
            } else if (direction === 'left') {
                sourceSelect = document.getElementById('selected_players');
                targetSelect = document.getElementById('available_players');
            }

            var selectedOptions = sourceSelect.selectedOptions;
            for (var i = 0; i < selectedOptions.length; i++) {
                var option = selectedOptions[i];
                targetSelect.appendChild(option);
            }
        }
    </script>
</head>
<body>
    <h1>Select Players</h1>
    <div class="container">
        <select id="available_players" multiple="multiple" class="list-box">
            <?php
            
            include "db_open.php";
            // Create a database connection
            $conn = mysqli_connect($host, $username, $password, $database);

            if (!$conn) {
                die("Connection failed: " . mysqli_connect_error());
            }

            // Fetch player data from the 'players' table and order by last_name
            $query = "SELECT player_id, last_name, first_name FROM players ORDER BY last_name";
            $result = mysqli_query($conn, $query);

            if (mysqli_num_rows($result) > 0) {
                while ($row = mysqli_fetch_assoc($result)) {
                    echo '<option value="' . $row['player_id'] . '">' . $row['last_name'] . ', ' . $row['first_name'] . '</option>';
                }
            }

            // Close the database connection
            mysqli_close($conn);
            ?>
        </select>
        <div>
            <button type="button" onclick="moveSelectedPlayers('right')">Add &rarr;</button>
            <br><br>
            <button type="button" onclick="moveSelectedPlayers('left')">&larr; Remove</button>
        </div>
        <select id="selected_players" name="selected_players[]" multiple="multiple" class="list-box"></select>
    </div>
    <br>
    <form method="post" action="process_signup.php">
        <input type="submit" value="Submit">
    </form>
</body>
</html>

I'm expecting that all the selected elements in the "available" list will get moved to the "selected" list when the button is clicked. Fair warning and full disclosure, I first learned javascript in 1998 when it was a new thing. My coding skills are so old they have grey hairs, so please be gentle if I've made any rookie mistakes. This isn't my primary occupation.


Solution

  • The issue you have is that you are modifying the collection as you are iterating through it. this means that element i gets removed, so the i+1 element is now the i element, and when you try to get i+1 you're given what would have been i+2.

    Instead, create a separate array and fill that with the elements, then iterate over that:

    let btnRight = document.getElementById('moveRight');
    let btnLeft = document.getElementById('moveLeft');
    
    btnRight.addEventListener('click', function()
    {
      moveSelectedPlayers('right');
    });
    
    
    btnLeft.addEventListener('click', function()
    {
      moveSelectedPlayers('left');
    });
            
            function moveSelectedPlayers(direction) {
                var sourceSelect, targetSelect;
    
                if (direction === 'right') {
                    sourceSelect = document.getElementById('available_players');
                    targetSelect = document.getElementById('selected_players');
                    
                } else if (direction === 'left') {
                    sourceSelect = document.getElementById('selected_players');
                    targetSelect = document.getElementById('available_players');
                }
    
                let selectedOptions = [];
                for (let i = 0; i < sourceSelect.selectedOptions.length; i++) {
                    selectedOptions.push(sourceSelect.selectedOptions[i]);
                }
                
                for(let opt of selectedOptions)
                {
                  targetSelect.appendChild(opt);
                }
            }
    <select multiple="true" id="available_players">
    <option> A </option>
    <option> B </option>
    <option> C </option>
    <option> D </option>
    </select>
    
    <select multiple="true" id="selected_players">
    </select>
    <br>
    <button id="moveRight"> >> </button>
    <button id="moveLeft"> &lt;&lt; </button>