我的登录页面上有一个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 没有提供任何内容..
答案 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();
};