Bootstrap JavaScript 中断 ASP.NET 回发

Bootstrap JavaScript breaks ASP.NET postback

似乎将 bootstrap.js 注册到我的页面会阻止我的所有服务器控件,例如asp:LinkButtonsasp:Buttons,来自触发回发。

我的母版页中有以下 C# 脚本。如果用户不在 Kentico 的设计模式下,它只会注册 jQuery 1.11.1 和 Bootstrap.js。否则它只会加载 jQuery 1.7.1.

如果我不包括 bootstrap.js,我的 asp:LinkButtonsasp: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
}