added support for multi form environment
[mono.git] / mcs / class / System.Web.Extensions / System.Web.UI / ScriptManager.cs
1 //
2 // ScriptManager.cs
3 //
4 // Author:
5 //   Igor Zelmanovich <igorz@mainsoft.com>
6 //
7 // (C) 2007 Mainsoft, Inc.  http://www.mainsoft.com
8 //
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.Collections.Generic;
32 using System.Text;
33 using System.ComponentModel;
34 using System.Security.Permissions;
35 using System.Collections.Specialized;
36 using System.Collections;
37 using System.Web.Handlers;
38 using System.Reflection;
39 using System.Web.Configuration;
40 using System.Web.UI.HtmlControls;
41 using System.IO;
42 using System.Globalization;
43 using System.Threading;
44 using System.Web.Script.Serialization;
45 using System.Web.Script.Services;
46 using System.Xml;
47
48 namespace System.Web.UI
49 {
50         [ParseChildrenAttribute (true)]
51         [DefaultPropertyAttribute ("Scripts")]
52         [DesignerAttribute ("System.Web.UI.Design.ScriptManagerDesigner, System.Web.Extensions.Design, Version=1.0.61025.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
53         [NonVisualControlAttribute]
54         [PersistChildrenAttribute (false)]
55         [AspNetHostingPermissionAttribute (SecurityAction.LinkDemand, Level = AspNetHostingPermissionLevel.Minimal)]
56         [AspNetHostingPermissionAttribute (SecurityAction.InheritanceDemand, Level = AspNetHostingPermissionLevel.Minimal)]
57         public class ScriptManager : Control, IPostBackDataHandler
58         {
59                 // the keywords are used in fomatting async response
60                 const string updatePanel = "updatePanel";
61                 const string hiddenField = "hiddenField";
62                 const string arrayDeclaration = "arrayDeclaration";
63                 const string scriptBlock = "scriptBlock";
64                 const string expando = "expando";
65                 const string onSubmit = "onSubmit";
66                 const string asyncPostBackControlIDs = "asyncPostBackControlIDs";
67                 const string postBackControlIDs = "postBackControlIDs";
68                 const string updatePanelIDs = "updatePanelIDs";
69                 const string asyncPostBackTimeout = "asyncPostBackTimeout";
70                 const string childUpdatePanelIDs = "childUpdatePanelIDs";
71                 const string panelsToRefreshIDs = "panelsToRefreshIDs";
72                 const string formAction = "formAction";
73                 const string dataItem = "dataItem";
74                 const string dataItemJson = "dataItemJson";
75                 const string scriptDispose = "scriptDispose";
76                 const string pageRedirect = "pageRedirect";
77                 const string error = "error";
78                 const string pageTitle = "pageTitle";
79                 const string focus = "focus";
80                 const string scriptContentNoTags = "ScriptContentNoTags";
81                 const string scriptContentWithTags = "ScriptContentWithTags";
82                 const string scriptPath = "ScriptPath";
83
84                 static readonly object ScriptManagerKey = new object ();
85
86                 int _asyncPostBackTimeout = 90;
87                 List<Control> _asyncPostBackControls;
88                 List<Control> _postBackControls;
89                 List<UpdatePanel> _childUpdatePanels;
90                 List<UpdatePanel> _panelsToRefresh;
91                 List<UpdatePanel> _updatePanels;
92                 ScriptReferenceCollection _scripts;
93                 ServiceReferenceCollection _services;
94                 bool _isInAsyncPostBack;
95                 bool _isInPartialRendering;
96                 string _asyncPostBackSourceElementID;
97                 ScriptMode _scriptMode = ScriptMode.Auto;
98                 bool _enableScriptGlobalization;
99                 bool _enableScriptLocalization;
100                 string _scriptPath;
101                 ScriptEntry _clientScriptBlocks;
102                 ScriptEntry _startupScriptBlocks;
103                 ScriptEntry _scriptIncludes;
104                 ScriptEntry _onSubmitStatements;
105                 List<ArrayDeclaration> _arrayDeclarations;
106                 Hashtable _hiddenFields;
107                 List<IScriptControl> _registeredScriptControls;
108                 Dictionary<IExtenderControl, Control> _registeredExtenderControls;
109                 bool? _supportsPartialRendering;
110                 bool _enablePartialRendering = true;
111                 bool _init;
112                 string _panelToRefreshID;
113                 Dictionary<Control, DataItemEntry> _dataItems;
114                 bool _enablePageMethods;
115                 string _controlIDToFocus;
116                 bool _allowCustomErrorsRedirect = true;
117                 string _asyncPostBackErrorMessage;
118                 List<DisposeScriptEntry> _disposeScripts;
119                 List<ScriptReferenceEntry> _scriptToRegister;
120                 bool _loadScriptsBeforeUI = true;
121                 AuthenticationServiceManager _authenticationService;
122                 ProfileServiceManager _profileService;
123
124                 [DefaultValue (true)]
125                 [Category ("Behavior")]
126                 public bool AllowCustomErrorsRedirect {
127                         get {
128                                 return _allowCustomErrorsRedirect;
129                         }
130                         set {
131                                 _allowCustomErrorsRedirect = value;
132                         }
133                 }
134
135                 [Category ("Behavior")]
136                 [DefaultValue ("")]
137                 public string AsyncPostBackErrorMessage {
138                         get {
139                                 if (String.IsNullOrEmpty (_asyncPostBackErrorMessage))
140                                         return String.Empty;
141                                 return _asyncPostBackErrorMessage;
142                         }
143                         set {
144                                 _asyncPostBackErrorMessage = value;
145                         }
146                 }
147
148                 [Browsable (false)]
149                 public string AsyncPostBackSourceElementID {
150                         get {
151                                 if (_asyncPostBackSourceElementID == null)
152                                         return String.Empty;
153                                 return _asyncPostBackSourceElementID;
154                         }
155                 }
156
157                 [DefaultValue (90)]
158                 [Category ("Behavior")]
159                 public int AsyncPostBackTimeout {
160                         get {
161                                 return _asyncPostBackTimeout;
162                         }
163                         set {
164                                 _asyncPostBackTimeout = value;
165                         }
166                 }
167
168                 [Category ("Behavior")]
169                 [MergableProperty (false)]
170                 [DefaultValue ("")]
171                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
172                 [PersistenceMode (PersistenceMode.InnerProperty)]
173                 public AuthenticationServiceManager AuthenticationService {
174                         get {
175                                 if (_authenticationService == null)
176                                         _authenticationService = new AuthenticationServiceManager ();
177                                 return _authenticationService;
178                         }
179                 }
180
181                 [Category ("Behavior")]
182                 [DefaultValue (false)]
183                 public bool EnablePageMethods {
184                         get {
185                                 return _enablePageMethods;
186                         }
187                         set {
188                                 _enablePageMethods = value;
189                         }
190                 }
191
192                 [DefaultValue (true)]
193                 [Category ("Behavior")]
194                 public bool EnablePartialRendering {
195                         get {
196                                 return _enablePartialRendering;
197                         }
198                         set {
199                                 if (_init)
200                                         throw new InvalidOperationException ();
201                                 _enablePartialRendering = value;
202                         }
203                 }
204
205                 [DefaultValue (false)]
206                 [Category ("Behavior")]
207                 public bool EnableScriptGlobalization {
208                         get {
209                                 return _enableScriptGlobalization;
210                         }
211                         set {
212                                 _enableScriptGlobalization = value;
213                         }
214                 }
215
216                 [Category ("Behavior")]
217                 [DefaultValue (false)]
218                 public bool EnableScriptLocalization {
219                         get {
220                                 return _enableScriptLocalization;
221                         }
222                         set {
223                                 _enableScriptLocalization = value;
224                         }
225                 }
226
227                 [Browsable (false)]
228                 public bool IsDebuggingEnabled {
229                         get {
230                                 if (IsDeploymentRetail)
231                                         return false;
232 #if !TARGET_J2EE
233                                 CompilationSection compilation = (CompilationSection) WebConfigurationManager.GetSection ("system.web/compilation");
234                                 if (!compilation.Debug && (ScriptMode == ScriptMode.Auto || ScriptMode == ScriptMode.Inherit))
235                                         return false;
236 #endif
237                                 if (ScriptMode == ScriptMode.Release)
238                                         return false;
239
240                                 return true;
241                         }
242                 }
243
244                 bool IsDeploymentRetail {
245                         get {
246 #if TARGET_J2EE
247                                 return false;
248 #else
249                                 DeploymentSection deployment = (DeploymentSection) WebConfigurationManager.GetSection ("system.web/deployment");
250                                 return deployment.Retail;
251 #endif
252                         }
253                 }
254
255                 [Browsable (false)]
256                 public bool IsInAsyncPostBack {
257                         get {
258                                 return _isInAsyncPostBack;
259                         }
260                 }
261
262                 internal bool IsInPartialRendering {
263                         get {
264                                 return _isInPartialRendering;
265                         }
266                         set {
267                                 _isInPartialRendering = value;
268                         }
269                 }
270
271                 [Category ("Behavior")]
272                 [DefaultValue (true)]
273                 public bool LoadScriptsBeforeUI {
274                         get {
275                                 return _loadScriptsBeforeUI;
276                         }
277                         set {
278                                 _loadScriptsBeforeUI = value;
279                         }
280                 }
281
282                 [PersistenceMode (PersistenceMode.InnerProperty)]
283                 [DefaultValue ("")]
284                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
285                 [Category ("Behavior")]
286                 [MergableProperty (false)]
287                 public ProfileServiceManager ProfileService {
288                         get {
289                                 if (_profileService == null)
290                                         _profileService = new ProfileServiceManager ();
291                                 return _profileService;
292                         }
293                 }
294
295                 [Category ("Behavior")]
296 #if TARGET_J2EE
297                 [MonoLimitation ("The 'Auto' value is the same as 'Debug'.")]
298 #endif
299                 public ScriptMode ScriptMode {
300                         get {
301                                 return _scriptMode;
302                         }
303                         set {
304                                 if (value == ScriptMode.Inherit)
305                                         value = ScriptMode.Auto;
306                                 _scriptMode = value;
307                         }
308                 }
309
310                 [DefaultValue ("")]
311                 [Category ("Behavior")]
312                 public string ScriptPath {
313                         get {
314                                 if (_scriptPath == null)
315                                         return String.Empty;
316                                 return _scriptPath;
317                         }
318                         set {
319                                 _scriptPath = value;
320                         }
321                 }
322
323                 [PersistenceMode (PersistenceMode.InnerProperty)]
324                 [DefaultValue ("")]
325                 [Category ("Behavior")]
326                 [MergableProperty (false)]
327                 public ScriptReferenceCollection Scripts {
328                         get {
329                                 if (_scripts == null)
330                                         _scripts = new ScriptReferenceCollection ();
331
332                                 return _scripts;
333                         }
334                 }
335
336                 [PersistenceMode (PersistenceMode.InnerProperty)]
337                 [DefaultValue ("")]
338                 [MergableProperty (false)]
339                 [Category ("Behavior")]
340                 public ServiceReferenceCollection Services {
341                         get {
342                                 if (_services == null)
343                                         _services = new ServiceReferenceCollection ();
344
345                                 return _services;
346                         }
347                 }
348
349                 [DefaultValue (true)]
350                 [Browsable (false)]
351                 public bool SupportsPartialRendering {
352                         get {
353                                 if (!_supportsPartialRendering.HasValue)
354                                         _supportsPartialRendering = CheckSupportsPartialRendering ();
355                                 return _supportsPartialRendering.Value;
356                         }
357                         set {
358                                 if (_init)
359                                         throw new InvalidOperationException ();
360                                 if (!EnablePartialRendering && value)
361                                         throw new InvalidOperationException ("The SupportsPartialRendering property cannot be set when EnablePartialRendering is false.");
362
363                                 _supportsPartialRendering = value;
364                         }
365                 }
366
367                 bool CheckSupportsPartialRendering () {
368                         if (!EnablePartialRendering)
369                                 return false;
370                         // TODO: consider browser capabilities
371                         return true;
372                 }
373
374                 [EditorBrowsable (EditorBrowsableState.Never)]
375                 [Browsable (false)]
376                 [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
377                 public override bool Visible {
378                         get {
379                                 return true;
380                         }
381                         set {
382                                 throw new NotImplementedException ();
383                         }
384                 }
385
386                 [Category ("Action")]
387                 public event EventHandler<AsyncPostBackErrorEventArgs> AsyncPostBackError;
388
389                 [Category ("Action")]
390                 public event EventHandler<ScriptReferenceEventArgs> ResolveScriptReference;
391
392                 public static ScriptManager GetCurrent (Page page) {
393                         if (page == null)
394                                 throw new ArgumentNullException("page");
395                         return (ScriptManager) page.Items [ScriptManagerKey];
396                 }
397
398                 static void SetCurrent (Page page, ScriptManager instance) {
399                         page.Items [ScriptManagerKey] = instance;
400                 }
401
402                 protected virtual bool LoadPostData (string postDataKey, NameValueCollection postCollection) {
403                         _isInAsyncPostBack = true;
404                         string arg = postCollection [postDataKey];
405                         if (!String.IsNullOrEmpty (arg)) {
406                                 string [] args = arg.Split ('|');
407                                 _panelToRefreshID = args [0];
408                                 _asyncPostBackSourceElementID = args [1];
409                                 return true;
410                         }
411                         return false;
412                 }
413
414                 protected internal virtual void OnAsyncPostBackError (AsyncPostBackErrorEventArgs e) {
415                         if (AsyncPostBackError != null)
416                                 AsyncPostBackError (this, e);
417                 }
418
419                 protected override void OnInit (EventArgs e) {
420                         base.OnInit (e);
421
422                         if (GetCurrent (Page) != null)
423                                 throw new InvalidOperationException ("Only one instance of a ScriptManager can be added to the page.");
424
425                         SetCurrent (Page, this);
426                         Page.Error += new EventHandler (OnPageError);
427                         _init = true;
428                 }
429
430                 void OnPageError (object sender, EventArgs e) {
431                         if (IsInAsyncPostBack)
432                                 OnAsyncPostBackError (new AsyncPostBackErrorEventArgs (Context.Error));
433                 }
434
435                 protected override void OnPreRender (EventArgs e) {
436                         base.OnPreRender (e);
437
438                         Page.PreRenderComplete += new EventHandler (OnPreRenderComplete);
439
440                         if (IsInAsyncPostBack) {
441                                 Page.SetRenderMethodDelegate (RenderPageCallback);
442                         }
443                         else {
444                                 if (EnableScriptGlobalization) {
445                                         CultureInfo culture = Thread.CurrentThread.CurrentCulture;
446                                         string script = String.Format ("var __cultureInfo = '{0}';", JavaScriptSerializer.DefaultSerializer.Serialize (new CultureInfoSerializer (culture)));
447                                         RegisterClientScriptBlock (this, typeof (ScriptManager), "ScriptGlobalization", script, true);
448                                 }
449
450                                 // Register dispose script
451                                 if (_disposeScripts != null && _disposeScripts.Count > 0) {
452                                         StringBuilder sb = new StringBuilder ();
453                                         sb.AppendLine ();
454                                         for (int i = 0; i < _disposeScripts.Count; i++) {
455                                                 DisposeScriptEntry entry = _disposeScripts [i];
456                                                 if (IsMultiForm)
457                                                         sb.Append ("Sys.WebForms.PageRequestManager.getInstance($get(\"" + Page.Form.ClientID + "\"))._registerDisposeScript(\"");
458                                                 else
459                                                 sb.Append ("Sys.WebForms.PageRequestManager.getInstance()._registerDisposeScript(\"");
460                                                 sb.Append (entry.UpdatePanel.ClientID);
461                                                 sb.Append ("\", ");
462                                                 sb.Append (JavaScriptSerializer.DefaultSerializer.Serialize (entry.Script)); //JavaScriptSerializer.Serialize used escape script literal 
463                                                 sb.AppendLine (");");
464                                         }
465                                         RegisterStartupScript (this, typeof (ExtenderControl), "disposeScripts;", sb.ToString (), true);
466                                 }
467
468 #if TARGET_DOTNET
469                                 // to cause webform client script being included
470                                 Page.ClientScript.GetPostBackEventReference (new PostBackOptions (this, null, null, false, false, false, true, true, null));
471 #else
472                                 Page.ClientScript.GetPostBackEventReference (this, null);
473 #endif
474                         }
475                 }
476
477                 void OnPreRenderComplete (object sender, EventArgs e) {
478                         // Resolve Scripts
479                         ScriptReference ajaxScript = new ScriptReference ("MicrosoftAjax.js", String.Empty);
480                         ajaxScript.NotifyScriptLoaded = false;
481                         OnResolveScriptReference (new ScriptReferenceEventArgs (ajaxScript));
482
483                         ScriptReference ajaxWebFormsScript = new ScriptReference ("MicrosoftAjaxWebForms.js", String.Empty);
484                         ajaxWebFormsScript.NotifyScriptLoaded = false;
485                         OnResolveScriptReference (new ScriptReferenceEventArgs (ajaxWebFormsScript));
486
487                         ScriptReference ajaxExtensionScript = null;
488                         ScriptReference ajaxWebFormsExtensionScript = null;
489                         if (IsMultiForm) {
490                                 ajaxExtensionScript = new ScriptReference ("MicrosoftAjaxExtension.js", String.Empty);
491                                 OnResolveScriptReference (new ScriptReferenceEventArgs (ajaxExtensionScript));
492                                 
493                                 ajaxWebFormsExtensionScript = new ScriptReference ("MicrosoftAjaxWebFormsExtension.js", String.Empty);
494                                 OnResolveScriptReference (new ScriptReferenceEventArgs (ajaxWebFormsExtensionScript));
495                         }
496
497                         foreach (ScriptReferenceEntry script in GetScriptReferences ()) {
498                                 OnResolveScriptReference (new ScriptReferenceEventArgs (script.ScriptReference));
499                                 if (!IsInAsyncPostBack || (script.Control != this && HasBeenRendered (script.Control))) {
500                                         if (_scriptToRegister == null)
501                                                 _scriptToRegister = new List<ScriptReferenceEntry> ();
502                                         _scriptToRegister.Add (script);
503                                 }
504                         }
505
506                         if (!IsInAsyncPostBack) {
507                                 // Register Ajax framework script.
508                                 RegisterScriptReference (ajaxScript, true);
509                                 if (IsMultiForm) {
510                                         RegisterScriptReference (ajaxExtensionScript, true);
511                                         RegisterClientScriptBlock (this, typeof (ScriptManager), "Sys.Application", "\nSys.Application._initialize(document.getElementById('" + Page.Form.ClientID + "'));\n", true);
512                                 }
513
514                                 StringBuilder sb = new StringBuilder ();
515                                 sb.AppendLine ("if (typeof(Sys) === 'undefined') throw new Error('ASP.NET Ajax client-side framework failed to load.');");
516
517                                 ScriptingProfileServiceSection profileService = (ScriptingProfileServiceSection) WebConfigurationManager.GetSection ("system.web.extensions/scripting/webServices/profileService");
518                                 if (profileService.Enabled)
519                                         sb.AppendLine ("Sys.Services._ProfileService.DefaultWebServicePath = '" + ResolveClientUrl ("~" + System.Web.Script.Services.ProfileService.DefaultWebServicePath) + "';");
520                                 if (_profileService != null && !String.IsNullOrEmpty (_profileService.Path))
521                                         sb.AppendLine ("Sys.Services.ProfileService.set_path('" + ResolveUrl (_profileService.Path) + "');");
522
523                                 ScriptingAuthenticationServiceSection authenticationService = (ScriptingAuthenticationServiceSection) WebConfigurationManager.GetSection ("system.web.extensions/scripting/webServices/authenticationService");
524                                 if (authenticationService.Enabled)
525                                         sb.AppendLine ("Sys.Services._AuthenticationService.DefaultWebServicePath = '" + ResolveClientUrl ("~/Authentication_JSON_AppService.axd") + "';");
526                                 if (_authenticationService != null && !String.IsNullOrEmpty (_authenticationService.Path))
527                                         sb.AppendLine ("Sys.Services.AuthenticationService.set_path('" + ResolveUrl (_authenticationService.Path) + "');");
528
529                                 RegisterClientScriptBlock (this, typeof (ScriptManager), "Framework", sb.ToString (), true);
530
531                                 RegisterScriptReference (ajaxWebFormsScript, true);
532
533                                 if (IsMultiForm)
534                                         RegisterScriptReference (ajaxWebFormsExtensionScript, true);
535                         }
536
537                         // Register Scripts
538                         if (_scriptToRegister != null)
539                                 for (int i = 0; i < _scriptToRegister.Count; i++)
540                                         RegisterScriptReference (_scriptToRegister [i].ScriptReference, _scriptToRegister [i].LoadScriptsBeforeUI);
541
542                         if (!IsInAsyncPostBack) {
543                                 // Register services
544                                 if (_services != null && _services.Count > 0) {
545                                         for (int i = 0; i < _services.Count; i++) {
546                                                 RegisterServiceReference (_services [i]);
547                                         }
548                                 }
549
550                                 if (EnablePageMethods) {
551                                         LogicalTypeInfo logicalTypeInfo = LogicalTypeInfo.GetLogicalTypeInfo (Page.GetType (), Page.Request.FilePath);
552                                         RegisterClientScriptBlock (this, typeof (ScriptManager), "PageMethods", logicalTypeInfo.Proxy, true);
553                                 }
554
555                                 // Register startup script
556                                 if (IsMultiForm)
557                                         RegisterStartupScript (this, typeof (ExtenderControl), "Sys.Application.initialize();", "Sys.Application.getInstance($get(\"" + Page.Form.ClientID + "\")).initialize();\n", true);
558                                 else
559                                 RegisterStartupScript (this, typeof (ExtenderControl), "Sys.Application.initialize();", "Sys.Application.initialize();\n", true);
560                         }
561                 }
562
563 #if TARGET_J2EE
564                 bool IsMultiForm {
565                         get {
566                                 Mainsoft.Web.Configuration.PagesSection pageSection = (Mainsoft.Web.Configuration.PagesSection) WebConfigurationManager.GetSection ("mainsoft.web/pages");
567                                 if (pageSection != null)
568                                         return pageSection.MultiForm;
569                                 return false;
570                         }
571                 }
572 #else
573                 bool IsMultiForm {
574                         get { return false; }
575                 }
576 #endif
577
578                 static bool HasBeenRendered (Control control) {
579                         if (control == null)
580                                 return false;
581
582                         UpdatePanel parent = control.Parent as UpdatePanel;
583                         if (parent != null && parent.RequiresUpdate)
584                                 return true;
585
586                         return HasBeenRendered (control.Parent);
587                 }
588
589                 IEnumerable<ScriptReferenceEntry> GetScriptReferences () {
590                         if (_scripts != null && _scripts.Count > 0) {
591                                 for (int i = 0; i < _scripts.Count; i++) {
592                                         yield return new ScriptReferenceEntry (this, _scripts [i], LoadScriptsBeforeUI);
593                                 }
594                         }
595
596                         if (_registeredScriptControls != null && _registeredScriptControls.Count > 0) {
597                                 for (int i = 0; i < _registeredScriptControls.Count; i++) {
598                                         IEnumerable<ScriptReference> scripts = _registeredScriptControls [i].GetScriptReferences ();
599                                         if (scripts != null)
600                                                 foreach (ScriptReference s in scripts)
601                                                         yield return new ScriptReferenceEntry ((Control) _registeredScriptControls [i], s, LoadScriptsBeforeUI);
602                                 }
603                         }
604
605                         if (_registeredExtenderControls != null && _registeredExtenderControls.Count > 0) {
606                                 foreach (IExtenderControl ex in _registeredExtenderControls.Keys) {
607                                         IEnumerable<ScriptReference> scripts = ex.GetScriptReferences ();
608                                         if (scripts != null)
609                                                 foreach (ScriptReference s in scripts)
610                                                         yield return new ScriptReferenceEntry ((Control) ex, s, LoadScriptsBeforeUI);
611                                 }
612                         }
613                 }
614
615                 protected virtual void OnResolveScriptReference (ScriptReferenceEventArgs e) {
616                         if (ResolveScriptReference != null)
617                                 ResolveScriptReference (this, e);
618                 }
619
620                 protected virtual void RaisePostDataChangedEvent () {
621                         UpdatePanel up = Page.FindControl (_panelToRefreshID) as UpdatePanel;
622                         if (up != null && up.ChildrenAsTriggers)
623                                 up.Update ();
624                 }
625
626                 public static void RegisterArrayDeclaration (Control control, string arrayName, string arrayValue) {
627                         RegisterArrayDeclaration (control.Page, arrayName, arrayValue);
628                 }
629
630                 public static void RegisterArrayDeclaration (Page page, string arrayName, string arrayValue) {
631                         ScriptManager sm = GetCurrent (page);
632                         if (sm.IsInAsyncPostBack)
633                                 sm.RegisterArrayDeclaration (arrayName, arrayValue);
634                         else
635                                 page.ClientScript.RegisterArrayDeclaration (arrayName, arrayValue);
636                 }
637
638                 void RegisterArrayDeclaration (string arrayName, string arrayValue) {
639                         if (_arrayDeclarations == null)
640                                 _arrayDeclarations = new List<ArrayDeclaration> ();
641
642                         _arrayDeclarations.Add (new ArrayDeclaration (arrayName, arrayValue));
643                 }
644
645                 public void RegisterAsyncPostBackControl (Control control) {
646                         if (control == null)
647                                 return;
648
649                         if (_asyncPostBackControls == null)
650                                 _asyncPostBackControls = new List<Control> ();
651
652                         if (_asyncPostBackControls.Contains (control))
653                                 return;
654
655                         _asyncPostBackControls.Add (control);
656                 }
657
658                 public static void RegisterClientScriptBlock (Control control, Type type, string key, string script, bool addScriptTags) {
659                         RegisterClientScriptBlock (control.Page, type, key, script, addScriptTags);
660                 }
661
662                 public static void RegisterClientScriptBlock (Page page, Type type, string key, string script, bool addScriptTags) {
663                         ScriptManager sm = GetCurrent (page);
664                         if (sm.IsInAsyncPostBack)
665                                 RegisterScript (ref sm._clientScriptBlocks, type, key, script, addScriptTags ? ScriptEntryType.ScriptContentNoTags : ScriptEntryType.ScriptContentWithTags);
666                         else
667                                 page.ClientScript.RegisterClientScriptBlock (type, key, script, addScriptTags);
668                 }
669
670                 public static void RegisterClientScriptInclude (Control control, Type type, string key, string url) {
671                         RegisterClientScriptInclude (control.Page, type, key, url);
672                 }
673
674                 public static void RegisterClientScriptInclude (Page page, Type type, string key, string url) {
675                         ScriptManager sm = GetCurrent (page);
676                         if (sm.IsInAsyncPostBack)
677                                 RegisterScript (ref sm._scriptIncludes, type, key, url, ScriptEntryType.ScriptPath);
678                         else
679                                 page.ClientScript.RegisterClientScriptInclude (type, key, url);
680                 }
681
682                 public static void RegisterClientScriptResource (Control control, Type type, string resourceName) {
683                         RegisterClientScriptResource (control.Page, type, resourceName);
684                 }
685
686                 public static void RegisterClientScriptResource (Page page, Type type, string resourceName) {
687                         RegisterClientScriptInclude (page, type, "resource-" + resourceName, ScriptResourceHandler.GetResourceUrl (type.Assembly, resourceName, true));
688                 }
689
690                 void RegisterScriptReference (ScriptReference script, bool loadScriptsBeforeUI) {
691
692                         bool isDebugMode = IsDeploymentRetail ? false : (script.ScriptModeInternal == ScriptMode.Inherit ? IsDebuggingEnabled : (script.ScriptModeInternal == ScriptMode.Debug));
693                         string url;
694                         if (!String.IsNullOrEmpty (script.Path)) {
695                                 url = GetScriptName (ResolveClientUrl (script.Path), isDebugMode, EnableScriptLocalization ? script.ResourceUICultures : null);
696                         }
697                         else if (!String.IsNullOrEmpty (script.Name)) {
698                                 Assembly assembly;
699                                 if (String.IsNullOrEmpty (script.Assembly))
700                                         assembly = typeof (ScriptManager).Assembly;
701                                 else
702                                         assembly = Assembly.Load (script.Assembly);
703                                 string name = GetScriptName (script.Name, isDebugMode, null);
704                                 if (script.IgnoreScriptPath || String.IsNullOrEmpty (ScriptPath))
705                                         url = ScriptResourceHandler.GetResourceUrl (assembly, name, script.NotifyScriptLoaded);
706                                 else {
707                                         AssemblyName an = assembly.GetName ();
708                                         url = ResolveClientUrl (String.Concat (VirtualPathUtility.AppendTrailingSlash (ScriptPath), an.Name, '/', an.Version, '/', name));
709                                 }
710                         }
711                         else {
712                                 throw new InvalidOperationException ("Name and Path cannot both be empty.");
713                         }
714
715                         if (loadScriptsBeforeUI)
716                                 RegisterClientScriptInclude (this, typeof (ScriptManager), url, url);
717                         else
718                                 RegisterStartupScript (this, typeof (ScriptManager), url, String.Format ("<script src=\"{0}\" type=\"text/javascript\"></script>", url), false);
719                 }
720
721                 static string GetScriptName (string releaseName, bool isDebugMode, string [] supportedUICultures) {
722                         if (!isDebugMode && (supportedUICultures == null || supportedUICultures.Length == 0))
723                                 return releaseName;
724
725                         if (releaseName.Length < 3 || !releaseName.EndsWith (".js", StringComparison.OrdinalIgnoreCase))
726                                 throw new InvalidOperationException (String.Format ("'{0}' is not a valid script path.  The path must end in '.js'.", releaseName));
727
728                         StringBuilder sb = new StringBuilder (releaseName);
729                         sb.Length -= 3;
730                         if (isDebugMode)
731                                 sb.Append (".debug");
732                         string culture = Thread.CurrentThread.CurrentUICulture.Name;
733                         if (supportedUICultures != null && Array.IndexOf<string> (supportedUICultures, culture) >= 0)
734                                 sb.AppendFormat (".{0}", culture);
735                         sb.Append (".js");
736
737                         return sb.ToString ();
738                 }
739
740                 void RegisterServiceReference (ServiceReference serviceReference) {
741                         if (serviceReference.InlineScript) {
742                                 string url = ResolveUrl (serviceReference.Path);
743                                 LogicalTypeInfo logicalTypeInfo = LogicalTypeInfo.GetLogicalTypeInfo (WebServiceParser.GetCompiledType (url, Context), url);
744                                 RegisterClientScriptBlock (this, typeof (ScriptManager), url, logicalTypeInfo.Proxy, true);
745                         }
746                         else {
747 #if TARGET_J2EE
748                                 string pathInfo = "/js.invoke";
749 #else
750                                 string pathInfo = "/js";
751 #endif
752                                 string url = String.Concat (ResolveClientUrl (serviceReference.Path), pathInfo);
753                                 RegisterClientScriptInclude (this, typeof (ScriptManager), url, url);
754                         }
755                 }
756
757                 public void RegisterDataItem (Control control, string dataItem) {
758                         RegisterDataItem (control, dataItem, false);
759                 }
760
761                 public void RegisterDataItem (Control control, string dataItem, bool isJsonSerialized) {
762                         if (!IsInAsyncPostBack)
763                                 throw new InvalidOperationException ("RegisterDataItem can only be called during an async postback.");
764                         if (control == null)
765                                 throw new ArgumentNullException ("control");
766
767                         if (_dataItems == null)
768                                 _dataItems = new Dictionary<Control, DataItemEntry> ();
769
770                         if (_dataItems.ContainsKey (control))
771                                 throw new ArgumentException (String.Format ("'{0}' already has a data item registered.", control.ID), "control");
772
773                         _dataItems.Add (control, new DataItemEntry (dataItem, isJsonSerialized));
774                 }
775
776                 public void RegisterDispose (Control control, string disposeScript) {
777                         if (control == null)
778                                 throw new ArgumentNullException ("control");
779                         if (disposeScript == null)
780                                 throw new ArgumentNullException ("disposeScript");
781
782                         UpdatePanel updatePanel = GetUpdatePanel (control);
783                         if (updatePanel == null)
784                                 return;
785
786                         if (_disposeScripts == null)
787                                 _disposeScripts = new List<DisposeScriptEntry> ();
788                         _disposeScripts.Add (new DisposeScriptEntry (updatePanel, disposeScript));
789                 }
790
791                 static UpdatePanel GetUpdatePanel (Control control) {
792                         if (control == null)
793                                 return null;
794
795                         UpdatePanel parent = control.Parent as UpdatePanel;
796                         if (parent != null)
797                                 return parent;
798
799                         return GetUpdatePanel (control.Parent);
800                 }
801
802                 public static void RegisterExpandoAttribute (Control control, string controlId, string attributeName, string attributeValue, bool encode) {
803                         Page page = control.Page;
804                         ScriptManager sm = GetCurrent (page);
805                         if (sm.IsInAsyncPostBack)
806                                 sm.RegisterExpandoAttribute (controlId, attributeName, attributeValue, encode);
807                         else
808                                 page.ClientScript.RegisterExpandoAttribute (controlId, attributeName, attributeValue, encode);
809                 }
810
811                 private void RegisterExpandoAttribute (string controlId, string attributeName, string attributeValue, bool encode) {
812                         // seems MS do nothing.
813                 }
814
815                 public static void RegisterHiddenField (Control control, string hiddenFieldName, string hiddenFieldInitialValue) {
816                         RegisterHiddenField (control.Page, hiddenFieldName, hiddenFieldInitialValue);
817                 }
818
819                 public static void RegisterHiddenField (Page page, string hiddenFieldName, string hiddenFieldInitialValue) {
820                         ScriptManager sm = GetCurrent (page);
821                         if (sm.IsInAsyncPostBack)
822                                 sm.RegisterHiddenField (hiddenFieldName, hiddenFieldInitialValue);
823                         else
824                                 page.ClientScript.RegisterHiddenField (hiddenFieldName, hiddenFieldInitialValue);
825                 }
826
827                 void RegisterHiddenField (string hiddenFieldName, string hiddenFieldInitialValue) {
828                         if (_hiddenFields == null)
829                                 _hiddenFields = new Hashtable ();
830
831                         if (!_hiddenFields.ContainsKey (hiddenFieldName))
832                                 _hiddenFields.Add (hiddenFieldName, hiddenFieldInitialValue);
833                 }
834
835                 public static void RegisterOnSubmitStatement (Control control, Type type, string key, string script) {
836                         RegisterOnSubmitStatement (control.Page, type, key, script);
837                 }
838
839                 public static void RegisterOnSubmitStatement (Page page, Type type, string key, string script) {
840                         ScriptManager sm = GetCurrent (page);
841                         if (sm.IsInAsyncPostBack)
842                                 RegisterScript (ref sm._onSubmitStatements, type, key, script, ScriptEntryType.OnSubmit);
843                         else
844                                 page.ClientScript.RegisterOnSubmitStatement (type, key, script);
845                 }
846
847                 public void RegisterPostBackControl (Control control) {
848                         if (control == null)
849                                 return;
850
851                         if (_postBackControls == null)
852                                 _postBackControls = new List<Control> ();
853
854                         if (_postBackControls.Contains (control))
855                                 return;
856
857                         _postBackControls.Add (control);
858                 }
859
860                 internal void RegisterUpdatePanel (UpdatePanel updatePanel) {
861                         if (_updatePanels == null)
862                                 _updatePanels = new List<UpdatePanel> ();
863
864                         if (_updatePanels.Contains (updatePanel))
865                                 return;
866
867                         _updatePanels.Add (updatePanel);
868                 }
869
870                 public void RegisterScriptDescriptors (IExtenderControl extenderControl) {
871                         if (extenderControl == null)
872                                 return;
873
874                         if (_registeredExtenderControls == null || !_registeredExtenderControls.ContainsKey (extenderControl))
875                                 return;
876
877                         Control targetControl = _registeredExtenderControls [extenderControl];
878                         RegisterScriptDescriptors (extenderControl.GetScriptDescriptors (targetControl));
879                 }
880
881                 public void RegisterScriptDescriptors (IScriptControl scriptControl) {
882                         if (scriptControl == null)
883                                 return;
884
885                         if (_registeredScriptControls == null || !_registeredScriptControls.Contains (scriptControl))
886                                 return;
887
888                         RegisterScriptDescriptors (scriptControl.GetScriptDescriptors ());
889                 }
890
891                 void RegisterScriptDescriptors (IEnumerable<ScriptDescriptor> scriptDescriptors) {
892                         if (scriptDescriptors == null)
893                                 return;
894                         if (IsInAsyncPostBack && !IsInPartialRendering)
895                                 return;
896
897                         StringBuilder sb = new StringBuilder ();
898                         foreach (ScriptDescriptor scriptDescriptor in scriptDescriptors) {
899                                 if (IsMultiForm) {
900                                         scriptDescriptor.FormID = Page.Form.ClientID;
901                                         sb.AppendLine ("Sys.Application.getInstance($get(\"" + Page.Form.ClientID + "\")).add_init(function() {");
902                                 }
903                                 else
904                                 sb.AppendLine ("Sys.Application.add_init(function() {");
905                                 sb.AppendLine (scriptDescriptor.GetScript ());
906                                 sb.AppendLine ("});");
907                         }
908                         string script = sb.ToString ();
909                         RegisterStartupScript (this, typeof (ExtenderControl), script, script, true);
910                 }
911
912                 public static void RegisterStartupScript (Control control, Type type, string key, string script, bool addScriptTags) {
913                         RegisterStartupScript (control.Page, type, key, script, addScriptTags);
914                 }
915
916                 public static void RegisterStartupScript (Page page, Type type, string key, string script, bool addScriptTags) {
917                         ScriptManager sm = GetCurrent (page);
918                         if (sm.IsInAsyncPostBack)
919                                 RegisterScript (ref sm._startupScriptBlocks, type, key, script, addScriptTags ? ScriptEntryType.ScriptContentNoTags : ScriptEntryType.ScriptContentWithTags);
920                         else
921                                 page.ClientScript.RegisterStartupScript (type, key, script, addScriptTags);
922                 }
923
924                 public void RegisterScriptControl<TScriptControl> (TScriptControl scriptControl) where TScriptControl : Control, IScriptControl {
925                         if (scriptControl == null)
926                                 throw new ArgumentNullException ("scriptControl");
927
928                         if (_registeredScriptControls == null)
929                                 _registeredScriptControls = new List<IScriptControl> ();
930
931                         if (!_registeredScriptControls.Contains (scriptControl))
932                                 _registeredScriptControls.Add (scriptControl);
933                 }
934
935                 public void RegisterExtenderControl<TExtenderControl> (TExtenderControl extenderControl, Control targetControl) where TExtenderControl : Control, IExtenderControl {
936                         if (extenderControl == null)
937                                 throw new ArgumentNullException ("extenderControl");
938                         if (targetControl == null)
939                                 throw new ArgumentNullException ("targetControl");
940
941                         if (_registeredExtenderControls == null)
942                                 _registeredExtenderControls = new Dictionary<IExtenderControl, Control> ();
943
944                         if (!_registeredExtenderControls.ContainsKey (extenderControl))
945                                 _registeredExtenderControls.Add (extenderControl, targetControl);
946                 }
947
948                 static void RegisterScript (ref ScriptEntry scriptList, Type type, string key, string script, ScriptEntryType scriptEntryType) {
949                         ScriptEntry last = null;
950                         ScriptEntry entry = scriptList;
951
952                         while (entry != null) {
953                                 if (entry.Type == type && entry.Key == key)
954                                         return;
955                                 last = entry;
956                                 entry = entry.Next;
957                         }
958
959                         entry = new ScriptEntry (type, key, script, scriptEntryType);
960
961                         if (last != null)
962                                 last.Next = entry;
963                         else
964                                 scriptList = entry;
965                 }
966
967                 protected override void Render (HtmlTextWriter writer) {
968                         // MSDN: This method is used by control developers to extend the ScriptManager control. 
969                         // Notes to Inheritors: 
970                         // When overriding this method, call the base Render(HtmlTextWriter) method 
971                         // so that PageRequestManager is rendered on the page.
972                         if (SupportsPartialRendering) {
973                                 writer.WriteLine ("<script type=\"text/javascript\">");
974                                 writer.WriteLine ("//<![CDATA[");
975                                 writer.WriteLine ("Sys.WebForms.PageRequestManager._initialize('{0}', document.getElementById('{1}'));", UniqueID, Page.Form.ClientID);
976                                 if (IsMultiForm)
977                                         writer.WriteLine ("Sys.WebForms.PageRequestManager.getInstance($get(\"{0}\"))._updateControls([{1}], [{2}], [{3}], {4});", Page.Form.ClientID, FormatUpdatePanelIDs (_updatePanels, true), FormatListIDs (_asyncPostBackControls, true), FormatListIDs (_postBackControls, true), AsyncPostBackTimeout);
978                                 else
979                                 writer.WriteLine ("Sys.WebForms.PageRequestManager.getInstance()._updateControls([{0}], [{1}], [{2}], {3});", FormatUpdatePanelIDs (_updatePanels, true), FormatListIDs (_asyncPostBackControls, true), FormatListIDs (_postBackControls, true), AsyncPostBackTimeout);
980                                 writer.WriteLine ("//]]");
981                                 writer.WriteLine ("</script>");
982                         }
983                         base.Render (writer);
984                 }
985
986                 static string FormatUpdatePanelIDs (List<UpdatePanel> list, bool useSingleQuote) {
987                         if (list == null || list.Count == 0)
988                                 return null;
989
990                         StringBuilder sb = new StringBuilder ();
991                         for (int i = 0; i < list.Count; i++) {
992                                 sb.AppendFormat ("{0}{1}{2}{0},", useSingleQuote ? "'" : String.Empty, list [i].ChildrenAsTriggers ? "t" : "f", list [i].UniqueID);
993                         }
994                         if (sb.Length > 0)
995                                 sb.Length--;
996
997                         return sb.ToString ();
998                 }
999
1000                 static string FormatListIDs<T> (List<T> list, bool useSingleQuote) where T : Control {
1001                         if (list == null || list.Count == 0)
1002                                 return null;
1003
1004                         StringBuilder sb = new StringBuilder ();
1005                         for (int i = 0; i < list.Count; i++) {
1006                                 sb.AppendFormat ("{0}{1}{0},", useSingleQuote ? "'" : String.Empty, list [i].UniqueID);
1007                         }
1008                         if (sb.Length > 0)
1009                                 sb.Length--;
1010
1011                         return sb.ToString ();
1012                 }
1013
1014                 public void SetFocus (Control control) {
1015                         if (control == null)
1016                                 throw new ArgumentNullException ("control");
1017
1018                         if (IsInAsyncPostBack) {
1019                                 EnsureFocusClientScript ();
1020                                 _controlIDToFocus = control.ClientID;
1021                         }
1022                         else
1023                                 Page.SetFocus (control);
1024                 }
1025
1026                 public void SetFocus (string clientID) {
1027                         if (String.IsNullOrEmpty (clientID))
1028                                 throw new ArgumentNullException ("control");
1029
1030                         if (IsInAsyncPostBack) {
1031                                 EnsureFocusClientScript ();
1032                                 _controlIDToFocus = clientID;
1033                         }
1034                         else
1035                                 Page.SetFocus (clientID);
1036                 }
1037
1038                 void EnsureFocusClientScript () {
1039 #if     TARGET_DOTNET
1040                         RegisterClientScriptResource (this, typeof (ClientScriptManager), "Focus.js");
1041 #endif
1042                 }
1043
1044                 #region IPostBackDataHandler Members
1045
1046                 bool IPostBackDataHandler.LoadPostData (string postDataKey, NameValueCollection postCollection) {
1047                         return LoadPostData (postDataKey, postCollection);
1048                 }
1049
1050                 void IPostBackDataHandler.RaisePostDataChangedEvent () {
1051                         RaisePostDataChangedEvent ();
1052                 }
1053
1054                 #endregion
1055
1056                 internal void WriteCallbackException (TextWriter output, Exception ex, bool writeMessage) {
1057 #if TARGET_DOTNET
1058                         if (ex is HttpUnhandledException)
1059                                 ex = ex.InnerException;
1060 #endif
1061                         HttpException httpEx = ex as HttpException;
1062                         string message = AsyncPostBackErrorMessage;
1063                         if (String.IsNullOrEmpty (message) && writeMessage)
1064                                 message = ex.Message;
1065                         WriteCallbackOutput (output, error, httpEx == null ? "500" : httpEx.GetHttpCode ().ToString (), message);
1066                 }
1067
1068                 static internal void WriteCallbackRedirect (TextWriter output, string redirectUrl) {
1069                         WriteCallbackOutput (output, pageRedirect, null, redirectUrl);
1070                 }
1071
1072                 internal void WriteCallbackPanel (TextWriter output, UpdatePanel panel, StringBuilder panelOutput) {
1073                         if (_panelsToRefresh == null)
1074                                 _panelsToRefresh = new List<UpdatePanel> ();
1075                         _panelsToRefresh.Add (panel);
1076
1077                         WriteCallbackOutput (output, updatePanel, panel.ClientID, panelOutput);
1078                 }
1079
1080                 internal void RegisterChildUpdatePanel (UpdatePanel updatePanel) {
1081                         if (_childUpdatePanels == null)
1082                                 _childUpdatePanels = new List<UpdatePanel> ();
1083                         _childUpdatePanels.Add (updatePanel);
1084                 }
1085
1086                 static void WriteCallbackOutput (TextWriter output, string type, string name, object value) {
1087                         string str = value as string;
1088                         StringBuilder sb = value as StringBuilder;
1089                         int length = 0;
1090                         if (str != null)
1091                                 length = str.Length;
1092                         else if (sb != null)
1093                                 length = sb.Length;
1094
1095                         //output.Write ("{0}|{1}|{2}|{3}|", value == null ? 0 : value.Length, type, name, value);
1096                         output.Write (length);
1097                         output.Write ('|');
1098                         output.Write (type);
1099                         output.Write ('|');
1100                         output.Write (name);
1101                         output.Write ('|');
1102                         for (int i = 0; i < length; i++)
1103                                 if (str != null)
1104                                         output.Write (str [i]);
1105                                 else
1106                                         output.Write (sb [i]);
1107                         output.Write ('|');
1108                 }
1109
1110                 void RenderPageCallback (HtmlTextWriter output, Control container) {
1111                         Page page = (Page) container;
1112
1113                         page.Form.SetRenderMethodDelegate (RenderFormCallback);
1114                         HtmlTextParser parser = new HtmlTextParser (output);
1115                         page.Form.RenderControl (parser);
1116
1117                         WriteCallbackOutput (output, asyncPostBackControlIDs, null, FormatListIDs (_asyncPostBackControls, false));
1118                         WriteCallbackOutput (output, postBackControlIDs, null, FormatListIDs (_postBackControls, false));
1119                         WriteCallbackOutput (output, updatePanelIDs, null, FormatUpdatePanelIDs (_updatePanels, false));
1120                         WriteCallbackOutput (output, childUpdatePanelIDs, null, FormatListIDs (_childUpdatePanels, false));
1121                         WriteCallbackOutput (output, panelsToRefreshIDs, null, FormatListIDs (_panelsToRefresh, false));
1122                         WriteCallbackOutput (output, asyncPostBackTimeout, null, AsyncPostBackTimeout.ToString ());
1123                         if (!IsMultiForm)
1124                                 WriteCallbackOutput (output, pageTitle, null, Page.Title);
1125
1126                         if (_dataItems != null)
1127                                 foreach (Control control in _dataItems.Keys) {
1128                                         DataItemEntry entry = _dataItems [control];
1129                                         WriteCallbackOutput (output, entry.IsJsonSerialized ? dataItemJson : dataItem, control.ClientID, entry.DataItem);
1130                                 }
1131
1132                         WriteArrayDeclarations (output);
1133                         WriteScriptBlocks (output, _clientScriptBlocks);
1134                         WriteScriptBlocks (output, _scriptIncludes);
1135                         WriteScriptBlocks (output, _startupScriptBlocks);
1136                         WriteScriptBlocks (output, _onSubmitStatements);
1137                         WriteHiddenFields (output);
1138
1139                         if (!String.IsNullOrEmpty (_controlIDToFocus))
1140                                 WriteCallbackOutput (output, focus, null, _controlIDToFocus);
1141
1142                         if (_disposeScripts != null)
1143                                 for (int i = 0; i < _disposeScripts.Count; i++) {
1144                                         DisposeScriptEntry entry = _disposeScripts [i];
1145                                         if ((_panelsToRefresh != null && _panelsToRefresh.IndexOf (entry.UpdatePanel) >= 0) || (_childUpdatePanels != null && _childUpdatePanels.IndexOf (entry.UpdatePanel) >= 0))
1146                                                 WriteCallbackOutput (output, scriptDispose, entry.UpdatePanel.ClientID, entry.Script);
1147                                 }
1148                 }
1149
1150                 void WriteArrayDeclarations (HtmlTextWriter writer) {
1151                         if (_arrayDeclarations != null) {
1152                                 for (int i = 0; i < _arrayDeclarations.Count; i++) {
1153                                         ArrayDeclaration array = _arrayDeclarations [i];
1154                                         WriteCallbackOutput (writer, arrayDeclaration, array.ArrayName, array.ArrayValue);
1155                                 }
1156                         }
1157                 }
1158
1159                 void WriteScriptBlocks (HtmlTextWriter output, ScriptEntry scriptList) {
1160                         while (scriptList != null) {
1161                                 switch (scriptList.ScriptEntryType) {
1162                                 case ScriptEntryType.ScriptContentNoTags:
1163                                         WriteCallbackOutput (output, scriptBlock, scriptContentNoTags, scriptList.Script);
1164                                         break;
1165                                 case ScriptEntryType.ScriptContentWithTags:
1166                                         string script = SerializeScriptBlock (scriptList);
1167                                         WriteCallbackOutput (output, scriptBlock, scriptContentWithTags, script);
1168                                         break;
1169                                 case ScriptEntryType.ScriptPath:
1170                                         WriteCallbackOutput (output, scriptBlock, scriptPath, scriptList.Script);
1171                                         break;
1172                                 case ScriptEntryType.OnSubmit:
1173                                         WriteCallbackOutput (output, onSubmit, null, scriptList.Script);
1174                                         break;
1175                                 }
1176                                 scriptList = scriptList.Next;
1177                         }
1178                 }
1179
1180                 void WriteHiddenFields (HtmlTextWriter output) {
1181                         if (_hiddenFields == null)
1182                                 return;
1183                         foreach (string key in _hiddenFields.Keys) {
1184                                 string value = _hiddenFields [key] as string;
1185                                 WriteCallbackOutput (output, hiddenField, key, value);
1186                         }
1187                 }
1188
1189                 static string SerializeScriptBlock (ScriptEntry scriptList) {
1190                         try {
1191                                 XmlTextReader reader = new XmlTextReader (new StringReader (scriptList.Script));
1192                                 while (reader.Read ()) {
1193                                         switch (reader.NodeType) {
1194                                         case XmlNodeType.Element:
1195                                                 if (String.Compare ("script", reader.Name, StringComparison.OrdinalIgnoreCase) == 0) {
1196                                                         Dictionary<string, string> dic = new Dictionary<string, string> ();
1197                                                         while (reader.MoveToNextAttribute ()) {
1198                                                                 dic.Add (reader.Name, reader.Value);
1199                                                         }
1200                                                         reader.MoveToContent ();
1201                                                         dic.Add ("text", reader.ReadInnerXml ());
1202                                                         return JavaScriptSerializer.DefaultSerializer.Serialize (dic);
1203                                                 }
1204                                                 break;
1205                                         default:
1206                                                 continue;
1207                                         }
1208                                 }
1209                         }
1210                         catch {
1211                         }
1212                         throw new InvalidOperationException (String.Format ("The script tag registered for type '{0}' and key '{1}' has invalid characters outside of the script tags: {2}. Only properly formatted script tags can be registered.", scriptList.Type, scriptList.Key, scriptList.Script));
1213                 }
1214
1215                 void RenderFormCallback (HtmlTextWriter output, Control container) {
1216                         output = ((HtmlTextParser) output).ResponseOutput;
1217                         HtmlForm form = (HtmlForm) container;
1218                         HtmlTextWriter writer = new HtmlDropWriter (output);
1219                         if (form.HasControls ()) {
1220                                 for (int i = 0; i < form.Controls.Count; i++) {
1221                                         form.Controls [i].RenderControl (writer);
1222                                 }
1223                         }
1224                 }
1225
1226                 internal class AlternativeHtmlTextWriter : HtmlTextWriter
1227                 {
1228                         readonly HtmlTextWriter _responseOutput;
1229
1230                         public HtmlTextWriter ResponseOutput {
1231                                 get { return _responseOutput; }
1232                         }
1233
1234                         public AlternativeHtmlTextWriter (TextWriter writer, HtmlTextWriter responseOutput)
1235                                 : base (writer) {
1236                                 _responseOutput = responseOutput;
1237                         }
1238                 }
1239
1240                 sealed class HtmlTextParser : AlternativeHtmlTextWriter
1241                 {
1242                         public HtmlTextParser (HtmlTextWriter responseOutput)
1243                                 : base (new TextParser (responseOutput), responseOutput) {
1244                         }
1245                 }
1246
1247                 sealed class TextParser : TextWriter
1248                 {
1249                         int _state;
1250                         char _charState = (char) 255;
1251                         const char nullCharState = (char) 255;
1252                         StringBuilder _sb = new StringBuilder ();
1253                         Dictionary<string, string> _currentField;
1254                         string _currentAttribute;
1255                         readonly HtmlTextWriter _responseOutput;
1256
1257                         public override Encoding Encoding {
1258                                 get { return Encoding.UTF8; }
1259                         }
1260
1261                         public TextParser (HtmlTextWriter responseOutput) {
1262                                 _responseOutput = responseOutput;
1263                         }
1264
1265                         public override void Write (char value) {
1266                                 switch (_state) {
1267                                 case 0:
1268                                         ParseBeginTag (value);
1269                                         break;
1270                                 case 1:
1271                                         ParseAttributeName (value);
1272                                         break;
1273                                 case 2:
1274                                         ParseAttributeValue (value);
1275                                         break;
1276                                 }
1277                         }
1278
1279                         private void ParseAttributeValue (char value) {
1280                                 switch (value) {
1281                                 case '>':
1282                                         ResetState ();
1283                                         break;
1284                                 case '"':
1285                                         _currentField.Add (_currentAttribute, _sb.ToString ());
1286                                         _state = 1;
1287                                         _sb.Length = 0;
1288                                         ProbeWriteOutput ();
1289                                         break;
1290                                 default:
1291                                         _sb.Append (value);
1292                                         break;
1293                                 }
1294                         }
1295
1296                         private void ParseAttributeName (char value) {
1297                                 switch (value) {
1298                                 case '>':
1299                                         ResetState ();
1300                                         break;
1301                                 case ' ':
1302                                 case '=':
1303                                         break;
1304                                 case '"':
1305                                         _currentAttribute = _sb.ToString ();
1306                                         _state = 2;
1307                                         _sb.Length = 0;
1308                                         break;
1309                                 default:
1310                                         _sb.Append (value);
1311                                         break;
1312                                 }
1313                         }
1314
1315                         void ParseBeginTag (char value) {
1316                                 switch (_charState) {
1317                                 case nullCharState:
1318                                         if (value == '<')
1319                                                 _charState = value;
1320                                         break;
1321                                 case '<':
1322                                         if (value == 'i')
1323                                                 _charState = value;
1324                                         else
1325                                                 ResetState ();
1326                                         break;
1327                                 case 'i':
1328                                         if (value == 'n')
1329                                                 _charState = value;
1330                                         else
1331                                                 ResetState ();
1332                                         break;
1333                                 case 'n':
1334                                         if (value == 'p')
1335                                                 _charState = value;
1336                                         else
1337                                                 ResetState ();
1338                                         break;
1339                                 case 'p':
1340                                         if (value == 'u')
1341                                                 _charState = value;
1342                                         else
1343                                                 ResetState ();
1344                                         break;
1345                                 case 'u':
1346                                         if (value == 't')
1347                                                 _charState = value;
1348                                         else
1349                                                 ResetState ();
1350                                         break;
1351                                 case 't':
1352                                         if (value == ' ') {
1353                                                 _state = 1;
1354                                                 _currentField = new Dictionary<string, string> ();
1355                                         }
1356                                         else
1357                                                 ResetState ();
1358                                         break;
1359                                 }
1360                         }
1361
1362                         private void ResetState () {
1363                                 _charState = nullCharState;
1364                                 _state = 0;
1365                                 _sb.Length = 0;
1366                         }
1367
1368                         private void ProbeWriteOutput () {
1369                                 if (!_currentField.ContainsKey ("name"))
1370                                         return;
1371                                 if (!_currentField.ContainsKey ("value"))
1372                                         return;
1373
1374                                 string value = _currentField ["value"];
1375                                 if (String.IsNullOrEmpty (value))
1376                                         return;
1377
1378                                 ScriptManager.WriteCallbackOutput (_responseOutput, hiddenField, _currentField ["name"], HttpUtility.HtmlDecode (value));
1379                         }
1380                 }
1381
1382                 sealed class HtmlDropWriter : AlternativeHtmlTextWriter
1383                 {
1384                         public HtmlDropWriter (HtmlTextWriter responseOutput)
1385                                 : base (new DropWriter (), responseOutput) {
1386                         }
1387                 }
1388
1389                 sealed class DropWriter : TextWriter
1390                 {
1391                         public override Encoding Encoding {
1392                                 get { return Encoding.UTF8; }
1393                         }
1394                 }
1395
1396                 sealed class ScriptEntry
1397                 {
1398                         readonly public Type Type;
1399                         readonly public string Key;
1400                         readonly public string Script;
1401                         readonly public ScriptEntryType ScriptEntryType;
1402                         public ScriptEntry Next;
1403
1404                         public ScriptEntry (Type type, string key, string script, ScriptEntryType scriptEntryType) {
1405                                 Key = key;
1406                                 Type = type;
1407                                 Script = script;
1408                                 ScriptEntryType = scriptEntryType;
1409                         }
1410                 }
1411
1412                 enum ScriptEntryType
1413                 {
1414                         ScriptContentNoTags,
1415                         ScriptContentWithTags,
1416                         ScriptPath,
1417                         OnSubmit
1418                 }
1419
1420                 sealed class ArrayDeclaration
1421                 {
1422                         readonly public string ArrayName;
1423                         readonly public string ArrayValue;
1424
1425                         public ArrayDeclaration (string arrayName, string arrayValue) {
1426                                 ArrayName = arrayName;
1427                                 ArrayValue = arrayValue;
1428                         }
1429                 }
1430
1431                 sealed class CultureInfoSerializer : JavaScriptSerializer.LazyDictionary
1432                 {
1433                         readonly CultureInfo _ci;
1434                         public CultureInfoSerializer (CultureInfo ci) {
1435                                 if (ci == null)
1436                                         throw new ArgumentNullException ("ci");
1437                                 _ci = ci;
1438                         }
1439                         protected override IEnumerator<KeyValuePair<string, object>> GetEnumerator () {
1440                                 yield return new KeyValuePair<string, object> ("name", _ci.Name);
1441                                 yield return new KeyValuePair<string, object> ("numberFormat", _ci.NumberFormat);
1442                                 yield return new KeyValuePair<string, object> ("dateTimeFormat", _ci.DateTimeFormat);
1443                         }
1444                 }
1445
1446                 sealed class ScriptReferenceEntry
1447                 {
1448                         readonly Control _control;
1449                         readonly ScriptReference _scriptReference;
1450                         readonly bool _loadBeforeUI;
1451
1452                         public Control Control { get { return _control; } }
1453                         public ScriptReference ScriptReference { get { return _scriptReference; } }
1454                         public bool LoadScriptsBeforeUI { get { return _loadBeforeUI; } }
1455
1456                         public ScriptReferenceEntry (Control control, ScriptReference scriptReference, bool loadBeforeUI) {
1457                                 _control = control;
1458                                 _scriptReference = scriptReference;
1459                                 _loadBeforeUI = loadBeforeUI;
1460                         }
1461                 }
1462
1463                 sealed class DataItemEntry
1464                 {
1465                         readonly string _dataItem;
1466                         readonly bool _isJsonSerialized;
1467
1468                         public string DataItem { get { return _dataItem; } }
1469                         public bool IsJsonSerialized { get { return _isJsonSerialized; } }
1470
1471                         public DataItemEntry (string dataItem, bool isJsonSerialized) {
1472                                 _dataItem = dataItem;
1473                                 _isJsonSerialized = isJsonSerialized;
1474                         }
1475                 }
1476
1477                 sealed class DisposeScriptEntry
1478                 {
1479                         readonly UpdatePanel _updatePanel;
1480                         readonly string _script;
1481
1482                         public UpdatePanel UpdatePanel { get { return _updatePanel; } }
1483                         public string Script { get { return _script; } }
1484
1485                         public DisposeScriptEntry (UpdatePanel updatePanel, string script) {
1486                                 _updatePanel = updatePanel;
1487                                 _script = script;
1488                         }
1489                 }
1490         }
1491 }