在多个列表之间移动选项

时间:2010-03-23 22:51:53

标签: javascript html forms asp-classic usability

我们目前有一个标准多选功能的表单“这里有可用选项,这里是选定的选项,这里有一些按钮来回移动东西。”但是,客户现在希望不仅可以选择某些项目,还可以对它们进行分类。例如,给定书籍清单,他们不仅要选择他们拥有的书籍,还要选择他们阅读的书籍,他们想要阅读的书籍以及他们听过的书籍。 (所有示例都是虚构的。)值得庆幸的是,所选项目一次只能在一个类别中。

我可以找到许多在列表框之间移动项目的示例,但没有一个用于在多个列表框之间移动项目的示例。要添加到复杂功能,表单需要有两组列表+类别,例如除上述书籍外还需要分类的电影列表。

编辑:现在实际上坐下来尝试编写非javascripty位,我需要修改我的问题,因为我意识到多个选择列表不会真正起作用“如何通知服务器所有这个可爱的新信息“立场。所以html代码现在是一个伪列表框,即带有滚动条的框中显示的无序列表(<ul>),每个列表项(<li>)都有一组五个单选按钮(未选中) /自己/读取/像/听到)。

我的任务仍然大致相同:如何使用这一个列表并轻松对项目进行分类,以便用户可以一目了然地了解哪个类别。 (伪列表框与多选列表框有一些相同的缺点,即如果列表足够长以滚动,很难说出选择了什么。)梦想的解决方案是拖放类型的东西,但是在这一点上,甚至按钮都可以。

另一个修改(一个好的修改)是客户修改了列表,因此最长的是“仅”62个项目(而不是之前的数百个)。这些类别仍将主要包含零个,一个或两个选定项目,如果用户过于热心,可能会多一些。

对于操作系统和东西,该网站是经典的asp(退出窃笑!),服务器端代码是VBScript,到目前为止,我们通过几乎从不使用客户端的简单权宜之计避免了各种Javascript库脚本编写。这个客户的这种形式目前是一个很大的例外。给他们一英寸,他们想要一英里......

哦,我必须补充一点:我很喜欢Javascript,或者真的使用任何C后代语言。卷曲括号给我荨麻疹。我真的非常喜欢我可以复制的东西。粘贴到我的页面,可能会调整一些变量名称,而不会再次查看它。一个女孩可以做梦,不是吗? :)

[删除现有代码,因为它基本上无关紧要。]

3 个答案:

答案 0 :(得分:1)

好笑,我也是,就在昨天用谷歌搜索“在多个列表框之间移动项目”并弹出你的问题。

我没看过你的整个帖子所以我不确定我是否可以提供帮助。 但这解决了我的问题。 我下载了this解决方案。 然后进行了以下更改......

  • 在html中添加一个额外的hidenfield 每(额外)列表框。
  • 如下修改,你可以 比较我做出的改变......

// ...

public partial class ErrorActions:System.Web.UI.Page     {         private XmlDocument _xmlDocument = new XmlDocument();         public ListBox FromListBox         {             得到             {                 return lstFrom;             }         }

    public ListBox AbortListBox
    {
        get
        {
            return lstToAbort;
        }
    }

    public ListBox ClearingListBox
    {
        get
        {
            return lstToClearing;
        }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        Page.ClientScript.RegisterClientScriptInclude("listboxjs", "/JavaScripts/listbox.js");

        if (!IsPostBack)
        {
            string movejs = "move('{0}','{1}','{2}')";
            string unselectjs = "unselect('{0}')";
            lstFrom.Attributes["onclick"] = String.Format(unselectjs, lstToAbort.ClientID);
            lstFrom.Attributes["onclick"] = String.Format(unselectjs, lstToClearing.ClientID);
            lstToAbort.Attributes["onclick"] = String.Format(unselectjs, lstFrom.ClientID);
            lstToAbort.Attributes["onclick"] = String.Format(unselectjs, lstToClearing.ClientID);
            lstToClearing.Attributes["onclick"] = String.Format(unselectjs, lstFrom.ClientID);
            lstToClearing.Attributes["onclick"] = String.Format(unselectjs, lstToAbort.ClientID);

            btnToAbort.Attributes["onclick"] = String.Format(movejs, lstFrom.ClientID, lstToAbort.ClientID, hdnDropdownsAbort.ClientID);
            btnFromAbort.Attributes["onclick"] = String.Format(movejs, lstToAbort.ClientID, lstFrom.ClientID, hdnDropdownsAbort.ClientID);

            btnToClearing.Attributes["onclick"] = String.Format(movejs, lstFrom.ClientID, lstToClearing.ClientID, hdnDropdownsClearing.ClientID);
            btnFromClearing.Attributes["onclick"] = String.Format(movejs, lstToClearing.ClientID, lstFrom.ClientID, hdnDropdownsClearing.ClientID);
        }
        else
        {
            //if (!(String.IsNullOrEmpty(hdnDropdowns.Value)))
            //{
            //    PopulateListBoxes();
            //}

            if (!(String.IsNullOrEmpty(hdnDropdownsAbort.Value)))
            {
                PopulateAbortListBox();
            }

            if (!(String.IsNullOrEmpty(hdnDropdownsClearing.Value)))
            {
                PopulateClearingListBox();
            }
        }
    }

    private void PopulateListBox(ListBox listBox)
    {
        listBox.Items.Clear();
        XmlNodeList nodes = _xmlDocument.SelectNodes("listboxes/" + listBox.ClientID + "/option");
        foreach (XmlNode node in nodes)
        {
            listBox.Items.Add(new ListItem(node["key"].InnerText, node["value"].InnerText));
        }
    }

    //private void PopulateListBoxes()
    //{
    //    _xmlDocument.LoadXml(HttpUtility.UrlDecode(hdnDropdownsAbort.Value));
    //    //PopulateListBox(lstFrom);
    //    PopulateListBox(lstToAbort);
    //    PopulateListBox(lstToClearing);
    //}

    private void PopulateAbortListBox()
    {
        _xmlDocument.LoadXml(HttpUtility.UrlDecode(hdnDropdownsAbort.Value));
        PopulateListBox(lstToAbort);
    }

    private void PopulateClearingListBox()
    {
        _xmlDocument.LoadXml(HttpUtility.UrlDecode(hdnDropdownsClearing.Value));
        PopulateListBox(lstToClearing);
    }

    protected void btnDoIt_Click(object sender, EventArgs e)
    {
        MissionErrorCodeDB db = new MissionErrorCodeDB();
        db.DeleteErrorCodeActions(ErrorAction.AbortMission);
        db.DeleteErrorCodeActions(ErrorAction.GoToClearingStation);

        foreach (ListItem item in lstToAbort.Items)
        {
            db.AddErrorCodeAction(Convert.ToInt32(item.Value), ErrorAction.AbortMission);
        }
        foreach (ListItem item in lstToClearing.Items)
        {
            db.AddErrorCodeAction(Convert.ToInt32(item.Value), ErrorAction.GoToClearingStation);
        }
    }

    protected override void OnPreRender(EventArgs e)
    {
        MissionErrorCodeDB db = new MissionErrorCodeDB();
        List<MissionErrorCode> aborts = db.GetAll(ErrorAction.AbortMission);
        List<MissionErrorCode> clearing = db.GetAll(ErrorAction.GoToClearingStation);
        List<MissionErrorCode> all = db.GetAll();

        all.RemoveAll(delegate(MissionErrorCode mec) 
                    {
                        foreach (MissionErrorCode item in aborts)
                        {
                            if( mec.ErrorCode == item.ErrorCode )
                                return true;

                        }
                        return false;
                    });
        all.RemoveAll(delegate(MissionErrorCode mec)
                    {
                        foreach (MissionErrorCode item in clearing)
                        {
                            if (mec.ErrorCode == item.ErrorCode)
                                return true;

                        }
                        return false;
                    });

        populateBoxFromDatabase(AbortListBox, aborts);
        populateBoxFromDatabase(ClearingListBox, clearing);
        populateBoxFromDatabase(FromListBox, all);

        base.OnPreRender(e);
    }

    private void populateBoxFromDatabase(ListBox listBox, List<MissionErrorCode> errorCodes)
    {
        string text;
        int textLength = 46;

        listBox.Items.Clear();
        foreach (MissionErrorCode item in errorCodes)
        {
            if (item.ErrorText.Length < textLength)
            {
                text = item.ErrorCode + "  - " + item.ErrorText;
            }
            else
            {
                text = item.ErrorCode + "  - " + item.ErrorText.Substring(0, textLength - 1) + "...";
            }
            listBox.Items.Add(new ListItem(text, item.ErrorCode.ToString()));
        }
    }

}

// ...

答案 1 :(得分:0)

为了避免大量的Javascript,我建议您使用几个Ajax调用来完成工作

  1. 在项目旁边添加几个按钮(已经拥有它,想要它等)。每个按钮都应调用服务器中的一个页面,该页面将项目设置为正确的类别。
  2. 在成功回调中,调用其他只刷新受影响的类别列表的ajax函数。
  3. 使用jQuery,您会看到拨打电话非常简单。

    祝你好运。

答案 2 :(得分:0)

好吧,似乎没有人愿意为我做我的工作,所以这就是我们最终做的事情。 (它还没有完全完成;当它完成时,我可能只是为了完整性而发布代码。)

我们采取了下载和下载JQuery,特别是JQuery UI“可排序”功能。就像我说的那样,主下拉列表现在是一个伪列表框,即高度受限且ul的{​​{1}}。每个项目旁边都有五个单选按钮,用Javascript隐藏。 (也就是说,如果Javascript不可用,用户只会看到带有单选按钮的列表。)当您将项目从主列表拖到(脚本生成的)类别列表中时,会标记相应的单选按钮。还会有一些代码在页面加载时运行,以将已标记的选项从主列表移动到适当的类别(即用于编辑功能)。