Bootstrap JavaScript 中断 ASP.NET 回发
Bootstrap JavaScript breaks ASP.NET postback
似乎将 bootstrap.js 注册到我的页面会阻止我的所有服务器控件,例如asp:LinkButtons
和 asp:Buttons
,来自触发回发。
我的母版页中有以下 C# 脚本。如果用户不在 Kentico 的设计模式下,它只会注册 jQuery 1.11.1 和 Bootstrap.js。否则它只会加载 jQuery 1.7.1.
如果我不包括 bootstrap.js,我的 asp:LinkButtons
和 asp:Buttons
的回发将正常进行。否则,根本就没有任何动作发生。知道会发生什么吗?
我在浏览器中没有看到任何控制台错误,而且我绝对确定包含 Bootstrap.js 是造成这种行为的部分原因,如果不是全部的话。一切正常,只要找到它是否不包括在内(当然,除了 bootstrap jQuery 模块)。
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
// Check for null document
if(CMSContext.CurrentDocument != null)
{
if(CMS.PortalEngine.PortalContext.ViewMode.ToString() == "Design")
{
CMS.GlobalHelper.ScriptHelper.RegisterJQuery(this.Page);
}
else
{
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),"jquery","<script src=\"//code.jquery.com/jquery-1.11.2.min.js\"><" + "/script>",false);
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),"bootstrap","<script src=\"/getmedia/453e9ad5-e05c-4fb2-b134-4d9cbd00c917/bootstrap-min.aspx\"><" + "/script>",false);
}
}
}
</script>
That bootstrap.min.js file is just the default bootstrap.min.js file for v3.3.2
前面的代码
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="IssuesSettings.ascx.cs" Inherits="CustomCode_Dashboard_Issues_Issues" %>
<div class="col-xs-12">
<div class="gap"></div>
<div class="btn-group" data-toggle="buttons">
<asp:LinkButton runat="server" ID="ButtonCompletedProjects" CssClass="btn btn-default btn-xs" OnClick="ButtonCompletedProjectsClicked">Show Completed Projects</asp:LinkButton>
<asp:LinkButton runat="server" ID="ButtonClosedIssues" CssClass="btn btn-default btn-xs" OnClick="ButtonClosedIssuesClicked">Show Closed Issues</asp:LinkButton>
</div>
</div>
代码隐藏
public partial class CustomCode_Dashboard_Issues_Issues : System.Web.UI.UserControl
{
// cookie name constants
private const string CookieClosedIssuesName = "Dashboard-Issues-ShowClosedIssues";
private const string CookieCompletedProjectsName = "Dashboard-Issues-ShowCompletedProjects";
// boolean switches
private bool _showClosedIssues;
private bool _showCompletedProjects;
protected void Page_Load(object sender, EventArgs e)
{
SetShowClosedIssues();
SetShowCompletedProjects();
SetButtonStyles();
}
private void SetButtonStyles()
{
if (_showClosedIssues)
{
ButtonClosedIssues.CssClass += " active";
}
else
{
ButtonClosedIssues.CssClass += " inactive";
}
if (_showCompletedProjects)
{
ButtonCompletedProjects.CssClass += " active";
}
else
{
ButtonCompletedProjects.CssClass += " inactive";
}
}
private void SetShowCompletedProjects()
{
if (Request.Cookies[CookieCompletedProjectsName] != null)
{
_showCompletedProjects = Convert.ToBoolean(Request.Cookies[CookieCompletedProjectsName].Value);
}
else
{
_showCompletedProjects = false;
}
}
private void SetShowClosedIssues()
{
if (Request.Cookies[CookieClosedIssuesName] != null)
{
_showClosedIssues = Convert.ToBoolean(Request.Cookies[CookieClosedIssuesName].Value);
}
else
{
_showClosedIssues = false;
}
}
protected void CLICKER(object sender, EventArgs e)
{
Response.Write("stuff");
}
protected void ButtonClosedIssuesClicked(Object sender, EventArgs e)
{
Response.Write("TEST");
// if we're turning this off
if (_showClosedIssues)
{
HttpCookie cookie = Request.Cookies[CookieClosedIssuesName];
cookie.Name = CookieClosedIssuesName;
cookie.Domain = ".domain.com";
cookie.Value = "False";
Response.Cookies.Set(cookie);
}
// if we're turning this on
else
{
HttpCookie cookie;
if (Request.Cookies[CookieClosedIssuesName] != null)
{
cookie = Request.Cookies[CookieClosedIssuesName];
cookie.Name = CookieClosedIssuesName;
cookie.Domain = ".domain.com";
cookie.Expires = DateTime.MaxValue;
cookie.Value = "True";
Response.Cookies.Set(cookie);
}
else
{
cookie = new HttpCookie(CookieClosedIssuesName);
cookie.Name = CookieClosedIssuesName;
cookie.Domain = ".domain.com";
cookie.Expires = DateTime.MaxValue;
cookie.Value = "True";
Response.Cookies.Set(cookie);
}
}
Response.Redirect(CMSContext.CurrentDocument.AbsoluteURL);
}
protected void ButtonCompletedProjectsClicked(Object sender, EventArgs e)
{
// if we're turning this off
if (_showCompletedProjects)
{
HttpCookie cookie = Request.Cookies[CookieCompletedProjectsName];
cookie.Name = CookieCompletedProjectsName;
cookie.Domain = ".domain.com";
cookie.Value = "False";
Response.Cookies.Set(cookie);
// change style of button
ButtonCompletedProjects.CssClass.Replace("active","inactive");
}
// if we're turning this on
else
{
HttpCookie cookie;
if (Request.Cookies[CookieCompletedProjectsName] != null)
{
cookie = Request.Cookies[CookieCompletedProjectsName];
cookie.Name = CookieCompletedProjectsName;
cookie.Domain = ".domain.com";
cookie.Expires = DateTime.MaxValue;
cookie.Value = "True";
Response.Cookies.Set(cookie);
ButtonCompletedProjects.CssClass.Replace("inactive", "active");
}
else
{
cookie = new HttpCookie(CookieCompletedProjectsName);
cookie.Name = CookieCompletedProjectsName;
cookie.Domain = ".domain.com";
cookie.Expires = DateTime.MaxValue;
cookie.Value = "True";
Response.Cookies.Set(cookie);
}
}
Response.Redirect(CMSContext.CurrentDocument.AbsoluteURL);
}
}
问题是 button.js 插件在具有 data-toggle="buttons"
数据属性的元素上调用 preventDefault()
,并且 <asp:LinkButton>
服务器控件放置了它的 '_doPostBack' 函数在它呈现的锚标记的 href=""
属性中调用。因此 button.js 插件阻止回传发生。
我只是 copy/pasted 来自 bootstrap 文档的标记,所以我碰巧在我的 <div class="btn-group">
:
上有那个属性
<div class="btn-group" data-toggle="buttons">
<asp:LinkButton runat="server" ID="ButtonCompletedProjects" CssClass="btn btn-default btn-xs" OnClick="ButtonCompletedProjectsClicked">Show Completed Projects</asp:LinkButton>
<asp:LinkButton runat="server" ID="ButtonClosedIssues" CssClass="btn btn-default btn-xs" OnClick="ButtonClosedIssuesClicked">Show Closed Issues</asp:LinkButton>
</div>
服务器控件呈现以下标记:
<div class="btn-group" data-toggle="buttons">
<a id="p_lt_ctl01_pageplaceholder_p_lt_ctl02_IssuesSettings_userControlElem_ButtonCompletedProjects" class="btn btn-default btn-xs" href="javascript:__doPostBack('p$lt$ctl01$pageplaceholder$p$lt$ctl02$IssuesSettings$userControlElem$ButtonCompletedProjects','')">Show Completed Projects</a>
<a id="p_lt_ctl01_pageplaceholder_p_lt_ctl02_IssuesSettings_userControlElem_ButtonClosedIssues" class="btn btn-default btn-xs" href="javascript:__doPostBack('p$lt$ctl01$pageplaceholder$p$lt$ctl02$IssuesSettings$userControlElem$ButtonClosedIssues','')">Show Closed Issues</a>
</div>
注意 _doPostBack
如何在两个锚元素的 href
属性中。现在,检查 button.js 插件,您将看到以下几行:
// BUTTON DATA-API
// ===============
$(document)
.on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
var $btn = $(e.target)
if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
Plugin.call($btn, 'toggle')
if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault() // here's the issue
})
.on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
$(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
})
在第 9 行(从 //BUTTON DATA-API 开始)您会看到 e.preventDefault()
在 if 语句的末尾被调用。这将阻止锚标记执行其默认行为,即调用 _doPostBack 函数。
如果您遇到此问题并且不需要按钮插件,只需从您的脚本中删除该插件即可。如果您确实需要按钮插件并且遇到了这个问题,您需要编写一些逻辑来处理这个问题。我修改了第 9 行的 if 语句,首先检查“.btn-asp”class,如果是这种情况则继续执行默认行为,否则继续执行按钮插件的逻辑:
if(!($e.target).hasClass(".btn-asp")){
if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault() // here's the issue
}
似乎将 bootstrap.js 注册到我的页面会阻止我的所有服务器控件,例如asp:LinkButtons
和 asp:Buttons
,来自触发回发。
我的母版页中有以下 C# 脚本。如果用户不在 Kentico 的设计模式下,它只会注册 jQuery 1.11.1 和 Bootstrap.js。否则它只会加载 jQuery 1.7.1.
如果我不包括 bootstrap.js,我的 asp:LinkButtons
和 asp:Buttons
的回发将正常进行。否则,根本就没有任何动作发生。知道会发生什么吗?
我在浏览器中没有看到任何控制台错误,而且我绝对确定包含 Bootstrap.js 是造成这种行为的部分原因,如果不是全部的话。一切正常,只要找到它是否不包括在内(当然,除了 bootstrap jQuery 模块)。
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
// Check for null document
if(CMSContext.CurrentDocument != null)
{
if(CMS.PortalEngine.PortalContext.ViewMode.ToString() == "Design")
{
CMS.GlobalHelper.ScriptHelper.RegisterJQuery(this.Page);
}
else
{
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),"jquery","<script src=\"//code.jquery.com/jquery-1.11.2.min.js\"><" + "/script>",false);
Page.ClientScript.RegisterClientScriptBlock(this.GetType(),"bootstrap","<script src=\"/getmedia/453e9ad5-e05c-4fb2-b134-4d9cbd00c917/bootstrap-min.aspx\"><" + "/script>",false);
}
}
}
</script>
That bootstrap.min.js file is just the default bootstrap.min.js file for v3.3.2
前面的代码
<%@ Control Language="C#" AutoEventWireup="true" CodeFile="IssuesSettings.ascx.cs" Inherits="CustomCode_Dashboard_Issues_Issues" %>
<div class="col-xs-12">
<div class="gap"></div>
<div class="btn-group" data-toggle="buttons">
<asp:LinkButton runat="server" ID="ButtonCompletedProjects" CssClass="btn btn-default btn-xs" OnClick="ButtonCompletedProjectsClicked">Show Completed Projects</asp:LinkButton>
<asp:LinkButton runat="server" ID="ButtonClosedIssues" CssClass="btn btn-default btn-xs" OnClick="ButtonClosedIssuesClicked">Show Closed Issues</asp:LinkButton>
</div>
</div>
代码隐藏
public partial class CustomCode_Dashboard_Issues_Issues : System.Web.UI.UserControl
{
// cookie name constants
private const string CookieClosedIssuesName = "Dashboard-Issues-ShowClosedIssues";
private const string CookieCompletedProjectsName = "Dashboard-Issues-ShowCompletedProjects";
// boolean switches
private bool _showClosedIssues;
private bool _showCompletedProjects;
protected void Page_Load(object sender, EventArgs e)
{
SetShowClosedIssues();
SetShowCompletedProjects();
SetButtonStyles();
}
private void SetButtonStyles()
{
if (_showClosedIssues)
{
ButtonClosedIssues.CssClass += " active";
}
else
{
ButtonClosedIssues.CssClass += " inactive";
}
if (_showCompletedProjects)
{
ButtonCompletedProjects.CssClass += " active";
}
else
{
ButtonCompletedProjects.CssClass += " inactive";
}
}
private void SetShowCompletedProjects()
{
if (Request.Cookies[CookieCompletedProjectsName] != null)
{
_showCompletedProjects = Convert.ToBoolean(Request.Cookies[CookieCompletedProjectsName].Value);
}
else
{
_showCompletedProjects = false;
}
}
private void SetShowClosedIssues()
{
if (Request.Cookies[CookieClosedIssuesName] != null)
{
_showClosedIssues = Convert.ToBoolean(Request.Cookies[CookieClosedIssuesName].Value);
}
else
{
_showClosedIssues = false;
}
}
protected void CLICKER(object sender, EventArgs e)
{
Response.Write("stuff");
}
protected void ButtonClosedIssuesClicked(Object sender, EventArgs e)
{
Response.Write("TEST");
// if we're turning this off
if (_showClosedIssues)
{
HttpCookie cookie = Request.Cookies[CookieClosedIssuesName];
cookie.Name = CookieClosedIssuesName;
cookie.Domain = ".domain.com";
cookie.Value = "False";
Response.Cookies.Set(cookie);
}
// if we're turning this on
else
{
HttpCookie cookie;
if (Request.Cookies[CookieClosedIssuesName] != null)
{
cookie = Request.Cookies[CookieClosedIssuesName];
cookie.Name = CookieClosedIssuesName;
cookie.Domain = ".domain.com";
cookie.Expires = DateTime.MaxValue;
cookie.Value = "True";
Response.Cookies.Set(cookie);
}
else
{
cookie = new HttpCookie(CookieClosedIssuesName);
cookie.Name = CookieClosedIssuesName;
cookie.Domain = ".domain.com";
cookie.Expires = DateTime.MaxValue;
cookie.Value = "True";
Response.Cookies.Set(cookie);
}
}
Response.Redirect(CMSContext.CurrentDocument.AbsoluteURL);
}
protected void ButtonCompletedProjectsClicked(Object sender, EventArgs e)
{
// if we're turning this off
if (_showCompletedProjects)
{
HttpCookie cookie = Request.Cookies[CookieCompletedProjectsName];
cookie.Name = CookieCompletedProjectsName;
cookie.Domain = ".domain.com";
cookie.Value = "False";
Response.Cookies.Set(cookie);
// change style of button
ButtonCompletedProjects.CssClass.Replace("active","inactive");
}
// if we're turning this on
else
{
HttpCookie cookie;
if (Request.Cookies[CookieCompletedProjectsName] != null)
{
cookie = Request.Cookies[CookieCompletedProjectsName];
cookie.Name = CookieCompletedProjectsName;
cookie.Domain = ".domain.com";
cookie.Expires = DateTime.MaxValue;
cookie.Value = "True";
Response.Cookies.Set(cookie);
ButtonCompletedProjects.CssClass.Replace("inactive", "active");
}
else
{
cookie = new HttpCookie(CookieCompletedProjectsName);
cookie.Name = CookieCompletedProjectsName;
cookie.Domain = ".domain.com";
cookie.Expires = DateTime.MaxValue;
cookie.Value = "True";
Response.Cookies.Set(cookie);
}
}
Response.Redirect(CMSContext.CurrentDocument.AbsoluteURL);
}
}
问题是 button.js 插件在具有 data-toggle="buttons"
数据属性的元素上调用 preventDefault()
,并且 <asp:LinkButton>
服务器控件放置了它的 '_doPostBack' 函数在它呈现的锚标记的 href=""
属性中调用。因此 button.js 插件阻止回传发生。
我只是 copy/pasted 来自 bootstrap 文档的标记,所以我碰巧在我的 <div class="btn-group">
:
<div class="btn-group" data-toggle="buttons">
<asp:LinkButton runat="server" ID="ButtonCompletedProjects" CssClass="btn btn-default btn-xs" OnClick="ButtonCompletedProjectsClicked">Show Completed Projects</asp:LinkButton>
<asp:LinkButton runat="server" ID="ButtonClosedIssues" CssClass="btn btn-default btn-xs" OnClick="ButtonClosedIssuesClicked">Show Closed Issues</asp:LinkButton>
</div>
服务器控件呈现以下标记:
<div class="btn-group" data-toggle="buttons">
<a id="p_lt_ctl01_pageplaceholder_p_lt_ctl02_IssuesSettings_userControlElem_ButtonCompletedProjects" class="btn btn-default btn-xs" href="javascript:__doPostBack('p$lt$ctl01$pageplaceholder$p$lt$ctl02$IssuesSettings$userControlElem$ButtonCompletedProjects','')">Show Completed Projects</a>
<a id="p_lt_ctl01_pageplaceholder_p_lt_ctl02_IssuesSettings_userControlElem_ButtonClosedIssues" class="btn btn-default btn-xs" href="javascript:__doPostBack('p$lt$ctl01$pageplaceholder$p$lt$ctl02$IssuesSettings$userControlElem$ButtonClosedIssues','')">Show Closed Issues</a>
</div>
注意 _doPostBack
如何在两个锚元素的 href
属性中。现在,检查 button.js 插件,您将看到以下几行:
// BUTTON DATA-API
// ===============
$(document)
.on('click.bs.button.data-api', '[data-toggle^="button"]', function (e) {
var $btn = $(e.target)
if (!$btn.hasClass('btn')) $btn = $btn.closest('.btn')
Plugin.call($btn, 'toggle')
if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault() // here's the issue
})
.on('focus.bs.button.data-api blur.bs.button.data-api', '[data-toggle^="button"]', function (e) {
$(e.target).closest('.btn').toggleClass('focus', /^focus(in)?$/.test(e.type))
})
在第 9 行(从 //BUTTON DATA-API 开始)您会看到 e.preventDefault()
在 if 语句的末尾被调用。这将阻止锚标记执行其默认行为,即调用 _doPostBack 函数。
如果您遇到此问题并且不需要按钮插件,只需从您的脚本中删除该插件即可。如果您确实需要按钮插件并且遇到了这个问题,您需要编写一些逻辑来处理这个问题。我修改了第 9 行的 if 语句,首先检查“.btn-asp”class,如果是这种情况则继续执行默认行为,否则继续执行按钮插件的逻辑:
if(!($e.target).hasClass(".btn-asp")){
if (!($(e.target).is('input[type="radio"]') || $(e.target).is('input[type="checkbox"]'))) e.preventDefault() // here's the issue
}