Click here to Skip to main content
15,884,473 members
Articles / Web Development / XHTML

ASP.NET - UpdatePanelProgressExtender

Rate me:
Please Sign up or sign in to vote.
4.69/5 (10 votes)
24 Aug 2009CPOL14 min read 65.6K   3.6K   66  
An ASP.NET extender control for displaying a template based progress message overlay on UpdatePanel controls while the UpdatePanel is updating. A good Web 2.0 way of letting the user know their long running request is being processed.
Type.registerNamespace('Vereyon.Web.UI');

Vereyon.Web.UI.UpdatePanelProgressMode = function() { }
Vereyon.Web.UI.UpdatePanelProgressMode.prototype = {
    Panel : 0,
    Page : 1
}
Vereyon.Web.UI.UpdatePanelProgressMode.registerEnum("Vereyon.Web.UI.UpdatePanelProgressMode", true);


Vereyon.Web.UI.UpdatePanelProgressBehavior = function(element) {

    Vereyon.Web.UI.UpdatePanelProgressBehavior.initializeBase(this, [element]);

    this._progressContent = null;
    this._onBeginRequestHandler = null;
    this._onEndRequestHandler = null;
    this._onUnblockHandler = null;
    this._bPanelKnown = false;
    this._mode = Vereyon.Web.UI.UpdatePanelProgressMode.Panel;
    this._elementContainer = null;
    this._elementParent = null;
}

Vereyon.Web.UI.UpdatePanelProgressBehavior.prototype = {

    initialize : function() {
        Vereyon.Web.UI.UpdatePanelProgressBehavior.callBaseMethod(this, 'initialize');
        
        // Create event handlers
        this._onBeginRequestHandler = Function.createDelegate(this, this._onBeginRequest);
        this._onEndRequestHandler = Function.createDelegate(this, this._onEndRequest);
        this._onUnblockHandler = Function.createDelegate(this, this._onUnblockElement);
        
        // Bind event handlers to the PageRequestManager events.
        Sys.WebForms.PageRequestManager.getInstance().add_beginRequest(this._onBeginRequestHandler);
        Sys.WebForms.PageRequestManager.getInstance().add_endRequest(this._onEndRequestHandler);
    },

    dispose : function() {
    
        // Unbind event handlers from the PageRequestManager events.
        Sys.WebForms.PageRequestManager.getInstance().remove_beginRequest(this._onBeginRequestHandler);
        Sys.WebForms.PageRequestManager.getInstance().remove_endRequest(this._onEndRequestHandler);

        Vereyon.Web.UI.UpdatePanelProgressBehavior.callBaseMethod(this, 'dispose');
    },
    
    _onBeginRequest : function(sender, args) {
    
        // HACK: Attempt to determine if this request originated from the update panel this blocker is bound to.
        // If not possible, just block the panel.
        if(sender._postBackSettings && sender._postBackSettings.panelID) {
			if(this._containsControl(this._element.id, sender._postBackSettings.panelID)) {
				this._bPanelKnown = true;
				this._block();
			}
		} else {
			this._bPanelKnown = false;
			this._block();
		}
    },
    
    _onEndRequest : function(sender, args) {
    
        // HACK: If in _onBeginRequest() the script succeeded in determining the exact id of the update panel, check
        // the id now again, if not, just unblock anyway.
        if(this._bPanelKnown) {
	        if(this._containsControl(this._element.id, sender._postBackSettings.panelID)) {
		        this._unblock();
	        }
        } else {
	        this._unblock();
        }
    },
    
    _block : function(blockParams) {
    
        // Construct jQuery blockUI parameters.
		var blockParams = { 
			message: this._progressContent
		};
    
        // Act according to the UpdatePanelProgressMode.
        switch(this._mode) {
            case Vereyon.Web.UI.UpdatePanelProgressMode.Panel:
    
            // Wrap the update panel to block in an extra div container in order to maintain IE compatability.
            // This is required because in IE (don't known why not in FireFox) all content of the update panel 
            // are lost when it updates, thus the jQuery blockUI extension is unable to restore the progress 
            // message for reuse.
            this._elementParent = this._element.parentNode;
            this._elementContainer = document.createElement("div");

            this._elementParent.insertBefore(this._elementContainer, this._element);
            this._elementParent.removeChild(this._element);
            this._elementContainer.appendChild(this._element);
            
            $(this._elementContainer).block(blockParams);
            break;
                
        case Vereyon.Web.UI.UpdatePanelProgressMode.Page:
		        $.blockUI(blockParams);
		        break;
		}
    },
    
    _unblock : function() {
    
        // Construct jQuery unblockUI parameters. The onUnblock handler is invoked after the jQuery BlockUI is fully finished
        // blocking the ui.
        var unblockParams = {
            onUnblock: this._onUnblockHandler 
        }
    
        // Act according to the UpdatePanelProgressMode.
        switch(this._mode) {
            case Vereyon.Web.UI.UpdatePanelProgressMode.Panel:
			    $(this._element).unblock(unblockParams);
		        break;
		    case Vereyon.Web.UI.UpdatePanelProgressMode.Page:
		        $.unblockUI();
		        break;
		}
    },
    
    _onUnblockElement : function() {
    
        // Act according to the UpdatePanelProgressMode.
        switch(this._mode) {
            case Vereyon.Web.UI.UpdatePanelProgressMode.Panel:
            
                // Revert the operation performed in _block().
                if(this._elementContainer) {
					this._elementContainer.removeChild(this._element);
					this._elementParent.insertBefore(this._element, this._elementContainer);
					this._elementParent.removeChild(this._elementContainer);
				}
        }
    },
    
    _containsControl : function(controlId, controlList) {
    
		var aControls, el, elId;
		
		// Check if the specified element id (control id in asp.net) is present in the passed list.
		// This is part of the hack for detecting which update panel is updating. For some unknown
		// reason, the control id's in the contro list use the $-character as a name spacer, while
		// the control id's are rendered with an underscore as name spacer. We thus need to convert
		// this using an expression...
		aControls = controlList.split("|");
		for(var i = 0; i < aControls.length; i++) {
			elId = aControls[i].replace(/\$/g, "_");
			if(elId == controlId)
				return true;
		}
		
		return false;
    },
    
    set_ProgressContentID : function(value) {
		this._progressContent = $get(value);
    },
    
    get_ProgressContentID : function() {
		return this._progressContent.id;
    },
    
    set_Mode : function(value) {
        this._mode = value;
    },
    
    get_Mode : function() {
        return this._mode;
    }
}

Vereyon.Web.UI.UpdatePanelProgressBehavior.registerClass('Vereyon.Web.UI.UpdatePanelProgressBehavior', AjaxControlToolkit.BehaviorBase);

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Netherlands Netherlands
Developer at AlertA contractbeheer.

Comments and Discussions