/Client/MicrosoftAjax/Extensions/Sys/WebForms/PageRequestManager.js

# · JavaScript · 1827 lines · 1234 code · 182 blank · 411 comment · 267 complexity · 99ccb4c68355dd5608b8853414a6f5cb MD5 · raw file

  1. $type = Sys.WebForms.PageRequestManager = function PageRequestManager() {
  2. this._form = null;
  3. this._activeDefaultButton = null;
  4. this._activeDefaultButtonClicked = false;
  5. this._updatePanelIDs = null;
  6. this._updatePanelClientIDs = null;
  7. this._updatePanelHasChildrenAsTriggers = null;
  8. this._asyncPostBackControlIDs = null;
  9. this._asyncPostBackControlClientIDs = null;
  10. this._postBackControlIDs = null;
  11. this._postBackControlClientIDs = null;
  12. this._scriptManagerID = null;
  13. this._pageLoadedHandler = null;
  14. this._additionalInput = null;
  15. this._onsubmit = null;
  16. this._onSubmitStatements = [];
  17. this._originalDoPostBack = null;
  18. this._originalDoPostBackWithOptions = null;
  19. this._originalFireDefaultButton = null;
  20. this._originalDoCallback = null;
  21. this._isCrossPost = false;
  22. this._postBackSettings = null;
  23. this._request = null;
  24. this._onFormSubmitHandler = null;
  25. this._onFormElementClickHandler = null;
  26. this._onWindowUnloadHandler = null;
  27. this._asyncPostBackTimeout = null;
  28. this._controlIDToFocus = null;
  29. this._scrollPosition = null;
  30. this._processingRequest = false;
  31. this._scriptDisposes = {};
  32. // DevDiv Bugs 161922, 138251:
  33. // List of hidden fields that should be removed if an async update does not
  34. // explictly define it.
  35. this._transientFields = ["__VIEWSTATEENCRYPTED", "__VIEWSTATEFIELDCOUNT"];
  36. }
  37. $type.prototype = {
  38. get_isInAsyncPostBack: function PageRequestManager$get_isInAsyncPostBack() {
  39. /// <value type="Boolean" locid="P:J#Sys.WebForms.PageRequestManager.isInAsyncPostBack"></value>
  40. //#if DEBUG
  41. if (arguments.length !== 0) throw Error.parameterCount();
  42. //#endif
  43. return this._request !== null;
  44. },
  45. // Events
  46. add_beginRequest: function PageRequestManager$add_beginRequest(handler) {
  47. /// <summary locid="E:J#Sys.WebForms.PageRequestManager.beginRequest">Adds a beginRequest event handler.</summary>
  48. //#if DEBUG
  49. var e = Function._validateParams(arguments, [{name: "handler", type: Function}]);
  50. if (e) throw e;
  51. //#endif
  52. Sys.Observer.addEventHandler(this, "beginRequest", handler);
  53. },
  54. remove_beginRequest: function PageRequestManager$remove_beginRequest(handler) {
  55. //#if DEBUG
  56. var e = Function._validateParams(arguments, [{name: "handler", type: Function}]);
  57. if (e) throw e;
  58. //#endif
  59. Sys.Observer.removeEventHandler(this, "beginRequest", handler);
  60. },
  61. add_endRequest: function PageRequestManager$add_endRequest(handler) {
  62. /// <summary locid="E:J#Sys.WebForms.PageRequestManager.endRequest">Adds a endRequest event handler.</summary>
  63. //#if DEBUG
  64. var e = Function._validateParams(arguments, [{name: "handler", type: Function}]);
  65. if (e) throw e;
  66. //#endif
  67. Sys.Observer.addEventHandler(this, "endRequest", handler);
  68. },
  69. remove_endRequest: function PageRequestManager$remove_endRequest(handler) {
  70. //#if DEBUG
  71. var e = Function._validateParams(arguments, [{name: "handler", type: Function}]);
  72. if (e) throw e;
  73. //#endif
  74. Sys.Observer.removeEventHandler(this, "endRequest", handler);
  75. },
  76. add_initializeRequest: function PageRequestManager$add_initializeRequest(handler) {
  77. /// <summary locid="E:J#Sys.WebForms.PageRequestManager.initializeRequest">Adds a initializeRequest event handler.</summary>
  78. //#if DEBUG
  79. var e = Function._validateParams(arguments, [{name: "handler", type: Function}]);
  80. if (e) throw e;
  81. //#endif
  82. Sys.Observer.addEventHandler(this, "initializeRequest", handler);
  83. },
  84. remove_initializeRequest: function PageRequestManager$remove_initializeRequest(handler) {
  85. //#if DEBUG
  86. var e = Function._validateParams(arguments, [{name: "handler", type: Function}]);
  87. if (e) throw e;
  88. //#endif
  89. Sys.Observer.removeEventHandler(this, "initializeRequest", handler);
  90. },
  91. add_pageLoaded: function PageRequestManager$add_pageLoaded(handler) {
  92. /// <summary locid="E:J#Sys.WebForms.PageRequestManager.pageLoaded">Adds a pageLoaded event handler.</summary>
  93. //#if DEBUG
  94. var e = Function._validateParams(arguments, [{name: "handler", type: Function}]);
  95. if (e) throw e;
  96. //#endif
  97. Sys.Observer.addEventHandler(this, "pageLoaded", handler);
  98. },
  99. remove_pageLoaded: function PageRequestManager$remove_pageLoaded(handler) {
  100. //#if DEBUG
  101. var e = Function._validateParams(arguments, [{name: "handler", type: Function}]);
  102. if (e) throw e;
  103. //#endif
  104. Sys.Observer.removeEventHandler(this, "pageLoaded", handler);
  105. },
  106. add_pageLoading: function PageRequestManager$add_pageLoading(handler) {
  107. /// <summary locid="E:J#Sys.WebForms.PageRequestManager.pageLoading">Adds a pageLoading event handler.</summary>
  108. //#if DEBUG
  109. var e = Function._validateParams(arguments, [{name: "handler", type: Function}]);
  110. if (e) throw e;
  111. //#endif
  112. Sys.Observer.addEventHandler(this, "pageLoading", handler);
  113. },
  114. remove_pageLoading: function PageRequestManager$remove_pageLoading(handler) {
  115. //#if DEBUG
  116. var e = Function._validateParams(arguments, [{name: "handler", type: Function}]);
  117. if (e) throw e;
  118. //#endif
  119. Sys.Observer.removeEventHandler(this, "pageLoading", handler);
  120. },
  121. abortPostBack: function PageRequestManager$abortPostBack() {
  122. if (!this._processingRequest && this._request) {
  123. // cancel the request if a response hasn't already been received
  124. this._request.get_executor().abort();
  125. this._request = null;
  126. }
  127. },
  128. beginAsyncPostBack: function PageRequestManager$beginAsyncPostBack(updatePanelsToUpdate, eventTarget, eventArgument, causesValidation, validationGroup) {
  129. /// <summary locid="M:J#Sys.WebForms.PageRequestManager.beginAsyncPostBack">Begins an asynchronous postback.</summary>
  130. /// <param name="updatePanelsToUpdate" type="Array" elementType="String" mayBeNull="true" optional="true">A list of UniqueIDs or ClientIDs of UpdatePanel controls that should have their rendering updated.</param>
  131. /// <param name="eventTarget" type="String" mayBeNull="true" optional="true"></param>
  132. /// <param name="eventArgument" type="String" mayBeNull="true" optional="true"></param>
  133. /// <param name="causesValidation" type="Boolean" mayBeNull="true" optional="true"></param>
  134. /// <param name="validationGroup" type="String" mayBeNull="true" optional="true"></param>
  135. //#if DEBUG
  136. var e = Function._validateParams(arguments, [
  137. {name: "updatePanelsToUpdate", type: Array, mayBeNull: true, optional: true, elementType: String},
  138. {name: "eventTarget", type: String, mayBeNull: true, optional: true},
  139. {name: "eventArgument", type: String, mayBeNull: true, optional: true},
  140. {name: "causesValidation", type: Boolean, mayBeNull: true, optional: true},
  141. {name: "validationGroup", type: String, mayBeNull: true, optional: true}
  142. ]);
  143. if (e) throw e;
  144. //#endif
  145. if (causesValidation && (typeof(Page_ClientValidate) === 'function') && !Page_ClientValidate(validationGroup || null)) {
  146. return;
  147. }
  148. this._postBackSettings = this._createPostBackSettings(true, updatePanelsToUpdate, eventTarget);
  149. var form = this._form;
  150. form.__EVENTTARGET.value = (eventTarget || "");
  151. form.__EVENTARGUMENT.value = (eventArgument || "");
  152. this._isCrossPost = false;
  153. this._additionalInput = null;
  154. this._onFormSubmit();
  155. },
  156. _cancelPendingCallbacks: function PageRequestManager$_cancelPendingCallbacks() {
  157. // DevDiv Bugs 125825: To avoid EVENTVALIDATION corruption we must cancel pending callbacks when an async postback begins
  158. // to cancel callbacks, we run logic similar to WebForm_CallbackComplete,
  159. // except we do not run WebForm_ExecuteCallback for them. This code is exactly
  160. // WebForm_CallbackComplete except without the call to WebForm_ExecuteCallback.
  161. // We are basically treating each callback as completed, ignoring the response if any.
  162. for (var i = 0, l = window.__pendingCallbacks.length; i < l; i++) {
  163. var callback = window.__pendingCallbacks[i];
  164. if (callback) {
  165. if (!callback.async) {
  166. // we just cancelled the single allowed instance of a synchronous callback
  167. window.__synchronousCallBackIndex = -1;
  168. }
  169. window.__pendingCallbacks[i] = null;
  170. var callbackFrameID = "__CALLBACKFRAME" + i;
  171. var xmlRequestFrame = document.getElementById(callbackFrameID);
  172. if (xmlRequestFrame) {
  173. xmlRequestFrame.parentNode.removeChild(xmlRequestFrame);
  174. }
  175. }
  176. }
  177. },
  178. _commitControls: function PageRequestManager$_commitControls(updatePanelData, asyncPostBackTimeout) {
  179. // DevDiv Bugs 154403:
  180. // commits context data parsed from a delta. This is called after an async response
  181. // has proceeded past the script include loading phase, which when it can no longer
  182. // be cancelled and the HTML DOM will be updated.
  183. // _processUpdatePanelArrays is the method that creates these arrays..
  184. // DevDiv Bugs 188564: Update may not have an async postback timeout node and/or updatepanel nodes.
  185. if (updatePanelData) {
  186. this._updatePanelIDs = updatePanelData.updatePanelIDs;
  187. this._updatePanelClientIDs = updatePanelData.updatePanelClientIDs;
  188. this._updatePanelHasChildrenAsTriggers = updatePanelData.updatePanelHasChildrenAsTriggers;
  189. this._asyncPostBackControlIDs = updatePanelData.asyncPostBackControlIDs;
  190. this._asyncPostBackControlClientIDs = updatePanelData.asyncPostBackControlClientIDs;
  191. this._postBackControlIDs = updatePanelData.postBackControlIDs;
  192. this._postBackControlClientIDs = updatePanelData.postBackControlClientIDs;
  193. }
  194. if (typeof(asyncPostBackTimeout) !== 'undefined' && asyncPostBackTimeout !== null) {
  195. this._asyncPostBackTimeout = asyncPostBackTimeout * 1000;
  196. }
  197. },
  198. _createHiddenField: function PageRequestManager$_createHiddenField(id, value) {
  199. // DevDiv Bugs 27075: Creates a hidden field via innerHTML to workaround a caching issue.
  200. var container, field = document.getElementById(id);
  201. if (field) {
  202. // the field already exists
  203. if (!field._isContained) {
  204. // but it is not contained within a SPAN container, so we must create one
  205. // in order to recreate it with innerHTML.
  206. field.parentNode.removeChild(field);
  207. }
  208. else {
  209. // and it already has a container, we'll just set the container innerHTML to replace it,
  210. // which is much faster than removing the element, recreating it, and then setting innerHTML
  211. container = field.parentNode;
  212. }
  213. }
  214. if (!container) {
  215. container = document.createElement('span');
  216. // set display none in case this SPAN would be styled
  217. container.style.cssText = "display:none !important";
  218. this._form.appendChild(container);
  219. }
  220. // now create/replace the input by setting innerHTML
  221. container.innerHTML = "<input type='hidden' />";
  222. field = container.childNodes[0];
  223. // flag it as contained, so if it needs to be removed we know to remove the container, too.
  224. field._isContained = true;
  225. field.id = field.name = id;
  226. field.value = value;
  227. },
  228. _createPageRequestManagerTimeoutError: function PageRequestManager$_createPageRequestManagerTimeoutError() {
  229. // Creates a PageRequestManagerTimeoutException representing a request that timed out.
  230. var displayMessage = "Sys.WebForms.PageRequestManagerTimeoutException: " + Sys.WebForms.Res.PRM_TimeoutError;
  231. var e = Error.create(displayMessage, {name: 'Sys.WebForms.PageRequestManagerTimeoutException'});
  232. e.popStackFrame();
  233. return e;
  234. },
  235. _createPageRequestManagerServerError: function PageRequestManager$_createPageRequestManagerServerError(httpStatusCode, message) {
  236. // Creates a PageRequestManagerServerErrorException representing an error that occurred on the server.
  237. var displayMessage = "Sys.WebForms.PageRequestManagerServerErrorException: " +
  238. (message || String.format(Sys.WebForms.Res.PRM_ServerError, httpStatusCode));
  239. var e = Error.create(displayMessage, {
  240. name: 'Sys.WebForms.PageRequestManagerServerErrorException',
  241. httpStatusCode: httpStatusCode
  242. });
  243. e.popStackFrame();
  244. return e;
  245. },
  246. _createPageRequestManagerParserError: function PageRequestManager$_createPageRequestManagerParserError(parserErrorMessage) {
  247. // Creates a PageRequestManagerParserErrorException representing a parser error that occurred while processing a response from the server.
  248. var displayMessage = "Sys.WebForms.PageRequestManagerParserErrorException: " + String.format(Sys.WebForms.Res.PRM_ParserError, parserErrorMessage);
  249. var e = Error.create(displayMessage, {name: 'Sys.WebForms.PageRequestManagerParserErrorException'});
  250. e.popStackFrame();
  251. return e;
  252. },
  253. _createPanelID: function PageRequestManager$_createPanelID(panelsToUpdate, postBackSettings) {
  254. var asyncTarget = postBackSettings.asyncTarget,
  255. toUpdate = this._ensureUniqueIds(panelsToUpdate || postBackSettings.panelsToUpdate),
  256. panelArg = (toUpdate instanceof Array)
  257. ? toUpdate.join(',')
  258. : (toUpdate || this._scriptManagerID);
  259. if (asyncTarget) {
  260. panelArg += "|" + asyncTarget;
  261. }
  262. return encodeURIComponent(this._scriptManagerID) + '=' + encodeURIComponent(panelArg) + '&';
  263. },
  264. _createPostBackSettings: function PageRequestManager$_createPostBackSettings(async, panelsToUpdate, asyncTarget, sourceElement) {
  265. return { async:async, asyncTarget: asyncTarget, panelsToUpdate: panelsToUpdate, sourceElement: sourceElement };
  266. },
  267. _convertToClientIDs: function PageRequestManager$_convertToClientIDs(source, destinationIDs, destinationClientIDs, version4) {
  268. if (source) {
  269. for (var i = 0, l = source.length; i < l; i += (version4 ? 2 : 1)) {
  270. var uniqueID = source[i],
  271. clientID = (version4 ? source[i+1] : "") || this._uniqueIDToClientID(uniqueID);
  272. Array.add(destinationIDs, uniqueID);
  273. Array.add(destinationClientIDs, clientID);
  274. }
  275. }
  276. },
  277. dispose: function PageRequestManager$dispose() {
  278. Sys.Observer.clearEventHandlers(this);
  279. if (this._form) {
  280. Sys.UI.DomEvent.removeHandler(this._form, 'submit', this._onFormSubmitHandler);
  281. Sys.UI.DomEvent.removeHandler(this._form, 'click', this._onFormElementClickHandler);
  282. Sys.UI.DomEvent.removeHandler(window, 'unload', this._onWindowUnloadHandler);
  283. Sys.UI.DomEvent.removeHandler(window, 'load', this._pageLoadedHandler);
  284. }
  285. if (this._originalDoPostBack) {
  286. window.__doPostBack = this._originalDoPostBack;
  287. this._originalDoPostBack = null;
  288. }
  289. if (this._originalDoPostBackWithOptions) {
  290. window.WebForm_DoPostBackWithOptions = this._originalDoPostBackWithOptions;
  291. this._originalDoPostBackWithOptions = null;
  292. }
  293. if (this._originalFireDefaultButton) {
  294. window.WebForm_FireDefaultButton = this._originalFireDefaultButton;
  295. this._originalFireDefaultButton = null;
  296. }
  297. if (this._originalDoCallback) {
  298. window.WebForm_DoCallback = this._originalDoCallback;
  299. this._originalDoCallback = null;
  300. }
  301. this._form = null;
  302. this._updatePanelIDs = null;
  303. this._updatePanelClientIDs = null;
  304. this._asyncPostBackControlIDs = null;
  305. this._asyncPostBackControlClientIDs = null;
  306. this._postBackControlIDs = null;
  307. this._postBackControlClientIDs = null;
  308. this._asyncPostBackTimeout = null;
  309. this._scrollPosition = null;
  310. },
  311. _doCallback: function PageRequestManager$_doCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync) {
  312. // DevDiv Bugs 125825: Do not allow callbacks to begin while an async postback is in progress to prevent EVENTVALIDATION corruption
  313. if (!this.get_isInAsyncPostBack()) {
  314. this._originalDoCallback(eventTarget, eventArgument, eventCallback, context, errorCallback, useAsync);
  315. }
  316. },
  317. // New implementation of __doPostBack
  318. _doPostBack: function PageRequestManager$_doPostBack(eventTarget, eventArgument) {
  319. this._additionalInput = null;
  320. var form = this._form;
  321. if ((eventTarget === null) || (typeof(eventTarget) === "undefined") || (this._isCrossPost)) {
  322. // Allow the default form submit to take place. Since it's a cross-page postback.
  323. // DevDiv 80942: we should fall to a full postback if event target is null or undefined
  324. this._postBackSettings = this._createPostBackSettings(false);
  325. // set to false so subsequent posts that don't go through DPWO aren't considered cross post
  326. this._isCrossPost = false;
  327. }
  328. else {
  329. var mpUniqueID = this._masterPageUniqueID;
  330. // If it's not a cross-page post, see if we can find the DOM element that caused the postback
  331. var clientID = this._uniqueIDToClientID(eventTarget);
  332. var postBackElement = document.getElementById(clientID);
  333. if (!postBackElement && mpUniqueID) {
  334. if (clientID.indexOf(mpUniqueID + "$") === 0) {
  335. // With ClientIDMode=Predictable, the MasterPageID is missing from the beginning
  336. // of the client ID.
  337. postBackElement = document.getElementById(clientID.substr(mpUniqueID.length + 1));
  338. }
  339. }
  340. if (!postBackElement) {
  341. // If the control has no matching DOM element we look for an exact
  342. // match from RegisterAsyncPostBackControl or RegisterPostBackControl.
  343. // If we can't find anything about it then we do a search based on
  344. // naming containers to still try and find a match.
  345. if (Array.contains(this._asyncPostBackControlIDs, eventTarget)) {
  346. // Exact match for async postback
  347. this._postBackSettings = this._createPostBackSettings(true, null, eventTarget);
  348. }
  349. else {
  350. if (Array.contains(this._postBackControlIDs, eventTarget)) {
  351. // Exact match for regular postback
  352. this._postBackSettings = this._createPostBackSettings(false);
  353. }
  354. else {
  355. // Find nearest element based on UniqueID in case the element calling
  356. // __doPostBack doesn't have an ID. GridView does this for its Update
  357. // button and without this we can't do async postbacks.
  358. var nearestUniqueIDMatch = this._findNearestElement(eventTarget);
  359. if (nearestUniqueIDMatch) {
  360. // We found a related parent element, so walk up the DOM to find out what kind
  361. // of postback we should do.
  362. this._postBackSettings = this._getPostBackSettings(nearestUniqueIDMatch, eventTarget);
  363. }
  364. else {
  365. // the control may have rendered without the master page id prefix due to ClientIDMode = Predictable
  366. // For example "ctl00$ctl00$foo$Button1" may have rendered an id of "foo_button1" if "ctl00$ctl00"
  367. // is the ID for a 2-level nested master page.
  368. // try stripping it from the beginning of the ID and trying again
  369. if (mpUniqueID) {
  370. mpUniqueID += "$";
  371. if (eventTarget.indexOf(mpUniqueID) === 0) {
  372. nearestUniqueIDMatch = this._findNearestElement(eventTarget.substr(mpUniqueID.length));
  373. }
  374. }
  375. if (nearestUniqueIDMatch) {
  376. // We found a related parent element, so walk up the DOM to find out what kind
  377. // of postback we should do.
  378. this._postBackSettings = this._getPostBackSettings(nearestUniqueIDMatch, eventTarget);
  379. }
  380. else {
  381. // Can't find any DOM element at all related to the eventTarget,
  382. // so we just give up and do a regular postback.
  383. this._postBackSettings = this._createPostBackSettings(false);
  384. }
  385. }
  386. }
  387. }
  388. }
  389. else {
  390. // The element was found, so walk up the DOM to find out what kind
  391. // of postback we should do.
  392. this._postBackSettings = this._getPostBackSettings(postBackElement, eventTarget);
  393. }
  394. }
  395. if (!this._postBackSettings.async) {
  396. // Temporarily restore the form's onsubmit handler expando while calling
  397. // the original ASP.NET 2.0 __doPostBack() function.
  398. form.onsubmit = this._onsubmit;
  399. this._originalDoPostBack(eventTarget, eventArgument);
  400. form.onsubmit = null;
  401. return;
  402. }
  403. form.__EVENTTARGET.value = eventTarget;
  404. form.__EVENTARGUMENT.value = eventArgument;
  405. this._onFormSubmit();
  406. },
  407. _doPostBackWithOptions: function PageRequestManager$_doPostBackWithOptions(options) {
  408. this._isCrossPost = options && options.actionUrl;
  409. // note that when DoPostBackWithOptions is used, _doPostBack or _onFormSubmit, one of the two,
  410. // are guaranteed to be called next.
  411. // In both of those methods it is important to clear the isCrossPost flag so subsequent posts that
  412. // don't use DoPostBackWithOptions are not considered cross page posts.
  413. this._originalDoPostBackWithOptions(options);
  414. },
  415. _elementContains: function PageRequestManager$_elementContains(container, element) {
  416. while (element) {
  417. if (element === container) {
  418. return true;
  419. }
  420. element = element.parentNode;
  421. }
  422. return false;
  423. },
  424. _endPostBack: function PageRequestManager$_endPostBack(error, executor, data) {
  425. if (this._request === executor.get_webRequest()) {
  426. // the postback being ended is the one being processed
  427. this._processingRequest = false;
  428. this._additionalInput = null;
  429. this._request = null;
  430. }
  431. var eventArgs = new Sys.WebForms.EndRequestEventArgs(error, data ? data.dataItems : {}, executor);
  432. Sys.Observer.raiseEvent(this, "endRequest", eventArgs);
  433. if (error && !eventArgs.get_errorHandled()) {
  434. // DevDiv 89485: throw, don't alert()
  435. throw error;
  436. }
  437. },
  438. _ensureUniqueIds: function PageRequestManager$_ensureUniqueIds(ids) {
  439. // given a single ID or an array of IDs that might be ClientIDs or UniqueIDs,
  440. // returns a list of the UniqueIDs. This is used from createPanelID and makes
  441. // it so beginAsyncPostBack and the panelstoUpdate property of the event args
  442. // supports a list of update panels by UniqueID or ClientID.
  443. // If an ID is not a ClientID we assume it is a UniqueID even though it could just be
  444. // that it does not exist.
  445. if (!ids) return ids;
  446. ids = ids instanceof Array ? ids : [ids];
  447. var uniqueIds = [];
  448. for (var i = 0, l = ids.length; i < l; i++) {
  449. var id = ids[i], index = Array.indexOf(this._updatePanelClientIDs, id);
  450. uniqueIds.push(index > -1 ? this._updatePanelIDs[index] : id);
  451. }
  452. return uniqueIds;
  453. },
  454. // Finds the nearest element to the given UniqueID. If an element is not
  455. // found for the exact UniqueID, it walks up the parent chain to look for it.
  456. _findNearestElement: function PageRequestManager$_findNearestElement(uniqueID) {
  457. while (uniqueID.length > 0) {
  458. var clientID = this._uniqueIDToClientID(uniqueID);
  459. var element = document.getElementById(clientID);
  460. if (element) {
  461. return element;
  462. }
  463. var indexOfLastDollar = uniqueID.lastIndexOf('$');
  464. if (indexOfLastDollar === -1) {
  465. return null;
  466. }
  467. uniqueID = uniqueID.substring(0, indexOfLastDollar);
  468. }
  469. return null;
  470. },
  471. _findText: function PageRequestManager$_findText(text, location) {
  472. var startIndex = Math.max(0, location - 20);
  473. var endIndex = Math.min(text.length, location + 20);
  474. return text.substring(startIndex, endIndex);
  475. },
  476. _fireDefaultButton: function PageRequestManager$_fireDefaultButton(event, target) {
  477. // This is a copy of the function WebForm_FireDefaultButton as defined in WebForms.js.
  478. // The purpose is to hook into the WebForm_FireDefaultButton call with the code commented in the middle.
  479. // Other than that, there have been a few minor changes to the code but the logic is the same.
  480. if (event.keyCode === 13) {
  481. var src = event.srcElement || event.target;
  482. if (!src || (src.tagName.toLowerCase() !== "textarea")) {
  483. var defaultButton = document.getElementById(target);
  484. if (defaultButton && (typeof(defaultButton.click) !== "undefined")) {
  485. // Beginning of new code...
  486. // In all but FF this causes the form.onclick event to fire with the button as the event target.
  487. // In FF the the form.onclick event has the current focus control as the target, which prevents the
  488. // default button's server-side click event from firing. So we ensure the correct control is determined
  489. // to have caused the postback by saving the default button before clicking on it. The code in
  490. // onFormSubmit looks for this field and ensures the postback target is the button.
  491. this._activeDefaultButton = defaultButton;
  492. this._activeDefaultButtonClicked = false;
  493. try {
  494. // click is synchronous -- it will immediately cause a form onclick event and then a form onsubmit event
  495. // assuming nothing uses preventDefault() to cancel the event.
  496. defaultButton.click();
  497. }
  498. finally {
  499. // form submission may or may not be occuring after this point
  500. this._activeDefaultButton = null;
  501. }
  502. // ...End of new code
  503. // cancel submission caused by hitting enter in the input control
  504. event.cancelBubble = true;
  505. if (typeof(event.stopPropagation) === "function") {
  506. event.stopPropagation();
  507. }
  508. return false;
  509. }
  510. }
  511. }
  512. return true;
  513. },
  514. _getPageLoadedEventArgs: function PageRequestManager$_getPageLoadedEventArgs(initialLoad, data) {
  515. // -------------+------------------------------------+-----------------------
  516. // Situation | In ID collections | In eventArg property
  517. // -------------+------------------------------------+-----------------------
  518. // Update (exp) | in panelsToRefresh | updated
  519. // Update (imp) | in new, in old, in childUP | created
  520. // Create (exp) | in new, not in old, not in childUP | created
  521. // Create (imp) | in new, not in old, in childUP | created
  522. // Delete (exp) | not in new, in old, not in childUP | ---
  523. // Delete (imp) | not in new, in old, in childUP | ---
  524. // -------------+------------------------------------+-----------------------
  525. // (exp) = explicit
  526. // (imp) = implicit (happened as result of parent UpdatePanel updating)
  527. // --------------------------------------------------------------------------
  528. // in panelsToRefresh = updated
  529. // not updated, in new = created
  530. // else = don't care
  531. // --------------------------------------------------------------------------
  532. var updated = [];
  533. var created = [];
  534. var version4 = data ? data.version4 : false;
  535. var upData = data ? data.updatePanelData : null;
  536. // All panels before update,
  537. // All panels after update,
  538. // Child panels created after update,
  539. // Parent panels created after update
  540. var newIDs, newClientIDs, childIDs, refreshedIDs;
  541. if (!upData) {
  542. // this is the initial load, consider the initialized update panels
  543. // to be the newly created ones
  544. newIDs = this._updatePanelIDs;
  545. newClientIDs = this._updatePanelClientIDs;
  546. childIDs = null;
  547. refreshedIDs = null;
  548. }
  549. else {
  550. newIDs = upData.updatePanelIDs;
  551. newClientIDs = upData.updatePanelClientIDs;
  552. childIDs = upData.childUpdatePanelIDs;
  553. refreshedIDs = upData.panelsToRefreshIDs;
  554. }
  555. var i, l, uniqueID, clientID;
  556. // in panelsToRefresh = updated
  557. if (refreshedIDs) {
  558. for (i = 0, l = refreshedIDs.length; i < l; i += (version4 ? 2 : 1)) {
  559. uniqueID = refreshedIDs[i];
  560. clientID = (version4 ? refreshedIDs[i+1] : "") || this._uniqueIDToClientID(uniqueID);
  561. Array.add(updated, document.getElementById(clientID));
  562. }
  563. }
  564. // If the panel is in the new list and it is either the initial load
  565. // of the page a refreshed child, it is 'created'.
  566. for (i = 0, l = newIDs.length; i < l; i++) {
  567. if (initialLoad || Array.indexOf(childIDs, newIDs[i]) !== -1) {
  568. Array.add(created, document.getElementById(newClientIDs[i]));
  569. }
  570. }
  571. return new Sys.WebForms.PageLoadedEventArgs(updated, created, data ? data.dataItems : {});
  572. },
  573. _getPageLoadingEventArgs: function PageRequestManager$_getPageLoadingEventArgs(data) {
  574. // -------------+------------------------------------+-----------------------
  575. // Situation | In ID collections | In eventArg property
  576. // -------------+------------------------------------+-----------------------
  577. // Update (exp) | in panelsToRefresh | updated
  578. // Update (imp) | in old, in new, in childUP | deleted
  579. // Create (exp) | not in old, in new, not in childUP | ---
  580. // Create (imp) | not in old, in new, in childUP | ---
  581. // Delete (exp) | in old, not in new, not in childUP | deleted
  582. // Delete (imp) | in old, not in new, in childUP | deleted
  583. // -------------+------------------------------------+-----------------------
  584. // (exp) = explicit
  585. // (imp) = implicit (happened as result of parent UpdatePanel updating)
  586. // --------------------------------------------------------------------------
  587. // in panelsToRefresh = updated
  588. // not updated, (not in new or in childUP) = deleted
  589. // else = don't care
  590. // --------------------------------------------------------------------------
  591. var updated = [],
  592. deleted = [],
  593. upData = data.updatePanelData,
  594. oldIDs = upData.oldUpdatePanelIDs,
  595. oldClientIDs = upData.oldUpdatePanelClientIDs,
  596. newIDs = upData.updatePanelIDs,
  597. childIDs = upData.childUpdatePanelIDs,
  598. refreshedIDs = upData.panelsToRefreshIDs,
  599. i, l, uniqueID, clientID,
  600. version4 = data.version4;
  601. // in panelsToRefresh = updated
  602. for (i = 0, l = refreshedIDs.length; i < l; i += (version4 ? 2 : 1)) {
  603. uniqueID = refreshedIDs[i];
  604. clientID = (version4 ? refreshedIDs[i+1] : "") || this._uniqueIDToClientID(uniqueID);
  605. Array.add(updated, document.getElementById(clientID));
  606. }
  607. // not in new or in childUP = deleted
  608. for (i = 0, l = oldIDs.length; i < l; i++) {
  609. uniqueID = oldIDs[i];
  610. if (Array.indexOf(refreshedIDs, uniqueID) === -1 &&
  611. (Array.indexOf(newIDs, uniqueID) === -1 || Array.indexOf(childIDs, uniqueID) > -1)) {
  612. Array.add(deleted, document.getElementById(oldClientIDs[i]));
  613. }
  614. }
  615. return new Sys.WebForms.PageLoadingEventArgs(updated, deleted, data.dataItems);
  616. },
  617. _getPostBackSettings: function PageRequestManager$_getPostBackSettings(element, elementUniqueID) {
  618. var originalElement = element;
  619. // Keep track of whether we have an AsyncPostBackControl but still
  620. // want to see if we're inside an UpdatePanel anyway.
  621. var proposedSettings = null;
  622. // Walk up DOM hierarchy to find out the nearest container of
  623. // the element that caused the postback.
  624. while (element) {
  625. if (element.id) {
  626. // First try an exact match for async postback, regular postback, or UpdatePanel
  627. if (!proposedSettings && Array.contains(this._asyncPostBackControlClientIDs, element.id)) {
  628. // The element explicitly causes an async postback
  629. proposedSettings = this._createPostBackSettings(true, null, elementUniqueID, originalElement);
  630. }
  631. else {
  632. if (!proposedSettings && Array.contains(this._postBackControlClientIDs, element.id)) {
  633. // The element explicitly doesn't cause an async postback
  634. return this._createPostBackSettings(false);
  635. }
  636. else {
  637. var indexOfPanel = Array.indexOf(this._updatePanelClientIDs, element.id);
  638. if (indexOfPanel !== -1) {
  639. // The element causes an async postback because it is inside an UpdatePanel
  640. if (this._updatePanelHasChildrenAsTriggers[indexOfPanel]) {
  641. // If it was in an UpdatePanel and the panel has ChildrenAsTriggers=true, then
  642. // we do an async postback and refresh the given panel
  643. // Although we do the search by looking at ClientIDs, we end
  644. // up sending a UniqueID back to the server so that we can
  645. // call FindControl() with it.
  646. return this._createPostBackSettings(true, [this._updatePanelIDs[indexOfPanel]], elementUniqueID, originalElement);
  647. }
  648. else {
  649. // The element was inside an UpdatePanel so we do an async postback,
  650. // but because it has ChildrenAsTriggers=false we don't update this panel.
  651. return this._createPostBackSettings(true, null, elementUniqueID, originalElement);
  652. }
  653. }
  654. }
  655. }
  656. // Then try near matches
  657. if (!proposedSettings && this._matchesParentIDInList(element.id, this._asyncPostBackControlClientIDs)) {
  658. // The element explicitly causes an async postback
  659. proposedSettings = this._createPostBackSettings(true, null, elementUniqueID, originalElement);
  660. }
  661. else {
  662. if (!proposedSettings && this._matchesParentIDInList(element.id, this._postBackControlClientIDs)) {
  663. // The element explicitly doesn't cause an async postback
  664. return this._createPostBackSettings(false);
  665. }
  666. }
  667. }
  668. element = element.parentNode;
  669. }
  670. // If we have proposed settings that means we found a match for an
  671. // AsyncPostBackControl but were still searching for an UpdatePanel.
  672. // If we got here that means we didn't find the UpdatePanel so we
  673. // just fall back to the original AsyncPostBackControl settings that
  674. // we created.
  675. if (!proposedSettings) {
  676. // The element doesn't cause an async postback
  677. return this._createPostBackSettings(false);
  678. }
  679. else {
  680. return proposedSettings;
  681. }
  682. },
  683. _getScrollPosition: function PageRequestManager$_getScrollPosition() {
  684. var d = document.documentElement;
  685. if (d && (this._validPosition(d.scrollLeft) || this._validPosition(d.scrollTop))) {
  686. return {
  687. x: d.scrollLeft,
  688. y: d.scrollTop
  689. };
  690. }
  691. else {
  692. d = document.body;
  693. if (d && (this._validPosition(d.scrollLeft) || this._validPosition(d.scrollTop))) {
  694. return {
  695. x: d.scrollLeft,
  696. y: d.scrollTop
  697. };
  698. }
  699. else {
  700. if (this._validPosition(window.pageXOffset) || this._validPosition(window.pageYOffset)) {
  701. return {
  702. x: window.pageXOffset,
  703. y: window.pageYOffset
  704. };
  705. }
  706. else {
  707. return {
  708. x: 0,
  709. y: 0
  710. };
  711. }
  712. }
  713. }
  714. },
  715. _initializeInternal: function PageRequestManager$_initializeInternal(scriptManagerID, formElement, updatePanelIDs, asyncPostBackControlIDs, postBackControlIDs, asyncPostBackTimeout, masterPageUniqueID) {
  716. if (this._prmInitialized) {
  717. throw Error.invalidOperation(Sys.WebForms.Res.PRM_CannotRegisterTwice);
  718. }
  719. this._prmInitialized = true;
  720. this._masterPageUniqueID = masterPageUniqueID;
  721. this._scriptManagerID = scriptManagerID;
  722. this._form = Sys.UI.DomElement.resolveElement(formElement);
  723. this._onsubmit = this._form.onsubmit;
  724. this._form.onsubmit = null;
  725. this._onFormSubmitHandler = Function.createDelegate(this, this._onFormSubmit);
  726. this._onFormElementClickHandler = Function.createDelegate(this, this._onFormElementClick);
  727. this._onWindowUnloadHandler = Function.createDelegate(this, this._onWindowUnload);
  728. Sys.UI.DomEvent.addHandler(this._form, 'submit', this._onFormSubmitHandler);
  729. Sys.UI.DomEvent.addHandler(this._form, 'click', this._onFormElementClickHandler);
  730. Sys.UI.DomEvent.addHandler(window, 'unload', this._onWindowUnloadHandler);
  731. this._originalDoPostBack = window.__doPostBack;
  732. if (this._originalDoPostBack) {
  733. window.__doPostBack = Function.createDelegate(this, this._doPostBack);
  734. }
  735. this._originalDoPostBackWithOptions = window.WebForm_DoPostBackWithOptions;
  736. if (this._originalDoPostBackWithOptions) {
  737. window.WebForm_DoPostBackWithOptions = Function.createDelegate(this, this._doPostBackWithOptions);
  738. }
  739. this._originalFireDefaultButton = window.WebForm_FireDefaultButton;
  740. if (this._originalFireDefaultButton) {
  741. window.WebForm_FireDefaultButton = Function.createDelegate(this, this._fireDefaultButton);
  742. }
  743. this._originalDoCallback = window.WebForm_DoCallback;
  744. if (this._originalDoCallback) {
  745. window.WebForm_DoCallback = Function.createDelegate(this, this._doCallback);
  746. }
  747. this._pageLoadedHandler = Function.createDelegate(this, this._pageLoadedInitialLoad);
  748. Sys.UI.DomEvent.addHandler(window, 'load', this._pageLoadedHandler);
  749. if (updatePanelIDs) {
  750. this._updateControls(updatePanelIDs, asyncPostBackControlIDs, postBackControlIDs, asyncPostBackTimeout, true);
  751. }
  752. },
  753. _matchesParentIDInList: function PageRequestManager$_matchesParentIDInList(clientID, parentIDList) {
  754. for (var i = 0, l = parentIDList.length; i < l; i++) {
  755. if (clientID.startsWith(parentIDList[i] + "_")) {
  756. return true;
  757. }
  758. }
  759. return false;
  760. },
  761. _onFormElementActive: function PageRequestManager$_onFormElementActive(element, offsetX, offsetY) {
  762. // element: the form element that is active
  763. // offsetX/Y: if the element is an image button, the coordinates of the click
  764. if (element.disabled) {
  765. return;
  766. }
  767. // Check if the element that was clicked on should cause an async postback
  768. this._postBackSettings = this._getPostBackSettings(element, element.name);
  769. if (element.name) {
  770. // DevDiv Bugs 146697: tagName needs to be case insensitive to work with xhtml content type
  771. var tagName = element.tagName.toUpperCase();
  772. if (tagName === 'INPUT') {
  773. var type = element.type;
  774. if (type === 'submit') {
  775. // DevDiv Bugs 109456: Encode the name as well as the value
  776. this._additionalInput = encodeURIComponent(element.name) + '=' + encodeURIComponent(element.value);
  777. }
  778. else if (type === 'image') {
  779. // DevDiv Bugs 109456: Encode the name as well as the value
  780. this._additionalInput = encodeURIComponent(element.name) + '.x=' + offsetX + '&' + encodeURIComponent(element.name) + '.y=' + offsetY;
  781. }
  782. }
  783. else if ((tagName === 'BUTTON') && (element.name.length !== 0) && (element.type === 'submit')) {
  784. // DevDiv Bugs 109456: Encode the name as well as the value
  785. this._additionalInput = encodeURIComponent(element.name) + '=' + encodeURIComponent(element.value);
  786. }
  787. }
  788. },
  789. _onFormElementClick: function PageRequestManager$_onFormElementClick(evt) {
  790. // flag used by fireDefaultButton to know whether calling click() on the default button raised this event.
  791. this._activeDefaultButtonClicked = (evt.target === this._activeDefaultButton);
  792. this._onFormElementActive(evt.target, evt.offsetX, evt.offsetY);
  793. },
  794. _onFormSubmit: function PageRequestManager$_onFormSubmit(evt) {
  795. var i, l, continueSubmit = true,
  796. isCrossPost = this._isCrossPost;
  797. // set to false so subsequent posts that don't go through DPWO aren't considered cross post
  798. this._isCrossPost = false;
  799. // Call the statically declared form onsubmit statement if there was one
  800. if (this._onsubmit) {
  801. continueSubmit = this._onsubmit();
  802. }
  803. // If necessary, call dynamically added form onsubmit statements
  804. if (continueSubmit) {
  805. for (i = 0, l = this._onSubmitStatements.length; i < l; i++) {
  806. if (!this._onSubmitStatements[i]()) {
  807. continueSubmit = false;
  808. break;
  809. }
  810. }
  811. }
  812. if (!continueSubmit) {
  813. if (evt) {
  814. evt.preventDefault();
  815. }
  816. return;
  817. }
  818. var form = this._form;
  819. if (isCrossPost) {
  820. // Allow the default form submit to take place. Since it's a cross-page postback.
  821. return;
  822. }
  823. // DevDiv Bugs 123782
  824. if (this._activeDefaultButton && !this._activeDefaultButtonClicked) {
  825. // we are submitting because a default button's click method was called by _fireDefaultButton
  826. // but calling click() explicitly did not cause a click event or raised it for a different element,
  827. // so we must manually create the correct postback options.
  828. // The button was clicked programmatically, so there are no offsetX or offsetY coordinates.
  829. this._onFormElementActive(this._activeDefaultButton, 0, 0);
  830. }
  831. // If the postback happened from outside an update panel, fall back
  832. // and do a normal postback.
  833. // Dev10 546632: postBackSettings may not exist in certain scenarios where
  834. // the form click events are cancelled.
  835. if (!this._postBackSettings || !this._postBackSettings.async) {
  836. return;
  837. }
  838. // Construct the form body
  839. var formBody = new Sys.StringBuilder(),
  840. count = form.elements.length,
  841. panelID = this._createPanelID(null, this._postBackSettings);
  842. // DevDiv Bugs 109456: ScriptManager and UpdatePanel IDs should be encoded as well
  843. formBody.append(panelID);
  844. for (i = 0; i < count; i++) {
  845. var element = form.elements[i];
  846. var name = element.name;
  847. if (typeof(name) === "undefined" || (name === null) || (name.length === 0) || (name === this._scriptManagerID)) {
  848. continue;
  849. }
  850. // DevDiv Bugs 146697: tagName needs to be case insensitive to work with xhtml content type
  851. var tagName = element.tagName.toUpperCase();
  852. if (tagName === 'INPUT') {
  853. var type = element.type;
  854. if ((type === 'text') ||
  855. (type === 'password') ||
  856. (type === 'hidden') ||
  857. (((type === 'checkbox') || (type === 'radio')) && element.checked)) {
  858. // DevDiv Bugs 109456: Encode the name as well as the value
  859. formBody.append(encodeURIComponent(name));
  860. formBody.append('=');
  861. formBody.append(encodeURIComponent(element.value));
  862. formBody.append('&');
  863. }
  864. }
  865. else if (tagName === 'SELECT') {
  866. var optionCount = element.options.length;
  867. for (var j = 0; j < optionCount; j++) {
  868. var option = element.options[j];
  869. if (option.selected) {
  870. // DevDiv Bugs 109456: Encode the name as well as the value
  871. formBody.append(encodeURIComponent(name));
  872. formBody.append('=');
  873. formBody.append(encodeURIComponent(option.value));
  874. formBody.append('&');
  875. }
  876. }
  877. }
  878. else if (tagName === 'TEXTAREA') {
  879. // DevDiv Bugs 109456: Encode the name as well as the value
  880. formBody.append(encodeURIComponent(name));
  881. formBody.append('=');
  882. formBody.append(encodeURIComponent(element.value));
  883. formBody.append('&');
  884. }
  885. }
  886. // DevDiv Bugs 188713: Some firewalls strip the X-MicrosoftAjax header, so send a custom form field as well.
  887. formBody.append("__ASYNCPOST=true&");
  888. if (this._additionalInput) {
  889. formBody.append(this._additionalInput);
  890. this._additionalInput = null;
  891. }
  892. var request = new Sys.Net.WebRequest();
  893. var action = form.action;
  894. if (Sys.Browser.agent === Sys.Browser.InternetExplorer) {
  895. // DevDiv Bugs 85367: In IE we must encode the path portion of the request because XHR doesn't do it for us.
  896. // First, we remove the url fragment, which can appear in history-related scenarios
  897. // but is not relevant to async postbacks.
  898. var fragmentIndex = action.indexOf('#');
  899. if (fragmentIndex !== -1) {
  900. action = action.substr(0, fragmentIndex);
  901. }
  902. // We only want to encode the path fragment, not the querystring.
  903. var queryIndex = action.indexOf('?');
  904. if (queryIndex !== -1) {
  905. var path = action.substr(0, queryIndex);
  906. if (path.indexOf("%") === -1) {
  907. // only encode if the path portion is not already encoded
  908. // tear off the query, encode, then put the query back
  909. action = encodeURI(path) + action.substr(queryIndex);
  910. }
  911. }
  912. else if (action.indexOf("%") === -1) {
  913. // only encode if the path portion is not already encoded
  914. action = encodeURI(action);
  915. }
  916. }
  917. request.set_url(action);
  918. request.get_headers()['X-MicrosoftAjax'] = 'Delta=true';
  919. request.get_headers()['Cache-Control'] = 'no-cache';
  920. request.set_timeout(this._asyncPostBackTimeout);
  921. request.add_completed(Function.createDelegate(this, this._onFormSubmitCompleted));
  922. request.set_body(formBody.toString());
  923. // eventArgs var reused for beginRequest below
  924. var panelsToUpdate, eventArgs;
  925. panelsToUpdate = this._postBackSettings.panelsToUpdate;
  926. eventArgs = new Sys.WebForms.InitializeRequestEventArgs(request, this._postBackSettings.sourceElement, panelsToUpdate);
  927. Sys.Observer.raiseEvent(this, "initializeRequest", eventArgs);
  928. continueSubmit = !eventArgs.get_cancel();
  929. if (!continueSubmit) {
  930. if (evt) {
  931. evt.preventDefault();
  932. }
  933. return;
  934. }
  935. if (eventArgs && eventArgs._updated) {
  936. // the initializeRequest event has changed the update panels to update
  937. panelsToUpdate = eventArgs.get_updatePanelsToUpdate();
  938. request.set_body(request.get_body().replace(panelID, this._createPanelID(panelsToUpdate, this._postBackSettings)));
  939. }
  940. // Save the scroll position
  941. this._scrollPosition = this._getScrollPosition();
  942. // If we're going on to make a new request (i.e. the user didn't cancel), and
  943. // there's still an ongoing request, we have to abort it. If we don't then it
  944. // will exhaust the browser's two connections per server limit very quickly.
  945. this.abortPostBack();
  946. eventArgs = new Sys.WebForms.BeginRequestEventArgs(request, this._postBackSettings.sourceElement,
  947. panelsToUpdate || this._postBackSettings.panelsToUpdate);
  948. Sys.Observer.raiseEvent(this, "beginRequest", eventArgs);
  949. // DevDiv Bugs 125825: Cancel any pending callbacks when an async postback begins
  950. if (this._originalDoCallback) {
  951. this._cancelPendingCallbacks();
  952. }
  953. this._request = request;
  954. // DevDiv Bugs 154403: A previous request may be loading scripts at this point.
  955. // If so, once its scripts finish, it will not be processed any further.
  956. // We must clear _processingRequest, otherwise in this scenario the 2nd post would
  957. // not be abortable because it would appear that its response is already received.
  958. this._processingRequest = false;
  959. request.invoke();
  960. // Suppress the default form submit functionality
  961. if (evt) {
  962. evt.preventDefault();
  963. }
  964. },
  965. _onFormSubmitCompleted: function PageRequestManager$_onFormSubmitCompleted(sender, eventArgs) {
  966. // setting this true means the request can no longer be aborted
  967. this._processingRequest = true;
  968. // sender is the executor object
  969. if (sender.get_timedOut()) {
  970. this._endPostBack(this._createPageRequestManagerTimeoutError(), sender, null);
  971. return;
  972. }
  973. if (sender.get_aborted()) {
  974. this._endPostBack(null, sender, null);
  975. return;
  976. }
  977. // If the response isn't the response to the latest request, ignore it (last one wins)
  978. // This can happen if a 2nd async post begins before the response for the 1st is received
  979. if (!this._request || (sender.get_webRequest() !== this._request)) {
  980. return;
  981. }
  982. // If we have an invalid status code, go into error mode
  983. if (sender.get_statusCode() !== 200) {
  984. this._endPostBack(this._createPageRequestManagerServerError(sender.get_statusCode()), sender, null);
  985. return;
  986. }
  987. var data = this._parseDelta(sender);
  988. if (!data) return;
  989. var i, l;
  990. if (data.asyncPostBackControlIDsNode && data.postBackControlIDsNode &&
  991. data.updatePanelIDsNode && data.panelsToRefreshNode && data.childUpdatePanelIDsNode) {
  992. var oldUpdatePanelIDs = this._updatePanelIDs,
  993. oldUpdatePanelClientIDs = this._updatePanelClientIDs;
  994. var childUpdatePanelIDsString = data.childUpdatePanelIDsNode.content;
  995. var childUpdatePanelIDs = childUpdatePanelIDsString.length ? childUpdatePanelIDsString.split(',') : [];
  996. var asyncPostBackControlIDsArray = this._splitNodeIntoArray(data.asyncPostBackControlIDsNode);
  997. var postBackControlIDsArray = this._splitNodeIntoArray(data.postBackControlIDsNode);
  998. var updatePanelIDsArray = this._splitNodeIntoArray(data.updatePanelIDsNode);
  999. var panelsToRefreshIDs = this._splitNodeIntoArray(data.panelsToRefreshNode);
  1000. // Validate that all the top level UpdatePanels that we plan to update exist
  1001. // in the active document. We do this early so that we can later assume that
  1002. // all referenced UpdatePanels exist.
  1003. var v4 = data.version4;
  1004. for (i = 0, l = panelsToRefreshIDs.length; i < l; i+= (v4 ? 2 : 1)) {
  1005. var panelClientID = (v4 ? panelsToRefreshIDs[i+1] : "") || this._uniqueIDToClientID(panelsToRefreshIDs[i]);
  1006. if (!document.getElementById(panelClientID)) {
  1007. this._endPostBack(Error.invalidOperation(String.format(Sys.WebForms.Res.PRM_MissingPanel, panelClientID)), sender, data);
  1008. return;
  1009. }
  1010. }
  1011. var updatePanelData = this._processUpdatePanelArrays(
  1012. updatePanelIDsArray,
  1013. asyncPostBackControlIDsArray,
  1014. postBackControlIDsArray, v4);
  1015. updatePanelData.oldUpdatePanelIDs = oldUpdatePanelIDs;
  1016. updatePanelData.oldUpdatePanelClientIDs = oldUpdatePanelClientIDs;
  1017. updatePanelData.childUpdatePanelIDs = childUpdatePanelIDs;
  1018. updatePanelData.panelsToRefreshIDs = panelsToRefreshIDs;
  1019. data.updatePanelData = updatePanelData;
  1020. }
  1021. // Process data items
  1022. data.dataItems = {};
  1023. var node;
  1024. for (i = 0, l = data.dataItemNodes.length; i < l; i++) {
  1025. node = data.dataItemNodes[i];
  1026. data.dataItems[node.id] = node.content;
  1027. }
  1028. for (i = 0, l = data.dataItemJsonNodes.length; i < l; i++) {
  1029. node = data.dataItemJsonNodes[i];
  1030. data.dataItems[node.id] = Sys.Serialization.JavaScriptSerializer.deserialize(node.content);
  1031. }
  1032. var handler = Sys.Observer._getContext(this, true).events.getHandler("pageLoading");
  1033. if (handler) {
  1034. handler(this, this._getPageLoadingEventArgs(data));
  1035. }
  1036. // DevDiv Bugs 127756: Load script includes before updating the HTML.
  1037. // After updating the HTML, load script blocks, startup scripts, hidden fields, arrays, expandos, and onsubmit statements
  1038. // Includes must be loaded first because the new DOM may have inline event handlers declared that depend on new
  1039. // resources in the include files. They may also depend on resources in client script BLOCKS,
  1040. // but script blocks can still load after updating the HTML because they load synchronously,
  1041. // and therefore will still be loaded before any event handlers could fire. They can't be loaded before updating the HTML,
  1042. // because dispose scripts must be executed first in case they dispose of resources declared by the script blocks.
  1043. // Neither can the HTML be disposed of, then scripts loaded, and then the HTML updated, because that would cause a flicker.
  1044. // This means ClientScriptIncludes and ClientScriptBlocks will load disjunct from one another during async updates,
  1045. // but script includes should not depend on script blocks. This mechanism allows inline event handlers, a likely scenario,
  1046. // whereas complex dependencies between script includes and script blocks is uncommon and not recommended.
  1047. // Finally -- startup scripts could contain more script includes, so there are two calls to the script loader, which breaks the
  1048. // completion handling of an async update into 3 separate functions: _onFormSubmitCompleted, _scriptIncludesLoadComplete, _scriptsLoadComplete.
  1049. // DevDiv Bugs 154403: Race condition
  1050. // The fix for 127756 (see above) introduced a race condition. It made it possible for a 2nd async post to
  1051. // begin after the response for the 1st is received but before the HTML is updated, because the page is
  1052. // interactive while scripts are loading. Previously, the HTML was updated immediately when a response was
  1053. // received. This extra gap made it possible for the 2nd post to send stale ViewState and EventValidation data
  1054. // to the server, which would ultimately be replaced by the processing of the 1st response once its scripts
  1055. // have finished loading. A queuing mechanism for async posts cannot work -- because a queued post may
  1056. // originate from HTML that is going to be destroyed or altered by an earlier post still being processed.
  1057. // Instead -- the processing of an async response is altered slightly. Before this fix, once a response is
  1058. // received it was definitely going to be fully processed (all scripts loaded, dom updated, etc). Now, if a
  1059. // 2nd async post begins while scripts are loading for the first, the first response is effectively cancelled.
  1060. // This means it might be possible to load script includes that aren't needed, but this should be harmless.
  1061. // Example:
  1062. // Click [Button1], async post sent to the server. The async response includes a script include [Script1.js],
  1063. // and updated ViewState. PRM begins using the ScriptLoader to load [Script1.js] (it has not updated ViewState
  1064. // yet). While the script is downloading, Click [Button2], which is in a different update panel. Async post is
  1065. // sent to the server with the same ViewState as the first post.
  1066. // Without this fix, Request #1 would continue processing after [Script1.js] has loaded, updating the DOM and
  1067. // ViewState. But then Request #2 would complete with more updated HTML and ViewState. The result would be a
  1068. // page with updated HTML for both UpdatePanels, but only the updated ViewState from the 2nd post.
  1069. // The fix is that when [Script1.js] finishes loading during the processing for Request #1, it is detected
  1070. // that a new request has been made, and no further processing occurs. The only thing Request #1 has caused is
  1071. // its Script Includes to be downloaded, which should be harmless. This also brings the model closer to what it
  1072. // originally was, before the fix for 127756, where it was not possible to perform a post before the viewstate
  1073. // update from a previous post was committed. Note that as always, a 2nd post still cancels the 1st if the
  1074. // response from the 1st is not yet received.
  1075. // Read existing script elements (user code may have manually inserted a script element, this will ensure we know about those).
  1076. // This is used to detect duplicates so we don't reload scripts that have already loaded.
  1077. Sys._ScriptLoader.readLoadedScripts();
  1078. // Starting batch mode for component creation to allow for
  1079. // two-pass creation and components that reference each other.
  1080. // endCreateComponents called from _scriptsLoadComplete.
  1081. Sys.Application.beginCreateComponents();
  1082. // First load ClientScriptIncludes
  1083. var scriptLoader = Sys._ScriptLoader.getInstance();
  1084. this._queueScripts(scriptLoader, data.scriptBlockNodes, true, false);
  1085. // Save context into a member so that we can later get it from the completion callback
  1086. this._processingRequest = true;
  1087. // PRM does not support load timeout
  1088. // timeout, completeCallback, failedCallback, timeoutCallback
  1089. scriptLoader.loadScripts(0,
  1090. Function.createDelegate(this, Function.createCallback(this._scriptIncludesLoadComplete, data)),
  1091. Function.createDelegate(this, Function.createCallback(this._scriptIncludesLoadFailed, data)),
  1092. null);
  1093. },
  1094. _onWindowUnload: function PageRequestManager$_onWindowUnload(evt) {
  1095. this.dispose();
  1096. },
  1097. _pageLoaded: function PageRequestManager$_pageLoaded(initialLoad, data) {
  1098. Sys.Observer.raiseEvent(this, "pageLoaded", this._getPageLoadedEventArgs(initialLoad, data));
  1099. if (!initialLoad) {
  1100. // If this isn't the first page load (i.e. we are doing an async postback), we
  1101. // need to re-raise the Application's load event.
  1102. Sys.Application.raiseLoad();
  1103. }
  1104. },
  1105. _pageLoadedInitialLoad: function PageRequestManager$_pageLoadedInitialLoad(evt) {
  1106. this._pageLoaded(true, null);
  1107. },
  1108. _parseDelta: function PageRequestManager$_parseDelta(executor) {
  1109. // General format: length|type|id|content|
  1110. var reply = executor.get_responseData();
  1111. var delimiterIndex, len, type, id, content;
  1112. var replyIndex = 0;
  1113. var parserErrorDetails = null;
  1114. var delta = [];
  1115. while (replyIndex < reply.length) {
  1116. // length| - from index to next delimiter
  1117. delimiterIndex = reply.indexOf('|', replyIndex);
  1118. if (delimiterIndex === -1) {
  1119. parserErrorDetails = this._findText(reply, replyIndex);
  1120. break;
  1121. }
  1122. len = parseInt(reply.substring(replyIndex, delimiterIndex), 10);
  1123. if ((len % 1) !== 0) {
  1124. parserErrorDetails = this._findText(reply, replyIndex);
  1125. break;
  1126. }
  1127. replyIndex = delimiterIndex + 1;
  1128. // type| - from index to next delimiter
  1129. delimiterIndex = reply.indexOf('|', replyIndex);
  1130. if (delimiterIndex === -1) {
  1131. parserErrorDetails = this._findText(reply, replyIndex);
  1132. break;
  1133. }
  1134. type = reply.substring(replyIndex, delimiterIndex);
  1135. replyIndex = delimiterIndex + 1;
  1136. // id| - from index to next delimiter
  1137. delimiterIndex = reply.indexOf('|', replyIndex);
  1138. if (delimiterIndex === -1) {
  1139. parserErrorDetails = this._findText(reply, replyIndex);
  1140. break;
  1141. }
  1142. id = reply.substring(replyIndex, delimiterIndex);
  1143. replyIndex = delimiterIndex + 1;
  1144. // content - the next 'len' characters after index
  1145. if ((replyIndex + len) >= reply.length) {
  1146. parserErrorDetails = this._findText(reply, reply.length);
  1147. break;
  1148. }
  1149. // DevDiv 75383: We no longer encode null characters in the response content, so we no longer decode them either.
  1150. // See comment in server side PageRequestManager for why.
  1151. content = reply.substr(replyIndex, len);
  1152. replyIndex += len;
  1153. // terminating delimiter
  1154. if (reply.charAt(replyIndex) !== '|') {
  1155. parserErrorDetails = this._findText(reply, replyIndex);
  1156. break;
  1157. }
  1158. replyIndex++;
  1159. Array.add(delta, {type: type, id: id, content: content});
  1160. }
  1161. // If there was a parser error, go into error mode
  1162. if (parserErrorDetails) {
  1163. this._endPostBack(this._createPageRequestManagerParserError(String.format(Sys.WebForms.Res.PRM_ParserErrorDetails, parserErrorDetails)), executor, null);
  1164. return null;
  1165. }
  1166. var updatePanelNodes = [];
  1167. var hiddenFieldNodes = [];
  1168. var arrayDeclarationNodes = [];
  1169. var scriptBlockNodes = [];
  1170. var scriptStartupNodes = [];
  1171. var expandoNodes = [];
  1172. var onSubmitNodes = [];
  1173. var dataItemNodes = [];
  1174. var dataItemJsonNodes = [];
  1175. var scriptDisposeNodes = [];
  1176. var asyncPostBackControlIDsNode, postBackControlIDsNode,
  1177. updatePanelIDsNode, asyncPostBackTimeoutNode,
  1178. childUpdatePanelIDsNode, panelsToRefreshNode, formActionNode,
  1179. versionNode;
  1180. // Sort delta by type
  1181. for (var i = 0, l = delta.length; i < l; i++) {
  1182. var deltaNode = delta[i];
  1183. switch (deltaNode.type) {
  1184. case "#":
  1185. versionNode = deltaNode;
  1186. break;
  1187. case "updatePanel":
  1188. Array.add(updatePanelNodes, deltaNode);
  1189. break;
  1190. case "hiddenField":
  1191. Array.add(hiddenFieldNodes, deltaNode);
  1192. break;
  1193. case "arrayDeclaration":
  1194. Array.add(arrayDeclarationNodes, deltaNode);
  1195. break;
  1196. case "scriptBlock":
  1197. Array.add(scriptBlockNodes, deltaNode);
  1198. break;
  1199. case "scriptStartupBlock":
  1200. Array.add(scriptStartupNodes, deltaNode);
  1201. break;
  1202. case "expando":
  1203. Array.add(expandoNodes, deltaNode);
  1204. break;
  1205. case "onSubmit":
  1206. Array.add(onSubmitNodes, deltaNode);
  1207. break;
  1208. case "asyncPostBackControlIDs":
  1209. asyncPostBackControlIDsNode = deltaNode;
  1210. break;
  1211. case "postBackControlIDs":
  1212. postBackControlIDsNode = deltaNode;
  1213. break;
  1214. case "updatePanelIDs":
  1215. updatePanelIDsNode = deltaNode;
  1216. break;
  1217. case "asyncPostBackTimeout":
  1218. asyncPostBackTimeoutNode = deltaNode;
  1219. break;
  1220. case "childUpdatePanelIDs":
  1221. childUpdatePanelIDsNode = deltaNode;
  1222. break;
  1223. case "panelsToRefreshIDs":
  1224. panelsToRefreshNode = deltaNode;
  1225. break;
  1226. case "formAction":
  1227. formActionNode = deltaNode;
  1228. break;
  1229. case "dataItem":
  1230. Array.add(dataItemNodes, deltaNode);
  1231. break;
  1232. case "dataItemJson":
  1233. Array.add(dataItemJsonNodes, deltaNode);
  1234. break;
  1235. case "scriptDispose":
  1236. Array.add(scriptDisposeNodes, deltaNode);
  1237. break;
  1238. case "pageRedirect":
  1239. if (versionNode && parseFloat(versionNode.content) >= 4) {
  1240. // asp.net 4+ will uri encode the entire value
  1241. deltaNode.content = unescape(deltaNode.content);
  1242. }
  1243. // DevDiv Bugs 100201: IE does not set referrer header on redirect if you set window.location, inject anchor node instead
  1244. // dynamic anchor technique only works on IE
  1245. if (Sys.Browser.agent === Sys.Browser.InternetExplorer) {
  1246. var anchor = document.createElement("a");
  1247. anchor.style.display = 'none';
  1248. // cancel bubble so body.onclick is not raised
  1249. anchor.attachEvent("onclick", cancelBubble);
  1250. anchor.href = deltaNode.content;
  1251. // do not append it to the body since that can cause the IE Operation Aborted error.
  1252. // do not append it to the form since that can have the same problem.
  1253. // appending it as a sibling _before_ the form is acceptable.
  1254. this._form.parentNode.insertBefore(anchor, this._form);
  1255. anchor.click();
  1256. anchor.detachEvent("onclick", cancelBubble);
  1257. this._form.parentNode.removeChild(anchor);
  1258. function cancelBubble(e) {
  1259. e.cancelBubble = true;
  1260. }
  1261. }
  1262. else {
  1263. window.location.href = deltaNode.content;
  1264. }
  1265. return null;
  1266. case "error":
  1267. // The id contains the HTTP status code and the content contains the message
  1268. this._endPostBack(this._createPageRequestManagerServerError(Number.parseInvariant(deltaNode.id), deltaNode.content), executor, null);
  1269. return null;
  1270. case "pageTitle":
  1271. document.title = deltaNode.content;
  1272. break;
  1273. case "focus":
  1274. this._controlIDToFocus = deltaNode.content;
  1275. break;
  1276. default:
  1277. // If there was an unknown message, go into error mode
  1278. this._endPostBack(this._createPageRequestManagerParserError(String.format(Sys.WebForms.Res.PRM_UnknownToken, deltaNode.type)), executor, null);
  1279. return null;
  1280. } // switch
  1281. } // for (var i = 0, l = delta.length; i < l; i++)
  1282. return {
  1283. version4: versionNode ? (parseFloat(versionNode.content) >= 4) : false,
  1284. executor: executor,
  1285. updatePanelNodes: updatePanelNodes,
  1286. hiddenFieldNodes: hiddenFieldNodes,
  1287. arrayDeclarationNodes: arrayDeclarationNodes,
  1288. scriptBlockNodes: scriptBlockNodes,
  1289. scriptStartupNodes: scriptStartupNodes,
  1290. expandoNodes: expandoNodes,
  1291. onSubmitNodes: onSubmitNodes,
  1292. dataItemNodes: dataItemNodes,
  1293. dataItemJsonNodes: dataItemJsonNodes,
  1294. scriptDisposeNodes: scriptDisposeNodes,
  1295. asyncPostBackControlIDsNode: asyncPostBackControlIDsNode,
  1296. postBackControlIDsNode: postBackControlIDsNode,
  1297. updatePanelIDsNode: updatePanelIDsNode,
  1298. asyncPostBackTimeoutNode: asyncPostBackTimeoutNode,
  1299. childUpdatePanelIDsNode: childUpdatePanelIDsNode,
  1300. panelsToRefreshNode: panelsToRefreshNode,
  1301. formActionNode: formActionNode };
  1302. },
  1303. _processUpdatePanelArrays: function PageRequestManager$_processUpdatePanelArrays(updatePanelIDs, asyncPostBackControlIDs, postBackControlIDs, version4) {
  1304. var newUpdatePanelIDs, newUpdatePanelClientIDs, newUpdatePanelHasChildrenAsTriggers;
  1305. // DevDiv Bugs 154403:
  1306. // Processes the lists of update panel data into their meaningful arrays.
  1307. // This was factored as part of the fix for 154403 to allow the arrays to be
  1308. // used in a temporary context before being committed to the PRM's instance
  1309. // variables. _commitControls copies the neccessary arrays when the temporary
  1310. // context can be committed (after all scripts have loaded).
  1311. if (updatePanelIDs) {
  1312. // Parse the array that has the UniqueIDs and split the data out.
  1313. // The array contains UniqueIDs with either a 't' or 'f' prefix
  1314. // indicating whether the panel has ChildrenAsTriggers enabled.
  1315. var l = updatePanelIDs.length,
  1316. m = version4 ? 2 : 1;
  1317. newUpdatePanelIDs = new Array(l/m);
  1318. newUpdatePanelClientIDs = new Array(l/m);
  1319. newUpdatePanelHasChildrenAsTriggers = new Array(l/m);
  1320. for (var i = 0, j = 0; i < l; i += m, j++) {
  1321. var ct,
  1322. uniqueID = updatePanelIDs[i],
  1323. clientID = version4 ? updatePanelIDs[i+1] : "";
  1324. // UpdatePanel's ClientID may be set. If so, both the uniqueID and clientID are given
  1325. // otherwise only the uniqueID is given, which we can convert to a clientID
  1326. ct = (uniqueID.charAt(0) === 't');
  1327. uniqueID = uniqueID.substr(1);
  1328. if (!clientID) {
  1329. clientID = this._uniqueIDToClientID(uniqueID);
  1330. }
  1331. // The three arrays are kept in sync by index
  1332. newUpdatePanelHasChildrenAsTriggers[j] = ct;
  1333. newUpdatePanelIDs[j] = uniqueID;
  1334. newUpdatePanelClientIDs[j] = clientID;
  1335. }
  1336. }
  1337. else {
  1338. newUpdatePanelIDs = [];
  1339. newUpdatePanelClientIDs = [];
  1340. newUpdatePanelHasChildrenAsTriggers = [];
  1341. }
  1342. var newAsyncPostBackControlIDs = [];
  1343. var newAsyncPostBackControlClientIDs = [];
  1344. this._convertToClientIDs(asyncPostBackControlIDs, newAsyncPostBackControlIDs, newAsyncPostBackControlClientIDs, version4);
  1345. var newPostBackControlIDs = [];
  1346. var newPostBackControlClientIDs = [];
  1347. this._convertToClientIDs(postBackControlIDs, newPostBackControlIDs, newPostBackControlClientIDs, version4);
  1348. return {
  1349. updatePanelIDs: newUpdatePanelIDs,
  1350. updatePanelClientIDs: newUpdatePanelClientIDs,
  1351. updatePanelHasChildrenAsTriggers: newUpdatePanelHasChildrenAsTriggers,
  1352. asyncPostBackControlIDs: newAsyncPostBackControlIDs,
  1353. asyncPostBackControlClientIDs: newAsyncPostBackControlClientIDs,
  1354. postBackControlIDs: newPostBackControlIDs,
  1355. postBackControlClientIDs: newPostBackControlClientIDs
  1356. };
  1357. },
  1358. _queueScripts: function PageRequestManager$_queueScripts(scriptLoader, scriptBlockNodes, queueIncludes, queueBlocks) {
  1359. for (var i = 0, l = scriptBlockNodes.length; i < l; i++) {
  1360. var scriptBlockType = scriptBlockNodes[i].id;
  1361. switch (scriptBlockType) {
  1362. case "ScriptContentNoTags":
  1363. if (!queueBlocks) {
  1364. continue;
  1365. }
  1366. // The content contains raw JavaScript
  1367. scriptLoader.queueScriptBlock(scriptBlockNodes[i].content);
  1368. break;
  1369. case "ScriptContentWithTags":
  1370. // The content contains serialized attributes for the script tag
  1371. var scriptTagAttributes = window.eval("(" + scriptBlockNodes[i].content + ")");
  1372. if (scriptTagAttributes.src) {
  1373. // Don't reload a script that's already in the DOM
  1374. // or if not queuing includes
  1375. if (!queueIncludes || Sys._ScriptLoader.isScriptLoaded(scriptTagAttributes.src)) {
  1376. continue;
  1377. }
  1378. }
  1379. else if (!queueBlocks) {
  1380. // its a script block
  1381. continue;
  1382. }
  1383. scriptLoader.queueCustomScriptTag(scriptTagAttributes);
  1384. break;
  1385. case "ScriptPath":
  1386. // Don't reload a script that's already in the DOM
  1387. // only if we aren't loading includes
  1388. if (!queueIncludes || Sys._ScriptLoader.isScriptLoaded(scriptBlockNodes[i].content)) {
  1389. continue;
  1390. }
  1391. // The content contains the URL reference of the script to load
  1392. scriptLoader.queueScriptReference(scriptBlockNodes[i].content);
  1393. break;
  1394. }
  1395. }
  1396. },
  1397. _registerDisposeScript: function PageRequestManager$_registerDisposeScript(panelID, disposeScript) {
  1398. if (!this._scriptDisposes[panelID]) {
  1399. this._scriptDisposes[panelID] = [disposeScript];
  1400. }
  1401. else {
  1402. Array.add(this._scriptDisposes[panelID], disposeScript);
  1403. }
  1404. },
  1405. _scriptIncludesLoadComplete: function PageRequestManager$_scriptIncludesLoadComplete(scriptLoader, data) {
  1406. // script includes have loaded, completing the asynchronous portion of the update
  1407. // processing. At this point, it is not possible for another async post to begin
  1408. // before we are finished updating the HTML and processing the delta's hidden fields
  1409. // and inline script blocks.
  1410. // But another async post may have started while we were loading script includes.
  1411. // If so, we abort processing this response, because the new request takes priority
  1412. // and has already sent viewstate and event validation to the server. If we were to process
  1413. // this old response further we could corrupt viewstate and event validation.
  1414. // At worst we may have loaded some unnecessary script includes, but its likely they would
  1415. // have been required for the new update anyway, and if not they should be harmless libraries.
  1416. if (data.executor.get_webRequest() !== this._request) {
  1417. return;
  1418. }
  1419. // DevDiv Bugs 188564: Update may not have an async postback timeout node.
  1420. this._commitControls(data.updatePanelData,
  1421. data.asyncPostBackTimeoutNode ? data.asyncPostBackTimeoutNode.content : null);
  1422. // Update the form action (it may have changed due to cookieless session, etc.)
  1423. if (data.formActionNode) {
  1424. this._form.action = data.formActionNode.content;
  1425. }
  1426. var i, l, node;
  1427. // Update the rendering for each delta panel and dispose all the contents.
  1428. // The dispose can happen either through DOM elements that have dispose
  1429. // support or through direct dispose registrations done on the server.
  1430. for (i = 0, l = data.updatePanelNodes.length; i < l; i++) {
  1431. node = data.updatePanelNodes[i];
  1432. var updatePanelElement = document.getElementById(node.id);
  1433. if (!updatePanelElement) {
  1434. this._endPostBack(Error.invalidOperation(String.format(Sys.WebForms.Res.PRM_MissingPanel, node.id)), data.executor, data);
  1435. return;
  1436. }
  1437. this._updatePanel(updatePanelElement, node.content);
  1438. }
  1439. // Update the dispose entries
  1440. // We have to do this after we disposed all the panels since otherwise
  1441. // we would run the dispose scripts on the brand new markup.
  1442. for (i = 0, l = data.scriptDisposeNodes.length; i < l; i++) {
  1443. node = data.scriptDisposeNodes[i];
  1444. this._registerDisposeScript(node.id, node.content);
  1445. }
  1446. // Update the hidden fields
  1447. // DevDiv Bugs 161922, 138251:
  1448. // First remove transient fields that might be omitted in the response
  1449. // If they are explictly defined they will be recreated.
  1450. for (i = 0, l = this._transientFields.length; i < l; i++) {
  1451. var field = document.getElementById(this._transientFields[i]);
  1452. if (field) {
  1453. // when removing the field, be sure to remove its parent container, if any
  1454. var toRemove = field._isContained ? field.parentNode : field;
  1455. toRemove.parentNode.removeChild(toRemove);
  1456. }
  1457. }
  1458. for (i = 0, l = data.hiddenFieldNodes.length; i < l; i++) {
  1459. node = data.hiddenFieldNodes[i];
  1460. this._createHiddenField(node.id, node.content);
  1461. }
  1462. if (data.scriptsFailed) {
  1463. // the script includes in the first step failed to load. Raise the error now that the DOM is updated.
  1464. throw Sys._ScriptLoader._errorScriptLoadFailed(data.scriptsFailed.src, data.scriptsFailed.multipleCallbacks);
  1465. }
  1466. // continue on to loading literal client script blocks, arrays, expandos, startup scripts, and onSubmitStatements (in that order)
  1467. // Load literal script blocks
  1468. this._queueScripts(scriptLoader, data.scriptBlockNodes, false, true);
  1469. // Update array declarations
  1470. var arrayScript = '';
  1471. for (i = 0, l = data.arrayDeclarationNodes.length; i < l; i++) {
  1472. node = data.arrayDeclarationNodes[i];
  1473. arrayScript += "Sys.WebForms.PageRequestManager._addArrayElement('" + node.id + "', " + node.content + ");\r\n";
  1474. }
  1475. // Update expandos
  1476. var expandoScript = '';
  1477. for (i = 0, l = data.expandoNodes.length; i < l; i++) {
  1478. node = data.expandoNodes[i];
  1479. expandoScript += node.id + " = " + node.content + "\r\n";
  1480. }
  1481. // Execute these dynamically created scripts through the ScriptLoader so that
  1482. // they get executed in the global window context. If we execute them through
  1483. // calls to eval() then they will evaluate in this function's context, which
  1484. // is incorrect.
  1485. if (arrayScript.length) {
  1486. scriptLoader.queueScriptBlock(arrayScript);
  1487. }
  1488. if (expandoScript.length) {
  1489. scriptLoader.queueScriptBlock(expandoScript);
  1490. }
  1491. this._queueScripts(scriptLoader, data.scriptStartupNodes, true, true);
  1492. // Update onsubmit statements
  1493. // Create a function that calls the submit statement and otherwise returns true;
  1494. var onSubmitStatementScript = '';
  1495. for (i = 0, l = data.onSubmitNodes.length; i < l; i++) {
  1496. if (i === 0) {
  1497. onSubmitStatementScript = 'Array.add(Sys.WebForms.PageRequestManager.getInstance()._onSubmitStatements, function() {\r\n';
  1498. }
  1499. onSubmitStatementScript += data.onSubmitNodes[i].content + "\r\n";
  1500. }
  1501. if (onSubmitStatementScript.length) {
  1502. onSubmitStatementScript += "\r\nreturn true;\r\n});\r\n";
  1503. scriptLoader.queueScriptBlock(onSubmitStatementScript);
  1504. }
  1505. // PRM does not support load timeout
  1506. // timeout, completeCallback, failedCallback, timeoutCallback
  1507. // no failed callback -- if there is a failure ScriptLoader will throw.
  1508. scriptLoader.loadScripts(0,
  1509. Function.createDelegate(this, Function.createCallback(this._scriptsLoadComplete, data)), null, null);
  1510. // Do not add code after the call to loadScripts(). If you need to do extra
  1511. // processing after scripts are loaded, do it in _scriptsLoadComplete.
  1512. },
  1513. _scriptIncludesLoadFailed: function PageRequestManager$_scriptIncludesLoadFailed(scriptLoader, scriptElement, multipleCallbacks, data) {
  1514. // called when script includes fail to load from _onFormSubmitComplete
  1515. // save error details so we can raise the error later
  1516. data.scriptsFailed = { src: scriptElement.src, multipleCallbacks: multipleCallbacks };
  1517. this._scriptIncludesLoadComplete(scriptLoader, data);
  1518. },
  1519. _scriptsLoadComplete: function PageRequestManager$_scriptsLoadComplete(scriptLoader, data) {
  1520. // This function gets called after all scripts have been loaded by the PRM.
  1521. // It might also get called directly if there aren't any scripts to load.
  1522. // Its purpose is to finish off the processing of a postback.
  1523. var response = data.executor;
  1524. // These two variables are used by ASP.net callbacks.
  1525. // Because of how callbacks work, we have to re-initialize the
  1526. // variables to an empty state so that their values don't keep
  1527. // growing on every async postback. Then we have to re-initialize
  1528. // the callback process.
  1529. if (window.__theFormPostData) {
  1530. window.__theFormPostData = "";
  1531. }
  1532. if (window.__theFormPostCollection) {
  1533. window.__theFormPostCollection = [];
  1534. }
  1535. if (window.WebForm_InitCallback) {
  1536. window.WebForm_InitCallback();
  1537. }
  1538. // Restore scroll position
  1539. if (this._scrollPosition) {
  1540. // window.scrollTo() is supported by IE and Firefox (and possibly Safari)
  1541. if (window.scrollTo) {
  1542. window.scrollTo(this._scrollPosition.x, this._scrollPosition.y);
  1543. }
  1544. this._scrollPosition = null;
  1545. }
  1546. Sys.Application.endCreateComponents();
  1547. // Raise completion events
  1548. this._pageLoaded(false, data);
  1549. this._endPostBack(null, response, data);
  1550. // Set focus
  1551. if (this._controlIDToFocus) {
  1552. var focusTarget;
  1553. var oldContentEditableSetting;
  1554. if (Sys.Browser.agent === Sys.Browser.InternetExplorer) {
  1555. // IE6 and IE7 have a bug where you can't focus certain elements
  1556. // if they've been changed in the DOM. To work around this they
  1557. // suggested turning off contentEditable temporarily while focusing
  1558. // the target element.
  1559. var targetControl = $get(this._controlIDToFocus);
  1560. focusTarget = targetControl;
  1561. // If the focus control isn't focusable, default to the first focusable child
  1562. if (targetControl && (!WebForm_CanFocus(targetControl))) {
  1563. focusTarget = WebForm_FindFirstFocusableChild(targetControl);
  1564. }
  1565. // If we found the focus target and it supports contentEditable then
  1566. // turn it off. Otherwise forget we ever tried to disable content editing.
  1567. if (focusTarget && (typeof(focusTarget.contentEditable) !== "undefined")) {
  1568. oldContentEditableSetting = focusTarget.contentEditable;
  1569. focusTarget.contentEditable = false;
  1570. }
  1571. else {
  1572. focusTarget = null;
  1573. }
  1574. }
  1575. WebForm_AutoFocus(this._controlIDToFocus);
  1576. if (focusTarget) {
  1577. // If we did the contentEditable hack, reset the value
  1578. focusTarget.contentEditable = oldContentEditableSetting;
  1579. }
  1580. this._controlIDToFocus = null;
  1581. }
  1582. },
  1583. _splitNodeIntoArray: function PageRequestManager$_splitNodeIntoArray(node) {
  1584. var str = node.content;
  1585. var arr = str.length ? str.split(',') : [];
  1586. return arr;
  1587. },
  1588. _uniqueIDToClientID: function PageRequestManager$_uniqueIDToClientID(uniqueID) {
  1589. // Convert unique IDs to client IDs by replacing all '$' with '_'
  1590. return uniqueID.replace(/\$/g, '_');
  1591. },
  1592. _updateControls: function PageRequestManager$_updateControls(updatePanelIDs, asyncPostBackControlIDs, postBackControlIDs, asyncPostBackTimeout, version4) {
  1593. this._commitControls(
  1594. this._processUpdatePanelArrays(updatePanelIDs, asyncPostBackControlIDs, postBackControlIDs, version4),
  1595. asyncPostBackTimeout);
  1596. },
  1597. _updatePanel: function PageRequestManager$_updatePanel(updatePanelElement, rendering) {
  1598. for (var updatePanelID in this._scriptDisposes) {
  1599. if (this._elementContains(updatePanelElement, document.getElementById(updatePanelID))) {
  1600. // Run all the dispose scripts for this panel
  1601. var disposeScripts = this._scriptDisposes[updatePanelID];
  1602. for (var i = 0, l = disposeScripts.length; i < l; i++) {
  1603. window.eval(disposeScripts[i]);
  1604. }
  1605. // Remove the dispose entries for this panel
  1606. delete this._scriptDisposes[updatePanelID];
  1607. }
  1608. }
  1609. Sys.Application.disposeElement(updatePanelElement, true);
  1610. // Update the region with the new UpdatePanel content
  1611. updatePanelElement.innerHTML = rendering;
  1612. },
  1613. _validPosition: function PageRequestManager$_validPosition(position) {
  1614. return (typeof(position) !== "undefined") && (position !== null) && (position !== 0);
  1615. }
  1616. }
  1617. $type.getInstance = function PageRequestManager$getInstance() {
  1618. /// <summary locid="M:J#Sys.WebForms.PageRequestManager.getInstance">Gets the current instance of the PageRequestManager.</summary>
  1619. /// <returns type="Sys.WebForms.PageRequestManager"></returns>
  1620. //#if DEBUG
  1621. if (arguments.length !== 0) throw Error.parameterCount();
  1622. //#endif
  1623. var prm = Sys.WebForms.PageRequestManager._instance;
  1624. if (!prm) {
  1625. prm = Sys.WebForms.PageRequestManager._instance = new Sys.WebForms.PageRequestManager();
  1626. }
  1627. return prm;
  1628. }
  1629. $type._addArrayElement = function PageRequestManager$_addArrayElement(arrayName) {
  1630. if (!window[arrayName]) {
  1631. // Create array if doesn't already exist
  1632. window[arrayName] = new Array();
  1633. }
  1634. // add the argument list, not counting arrayName
  1635. // note: cannot use Array.addRange or Array.dequeue
  1636. // because 'arguments' is not actually an instance of an Array.
  1637. for (var i = 1, l = arguments.length; i < l; i++) {
  1638. Array.add(window[arrayName], arguments[i]);
  1639. }
  1640. }
  1641. $type._initialize = function PageRequestManager$_initialize() {
  1642. var prm = Sys.WebForms.PageRequestManager.getInstance();
  1643. prm._initializeInternal.apply(prm, arguments);
  1644. }
  1645. $type.registerClass('Sys.WebForms.PageRequestManager');