动态更新和AJAX数据启用JQuery网页对话框

分享于 

26分钟阅读

Web开发

  繁體

介绍

在具有多个级别对话框的web应用程序项目中,需要在工作流中动态更新现有对话框中的组件。 我还需要加载 ASP.NET MVC部分视图和从调用对话获得的相应数据,从调用方的最少代码行。 我的插件基于这些需求和功能,没有找到任何库或者商业工具来满足我的所有需要,我是插件。

  • 易于使用和定制。
  • 对话框可以单独打开或者关闭,单独关闭或者多个级别一起打开。
  • 任何现有对话框组件都可以动态更新,以便同一对话框实例可以按顺序呈现不同的Windows。
  • 内置用于从AJAX调用加载任何部分视图和分离JSON数据的函数。
  • 使用现有或者新对话框实例显示任何处理延迟的进度栏窗口。
  • 包括模态。非模态和关闭对话框的选项,单击外部。
  • 可以由自定义样式表修改的整体主题和样式的Bootstrap。
  • 具有所有通用的对话框行为,以便一个工具能够满足网站所有页面的所有需求。

运行演示项目

下载源码包含一个 ASP.NET 5.0网站,以演示如何使用 jqsDialog插件插件。 在重新生成过程中,项目可以直接打开 Visual Studio 2012/2013.,该项目应该自动下载引用的.NET 相关库。 在 JQuery。jQuery UI。Bootstrap 和KnockoutJS项目中包含所有依赖JS和CSS库,在 8.0到的浏览器中应该可以使用模式对话框 Windows 和数据加载,Mozilla Firefox 25.0和 Google Chrome。 请参见 App_StartBundleConfig.cs 中演示应用程序使用的JS和CSS文件的列表。 如果运行其他浏览器类型或者版本,则可能需要调整这些依赖库的版本或者内容。

创建对话框的基函数

popupDialog 函数构建一个对话框的核心结构和组件。 这个函数通常被称为 inside 插件by其他功能working在通用的数据加载和进度栏对话框中,虽然它也可以直接使用语法在插件之外调用:

[[__em__]returned dialog instance] = $("[selector]").jqsDialog("popupDialog", [argObject]);

下面是一个使用输入参数对象中的属性调用函数的示例。 默认值显示在方括号中。

var popup = $("[selector]").jqsDialog("popupDialog", {
 message: "(text)",
 id: ["(GUID)"],
 width: [250],
 maxHeight: [$(window).height() - 120],
 title: ["Information"],
 titleTag: ["h4"],
 icon: [undefined],
 actionButtonLabel: [undefined],
 actionButtonType: [undefined or "button"if actionButtonLabel has value],
 closeButtonLabel: ["OK"],
 mainCssClass: ["jqs-dialog-main"],
 headerCssClass: ["jqs-dialog-header"],
 bodyCssClass: ["jqs-dialog-body"],
 footerCssClass: ["jqs-dialog-footer"],
 animation: [undefined],
 clickOutside: [false], 
 modal: [true],
 fadeIn: [true],
 parentResetClickOutside: [undefined],
 parentsToClose: [undefined],
 stopClose: [false] 
});

我们可以使用消息文本作为唯一必需的输入参数项来调用这里函数,以创建简单的警报类型对话框。 注意,基函数只能创建,而不是更新,如果它是直接调用的。 已经发布的对话框实例成员或者包装函数将用于动态更新现有对话框实例。

虚拟对话框容器和已经发布成员

调用 popupDialog 函数时,将创建一个名为虚拟对话框容器 ( VDC )的不可见包装,并添加可见的对话框。 它绑定到一个模态对话框的顶级元素 document.body,用于非模态对话框的JQuery选择器。

//Set virtual dialog container var vdc = $("<table><tr><td align='center'>"); if (args.modal) {
 //Append virtual dialog container to document.body $("body").append(vdc);
}else {
 //Append virtual dialog container to selector container.append(vdc);
}

VDC还承载了元素。函数和事件,这些元素和事件可以在创建对话框之后从插件外部调用。 这些已经发布成员是实现动态更新功能的基础。 调用任何对话实例成员都很简单。 例如使用此行代码将现有对话框实例 popupcloseButton 标签更改为 "Cancel":

popup.setCloseBtn("Cancel");

插件中有一个完整的规范节 上面,每个主要函数。 你可以从 jqsDialog.js 文件中的popupDialog 函数中看到这些已经发布对话框实例成员的详细信息。

通用对话框的功能

尽管可以通过直接调用已经发布对话框实例成员来动态更新现有对话框的组件。 为了进一步简化调用代码,插件提供了 showCommonPopup 包装函数来创建和更新对话框的警报/消息传递和确认类型。 函数已经重载版本。 我们可以为简单的单按钮模式对话框或者任何对话框的对象参数指定有限的单个参数。

showCommonPopup 函数的语法:

[[__em__]returned vdc instance] = $("[selector]").jqsDialog("showCommonPopup", [argObject]);
[returned vdc instance] = $("[selector]").jqsDialog("showCommonPopup", messageText, [title], [icon], [popup], [parentsToClose]);

argObject 包含与 popupDialog 函数的argObject 和附加属性 popup 相同的所有属性,后者用于接收用于更新进程的现有VDC实例。 下面的代码段演示使用现有VDC实例( 前三个对话框 Windows ) 和新的VDC实例( 最后一个对话框窗口)的确认和消息对话框的级联显示:

//Show a confirmation dialogvar popup = container.jqsDialog("showCommonPopup", {
 message: "This will overwrite your changes. Continue?",
 title: "Warning",
 icon: "warning",
 actionButtonLabel: "Yes",
 closeButtonLabel: "No"}); 
popup.actionButton.on("click", function () {
 //Dynamically switch to message dialog and set stopClose to true for keeping dialog open container.jqsDialog("showCommonPopup", {
 message: "Your request has been processed successfully",
 title: "Information",
 icon: "info",
 stopClose: true,
 popup: popup
 });
 popup.closeButton.on("click", function () {
 //Dynamically switch to another dialog container.jqsDialog("showCommonPopup", {
 message: "There is an error closing the dialog.",
 title: "Error",
 icon: "error",
 actionButtonLabel: "Ignore",
 closeButtonLabel: "Cancel", 
 popup: popup
 });
 popup.actionButton.on("click", function () { 
 //Show a new dialog using everything else by default and close this and parent dialogs together container.jqsDialog("showCommonPopup", {
 message: "You will ignore the error and close all dialogs",
 title: "Message",
 icon: "info", 
 parentsToClose: popup 
 });
 });
 });
});

在运行代码时,首先显示确认对话框:

单击 yes 按钮,现有对话框将更新到消息对话框:

单击 ok 按钮,现有对话框将进一步更新为一个错误确认对话框:

单击 Ignore Ignore按钮,将在前一个对话框中创建一个新消息对话框。 点击 ok 按钮将关闭活动对话框及其父节点。

加载部分视图和数据

showDataPopup 函数被设计用来加载一个onto视图,通过从对话窗口获取的AJAX调用获取数据。 下面是调用函数的语法:

[[__em__]returned vdc instance] = $("[selector]").jqsDialog("showDataPopup", [argObject]);

对话框的argObject 属性与前面列出的popupDialog 函数的属性相同。 AJAX调用的属性加上一些附加项被添加到参数对象。 below 是调用代码示例:

var popup = container.jqsDialog("showDataPopup", {
 //For Ajax call url: ["(URL string)"],
 data: [undefined], 
 type: ["GET"], 
 contentType: ["application/x-www-form-urlencoded; charset=utf-8"], 
 cache: [true - Ajax() default],
 async: [true - Ajax() default],
 beforeSend: [undefined] 
 success: [undefined],
 error: [undefined],
 complete: [undefined],
 //Additional args.stopProgress: [undefined or false], //Set true to disable built-in progress bar.  popup: [undefined] //existing vdc instance //Remaining properties are the same as those for popupDialog function. . . 
});

AJAX调用的输入参数属性和默认值与本机 JQuery Ajax() 函数相同,但仅包含参数对象的常用属性。 dataType 属性不公开给用户。 由于函数总是返回JSON类型中的数据,所以它硬编码到 "json"。 虽然发布回调的successerrorcomplete 属性,但大多数情况下,我们使用 callForJsonView 函数中引发的jsonViewSuccessjsonViewErrorjsonViewComplete 事件。 jsonViewSuccess 事件是我们用来从AJAX调用获取任何部分视图和数据的方法:

callForJsonView 函数中:

container.trigger("JsonViewSuccess", { html: result.html, data: result.data });

在使用者代码中:

container.on("JsonViewSuccess", function (html, data) {
 //Do something on html and data...}

在 ASP.NET MVC应用程序中,控制器通常将与数据模型的部分视图返回到 @Html.Partial 或者 @Html.RenderPartial helper 函数的位置。 这种方法实际上不能用于将任何部分视图和数据加载到动态生成或者更新的对话框中。 我们需要使用JQuery插件中的逻辑将部分视图HTML文本注入对话框内容并绑定从AJAX调用返回的数据。 因此,MVC控制器应该将这些项目返回给AJAX调用者:

  • 局部视图中用于字段类型映射的空数据模型。
  • 包含以下内容的数据 array:
  • 生成的部分视图HTML文本。
  • JSON对象实例,包含所有请求的数据记录。

在页面控制器的方法中:

//The product parameter contains data obtained from data sourcereturn PartialViewJson("../Demo/_Product", new Product(), product);

在 BaseController.cs 中:

protected JsonViewResult PartialViewJson(string viewName, object model = null, params object[] data)
{
 //viewName is used for getting the partial view for streaming processreturnnew JsonViewResult 
 {
 Data = new {
 html = RenderPartialViewToString(viewName, model),
 data = Json(data, "application/json; charset=utf-8", System.Text.Encoding.UTF8, JsonRequestBehavior.AllowGet).Data
 } 
 };
}protectedstring RenderPartialViewToString(string viewName, object model)
{
 if (string.IsNullOrEmpty(viewName))
 viewName = ControllerContext.RouteData.GetRequiredString("action");
 ViewData.Model = model;
 using (StringWriter sw = new StringWriter(CultureInfo.CurrentCulture))
 {
 //Streaming the partial view to HTML text ViewEngineResult viewResult = ViewEngines.Engines.FindPartialView(ControllerContext, viewName);
 ViewContext viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, sw);
 viewResult.View.Render(viewContext, sw);
 return sw.GetStringBuilder().ToString();
 }
}

JsonViewResult 是从 System.Web.Mvc.JsonResult 类派生的自定义类型。 你可以在演示项目中看到来自 ClassesJsonViewResult.cs 文件的详细信息。

最后,dataDialog.js 页面插件中的使用者代码在对话框插件中调用 showDataPopup 函数。 然后按照以下顺序执行这些任务:

  • 从服务器获取部分视图HTML和JSON对象数据。
  • 将HTML注入对话框的内容并使用数据字段呈现对话框结构。
  • 使用KnockoutJS处理 jsonViewSuccess 事件中的JSON数据。
  • 通过KnockoutJS将数据绑定到HTML元素并显示完整的对话框。
loadProductPopup: function (container, rowid) { 
 var popup = container.jqsDialog("showDataPopup", {
 url: "/Products/LoadProductById/" + rowid, 
 width: 450, 
 title: "Product",
 titleTag: "h3",
 actionButtonLabel: "Save",
 closeButtonLabel: "Cancel", 
 animation: "top,200" }); 
 container.on("jsonViewSuccess", function (html, data) { 
 //html already injected to dialog inside showDataPopupvar viewModel = ko.mapping.fromJS(data.data[0]); 
 var bindNode = document.getElementById("divPupContent");
 if (bindNode) {
 ko.cleanNode(bindNode);
 ko.applyBindings(viewModel, bindNode);
 } 
 container.off();
 });
 popup.actionButton.on("click", function () { 
 //Pass dialog as parent for closing together later methods.saveProduct(container, popup);
 });
}

你可以看到从消费者端编码代码和 LESS 代码行是多么容易。 为它的他任何用户使用默认值,只有 url 参数值在AJAX调用部分的参数对象的属性中指定。 如果向AJAX调用传递复杂数据,你只需要将另外两个属性( data: [object]contentType:"application/json" ) 添加到参数对象中。 函数将自动使用 POST 方法处理请求。 部分视图文件( _Product.cshtml ) 中的代码也非常整洁,并且在这个例子中保持了minimal行( 大约10行。 有关详细信息,请参阅文件)。 生成的对话框窗口如下所示:

单击保存按钮时,将显示一个新的确认对话框。 原始页面和数据对话框窗口现在变成了淡入的背景。

单击 yes 按钮时,提交请求将发送到服务器。 返回状态响应后,现有的VDC实例被更新到状态通知的消息对话框。

如果在确认和状态通知对话框之间使用相同的VDC实例,则可以使用相同的VDC实例来显示进度状态,如果有任何延迟消息,则显示。

上面 示例只显示对话框窗口中的数据的简单形式。 对话框上的数据和显示结构可能更为复杂,例如具有多个JqGrid或者KnockoutJS网格的分层数据集。 你可以使用插件插件的数据加载特性实现这些结构。

进度栏 Windows

进度条窗口使用基本对话框结构,但将动画图像加载到带有或者不带标题和页脚的对话框内容中。 下面是调用进度栏显示的语法:

[[__em__]returned vdc instance] = $("[selector]").jqsDialog("showProgressBar", [existingDialog], [keepParts])

由于动态更新特性,可以使用相同的VDC实例将进度条从其他类型的对话框切换到任何其他类型的对话框。 如果 existingDialog 参数有值,进度条将处于更新的VDC模式。 否则,将创建一个单独的VDC实例来显示进度栏。 进度栏 Windows的外观也基于 keepParts 参数的boolean 值。

当为 keepParts 参数传递 true 时,保留按钮的标题和页脚,只有内容被动画图像替换。 示例是在演示项目中成功加载来自AJAX调用的数据之前出现的进度条。 在这种情况下,将呈现对话框的完整结构,但进度条图像被注入到内容中,直到它被部分视图和数据结果替换。 在等待期间,页脚上的 Save Save按钮被禁用。 这种进度栏显示是数据加载对话框的默认行为,可以在调用 showDataPopup 函数时将参数对象属性设置为 "stopProgress: true",从而关闭该对话框。

keepParts 参数未定义或者设置为 false 时,进度栏显示在带有标题"请稍候。"和页脚中没有按钮的弹出窗口中。 在演示项目中可以看到这个场景,在单击确认对话框中的保存按钮后,单击保存data按钮,然后再单击。 通常,该进度条窗口应该切换到消息对话框,以便在接收服务器的任何反馈后成功或者错误。

注意,我仍然在对话框的右上角保留按钮,当显示进度栏时。 用户可以单击它来取消进程,如果该进程占用太长或者挂起。 如果你不喜欢进度栏窗口中的 x 按钮,你可以通过调用对话框实例函数来删除它:

//Remove x button for progress bar (pass anything with not-null value)popup.setHeader("no-x");

但是别忘了向切换到它的下一个对话框添加 x 按钮:

//Reset header with x buttonpopup.setHeader();

对于进度条,在出现任何单击外部操作时,它不是一个好实践。 因此,在加载进度栏时,单击 showProgressBar 函数中的这些代码行时,应该始终禁用外部选项:

//Set type status used for re-setting click-outside for next updated dialogpopup.typeStatus = "progress";//Always disable click-outside but doesn't change isClickOutside value when calling VDC's clickOutside function. Thus isClickOutside can be used to resume setting after progress bar dialog is switched to other type.popup.clickOutside(false);

如果在 showCommonPopupshowDataPopup 函数中使用的代码最初启用了该选项,则应为后续更新对话框恢复单击外部选项:

//Reset click-outside if updated from progress bar if (args.popup.typeStatus == "progress" && args.clickOutside == undefined) {
 args.popup.clickOutside(args.popup.isClickOutside);
}

在对话框页脚上设置更多按钮

通过设计,对话框插件有两个预定义按钮。 如果需要,可以在创建或者更新对话框之后,通过调用VDC实例函数 setOtherBtn 将附加按钮添加到对话框页脚中。

[[__em__]returned button instance] = containerInstance.setOtherBtn(label, [type])

下面是在对话框中添加第三个按钮的示例。

//Call base popupDialog for demo purpose. Could call showCommonPopup.var popup = container.jqsDialog("popupDialog", {
 message: "<br/><br/>(Content could be anything injected)<br/>",
 title: "Selection",
 actionButtonLabel: "Upload",
 closeButtonLabel: "Cancel",
 width: 320});//Add a new button with function for click event.var emailButton = popup.setOtherBtn("Email");
emailButton.on("click", function () { 
 container.jqsDialog("showCommonPopup", "You selected sending out an email", "Message", "info", popup);
});

对话框窗口的屏幕抓图如下所示:

非模态对话框

当使用非模态类型时,可能需要一些注意事项,例如插件。

  • 默认情况下,输入参数的modal 属性设置为 true。 将它的设置为 false 以呈现非模态类型的对话框。
  • 默认情况下,输入参数的fadeIn 属性设置为 true。 将 modal 设置为 false 将自动将 fadeIn 设置为 false
  • 非模态对话框只能在它的基本父窗口上打开。 不支持从非模态父对话框打开任何非模态子对话框。 要从非模态父对话框打开这样的子对话框,你可以将输入参数的fadeIn 属性设置为 false,这样就不会显示灰色 background。
  • 不应为从非模态父对话框打开的子对话框设置单击外部选项,单击外部选项。
  • 如果单击外部选项设置非模态父对话框,则需要在从父对话框打开子对话框时禁用该选项。 然后,你需要在子对话框输入参数对象中设置 parentResetClickOutside 属性值,以便在关闭子对话框后恢复父选项之外的单击。
  • 需要显式定义非模态对话框的id 属性值,以避免在从父窗口发送相同的命令时打开多个对话框。

下面是创建非模态对话框及其子对话框的代码 Fragment,它带有父级单击外部禁用和启用的场景。

//Needs explicit Id for non-modal dialog to prevent opening the same dialog again.var popup = container.jqsDialog("showCommonPopup", {
 message: "It's the parent non-modal dialog window.",
 title: "Non-modal Dialog", 
 actionButtonLabel: "Open Child",
 closeButtonLabel: "Cancel",
 clickOutside: true,
 modal: false, 
 id: "non-modal-1"});//Needs to check button existence for IE 8 if (popup.actionButton!= undefined) {
 popup.actionButton.on("click", function (event) {
 //Need to disable non-modal parent click-outside when opening child dialog from it popup.clickOutside(false);
 var popupChild = container.jqsDialog("showCommonPopup", {
 message: "It's the child dialog opened from the non-modal parent.",
 title: "Child Dialog",
 fadeIn: false,
 //Re-enable parent's click-outside option parentResetClickOutside: popup
 });
 }); 
} 

非模态对话框示例在 below 屏幕快照中显示。 你可以使用示例应用程序或者自己的应用程序来测试各种其他方案。

主题和样式的文件

演示项目中的插件插件使用了来自这些源文件的CSS:

  • bootstrap_spacelab.css: 设置整体主题。 默认情况下,类 header。body。footer和按钮设置了类 modal-headermodal-bodymodal-footer,以及 btn。 更改其他 Bootstrap 主题也可能改变对话框的外观和感觉。
  • jqsDialog.css: 为对话框结构提供自定义的特定样式。 当你更改 Bootstrap 主题时,可能需要调整自定义样式。
  • site.css: 保存适用于整个站点的所有页面的通用样式。 例如 btn 类被添加到这个文件中,以覆盖 Bootstrap CSS文件中按钮的某些设置。 更新的样式应用于包括对话框在内的所有页面上的按钮。

摘要

这里提供的JQuery对话框实现了本文开头列出的所有需求和特性。 尽管演示项目构建为 ASP.NET MVC网站应用程序,但是插件中的所有JavaScript函数都可以由任何平台的应用程序使用。 可以在对话框内容或者媒体中插入任何形式的数据或者媒体,如标题,图标,页脚和按钮。 你可以根据需要自由修改插件中的任何内容和关联的支持文件。 开心编码!


WEB  数据  动态  DIA  对话框  dialogs  
相关文章