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

3

6

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.

Refrigerator answered 9/9, 2011 at 8:52 Comment(2)
Just to be clear, are you saying the problem is that when you click your link after the jGrowl has been shown, it just acts like a normal link, and does not open the page in a thickbox?Lectureship
Yes, that's exactly what I meantRefrigerator
L
2

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.

Lectureship answered 26/9, 2011 at 14:40 Comment(2)
Your possible solutions have been incredibly helpful. After waiting for long time I have finally found answers to the problem. I tried your Option 1 and Option 3 and both solved my problem. Personally, I prefer the option 3 since there are cases where I may need to have the links within the UpdatePanel (this example was just a simplified case to clearly illustrate the problem). Therefore, I wonder in which cases the Option 3 would not work? When should I be more careful using this solution? Once again. Thanks a lot.Refrigerator
+1 for option 2. I think it is the best way to go after this problem.Burkholder
D
2

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.

Dispassion answered 26/9, 2011 at 14:53 Comment(1)
This is just javascript. It doesn't matter where it appears on your page. You could use RegisterStartupScript the same as you are doing already. You could put it in markup between <script type="text/javascript"></script> tags in your ascx/aspx file. You could put in in an external .js file which you include.Dispassion
C
1
protected void Button1_Click(object sender, EventArgs e)
{
    ScriptManager.RegisterStartupScript(this.Page, typeof(Page), Guid.NewGuid().ToString(),
            "$.jGrowl('My Message');", true);
}
Cirsoid answered 20/9, 2011 at 2:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.