HTML/JS:从对象创建下拉菜单

HTML/JS: Making a dropdown menu from object

提问人:OADINC 提问时间:6/24/2023 最后编辑:Mark SchultheissOADINC 更新时间:6/24/2023 访问量:59

问:

[背景]

我正在尝试建立一个 RailRoadsOnline Train Builder 网站。您可以在哪里选择机车和货车。然后它会计算您是否可以取得某些成绩。我计划稍后添加更多功能,但首先是基础知识。这是我用HTML/JS做的第一个项目。我确实有C / C++ + + / Py/VHDL的经验。

[问题]

我在生成由按钮生成的下拉列表时遇到了问题,这是为了让 locs/wagons 的数量动态而不是硬编码。 当我预设按钮时,我希望它制作一个下拉列表,该列表从对象中获取其内容列表。下拉列表必须显示Display_Name值,但在读取自时返回密钥。对象示例(抽象/示例值) 因此,当您在代码中选择 Porter 1 时,它将返回/读出为Porter_1{Important_Key_Name_I_Need_Later: {Display_Name: "The Name", ...}, Porter_1: {Display_Name: "Porter 1", Mass: 7242, Length: 4, Tractive_Effort: 12.8}, ...}

我已经从这个中调整了我的代码,有效,但现在我正在生成整个下拉列表,它中断了。

这是代码,对不起,它有点多:

<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Test Web Page</title>
</head>
<body>
<form>
    <input type="button" id="Calculate" value="Calculate">
    <p> Total Weight</p>
    <p id="Loc_Sel">Selected Loc</p>

    <input type="button" id="Add_Locomotive" value="Add a locomotive">
    <input type="button" id="Add_Wagon" value="Add a wagon">
    <input type="button" id="Reset" value="Reset">

</form>
</script>
<div id="Button_Div"></div>
<script type="text/javascript">
    //Locomotives
    let Locomotives = {
        Porter_1: {Mass: 7242, Length: 4, Tractive_Effort: 12.8, Display_Name: "Porter 1"},
        Porter_2: {Mass: 8145, Length: 4.8, Tractive_Effort: 12.8, Display_Name: "Porter 2"},
        Montezuma: {Mass: 14969, Length: 11, Tractive_Effort: 16.2, Display_Name: "Montezuma"},
        Shay: {Mass: 21754, Length: 8.1, Tractive_Effort: 26.2, Display_Name: "Shay"},
        Tenmile: {Mass: 19848, Length: 11.8, Tractive_Effort: 37.7, Display_Name: "Tenmile"},
        Eureka: {Mass:17164 , Length: 13.1, Tractive_Effort: 25, Display_Name: "Eureka"},
        Glenbrook: {Mass: 17128, Length: 13.5, Tractive_Effort: 34.1, Display_Name: "Glenbrook"},
        DRGW_Class_48: {Mass: 14969, Length: 7.7, Tractive_Effort: 41.7, Display_Name: "D&RGW Class 48"},
        Mosca: {Mass: 25348, Length: 13.8, Tractive_Effort: 38.3, Display_Name: "Mosca"},
        Cooke_Mogul: {Mass: 26388, Length: 15.1, Tractive_Effort: 52.8, Display_Name: "Cooke Mogul"},
        Heisler: {Mass: 28064, Length: 9.1, Tractive_Effort: 57.9, Display_Name: "Heisler"},
        Ruby_Basin: {Mass: 33042, Length: 10.3, Tractive_Effort: 60.1, Display_Name: "Ruby Basin"},
        Cooke_Consilidation: {Mass: 26706, Length: 15.1, Tractive_Effort: 59.9, Display_Name: "Cooke Consilidation"},
        Climax: {Mass: 24194, Length: 8.7, Tractive_Effort: 76.6, Display_Name: "Climax"},
        DRG_Class_70: {Mass: 15468, Length: 15.6, Tractive_Effort: 68.8, Display_Name: "D&RG Class 70"},
        ETWNC_2_8_0: {Mass: 16545, Length: 16.2, Tractive_Effort: 73.6, Display_Name: "ET&WNC 2-8-0"}
    };
    //Wagons
    let Wagons = {
        No_Car: {Mass: 0, Length: 0, Display_Name: "No_Car", Cargo: {}},
        Skeleton_Car: {Mass: 3000, Length: 6.4, Display_Name: "Skeleton Car", Cargo: {Logs: 5}},
        Flatcar_Rounds: {Mass: 3800, Length: 8.4, Display_Name: "Flatcar Rounds", Cargo: {Logs: 6, Steel_Pipes: 9}},
        Flatcar_Stakes: {Mass: 4000, Length: 8.4, Display_Name: "Flatcar Stakes", Cargo: {Lumber: 6, Beams: 3, Raw_Iron: 3, Rails: 10}},
        Flatcar_Bulkhead: {Mass: 4100, Length: 8.4, Display_Name: "Flatcar Bulkhead", Cargo: {Cordwood: 6, Oil_Barrels: 46}},
        Hopper: {Mass: 6000, Length: 8.2, Display_Name: "Hopper", Cargo: {Iron_ore: 10, Coal_Ore: 10}},
        EBT_Hopper: {Mass: 6000, Length: 7.75, Display_Name: "EBT Hopper", Cargo: {Iron_ore: 8, Coal_Ore: 10}},
        Tanker: {Mass: 13968, Length: 8.1, Display_Name: "Tanker", Cargo: {Crude_Oil: 12}},
        Coffin_Tank_Car: {Mass: 14250, Length: 10, Display_Name: "Coffin Tank Car", Cargo: {Crude_Oil: 8}},
        Box_Car: {Mass: 7938, Length: 8.1, Display_Name: "Box Car", Cargo: {Tool_Crates: 32}},
        Stock_Car: {Mass: 8000, Length: 9.4, Display_Name: "Stock Car", Cargo: {Tool_Crates: 32}},
        Bobber_Caboose: {Mass: 5400, Length: 6.8, Display_Name: "Bobber Caboose", Cargo: {}},
        DSPP_Waycar: {Mass: 5000, Length: 6.1, Display_Name: "DSP&P Waycar", Cargo: {}},
        Snow_Plow: {Mass: 6000, Length: 6, Display_Name: "Snow Plow", Cargo: {}}
    };
    //Cargo Types
    let Cargo_Types = {
        Logs: {Money: 10, Mass: 2000, Display_Name: "Logs"},
        Cordwood: {Money: 10, Mass: 1200, Display_Name: "Cordwood"},
        Beams: {Money: 24, Mass: 1410, Display_Name: "Beams"},
        Lumber: {Money: 12, Mass: 1350, Display_Name: "Lumber"},
        Iron_Ore: {Money: 20, Mass: 1000, Display_Name: "Iron Ore"},
        Coal_Ore: {Money: 15, Mass: 1000, Display_Name: "Coal Ore"},
        Raw_Iron: {Money: 25, Mass: 1490, Display_Name: "Raw Iron"},
        Rails: {Money: 25, Mass: 900, Display_Name: "Rails"},
        Steel_Pipes: {Money: 40, Mass: 1800, Display_Name: "Steel Pipes"},
        Tool_Crates: {Money: 30, Mass: 100, Display_Name: "Tool Crates"},
        Crude_Oil: {Money: 25, Mass: 1000, Display_Name: "Crude Oil"},
        Oil_Barrels: {Money: 40, Mass: 137, Display_Name: "Oil Barrels"}
    };

    let Vehicles = {Loc: -1, Wag: -1};
    
    const Button_Calculate = document.getElementById('Calculate');
    const Button_Add_Locomotive = document.getElementById('Add_Locomotive');
    const Button_Add_Wagon = document.getElementById('Add_Wagon');
    const Button_Reset = document.getElementById('Reset');
    
    //This is the adapted version of the linked code.
    function Mk_DropDown(Id, Dictionairy){
        var Options = document.getElementById(Id);
        Object.keys(Dictionairy).forEach(key => {
            Options.appendChild(new Option(Dictionairy[key]['Display_Name'], key));
        });
    }
    

    //This function should not becausing issues, just included for completeness.
    function changeText(element, value) {
        document.getElementById(element).innerHTML = value;
    }
    
    //This function should not becausing issues, just included for completeness.
    function Calculate_Train_Weight() {
        let Weight = 0;
        for(let i = 0; i < Vehicles['Loc']; i++) {
            Locomotives[document.getElementById("Select_Loc_" + i).value]['Mass'];
        }
        for(let i = 0; i < Vehicles['Wag']; i++) {
            Wagons[document.getElementById("Select_Wagon_" + i).value]['Mass'];
        }
        return Weight;
    }

    //This function should not becausing issues, just included for completeness.
    function Calculate() {
        changeText('Loc_Sel', Calculate_Train_Weight());
    }

    function Add_Locomotive() {
        Vehicles['Loc']++;
        console.log(Vehicles['Loc']);
        document.getElementById("Button_Div").innerHTML = "<select> id=\"Select_Locomotive_" + Vehicles['Loc'] + "<option>Choose a locomotive</option></select>" + document.getElementById("Button_Div").innerHTML
//Is doing it once when creating new box enough or should it loop through al existing dropdowns as well?
        Mk_DropDown("Select_Loc_" + Vehicles['Loc'], Locomotives); 
    }

    function Add_Wagon() {
        Vehicles['Wag']++;
        document.getElementById("Button_Div").innerHTML += "<select> id=\"Select_Wagon_" + Vehicles['Wag'] + "<option>Choose a wagon</option></select>"
//Is doing it once when creating new box enough or should it loop through al existing dropdowns as well?
        for(let i = 0; i < Vehicles['Wag']; i++) {
            Mk_DropDown("Select_Wagon_" + i, Wagons); 
        }
    }

    //This function works but feels like a hack, so if you have suggestions for this feel free to mention it!
    function Reset() {
        document.getElementById("Button_Div").innerHTML = "";
        Vehicles['Loc'] = 0;
        Vehicles['Wag'] = 0;
    }

    Button_Add_Locomotive.addEventListener('click', Add_Locomotive);
    Button_Add_Wagon.addEventListener('click', Add_Wagon);
    Button_Reset.addEventListener('click', Reset);
    Button_Calculate.addEventListener('click', Calculate);
</script>
</body>
</html>

JavaScript HTML 对象

评论

1赞 David 6/24/2023
以什么方式“休息”?在浏览器的开发工具中,控制台上是否有错误?使用浏览器的脚本调试器时,哪个操作首先失败或产生意外结果?
1赞 Mark Schultheiss 6/24/2023
您发布的 HTML 无效

答:

1赞 Eyas Valdez 6/24/2023 #1

老实说,这个实现有点卡顿,但你的主要问题是你连接字符串的方式。您正在以一种无法找到已传递的元素的方式连接字符串。Mk_DropDownid

在中,您需要传递一个与您分配给元素的内容一致的内容。您已为每次按下带有前缀的按钮分配了 s,以迭代 。我将把它改成像传入的内容一样.Add_LocomotiveidselectidSelect_Locomotive_[someindex]Select_Loc_[someindex]Mk_DropDown

第二个问题是属性需要位于前导标记内。idselect

第三个问题是反斜杠异常需要关闭 以及 start。id

修订后的内容可能如下所示:Add_Locomotive

function Add_Locomotive() {
        Vehicles['Loc']++;
        console.log(Vehicles['Loc']);
        document.getElementById("Button_Div").innerHTML = "<select " + "id=\"Select_Loc_" + Vehicles['Loc'] + "\" >" + "<option>Choose a locomotive</option></select>" + document.getElementById("Button_Div").innerHTML
        Mk_DropDown("Select_Loc_" + Vehicles['Loc'], Locomotives);
}

为了进一步简化,我将使用字符串插值:

function Add_Locomotive() {
        Vehicles['Loc']++;
        console.log(Vehicles['Loc']);
        document.getElementById("Button_Div").innerHTML = `<select id="Select_Loc_${Vehicles['Loc']}" > <option>Choose a locomotive</option></select>` + document.getElementById("Button_Div").innerHTML
        Mk_DropDown("Select_Loc_" + Vehicles['Loc'], Locomotives);
}

我无法判断你是否只是在你的实现中尝试一些东西,或者你是否在测试性能,但你需要在 to 中更改你的相等性检查,否则它不会运行,因为添加第一个货车将使 ,它不小于 并且你的循环仅在 .Add_Wagonfor loopi <= Vehicles['Wag']Vehicles['Wag'] === 00i < 0

function Add_Wagon() {
        Vehicles['Wag']++;
        document.getElementById("Button_Div").innerHTML += `<select id="Select_Wagon_${Vehicles['Wag']}" > <option>Choose a wagon</option></select>`
        for (let i = 0; i <= Vehicles['Wag']; i++) {
            Mk_DropDown("Select_Wagon_" + i, Wagons);
        }
}

最后,您的函数将中断该函数,因为它会重置对象,而该对象不是重置的,因为它是使用 启动的。进行循环是行不通的,因为您将运行,运行并附加一个子项,然后您将运行该循环,并且要传递给的第一个参数不是DOM中的子项。ResetAdd_WagonVehicles{"Wag": 0, "Loc": 0}{"Wag": -1, "Loc": -1}Add_WagResetAdd_Wagonid="Select_Wagon_1"Mk_DropDownMk_DropDown("Select_Wagon_0", Wagons)

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Test Web Page</title>
</head>

<body>
    <form>
        <input type="button" id="Calculate" value="Calculate">
        <p> Total Weight</p>
        <p id="Loc_Sel">Selected Loc</p>

        <input type="button" id="Add_Locomotive" value="Add a locomotive">
        <input type="button" id="Add_Wagon" value="Add a wagon">
        <input type="button" id="Reset" value="Reset">

    </form>
    </script>
    <div id="Button_Div"></div>
    <script type="text/javascript">
        //Locomotives
        let Locomotives = {
            Porter_1: { Mass: 7242, Length: 4, Tractive_Effort: 12.8, Display_Name: "Porter 1" },
            Porter_2: { Mass: 8145, Length: 4.8, Tractive_Effort: 12.8, Display_Name: "Porter 2" },
            Montezuma: { Mass: 14969, Length: 11, Tractive_Effort: 16.2, Display_Name: "Montezuma" },
            Shay: { Mass: 21754, Length: 8.1, Tractive_Effort: 26.2, Display_Name: "Shay" },
            Tenmile: { Mass: 19848, Length: 11.8, Tractive_Effort: 37.7, Display_Name: "Tenmile" },
            Eureka: { Mass: 17164, Length: 13.1, Tractive_Effort: 25, Display_Name: "Eureka" },
            Glenbrook: { Mass: 17128, Length: 13.5, Tractive_Effort: 34.1, Display_Name: "Glenbrook" },
            DRGW_Class_48: { Mass: 14969, Length: 7.7, Tractive_Effort: 41.7, Display_Name: "D&RGW Class 48" },
            Mosca: { Mass: 25348, Length: 13.8, Tractive_Effort: 38.3, Display_Name: "Mosca" },
            Cooke_Mogul: { Mass: 26388, Length: 15.1, Tractive_Effort: 52.8, Display_Name: "Cooke Mogul" },
            Heisler: { Mass: 28064, Length: 9.1, Tractive_Effort: 57.9, Display_Name: "Heisler" },
            Ruby_Basin: { Mass: 33042, Length: 10.3, Tractive_Effort: 60.1, Display_Name: "Ruby Basin" },
            Cooke_Consilidation: { Mass: 26706, Length: 15.1, Tractive_Effort: 59.9, Display_Name: "Cooke Consilidation" },
            Climax: { Mass: 24194, Length: 8.7, Tractive_Effort: 76.6, Display_Name: "Climax" },
            DRG_Class_70: { Mass: 15468, Length: 15.6, Tractive_Effort: 68.8, Display_Name: "D&RG Class 70" },
            ETWNC_2_8_0: { Mass: 16545, Length: 16.2, Tractive_Effort: 73.6, Display_Name: "ET&WNC 2-8-0" }
        };
        //Wagons
        let Wagons = {
            No_Car: { Mass: 0, Length: 0, Display_Name: "No_Car", Cargo: {} },
            Skeleton_Car: { Mass: 3000, Length: 6.4, Display_Name: "Skeleton Car", Cargo: { Logs: 5 } },
            Flatcar_Rounds: { Mass: 3800, Length: 8.4, Display_Name: "Flatcar Rounds", Cargo: { Logs: 6, Steel_Pipes: 9 } },
            Flatcar_Stakes: { Mass: 4000, Length: 8.4, Display_Name: "Flatcar Stakes", Cargo: { Lumber: 6, Beams: 3, Raw_Iron: 3, Rails: 10 } },
            Flatcar_Bulkhead: { Mass: 4100, Length: 8.4, Display_Name: "Flatcar Bulkhead", Cargo: { Cordwood: 6, Oil_Barrels: 46 } },
            Hopper: { Mass: 6000, Length: 8.2, Display_Name: "Hopper", Cargo: { Iron_ore: 10, Coal_Ore: 10 } },
            EBT_Hopper: { Mass: 6000, Length: 7.75, Display_Name: "EBT Hopper", Cargo: { Iron_ore: 8, Coal_Ore: 10 } },
            Tanker: { Mass: 13968, Length: 8.1, Display_Name: "Tanker", Cargo: { Crude_Oil: 12 } },
            Coffin_Tank_Car: { Mass: 14250, Length: 10, Display_Name: "Coffin Tank Car", Cargo: { Crude_Oil: 8 } },
            Box_Car: { Mass: 7938, Length: 8.1, Display_Name: "Box Car", Cargo: { Tool_Crates: 32 } },
            Stock_Car: { Mass: 8000, Length: 9.4, Display_Name: "Stock Car", Cargo: { Tool_Crates: 32 } },
            Bobber_Caboose: { Mass: 5400, Length: 6.8, Display_Name: "Bobber Caboose", Cargo: {} },
            DSPP_Waycar: { Mass: 5000, Length: 6.1, Display_Name: "DSP&P Waycar", Cargo: {} },
            Snow_Plow: { Mass: 6000, Length: 6, Display_Name: "Snow Plow", Cargo: {} }
        };
        //Cargo Types
        let Cargo_Types = {
            Logs: { Money: 10, Mass: 2000, Display_Name: "Logs" },
            Cordwood: { Money: 10, Mass: 1200, Display_Name: "Cordwood" },
            Beams: { Money: 24, Mass: 1410, Display_Name: "Beams" },
            Lumber: { Money: 12, Mass: 1350, Display_Name: "Lumber" },
            Iron_Ore: { Money: 20, Mass: 1000, Display_Name: "Iron Ore" },
            Coal_Ore: { Money: 15, Mass: 1000, Display_Name: "Coal Ore" },
            Raw_Iron: { Money: 25, Mass: 1490, Display_Name: "Raw Iron" },
            Rails: { Money: 25, Mass: 900, Display_Name: "Rails" },
            Steel_Pipes: { Money: 40, Mass: 1800, Display_Name: "Steel Pipes" },
            Tool_Crates: { Money: 30, Mass: 100, Display_Name: "Tool Crates" },
            Crude_Oil: { Money: 25, Mass: 1000, Display_Name: "Crude Oil" },
            Oil_Barrels: { Money: 40, Mass: 137, Display_Name: "Oil Barrels" }
        };

        let Vehicles = { Loc: -1, Wag: -1 };

        const Button_Calculate = document.getElementById('Calculate');
        const Button_Add_Locomotive = document.getElementById('Add_Locomotive');
        const Button_Add_Wagon = document.getElementById('Add_Wagon');
        const Button_Reset = document.getElementById('Reset');

        //This is the adapted version of the linked code.
        function Mk_DropDown(Id, Dictionairy) {
            var Options = document.getElementById(Id);
            Object.keys(Dictionairy).forEach(key => {
                Options.appendChild(new Option(Dictionairy[key]['Display_Name'], key));
            });
        }


        //This function should not becausing issues, just included for completeness.
        function changeText(element, value) {
            document.getElementById(element).innerHTML = value;
        }

        //This function should not becausing issues, just included for completeness.
        function Calculate_Train_Weight() {
            let Weight = 0;
            for (let i = 0; i < Vehicles['Loc']; i++) {
                Locomotives[document.getElementById("Select_Loc_" + i).value]['Mass'];
            }
            for (let i = 0; i < Vehicles['Wag']; i++) {
                Wagons[document.getElementById("Select_Wagon_" + i).value]['Mass'];
            }
            return Weight;
        }

        //This function should not becausing issues, just included for completeness.
        function Calculate() {
            changeText('Loc_Sel', Calculate_Train_Weight());
        }

        function Add_Locomotive() {
            Vehicles['Loc']++;
            console.log(Vehicles['Loc']);
            document.getElementById("Button_Div").innerHTML = `<select id="Select_Loc_${Vehicles['Loc']}" > <option>Choose a locomotive</option></select>` + document.getElementById("Button_Div").innerHTML
            //Is doing it once when creating new box enough or should it loop through al existing dropdowns as well?
            Mk_DropDown("Select_Loc_" + Vehicles['Loc'], Locomotives);
        }

        function Add_Wagon() {
            Vehicles['Wag']++;
            document.getElementById("Button_Div").innerHTML += `<select id="Select_Wagon_${Vehicles['Wag']}" > <option>Choose a wagon</option></select>`
            //Is doing it once when creating new box enough or should it loop through al existing dropdowns as well?
            for (let i = 0; i <= Vehicles['Wag']; i++) {
                console.log(i)
                Mk_DropDown("Select_Wagon_" + i, Wagons);
            }
        }

        //This function works but feels like a hack, so if you have suggestions for this feel free to mention it!
        function Reset() {
            document.getElementById("Button_Div").innerHTML = "";
            Vehicles['Loc'] = -1;
            Vehicles['Wag'] = -1;
        }

        Button_Add_Locomotive.addEventListener('click', Add_Locomotive);
        Button_Add_Wagon.addEventListener('click', Add_Wagon);
        Button_Reset.addEventListener('click', Reset);
        Button_Calculate.addEventListener('click', Calculate);
    </script>
</body>

</html>

评论

0赞 Eyas Valdez 6/24/2023
我没有删除代码中的任何控制台日志,因此控制台占据了该部分的很大一部分。如果要运行代码片段,我建议单击“完整页面”选项。
0赞 OADINC 6/24/2023
谢谢,这太棒了!您将如何以一种不那么卡顿的方式实现这一点?我正在尝试学习编写代码,减少卡顿。在添加另一辆车(Loc/Wag)时,是否有简单的方法可以保留所选车辆?
0赞 OADINC 6/24/2023
另外,是的,我正在Add_Wagon测试不同的实现。