jQuery ASP.NET Accordion event.target Ошибка

Я пытался изучить jQuery с помощью ASP.NET. Я следил за отличной статьей Бипина Джоши «http://www.codeguru.com/csharp/article.php/c18665/Developing-a-Database-Driven-Accordion-Menu-Using-WCF-и-jQuery.htm'

Я внес некоторые изменения в код статьи: я использую методы страницы, а не службу WCF; Я использую таблицу [AdventureWorksLT].[SalesLT].[ProductCategory] для построения меню и элементов меню.

Меню отображаются, но когда я нажимаю на меню, элементы меню не отображаются. Я получаю сообщение об ошибке со следующими строками:

$(событие.цель).дети().удалить(); -- который удаляет все дочерние элементы меню, которые были нажаты пользователем.

$(событие.цель).append(html); -- который добавляет HTML-фрагмент MenuItems к меню, выбранному пользователем.

в функции OnMenuClick(событие)

Я получаю сообщение об ошибке «event.target is undefined».

Что я делаю не так? Я что-то упускаю? Есть ли более простой способ сделать это?

Вот мой код:

У меня есть div с id="accordionContainer" в теле моей страницы ASP.NET.

    $(document).ready(function () {
        $('#accordionContainer').html('Loading...')
        $.ajax({
            type: "POST",
            contentType: "application/json",
            data: "{}",
            url: "Catalogue.aspx/GetMenus",
            dataType: "json",
            success: function (response) {
                if (response != null && response.d != null) {
                    CreateMenus(response.d);
                }
            }
        });
    });

    function CreateMenus(results) {
        $("#accordionContainer").empty();
        var _html = '';
        for (var i = 0; i < results.length; i++) {
            //_html += '<div class="Menu" onclick="OnMenuClick(' + results[i].MenuID + ');">' + results[i].Text + '</div>';
            _html += '<div class="Menu" onclick="OnMenuClick({ MenuID: ' + results[i].MenuID + '});">' + results[i].Text + '</div>';
        }
        document.getElementById('accordionContainer').innerHTML = _html;
    }

    //function OnMenuClick(MenuID) {
    function OnMenuClick(event) {
        $("div[id ^= 'menuItemGroup']").slideUp(500);
        $.ajax(
            {
                type: "POST",
                contentType: "application/json",
                data: "{'MenuID':'" + event.MenuID + "'}",
                url: "Catalogue.aspx/GetMenuItems",
                dataType: "json",
                success: function (items) {
                    $(event.target).children().remove();
                    var html = "<div id='menuItemGroup" + event.MenuID + "' style='display:none'>";
                    for (var j = 0; j < items.d.length; j++) {
                        html += "<div class='MenuItem'><a href='#' onclick='GetProducts(" + items.d[j].MenuItemID + ");'>" + items.d[j].Text + "</a></div>";
                    }
                    html += "</div>";
                    $(event.target).append(html);
                    $("#menuItemGroup" + event.MenuID).slideDown(500);
                },
                error: function (err) {
                    alert(err.status + " - " + err.statusText);
                }
            })
    } 

В коде позади:

[Serializable]
public class Menu
{
    public int MenuID { get; set; }
    public string Text { get; set; }
}
[System.Web.Services.WebMethod]
public static List<Menu> GetMenus()
{
    List<Menu> myMenus = new List<Menu>();

    using (SqlConnection conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["AdventureWorksLTConnectionString"].ConnectionString))
    {
        // Fetch Menus from AdventureWorksLT database.
        string sqlString = "SELECT [ProductCategoryID],[ParentProductCategoryID],[Name] FROM [SalesLT].[ProductCategory] WHERE [ParentProductCategoryID] IS NULL";
        using (SqlCommand cmd = new SqlCommand(sqlString, conn))
        {
            conn.Open();

            SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

            while (rdr.Read())
            {
                Menu m = new Menu();
                m.MenuID = Convert.ToInt32(rdr["ProductCategoryID"]);
                m.Text = rdr["Name"].ToString();
                myMenus.Add(m);
            }

            conn.Close();

            return myMenus;
        }
    }
}
[Serializable]
public class MenuItem
{
    public int MenuID { get; set; }
    public int MenuItemID { get; set; }
    public string Text { get; set; }
}
[System.Web.Services.WebMethod]
public static List<MenuItem> GetMenuItems(int MenuID)
{
    List<MenuItem> myMenuItems = new List<MenuItem>();

    using (SqlConnection conn = new SqlConnection(WebConfigurationManager.ConnectionStrings["AdventureWorksLTConnectionString"].ConnectionString))
    {
        // Fetch Products from AdventureWorksLT database.
        string sqlString = "SELECT [ProductCategoryID],[ParentProductCategoryID],[Name] FROM [SalesLT].[ProductCategory] WHERE [ParentProductCategoryID]=@MenuID";

        using (SqlCommand cmd = new SqlCommand(sqlString, conn))
        {
            SqlParameter paramMenuID = new SqlParameter("@MenuID", SqlDbType.Int);
            paramMenuID.Value = MenuID;
            cmd.Parameters.Add(paramMenuID);

            conn.Open();

            SqlDataReader rdr = cmd.ExecuteReader(CommandBehavior.CloseConnection);

            while (rdr.Read())
            {
                MenuItem mi = new MenuItem();
                mi.MenuID = Convert.ToInt32(rdr["ParentProductCategoryID"]);
                mi.MenuItemID = Convert.ToInt32(rdr["ProductCategoryID"]);
                mi.Text = rdr["Name"].ToString();
                myMenuItems.Add(mi);
            }

            conn.Close();

            return myMenuItems;
        }
    }
}

Заранее спасибо.

С уважением

Уолтер


person Walter Lockhart    schedule 31.05.2011    source источник


Ответы (1)


Вы onclick вызываете OnMenuClick и передаете объект, а объект не является событием, поэтому целевого свойства нет.

Если бы это был мой код, я бы написал его так, используя делегирование событий. Это использует jQuery 1.6; дайте мне знать, если вы используете другую версию, и я внесу изменения в этот код для поддержки вашей версии:

(function() {
    var accordion = $("#accordionContainer");

    var createMenus = function(results) {
        var stringBuilder = [];

        accordion.empty();

        for (var i = 0, len = results.length; i < len; i++) {
            stringBuilder.push('<div class="menu" data-menu-id="'+ results[i].MenuId +'">' + results[i].Text + '</div>');
        }

        accordion.html(stringBuilder.join(''));
    };

    var menuClick = function(e) {
        var element = $(this),
            menuId = element.data('menuId');

        $("div[id^='menuItemGroup']").slideUp(500);

        $.ajax({
            type: "POST",
            contentType: "application/json",
            data: { MenuID: element.data('menuId') },
            url: "Catalogue.aspx/GetMenuItems",
            dataType: "json",
            success: function (items) {
                var stringBuilder = [],
                    currentItem;

                stringBuilder.push("<div id='menuItemGroup" + event.MenuID + "' style='display:none'>");

                for (var i = 0, len = items.d.length; i < len; i++) {
                    currentItem = item.d[i];

                    stringBuilder.push("<div class='menu-item'><a href='#' data-menu-item-id='" + currentItem.MenuItemID + "'>" + currentItem.Text + "</a></div>");
                }

                stringBuilder.push("</div>");

                element.html(stringBuilder.join(''));

                $("#menuItemGroup" + event.MenuID).slideDown(500);
            },
            error: function (err) {
                alert(err.status + " - " + err.statusText);
            }
        });
    };  

    $(document)
        .delegate('.menu', 'click', menuClick)
        .delegate('.menu-item', click, GetProducts)
        .ready(function() {
            accordion.html('Loading...');

            $.ajax({
                type: "POST",
                contentType: "application/json",
                url: "Catalogue.aspx/GetMenus",
                dataType: "json",
                success: function (response) {
                    if (response && response.d) {
                        createMenus(response.d);
                    }
                }
            });
        });
});
person Eli    schedule 31.05.2011
comment
Спасибо, Эли. Очень признателен. - person Walter Lockhart; 31.05.2011
comment
Спасибо Эли. Это выглядит более элегантно. Спасибо за рефакторинг. Я попробовал, и оказалось, что событие OnMenuClick настроено неправильно. Любые предложения о том, что я должен изменить, пожалуйста? - person Walter Lockhart; 31.05.2011
comment
Я покажу вам, как сделать это лучше с помощью делегирования событий. - person Eli; 31.05.2011
comment
Спасибо Эли. Я использую 1.6.1 - последнюю версию, насколько я знаю. Я попробую сейчас. - person Walter Lockhart; 31.05.2011
comment
Привет Эли. Немного больше прогресса, чем раньше. Когда я нажимаю на меню, оно исчезает, но появляются элементы меню. Трудно описать. Могу ли я заархивировать страницу и отправить вам электронное письмо, пожалуйста? - person Walter Lockhart; 31.05.2011