Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When jGrowl is called, the thickbox stops working properly (using UpdatePanel)

I am calling a thickbox when a link is clicked:

<a href="createContact.aspx?placeValuesBeforeTB_=savedValues&TB_iframe=true&height=400&width=550&modal=true"
                            title="Add a new Contact" class="thickbox">Add a new Contact</a>

And, when a server button is clicked I call this javascript function to show a jGrowl notification:

ScriptManager.RegisterClientScriptBlock(this, typeof(Page), Guid.NewGuid().ToString(), "$(function(){$.jGrowl('No Contact found: " + searchContactText.Text + "');});", true);

Both works as expected except when the jGrowl is shown first than the thickbox. This will cause the thickbox not to work and the page will be shown as a normal web (as if the thickbox had been gone).

Does anyone know what is happening?

UPDATE: This is the a test page without Master Page:

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm2.aspx.cs" Inherits="RoutingPortal.Presentation.WebForm2" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script src="../Scripts/jquery-1.6.2.js" type="text/javascript"></script>
<script src="../Scripts/jquery-ui-1.8.16.custom.min.js" type="text/javascript"></script>
<script src="../Scripts/thickbox.js" type="text/javascript"></script>
<script src="../Scripts/jquery.jgrowl.js" type="text/javascript"></script>
<link href="../Scripts/css/jquery.jgrowl.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="~/CSS/thickbox.css" type="text/css" media="screen" />
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<div>
    <a href="createContact.aspx?placeValuesBeforeTB_=savedValues&TB_iframe=true&height=400&width=550&modal=true"
            title="Add a new Contact" class="thickbox">Add a new Contact</a>
        <asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</div>
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>

This is the codebehind:

namespace RoutingPortal.Presentation
{
public partial class WebForm2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {

    }

    protected void Button1_Click(object sender, EventArgs e)
    {
        ScriptManager.RegisterClientScriptBlock(this.Page, typeof(Page), Guid.NewGuid().ToString(),
                "$(function(){$.jGrowl('My Message');});", true);
    }
}
}

I have just tested it without the UpdatePanel and it worked perfectly. So, it is definitely a problem with the UpdatePanel or the way that it is interacting with the jGrowl called from the codebehind.

I would massively appreciate your help guys.

UPDATE: I have even created a demo project where this problem can be easily identified. Wouldn't mind to send it to anyone willing to help me out with this. Thanks in advance guys!

UPDATE: I have also tried the solution given by @Rick, changing the way the jGrowl script is executed from codebehind:

ScriptManager.RegisterStartupScript(this.Page, typeof(Page), Guid.NewGuid().ToString(),
        "$.jGrowl('My Message');", true);

However, the problem persist since the outcome is exactly the same. Any other ideas? I'd massively appreciate your help.

UPDATE: I have also tried this in IE8 and Chrome, facing the same problem. So, this is nothing to do with the browser. Just in case.

like image 987
aleafonso Avatar asked Sep 09 '11 08:09

aleafonso


3 Answers

I believe your problem has nothing to do with jGrowl, and all to do with your use of an UpdatePanel.

When you use an UpdatePanel, it refreshes all the elements in the DOM that are contained in it. What this means is that the original <a> tag that was created in the page and that had its click event set to use thickbox no longer exists. After the UpdatePanel refreshes, you now have a NEW <a> tag that has the thickbox class, but has not been "initialized" (since thickbox sets the click handler during page load, which doesn't happen like normal during a partial postback). Hence, when you click on the link, it acts like a normal link.

There are several ways to fix this, depending on your situation.

Option 1: Based on your code pasted above, it does not look like anything actually changes related to the link during your postback handling. So maybe you could move your <div><a ...></a> </div> outside of the UpdatePanel, and leave only the button inside. This will keep your link as part of the page and it will still have its thickbox handler attached.

Option 2: If there's some reason you can't go with Option 1, then you can set some javascript to run during the load of your UpdatePanel to re-attach the click handler for your link. In the function that calls jGrowl, try adding tb_init('a.thickbox'); to your code.

Option 3: You could modify the thickbox.js file to use jQuery's live handler instead of the normal click handler. In the tb_init function, you would change it to be $(domChunk).live('click', function(){..}). I think this would work, though it's possible the update panel process might still foil it.

Hope this helps.

like image 146
patmortech Avatar answered Sep 30 '22 13:09

patmortech


I don't understand the architecture of your page completely, but as @patmortech notes the UpdatePanel causes the DOM elements to be replaced completely on each async postback. You need to rebind any affected elements.

$(document).ready is not good enough when you're dealing with updatepanels. It will only be called on the first page load (not after an UpdatePanel refresh). The solution is to hook into ASP.NET's ajax architecture for your config code.

Whatever code you are using to configure the ThickBox and jGrowl links, add here:

Sys.WebForms.PageRequestManager.getInstance().add_endRequest(function() {
    // page config code
});

This gets called at the end of the ASP.NET client lifecycle, so put your config code for anything within anUpdatePanel there. If you have multiple UpdatePanels, you can test which has been updated (google add_endRequest). However it's often easier just to use the client markup state to determine if you need to configure something or not, or just use config code that will not break things if run twice against the same markup.

Using jquery live is also an option, but it doesn't work for all situations.

like image 28
Jamie Treworgy Avatar answered Sep 30 '22 13:09

Jamie Treworgy


protected void Button1_Click(object sender, EventArgs e)
{
    ScriptManager.RegisterStartupScript(this.Page, typeof(Page), Guid.NewGuid().ToString(),
            "$.jGrowl('My Message');", true);
}
like image 38
rick schott Avatar answered Sep 30 '22 13:09

rick schott