Javascript - 动态更改ID?

时间:2011-07-05 03:44:03

标签: javascript html

我已经问了好几次,但是我没能正确地传达我的问题,所以我想我会再试一次:

我想制作一张表格。结构将是:

<html>
<head>
<script type="text/javascript">

</script>
<style type="text/css">
ul {
list-style-type:none;
}
</style>
</head>

<body>

<input type="text" value="Menu 1 Name" />
<input type="button" value="Remove Menu" />
<ul>
<li><input type="text" value="Option 1" /><input type="button" value="Remove Option" /></li>
<li><input type="text" value="Option 2" /><input type="button" value="Remove Option" /></li>
<li><input type="button" value="Add Option" /></li>
</ul>
<input type="text" value="Menu 2 Name" />
<input type="button" value="Remove Menu" />
<ul>
<li><input type="text" value="Option 1" /><input type="button" value="Remove Option" /></li>
<li><input type="text" value="Option 2" /><input type="button" value="Remove Option" /></li>
<li><input type="button" value="Add Option" /></li>
</ul>
<input type="text" value="Menu 3 Name" />
<input type="button" value="Remove Menu" />
<ul>
<li><input type="text" value="Option 1" /><input type="button" value="Remove Option" /></li>
<li><input type="text" value="Option 2" /><input type="button" value="Remove Option" /></li>
<li><input type="button" value="Add Option" /></li>
</ul>
<input type="button" value="Add Menu" />
</body>
</html>

我需要能够获得菜单名称和菜单选项的表单数据,无论有多少菜单和选项。我正在考虑做一些事情,就是做一个放在菜单id中的变量和菜单选项的另一个变量,然后做一个for循环,直到它从所有表单中获取信息。

问题在于我希望菜单ID和选项ID始终按顺序排列,无论他们添加或删除菜单多少次。例如,假设我有三个选项,其中包含Menu1Option1,Menu1Option2和Menu1Option3的ID。如果我删除第二个选项,它将显示第一个和第三个选项。由于只有两个,我希望第三个选项的ID成为Menu1Option2。我能想到的唯一方法是每次添加菜单时为选项数量创建一个新变量,然后使用该变量来确定选项的ID,并在删除选项时重新输入所有选项基于选项ID删除后的选项...

如果你明白我要做什么,你能告诉我怎么做正确的方法吗?我相信我离这里很远。我猜这是更好的方法是不是ID每个菜单和选项,而是让他们的数组如何?它似乎更适合我想要的东西,但我不知道该怎么做。

3 个答案:

答案 0 :(得分:1)

我建议如下:

  1. 在页面上创建隐藏元素,其中包含要动态添加的内容的模板标记:

    <div id="menuSectionTemplate" style="display:none;">
        <input type="text" value="MENU_NAME" />
        <input type="button" value="Remove Menu" onclick="removeMenu('MENU_ID');"/>
        <ul>
            OPTION_LIST
            <li><input type="button" value="Add Option" onclick="addOption('MENU_ID')" /></li>
        </ul>
    </div>
    <div id="menuListItemTemplate" style="display:none;">
        <li><input type="text" id="MenuMENU_IDOptionOPTION_ID" value="OPTION_VALUE" />
            <input type="button" value="Remove Option" onclick="removeOption('MENU_ID', 'OPTION_ID');" />
        </li>
    </div>
    
  2. 计算出一个数据结构来表示您当前的接口状态。类似的东西:

    window.menus = [{name: "Menu 1", options: 
                       [{value: "Option 1" }, 
                        {value: "Option 2" }
                       ]
                    },
                    {name: "Menu 2", options: 
                       [{value: "Option 2.1" }, 
                        {value: "Option 2.2" }
                       ]
                    }];
    
  3. 根据您的后备数据计算出生成界面的逻辑。大致像:

    //draws the current state
    window.render = function() {
       var allMenus = "";
       var menuTemplate = document.getElementById("menuSectionTemplate").innerHTML;
       var listTemplate = document.getElementById("menuListItemTemplate").innerHTML;
       for (var index = 0; index < menus.length; index++) {
           var menuOptions = "";
           var menu = menus[index];
           for (var optionIndex = 0; optionIndex < menu.options.length; optionIndex++) {
               var option = menu.options[optionIndex];
               var optionMarkup = processTemplate(listTemplate, 
                                                  ["MENU_ID", "OPTION_ID", "OPTION_VALUE"],
                                                  [index, optionIndex, option.value]);
               menuOptions += optionMarkup;
           }
           var menuMarkup = processTemplate(menuTemplate, 
                                            ["MENU_ID", "MENU_NAME", "OPTION_LIST"], 
                                            [index, menu.name, menuOptions]);
           allMenus += menuMarkup;
       }
       var existingContainer = document.getElementById("menus");
       if (existingContainer) {
          document.body.removeChild(existingContainer);
       }
       existingContainer = document.createElement("div");
       existingContainer.id = "menus";
       existingContainer.innerHTML = allMenus;
       document.body.appendChild(existingContainer);
    };
    
    
    //utility methods
    window.processTemplate = function(template, targets, replacements) {
        var result = template;
        for (var index = 0; index < targets.length; index++) {
            result = replaceAllSubstrings(result, targets[index], replacements[index]);
        }
        return result;
    };
    
    window.replaceAllSubstrings = function(haystack, find, sub) {
        return haystack.split(find).join(sub);
    };
    
  4. 实施添加/删除处理程序,以便他们适当地修改后台数据,然后重新绘制界面,如下所示:

    window.removeOption = function(menuIndex, optionIndex) {
        menus[menuIndex].options.splice(optionIndex, 1);
        render();
    };
    
    window.removeMenu = function(menuIndex) {
        menus.splice(menuIndex, 1);
        render();
    };
    
    window.addMenu = function() {
        var menuName = prompt("Enter a menu name:", "Menu " + menus.length);
        menus.push({name: menuName, options:[]});
        render();
    };
    
    window.addOption = function(menuIndex) {
        var optionValue = prompt("Enter a default value:", "Option " + menus[menuIndex].options.length);
        menus[menuIndex].options.push({value: optionValue}); 
        render();
    };
    
  5. 利润!

  6. 以下是一个工作示例:http://jsfiddle.net/cYtdN/2/

答案 1 :(得分:0)

如果您不关心特定ID,请不要给他们特定的ID。 DOM已经为您保留了所有元素的树。您不需要保留单独的菜单项数组。只需让DOM成为您的数据结构,并使用DOM API和/或jQuery来访问您想要的内容。

$('.menuItem').each(function (index, item) { //Do what you need here. });

请参阅jQuery.each

答案 2 :(得分:0)

而不是动态更改ID。我想你可以转向另一个想法:

1)假设您要根据菜单/选项提交结果,可以使用wrapData()来加载信息:

function wrapData(){
    var data = [];
    $('.menu').each(function(){
        var $t = $(this);
        var m = {'name': $t.val(), 'options': []};
        $t.nextAll('ul:eq(0)').find('[type=text]').each(function(){
            m.options.push({'name': $(this).val()});
        });
        data.push(m);
    });
    return data;
}

2)如果你想从数据渲染用户界面,你可以调用loadData(),如:

function loadData(data){
    for(var i = 0; i < data.length; i++){
        // generating menus
        for(var j = 0; j < data[i].options.length; j++){
            // generating options
        }
    }
    // finally update your user interface
}

请从http://jsfiddle.net/rd8Wp/3/

查看

<强>更新

我已经编写了另一个没有jquery的完整解决方案,但我不小心关闭了broswer而没有保存。所以我用jquery编写了这个更简单的解决方案。实际上,使用框架,无论它是什么,都会有所帮助。您可以看到下面的代码更清晰,以后也更容易维护。

HTML:

<input class='menu' type="text" value="Menu 1 Name" />
<input type="button" value="Remove Menu"/>
<ul>
    <li><input type="text" value="Option 1 1" /><input type="button" value="Remove Option"/></li>
    <li><input type="text" value="Option 2 1" /><input type="button" value="Remove Option"/></li>
    <li><input type="button" value="Add Option" /></li>
</ul>
<input type="button" value="Add Menu" /><input type="button" value="Wrap Data" />

JS:

function wrapData(){
        var data = [];
        $('.menu').each(function(){
            var $t = $(this);
            var m = {'name': $t.val(), 'options': []};
            $t.nextAll('ul:eq(0)').find('[type=text]').each(function(){
                m.options.push({'name': $(this).val()});
            });
            data.push(m);
        });
        return data;
    }

$(document).ready(function(){
    $('[value="Remove Option"]').live('click', function(){
        $(this).closest('li').remove();
    });
    $('[value="Add Option"]').live('click', function(){
        $(this).closest('li')
            .before('<li><input type="text" value="Unnamed Option" /><input type="button" value="Remove Option"/></li>');
    });
    $('[value="Add Menu"]').live('click', function(){
        $(this).before('<input class="menu" type="text" value="Unnamed Menu" /> <input type="button" value="Remove Menu"/> <ul> <li><input type="button" value="Add Option" /></li> </ul>');
    });
    $('[value="Remove Menu"]').live('click', function(){
        var $t = $(this);
        $t.next().remove();
        $t.prev().remove();
        $t.remove();
    });
    $('[value="Wrap Data"]').live('click', function(){
        console.log(wrapData());
    });
})

http://jsfiddle.net/rd8Wp/7/

尝试