4

我有一个表单 UI,其中几个部分需要从单个可动态更新的选择列表中动态更新重复的 HTML 选择列表。

动态可更新列表工作得很好,因为可以动态添加和删除新选项。然后,我可以使用 JQuery .find() 让这个更新传播到每个重复的列表中。我什至添加了一些逻辑来维护原始选择列表的当前选定索引。

我无法做的是在原始选择列表中添加和删除新选项时保持每个重复选择列表的选定状态。由于对原始选择列表的每次更新都会遍历每个重复的选择列表,因此它们会丢失当前选择的选项索引。

这是我的难题的一个示例- *编辑-我鼓励您尝试并执行我在下面提供的代码并在提出解决方案之前应用您的理论,因为到目前为止没有任何建议有效。我相信你会发现这个问题比你一开始想象的要棘手得多:

<form>
<div id="duplicates">
<!--// I need for each of these duplicates to maintain their currently selected option index as the original updates dynamically //-->
  <select>
  </select>
  <select>
  </select>
  <select>
  </select>
</div>
<div>
  <input type="button" value="add/copy" onclick="var original_select = document.getElementById('original'); var new_option = document.createElement('option'); new_option.text = 'Option #' + original_select.length; new_option.value = new_option.text; document.getElementById('original').add(new_option); original_select.options[original_select.options.length-1].selected = 'selected'; updateDuplicates();" />
  <input type="button" value="remove" onclick="var original_select = document.getElementById('original'); var current_selected = original_select.selectedIndex; original_select.remove(original_select[current_selected]); if(original_select.options.length){original_select.options[current_selected < original_select.options.length?current_selected:current_selected - 1].selected = 'selected';} updateDuplicates();" />
  <select id="original">
  </select>
</div>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
    function updateDuplicates(){
        $("#duplicates").find("select").html($("#original").html());
     }
</script>
</form>

重要的是要注意,如果可能的话,重复的 HTML 选择列表应该保持一定程度的随意性(即没有 ID),因为这种方法需要通用地应用于整个文档中的其他动态创建的选择列表。

提前致谢!

4

4 回答 4

0

只需将当前选择的项目/选择值设置为某个变量,然后进行操作,最后将值重新选择为选择。

于 2011-12-03T20:44:12.830 回答
0

好吧,我想我有一个可行的解决方案,如果不是一个笨拙的方法。棘手的部分不是向原始列表添加值,因为添加的选项始终位于列表的末尾。问题在于删除选择选项,因为这样做会更改当前 selectedIndex 的索引。我已经在 Mac 上使用 Google Chrome 进行了测试,没有出现任何错误。我已经对代码进行了注释,以演示我如何处理我的解决方案:

<form>
<div id="duplicates">
  <!--// Each of these select lists should maintain their currently selected index //-->
  <select>
  </select>
  <select>
  </select>
  <select>
  </select>
</div>
<div>
  <!--// Using a generic function to capture each event //-->
  <input type="button" value="add/copy" onClick="updateDuplicates('add');" />
  <input type="button" value="remove" onClick="updateDuplicates('remove');" />
  <select id="original">
  </select>
</div>
<script type="text/javascript" src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
    function updateDuplicates(editMode){
        ///* Capture the selectedIndex of each select list and store that value in an Array *///
        var original_select = document.getElementById('original');
        var current_selected = new Array();
        $("#duplicates").find("select").each(function(index, element) {
            current_selected[index] = element.selectedIndex;
        });
        switch(editMode){
            case "add":
                var new_option = document.createElement('option');
                new_option.text = 'Option #' + original_select.length;
                new_option.value = new_option.text;
                original_select.add(new_option);
                original_select.options[original_select.options.length-1].selected = 'selected';
                ///* Traverse each select element and copy the original into it, then set the defaultSelected attribute for each *///
                $("#duplicates").find("select").each(function(index, element){
                    $(element).html($("#original").html());
                    ///* Retrieve the currently selected state stored in the array from before, making sure it is a non -1 value, then set the defaultSelected attribute of the currently indexed element... *///
                    if(current_selected[index] > -1){
                        element.options[current_selected[index]].defaultSelected = true;
                    }
                });
                break;
            case "remove":
                var current_index = original_select.selectedIndex;
                original_select.remove(original_select[current_index]);
                ///* Thou shalt not remove from thine empty list *///
                if(original_select.options.length){
                    original_select.options[current_index > 0?current_index - 1:0].selected = 'selected';
                }
                ///* Traverse each select element and copy the original into it... *///
                $("#duplicates").find("select").each(function(index, element){
                    $(element).html($("#original").html());
                    ///* Avoid operating on empty lists... *///
                    if(original_select.options.length){
                        ///* Retrieve the currently selected state stored in the array from before, making sure it is a non -1 value... *///
                        if(current_selected[index] > -1){
                            ///* If the stored index state is less or equal to the currently selected index of the original... *///
                            if(current_selected[index] <= current_index){
                                element.options[current_selected[index]].defaultSelected = true;
                            ///* ...otherwise, the stored index state must be greater than the currently selected index of the original, and therefore we want to select the index after the stored state *///
                            }else{
                                element.options[current_selected[index] -  1].defaultSelected = true;
                            }
                        }
                    }
                });
            }           
     }
</script>
</form>

有足够的空间来修改我的代码,以便可以在当前 selectedIndex 之后插入选项,而不是附加到原始选择列表的末尾。从理论上讲,多选列表/菜单也应该可以工作。给你。

我相信这里的一位天才将能够用比我更干净、更漂亮的代码来做同样的事情。感谢所有对我最初的问题进行评论和评论的人!干杯。

于 2011-12-05T19:07:09.003 回答
0

如果您可以稍微重置一下,我认为问题在于您将选择列表的 HTML 设置为另一个列表的 HTML。如果所有底层 html 都被更改,浏览器可能不会尝试保留当前选定的项目。

因此,我认为您可能会尝试将选项元素显式添加到目标列表中。

试试这个jsfiddle。如果选择默认第一个项目以外的项目并单击“添加”,请注意所选项目保持不变。因此,您需要在管理目标列表项时更加外科手术。

也许这会有所帮助,或者我错过了重点。

于 2011-12-05T19:36:30.380 回答
0

仍然不能 100% 确定您要问什么,但似乎这应该可以满足您的需求,而且代码行数也少了几行。

(function () {
        function updateDuplicates() {
            $("#duplicates").find("select").html($("#original").html());

            $('#duplicates select').each(function () {
                var lastSelectedValue = $(this).data('lastSelectedValue');
                $(this).val(lastSelectedValue || $(this).val());
            });
        }

        $(document).ready(function () {
            $('button:contains(remove)').bind('click', function (e) {
                e.preventDefault();
                var original_select = document.getElementById('original'),
                current_selected = original_select.selectedIndex;

                original_select.remove(original_select[current_selected]);
                if (original_select.options.length) {
                    original_select.options[current_selected < original_select.options.length ? current_selected : current_selected - 1].selected = 'selected';
                }
                updateDuplicates();
            });

            $('button:contains(add/copy)').bind('click', function (e) {
                e.preventDefault();
                var original_select = document.getElementById('original'),
                new_option = document.createElement('option');

                new_option.text = 'Option #' + original_select.length;
                new_option.value = new_option.text;
                document.getElementById('original').add(new_option);
                original_select.options[original_select.options.length - 1].selected = 'selected';
                updateDuplicates();
            });

            $('#duplicates select').bind('change', function () {
                $(this).data('lastSelectedValue', $(this).val());
            });
        } ());
    } ());

编辑:我将您的标记更改为

<button>add/copy</button>
<button>remove</button>
于 2011-12-06T21:49:37.927 回答