Jquery上下文菜单ajax获取菜单项

时间:2014-06-09 05:46:17

标签: javascript jquery asp.net-mvc-4 contextmenu

我的登录页面上有一个jquery上下文菜单,其中包含硬编码菜单项。现在我想从服务器获取菜单项。基本上,我们的想法是在上下文菜单列表中的指定目录中显示文件名,并在用户单击它时打开该文件...

到目前为止,我已经达到了......

*** *** UPDATE

C#代码

[HttpPost]
        public JsonResult GetHelpFiles()
         {
            List<Manuals> manuals = null;

            var filesPath = Server.MapPath(@"\HelpManuals");

            var standardPath = new DirectoryInfo(filesPath);

            if (standardPath.GetFiles().Any())
            {
               manuals = standardPath.GetFiles().Select(x => new Manuals
               {
                    Name = GetFileNamewithoutExtension(x.Name),
                    Path = x.Name
                }).ToList();
            }

            return Json(manuals, JsonRequestBehavior.AllowGet);
        }

        private string GetFileNamewithoutExtension(string filename)
        {
            var extension = Path.GetExtension(filename);

           return filename.Substring(0, filename.Length - extension.Length);
        }

JavaScript代码

$.post("/Home/GetHelpFiles", function (data) {
    $.contextMenu({
        selector: '#helpIcon',
        trigger: 'hover',
        delay: 300,
        build: function($trigger, e) {
            var options = {
                callback: function(key) {
                    window.open("/HelpManuals/" + key);
                },
                items: {}
            };
            $.each(data, function (item, index) {
                console.log("display name:" + index.Name);
                console.log("File Path:" + index.Path);
                options.items[item.Value] = {
                    name: index.Name,
                    key: index.Path
                }
            });
        }
    });
});

感谢 Matt 。现在,构建函数在悬停时触发..但是我得到非法调用...当迭代json结果时, index.Name this.Name 给出正确的结果。但 item.Name 没有提供任何内容..

4 个答案:

答案 0 :(得分:1)

要动态地向上下文菜单添加项目,您需要进行一些更改

$.contextMenu({
    selector: '#helpIcon',
    trigger: 'hover',
    delay: 300,
    build: function($trigger, e){
        var options = {
            callback: function (key) {
                var manual;
                if (key == "adminComp") {
                    manual = "AdminCompanion.pdf";
                } else {
                    manual = "TeacherCompanion.pdf";
                }
                window.open("/HelpManuals/" + manual);
            },
            items: {}
        }

        //how to populate from model
        @foreach(var temp in Model.FileList){
            <text> 
                options.items[temp.Value] = {
                    name: temp.Name,
                    icon: 'open'
                }
            </text>
        }

        //should be able to do an ajax call here but I believe this will be called 
        //every time the context is triggered which may cause performance issues
        $.ajax({
            url: '@Url.Action("Action", "Controller")',
            type: 'get',
            cache: false,
            async: true,
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function (_result) {
            if (_result.Success) {
                $.each(_result, function(item, index){
                    options.items[item.Value] = {
                        name: item.Name,
                        icon: 'open'
                    }
                });
            }
        });
        return options;
    }

});

所以你使用build和inside定义选项并将你的回调放在那里。其中定义的项目为空,并在构建中动态填充。我们建立了通过模型传递的列表,但我相信你可以像我上面所示的那样在构建中放置ajax调用。希望这至少会让你走上正确的轨道。

答案 1 :(得分:1)

我通过以下方式解决了这个问题。

在用户触发的右键单击中,我在构建函数中返回false。这将阻止上下文菜单打开。我没有打开上下文菜单,而是启动对服务器的ajax调用来获取contextMenu条目。

当ajax-call成功完成时,我创建项目并将项目保存在数据属性中的$ trigger上。 在data-property中保存menuItem后,我手动打开上下文菜单。

当再次执行构建函数时,我从data-property获取项目。

$.contextMenu({
    build: function ($trigger, e)
    {
        // check if the menu-items have been saved in the previous call
        if ($trigger.data("contextMenuItems") != null)
        {
            // get options from $trigger
            var options = $trigger.data("contextMenuItems");

            // clear $trigger.data("contextMenuItems"),
            // so that menuitems are gotten next time user does a rightclick 
            // from the server again.
            $trigger.data("contextMenuItems", null);
            return options;
        }
        else
        {
            var options = {
                callback: function (key)
                {
                    alert(key);
                },
                items: {}
            };
            $.ajax({
                url: "GetMenuItemsFromServer",
                success: function (response, status, xhr)
                {
                    // for each menu-item returned from the server
                    for (var i = 0; i < response.length; i++)
                    {
                        var ri = response[i];
                        // save the menu-item from the server in the options.items object
                        options.items[ri.id] = ri;
                    }
                    // save the options on the table-row;
                    $trigger.data("contextMenuItems", options);

                    // open the context-menu (reopen)
                    $trigger.contextMenu();
                },
                error: function (response, status, xhr)
                {
                    if (xhr instanceof Error)
                    {
                        alert(xhr);
                    }
                    else
                    {
                        alert($($.parseHTML(response.responseText)).find("h2").text());
                    }
                }
            });
            // This return false here is important                
            return false;
        }
   });

答案 2 :(得分:0)

在完整阅读jquery上下文菜单文档后,我终于找到了更好的解决方案..

C#CODE

 public JsonResult GetHelpFiles()
         {
            List<Manuals> manuals = null;

            var filesPath = Server.MapPath(@"\HelpManuals");

            var standardPath = new DirectoryInfo(filesPath);

            if (standardPath.GetFiles().Any())
            {
               manuals = standardPath.GetFiles().Select(x => new Manuals
               {
                    Name = GetFileNamewithoutExtension(x.Name),
                    Path = x.Name
                }).ToList();
            }

            return Json(manuals, JsonRequestBehavior.AllowGet);
        } 

HTML 5

<div id="dynamicMenu">
                        <menu id="html5menu" type="context" style="display: none"></menu>
                    </div> 

JavaScript代码

$.post("/Home/GetHelpFiles", function (data) {
                $.each(data, function (index, item) {
                    var e = '<command label="' + item.Name + '" id ="' + item.Path + '"></command>';
                    $("#html5menu").append(e);
                });


                $.contextMenu({
                    selector: '#helpIcon',
                    trigger: 'hover',
                    delay: 300,
                    items: $.contextMenu.fromMenu($('#html5menu'))
                });
            });


 $("#dynamicMenu").on("click", "menu command", function () {
        var link = $(this).attr('id');
        window.open("/HelpManuals/" + link);
    });

答案 3 :(得分:0)

这是我使用延期的解决方案,重要的是要知道此功能仅支持子菜单

$(function () {
            $.contextMenu({
                selector: '.SomeClass',
                build: function ($trigger, e) {
                    var options = {
                        callback: function (key, options) {
                            // some call back
                        },
                        items: JSON.parse($trigger.attr('data-storage')) //this is initial static menu from HTML attribute you can use any static menu here
                    };

                    options.items['Reservations'] = {
                            name: $trigger.attr('data-reservations'),
                            icon: "checkmark",
                            items: loadItems($trigger) // this is AJAX loaded submenu
                        };
                    return options;
                }
            });
        });
        
        // Now this function loads submenu items in my case server responds with 'Reservations' object
        var loadItems = function ($trigger) {
        var dfd = jQuery.Deferred();
        $.ajax({
            type: "post",
            url: "/ajax.php",
            cache: false,
            data: {
              // request parameters are not importaint here use whatever you need to get data from your server
                
            },
            success: function (data) {
                dfd.resolve(data.Reservations);
            }
        });
        return dfd.promise();
    };