Common_PostbackManager_VBNet\PostbackManager_VBNet\JavaScript\PostbackManager.js
Copyright 2011 ESRI All rights reserved under the copyright laws of the United States and applicable international laws, treaties, and conventions. You may freely redistribute and use this sample code, with or without modification, provided you include the original copyright notice and use restrictions. See <a href="http://resourcesbeta.arcgis.com/en/help/arcobjects-net/usagerestrictions.htm">the use restrictions</a>. // Register the namespace for the control. Type.registerNamespace('ESRI.ADF.Samples'); // === PostbackManager ASP.NET AJAX Client Control === ESRI.ADF.Samples._PostbackManager = function(element) { /// <summary>The PostbackManager control allows developers to intercept requests made by Web ADF /// controls and provides a convenient method of asynchronously passing data to and from the server. /// </summary> ESRI.ADF.Samples._PostbackManager.initializeBase(this, [element]); // Unique ID of the web tier PostbackManager this._uniqueID = null; // Syntax for invoking an asynchronous request to the web tier PostbackManager this._callbackFunctionString = null; // Web ADF function for invoking a partial postback this._esriPostbackOriginal = null; // Web ADF function for invoking a callback this._esriCallbackOriginal - null; // Tracks whether callbacks or partial postbacks are being used for asynchronous functionality this._callbackMode = false; // Whether events will be exposed that allow attaching to asynchronous requests made by Web ADF // controls. If true, all asynchronous requests are routed through the PostbackManager server // control. this._exposeAdfRequestEvents = true; }; ESRI.ADF.Samples._PostbackManager.prototype = { // === Public Functions === initialize: function() { /// <summary>Initializes the PostbackManager control. Fires when the control is instantiated via $create.</summary> ESRI.ADF.Samples._PostbackManager.callBaseMethod(this, 'initialize'); // No more initialization needs to be done if ADF requests won't be exposed via events if (!this._exposeAdfRequestEvents) return; // Store the Web ADF's partial postback invocation function in a private property and override it // with the control's _doPostback method. this._esriPostBackOriginal = ESRI.ADF.System.__DoPostBack; __esriDoPostBack = ESRI.ADF.System.__DoPostBack = Function.createDelegate(this, this._doPostback); // Store the Web ADF's callback invocation function in a private property and override it with the // control's _doPostback method. this._esriCallbackOriginal = ESRI.ADF.System._doCallback; ESRI.ADF.System._doCallback = Function.createDelegate(this, this._doCallback); // If the callback framework is being used (i.e. no ScriptManager on the page), call method to // modify Web ADF client controls such that their callback invocations all go through // PostbackManager's _doCallback function. Also, set the private member indicating that // callbacks are being used if (!Sys.WebForms || !Sys.WebForms.PageRequestManager) { this._redirectAdfCallbackInvocations(); this._callbackMode = true; } }, dispose: function() { /// <summary>Disposes the PostbackManager instance.</summary> ESRI.ADF.Samples._PostbackManager.callBaseMethod(this, 'dispose'); }, doAsyncRequest: function(argument, context) { /// <summary>Issues an asynchronous callback or partial postback to the server</summary> /// <param name="argument" type="String">The argument passed back to the server control</param> /// <param name="context" type="String">The context of the request</param> argument += String.format("&ControlID={0}", this.get_id()); ESRI.ADF.System._doCallback(this._callbackFunctionString, this.get_uniqueID(), this.get_id(), argument, context); }, // === Public Properties === get_uniqueID: function() { /// <value type="String">Unique ID of the PostbackManager server control instance that is // associated with the client control instance</value> return this._uniqueID; }, set_uniqueID: function(value) { this._uniqueID = value; }, get_callbackFunctionString: function() { /// <value type="String">Syntax for invoking an asynchronous request to the PostbackManager // server control</value> return this._callbackFunctionString; }, set_callbackFunctionString: function(value) { this._callbackFunctionString = value; }, get_exposeAdfRequestEvents: function() { /// <value type="Boolean">Determines whether or not to expose events that fire whenever an /// asynchronous request is initiated by a Web ADF control</value> return this._exposeAdfRequestEvents; }, set_exposeAdfRequestEvents: function(value) { this._exposeAdfRequestEvents = value; }, // === Events === add_invokingRequest: function(handler) { /// <summary>Raised when a Web ADF component invokes an asynchronous server request</summary> this.get_events().addHandler('invokingRequest', handler); }, remove_invokingRequest: function(handler) { this.get_events().removeHandler('invokingRequest', handler); }, add_requestProcessed: function(handler) { /// <summary>Raised when a reponse is returned to the client after a Web ADF component has /// issued an asynchronous server request</summary> this.get_events().addHandler('requestProcessed', handler); }, remove_requestProcessed: function(handler) { this.get_events().removeHandler('requestProcessed', handler); }, // === Private Functions === // Fires handlers attached to the event of the passed in name _raiseEvent: function(name, e) { // Get the handler for the event. Note that the ASP.NET AJAX framework combines multiple // handlers into one function var handler = this.get_events().getHandler(name); // Make sure a handler exists if (handler) { // Create an empty arguments object if no event arguments were passed-in if (e === null || typeof (e) === 'undefined') { e = Sys.EventArgs.Empty; } // Fire the handler handler(this, e); } }, // Issues a partial postback to the PostbackManager server control instance. Note that, when // partial postbacks are being used, some controls issue requests via _doCallback before executing // _doPostback. _doPostback: function(uniqueID, clientID, argument, clientCallback, context) { // Check whether callbacks or partial postbacks are being used for asynchronous functionality if (!this._callbackMode) { // Package arguments and raise the invokingRequest event var args = { 'requestArgument': argument, 'callingControlID': clientID }; this._raiseEvent('invokingRequest', args); // Update the argument to be passed to the server with that passed to the invokingRequest // argument. Necessary in case the argument was modified in invokingRequest handlers. argument = args.requestArgument; // Add the ID of the control initiating the request to the argument string if (argument.indexOf('ControlID=') == -1) argument += String.format('&ControlID={0}', clientID); // Replace the passed-in control IDs with the PostbackManager's IDs to reroute the program // flow through the PostbackManager when the request reaches the server. clientID = this.get_id(); uniqueID = this.get_uniqueID(); } // Invoke the Web ADF's postback function to issue the request this._esriPostBackOriginal(uniqueID, clientID, argument, clientCallback, context); }, // Issues a callback to the PostbackManager server control instance _doCallback: function(callbackFunctionString, uniqueID, clientID, argument, context) { // If a control ID was not specified, try to extract it from callbackFunctionString if (!clientID) { var startIndex = callbackFunctionString.indexOf("'") + 1; var stopIndex = callbackFunctionString.indexOf("'", startIndex + 1); clientID = callbackFunctionString.substring(startIndex, stopIndex); clientID = clientID.replace(/\$/g, '_'); if (!$get(clientID)) clientID = null; } // Package arguments and raise the invokingRequest event var args = { 'requestArgument': argument, 'callingControlID': clientID }; // Update the argument to be passed to the server with that passed to the invokingRequest // argument. Necessary in case the argument was modified in invokingRequest handlers. this._raiseEvent('invokingRequest', args); argument = args.requestArgument; // Check whether a control ID was found. If not, do not redirect the request. if (clientID) { // Add the ID of the control initiating the request to the argument string if (argument.indexOf('ControlID=') == -1) argument += String.format('&ControlID={0}', clientID); // Replace the passed-in control IDs and callback invocation with those of the // PostbackManager to reroute the program flow through the PostbackManager when the // request reaches the server. callbackFunctionString = this.get_callbackFunctionString(); clientID = this.get_id(); uniqueID = this.get_uniqueID(); } // Invoke the Web ADF's postback function to issue the request this._esriCallbackOriginal(callbackFunctionString, uniqueID, clientID, argument, context); }, // Modifies the definitions of Web ADF client controls so they call PostbackManager._doCallback // when making asynchronous requests _redirectAdfCallbackInvocations: function() { var originalInvocation = 'eval(this._callbackFunctionString)'; var newInvocation = 'ESRI.ADF.System._doCallback(this._callbackFunctionString, ' + 'this.get_uniqueID(), this.get_element().id, argument, context)'; if (ESRI.ADF.UI.TreeViewPlus) { ESRI.ADF.UI.TreeViewPlus.prototype._nodeChecked = this._modifyFunction(ESRI.ADF.UI.TreeViewPlus.prototype._nodeChecked, originalInvocation, newInvocation); ESRI.ADF.UI.TreeViewPlus.prototype._nodeClicked = this._modifyFunction(ESRI.ADF.UI.TreeViewPlus.prototype._nodeClicked, originalInvocation, newInvocation); ESRI.ADF.UI.TreeViewPlus.prototype._clearNode = this._modifyFunction(ESRI.ADF.UI.TreeViewPlus.prototype._clearNode, originalInvocation, newInvocation); ESRI.ADF.UI.TreeViewPlus.prototype._nextPage = this._modifyFunction(ESRI.ADF.UI.TreeViewPlus.prototype._nextPage, originalInvocation, newInvocation); ESRI.ADF.UI.TreeViewPlus.prototype._previousPage = this._modifyFunction(ESRI.ADF.UI.TreeViewPlus.prototype._previousPage, originalInvocation, newInvocation); ESRI.ADF.UI.TreeViewPlus.prototype._clearAllNodes = this._modifyFunction(ESRI.ADF.UI.TreeViewPlus.prototype._clearAllNodes, originalInvocation, newInvocation); ESRI.ADF.UI.TreeViewPlus.prototype._nodeLegendClicked = this._modifyFunction(ESRI.ADF.UI.TreeViewPlus.prototype._nodeLegendClicked, originalInvocation, newInvocation); ESRI.ADF.UI.TreeViewPlus.prototype._toggleNodeState = this._modifyFunction(ESRI.ADF.UI.TreeViewPlus.prototype._toggleNodeState, originalInvocation, newInvocation); } if (ESRI.ADF.UI.TaskResults) { ESRI.ADF.UI.TaskResults.prototype._rerunTask2 = this._modifyFunction(ESRI.ADF.UI.TaskResults.prototype._rerunTask2, originalInvocation, newInvocation); } if (ESRI.ADF.UI.FloatingPanel) { ESRI.ADF.UI.FloatingPanel.prototype.hide = this._modifyFunction(ESRI.ADF.UI.FloatingPanel.prototype.hide, originalInvocation, newInvocation); ESRI.ADF.UI.FloatingPanel.prototype.show = this._modifyFunction(ESRI.ADF.UI.FloatingPanel.prototype.show, originalInvocation, newInvocation); ESRI.ADF.UI.FloatingPanel.prototype.toggleState = this._modifyFunction(ESRI.ADF.UI.FloatingPanel.prototype.toggleState, originalInvocation, newInvocation); } if (ESRI.ADF._Tasks) { originalInvocation = 'eval(callbackFunctionString)'; newInvocation = "ESRI.ADF.System._doCallback(callbackFunctionString, " + "null, null, argument, context)"; startActivityIndicator = ESRI.ADF._Tasks.prototype.startActivityIndicator = this._modifyFunction(ESRI.ADF._Tasks.prototype.startActivityIndicator, originalInvocation, newInvocation); startJob = ESRI.ADF._Tasks.prototype.startJob = this._modifyFunction(ESRI.ADF._Tasks.prototype.startJob, originalInvocation, newInvocation); } if (typeof(esriHideContextMenu) != 'undefined' && typeof(esriContextMenuItemClicked) != 'undefined') { originalInvocation = 'eval(esriContextMenu.callbackFunctionString)'; newInvocation = "ESRI.ADF.System._doCallback(esriContextMenu.callbackFunctionString, " + "null, null, argument, context)"; esriHideContextMenu = this._modifyFunction(esriHideContextMenu, originalInvocation, newInvocation); esriContextMenuItemClicked = this._modifyFunction(esriContextMenuItemClicked, originalInvocation, newInvocation); } }, // Replaces the specified code in the passed-in function with the passed-in new code and returns the // updated function _modifyFunction: function(originalFunction, codeToReplace, newCode) { // Get a string representation of the passed-in function var oldFunction = String(originalFunction); // Change the code as specified var newFunction = oldFunction.replace(codeToReplace, newCode); // Get the indexes of parentheses for parameter name retrieval var startIndex = newFunction.indexOf('(') + 1; var stopIndex = newFunction.indexOf(')'); // Retrieve the function's parameter names var parameters = []; if (stopIndex > startIndex) { var parameterString = newFunction.substring(startIndex, stopIndex); var parameters = parameterString.split(','); } // Extract the body of the function var newFunctionBody = newFunction.substring(newFunction.indexOf('{') + 1, newFunction.lastIndexOf('}')); // Return a new function instance with the extracted parameters and function body return new Function(parameters, newFunctionBody); } } // Register the PostbackManager, specifying inheritance from the ASP.NET AJAX client control base class ESRI.ADF.Samples._PostbackManager.registerClass('ESRI.ADF.Samples._PostbackManager', Sys.UI.Control);