views:

478

answers:

3

Hi,

I am having major issues using UpdatePanels on a website. The problem is that when i use a ScriptManager, all client side JavaScript that was active when the page was originally loaded is lost once an update panel posts back.

Here's what i'm trying to do...

I have a number of .net calender controls on the same page each within its own update panel. The calendars are initially hidden, until you click within an associated text box (also within the update panel), at that point the calender pops up so you can select a date. They calendars work great untill you actually change the date (post back), after which the calenders no longer pop up when you click within the text boxes, the "onfocus" JavaScript is lost.

After looking on google for what seems like hours, I can get things semi-working by dynamically adding an "onfocus" attribute to the TextBox and registering start up script with the ScriptManager when the calendar posts back.

Example:

TextBox1.Attributes.Add("onfocus", "document.getElementById('searchArrivalDateCalendarDiv').style.display = 'block';")
ScriptManager.RegisterStartupScript(Page, GetType(Page), "StopTxtClick", "$(document).ready(function(){$('.txtArrivalDate').click(function(event){event.stopPropagation(); $('div.searchArrivalDateCalendarDiv').show(); });});", True)

This seems really impractical, especially when I introduce a master page. I'm going to end up having to re-register a hell of a lot of start up script.

There must be an easier way?

A: 

It looks like you want to use event delegation. The main idea is that events bubble up and so you would attach your event handler outside of the update panel (perhaps to a div or table that the updatepanel resides in). This handler is in charge of all events it receives so even when your update panel posts back and a new textbox is rendered, you won't need to reattach the event handler. When the new textbox raises its event your existing event handler can try to handle it.

The following is just one way of doing event delegation in javascript (using jquery and taken from http://www.danwebb.net/2008/2/8/event-delegation-made-easy-in-jquery)

jQuery.delegate = function() {
            return function(e) {
                var target = $(e.target);
                if (target.attr("showCalendar")) {
                    var calendar = $("#" + target.attr("showCalendar"));
                    calendar.css("display", "block");
                }
            }
        }

        $(document).ready(function() 
        {
            $('#test').click($.delegate());
        });

<form id="form1" runat="server">
        <asp:ScriptManager runat="server" EnablePartialRendering="true"/>
        <div id="test" style="width:100%;">
            <asp:UpdatePanel runat="server">
                <ContentTemplate>
                    <input type="text" id="testText" showCalendar="testCalendarDiv" />
                    <div id="testCalendarDiv" style="display:none;">
                        <asp:Calendar runat="server" ID="testCalendar1"/>
                    </div>
               </ContentTemplate>
           </asp:UpdatePanel>
        </div>
    </form>

In this simple example I register the delegate method on click of this div (the textbox and calendar are inside of this div). When you click the textbox the click event bubbles up to the div. The delegate method gets called and I check for the showCalendar attribute from the element who raised the event. If this attribute exists I find the element this attribute points to and update its display style. This is a pretty simple example but you could easily extend the delegate method to take in functions it will call based on some kind of rules you register.

Matt Dearing
A: 

The problem is that an UpdatePanel refresh completely wipes out the DOM within its div element(s). The easiest way to fix that is to use the live() functionality where possible, e.g.:

$(document).ready(function () {
  $('.txtArrivalDate').live('click', function (event) {
    event.stopPropagation();

    $('div.searchArrivalDateCalendarDiv').show();
  });
});
Dave Ward
A: 

Thanks for the answers.

I still did not manage to solve this problem. However, i have found an alternate solution for the calendar pop up.

I am now using the CalendarExtender control which is part of the ASP.Net AJAX Control Toolkit. It is a much better solution for what I need. The calendar as a whole is much smoother and neater and I no longer need to use the update panel. It also supports multiple cultures without any extra coding which is great.

Cheers.

DazzledKid