skip to Main Content

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.

3

Answers


  1. document.addEventListener('DOMContentLoaded', function () {
        const addButton = document.getElementById('addButton');
        const removeButton = document.getElementById('removeButton');
    
        addButton.addEventListener('click', function () {
          moveSelectedPlayers('right');
        });
    
        removeButton.addEventListener('click', function () {
          moveSelectedPlayers('left');
        });
    
        function moveSelectedPlayers(direction) {
          let i;
          let 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');
          }
    
          const selectedOptions = [];
          for (i = 0; i < sourceSelect.options.length; i++) {
            if (sourceSelect.options[i].selected) {
              selectedOptions.push(sourceSelect.options[i]);
            }
          }
    
          for (i = 0; i < selectedOptions.length; i++) {
            targetSelect.appendChild(selectedOptions[i]);
          }
        }
      });
    <h1>Select Players</h1>
    <div class="container">
        <label for="available_players">Available players</label>
        <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>';
            }
            }
    
            mysqli_close($conn);
            ?>
        </select>
        <div>
            <button type="button" id="addButton">Add &rarr;</button>
            <br><br>
            <button type="button" id="removeButton">&larr; Remove</button>
        </div>
        <label for="selected_players">Selected player</label>
        <select id="selected_players" name="selected_players[]" multiple="multiple" class="list-box"></select>
    </div>
    
    
    <form method="post" action="process_signup.php">
        <input type="submit" value="Submit">
    </form>
    Login or Signup to reply.
  2. Since appendChild modifies selectedOptions your loop counter doesn’t point to the right element. Instead of the for loop you can try:

    while (selectedOptions.length) {
      targetSelect.appendChild(selectedOptions[0]);
    }
    
    Login or Signup to reply.
  3. 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>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search